Ejemplo n.º 1
0
    def store_compressed_volume(self):
        if len(self.volume) == 0 or self.volume_compressed:
            return

        volume = self.volume

        compressed_volume_file = os.path.join(
            self.compressed_volume_directory,
            string2hash(self.uid) + '.dat.gz')
        with open(compressed_volume_file, 'wb') as f:
            gzip_file = gzip.GzipFile(mode='wb', fileobj=f, compresslevel=9)
            gzip_file.write(volume.tobytes())
            gzip_file.close()
Ejemplo n.º 2
0
    def fromID(cls,
               uid,
               scanfolder='',
               read_volume=True,
               prefer_compressed_volume=True,
               compressed_volumes_dir=None):
        series_uid = SeriesUID(uid)
        scan = cls()
        scan_dir = os.path.join(scanfolder, series_uid.dicom_dir_name)

        if not os.path.isdir(scan_dir):
            scan_dir = os.path.join(scanfolder,
                                    series_uid.optimized_dicom_dir_name)
            if not os.path.isdir(scan_dir):
                raise IOError("Could not find dicom dir " + scan_dir)

        series_builder = SeriesBuilder(uid)

        slices = 0
        for f in os.listdir(scan_dir):
            ds = dicom.read_file(os.path.join(scan_dir, f),
                                 force=True,
                                 stop_before_pixels=not read_volume)
            z_pos = get_image_z_position_or_default(ds)
            scan.image_positions.append(z_pos)
            if read_volume:
                series_builder.add_slice(dicom.read_file(
                    os.path.join(scan_dir, f)),
                                         override_z_pos=z_pos)
            slices += 1

        scan.size = [slices, ds.Rows, ds.Columns]

        scan.uid = uid
        scan.directory = scanfolder
        scan.compressed_volume_directory = compressed_volumes_dir or scanfolder
        scan.name = str(ds.PatientName)
        scan.metadata = _read_metadata(ds)
        scan.body_part = _get_body_part(ds)
        if 'ImageOrientationPatient' in scan.metadata:
            scan.plane = get_plane(scan.metadata['ImageOrientationPatient'])
            scan.image_orientation = scan.metadata['ImageOrientationPatient']
        elif slices == 1:
            scan.image_orientation = get_orientation_vector_for_plane_name(
                AXIAL)
            scan.plane = get_plane(scan.image_orientation)
        else:
            raise NoImageOrientationError()
        scan.date = scan.metadata['StudyDate']
        scan.time = scan.metadata['StudyTime']
        scan.patient_id = scan.metadata[
            'PatientID'] if 'PatientID' in scan.metadata else ''

        if read_volume:
            scan.volume = None
            compressed_volume_file = os.path.join(
                scan.compressed_volume_directory,
                string2hash(uid) + '.dat.gz')
            if prefer_compressed_volume and os.path.isfile(
                    compressed_volume_file):
                try:
                    with open(compressed_volume_file, 'rb') as f:
                        scan.volume = f.read()
                    scan.volume_compressed = True
                except Exception:
                    logger.exception('uid %s: Error reading compressed volume',
                                     uid)

            if not scan.volume:
                ignore_missing_orientation = False
                if slices == 1:
                    ignore_missing_orientation = True
                series = series_builder.build(
                    ignore_missing_orientation=ignore_missing_orientation)

                scan.volume = series.volume
                scan.volume_compressed = False

        return scan
Ejemplo n.º 3
0
    def fromID(cls,
               uid,
               scanfolder='',
               read_volume=True,
               prefer_compressed_volume=True,
               compressed_volumes_dir=None):
        series_uid = SeriesUID(uid)
        if len(scanfolder) == 0:
            scanfolder = common.getTMpath('CTscans')

        filename = os.path.join(scanfolder, series_uid.mat_filename)
        if not os.path.isfile(filename):
            return dicom_scan.Scan.fromID(uid, scanfolder, read_volume,
                                          prefer_compressed_volume,
                                          compressed_volumes_dir)

        rawScan = h5py.File(filename)

        if 'volume' not in rawScan:
            raise IOError("Invalid scan in file " + filename)

        scan = cls()
        scan.uid = uid
        scan.directory = scanfolder
        scan.compressed_volume_directory = compressed_volumes_dir or scanfolder
        scan.name = rawScan['name'].value.tostring().decode('utf-16')
        scan.defWindow = rawScan['defWindow'].value
        scan.normWindow = rawScan['defWindow'].value + rawScan[
            'matlabWindowShift'].value
        scan.metadata = _read_metadata(rawScan, rawScan['metadata'])
        scan.body_part = _get_scan_type(rawScan)
        try:
            scan.plane = _get_plane(rawScan)
        except Exception as e:
            if scan.body_part == 'brain':
                # We can assume the scan is axial
                logger.warning('uid %s: %s - assuming Axial', uid, str(e))
                scan.plane = 'axial'
            else:
                raise e

        scan.image_orientation = scan.metadata[
            'ImageOrientationPatient'].tolist()
        scan.date = scan.metadata['StudyDate']
        scan.time = scan.metadata['StudyTime']
        scan.patient_id = scan.metadata[
            'PatientID'] if 'PatientID' in scan.metadata else ''

        if 'size' not in rawScan:
            logger.warning(
                'CTscan is missing the "size" field - computing from volume')
            # Volume shape is read as (slice, columns, rows). We want to reorder it to (slice, rows, columns)
            scan.size = rawScan['volume'].shape
            scan.size = [scan.size[0], scan.size[2], scan.size[1]]
        else:
            # The size is read as (rows, columns, slices). To match the volume, we change it to (slices, rows, colums)
            scan.size = rawScan['size'].value.flatten().astype(np.uint16)
            scan.size = [scan.size[2], scan.size[0], scan.size[1]]

        try:
            scan.image_positions = _read_image_positions(
                rawScan, scan.size[0], scan.plane)
        except Exception as e:
            logger.warning('uid %s: %s', uid, str(e))
            scan.image_positions = []

        if read_volume:
            scan.volume = None
            compressed_volume_file = os.path.join(
                scan.compressed_volume_directory,
                string2hash(uid) + '.dat.gz')
            if prefer_compressed_volume and os.path.isfile(
                    compressed_volume_file):
                try:
                    with open(compressed_volume_file, 'rb') as f:
                        scan.volume = f.read()
                    scan.volume_compressed = True
                except Exception:
                    logger.exception('uid %s: Error reading compressed volume',
                                     uid)

            if not scan.volume:
                scan.volume = rawScan['volume']
                # Volume shape is read as (slice, columns, rows). We want to reorder it to (slice, rows, columns)
                scan.volume = np.transpose(scan.volume, (0, 2, 1))
                scan.volume_compressed = False

        return scan
