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()
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
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
def generate_patient_location(): if self.patient_name: return patientLocations[int(string2hash(self.patient_name)) % len(patientLocations)] else: return patientLocations[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 } }
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)))