Ejemplo n.º 4
0
 def generate_patient_location():
     if self.patient_name:
         return patientLocations[int(string2hash(self.patient_name)) % len(patientLocations)]
     else:
         return patientLocations[0]
Ejemplo n.º 5
0
    def load_worklist(self,
                      user,
                      worklist_filename,
                      delete_user_metadata_before_loading=False,
                      overwrite_findings_metadata=False,
                      overwrite_volumes=False):
        if delete_user_metadata_before_loading:
            for work_item in user.worklist:
                self.delete_work_item(work_item)

        worklist_report = []
        try:
            uids, worklist_metadata = self.load_worklist_data(
                worklist_filename)
        except IllegalWorklistFormat as e:
            self.logger.error(e)
            uids = []
            worklist_metadata = None
            worklist_report.append('{}'.format(e))

        # Collect study information
        studies = {}
        for uid in uids:
            try:
                try:
                    scan = Scan.fromID(uid,
                                       self.ct_scans_dir,
                                       read_volume=False)
                except IOError:
                    self.logger.warning(
                        'Cannot find CTscan file for uid {}'.format(uid))
                    worklist_report.append({
                        uid:
                        'No scan file {} found'.format(string2hash(uid))
                    })
                    continue
                if 'StudyInstanceUID' in scan.metadata:
                    study_uid = scan.metadata['StudyInstanceUID']
                else:
                    self.logger.warning(
                        'Missing StudyInstanceUID for scan with uid %s - using accession number or '
                        'series uid instead', uid)
                    if 'AccessionNumber' in scan.metadata:
                        study_uid = scan.metadata['AccessionNumber']
                    else:
                        study_uid = scan.uid

                curr_scan_should_have_findings = self._scan_should_have_findings(
                    scan, worklist_metadata[study_uid]
                    if study_uid in worklist_metadata else {})
                load_finding_files = user.load_finding_files
                if load_finding_files and curr_scan_should_have_findings:
                    findings_filename = self.get_findings_file(scan.uid)
                    if not os.path.isfile(findings_filename):
                        self.logger.warning(
                            'Cannot locate findings JSON file for scan with uid "%s" - skipping',
                            uid)
                        worklist_report.append({uid: 'No findings file'})
                        continue

                if study_uid not in studies:
                    studies[study_uid] = []

                # check for duplicate series uids in the worklist
                duplicate_found = False
                for added_scan in studies[study_uid]:
                    if added_scan.uid == scan.uid:
                        duplicate_found = True
                        break

                if duplicate_found:
                    self.logger.warning(
                        'Duplicate uid {} in worklist'.format(uid))
                    worklist_report.append({uid: 'Duplicate uid in worklist'})
                    continue

                studies[study_uid].append(scan)
            except Exception as e:
                self.logger.warning(
                    'Unknown error for uid {} string2hash {}'.format(
                        uid, string2hash(uid)))
                worklist_report.append({
                    uid:
                    'Unknown error for uid {} string2hash {}'.format(
                        uid, string2hash(uid))
                })

        study_count = 0
        study_load_count = 0
        series_count = 0
        series_load_count = 0
        studies_report = []
        for study_uid, scans in studies.items():
            try:
                loaded, loaded_series = self.load_study(
                    study_uid, scans, user.id, worklist_metadata[study_uid] if
                    study_uid in worklist_metadata else {}, overwrite_volumes,
                    load_finding_files, overwrite_findings_metadata)
                study_count += 1
                series_count += len(scans)

                if loaded:
                    study_load_count += 1

                series_load_count += loaded_series

            except Exception as e:
                self.logger.warning(str(e))
                studies_report.append({'study': study_uid, 'error': str(e)})

        return {
            'worklist_report': {
                'loaded': series_load_count,
                'already-exist': series_count - series_load_count,
                'errors': worklist_report
            },
            'studies_report': {
                'loaded': study_load_count,
                'already-exist': study_count - study_load_count,
                'errors': studies_report
            }
        }
Ejemplo n.º 6
0
from dicomaizer.common.uid import string2hash

worklist_file = '/Users/annabankirer/Downloads/sheba_abdomen'
command = ' scp -i ~/.ssh/aidoc [email protected]:/datadrive/viewer-data/scans/{}.mat .'
with open(worklist_file) as f:
    for line in f:
        line = line.strip()
        if len(line) == 0:
            continue

        print(command.format(string2hash(line)))