def setData(self, index, value, role): # return if no edit if not index.isValid(): return False if role != QtCore.Qt.EditRole: return False # prepare information row = index.row() col = index.column() col_name = self._headers[col] table_name = self._table db = self._db # copy previous in case of error element = self._data[row] previous = copy.deepcopy(element) # determine if view or table # if it is a view, must get the real col and table real_col_name = col_name real_table_name = table_name real_element = element if table_name not in db.tables: view = syd.find_one(db['FormatView'], view_name=table_name) columns_format = syd.parse_columns_view_format(db, view.format) format = columns_format[col_name] if len(format.tables) > 0: real_table_name = format.tables[-1] rid = real_table_name.lower() + '_id' else: real_table_name = view.table_name rid = 'id' real_col_name = format.id e = syd.find_one(db[view.table_name], id=element.id) real_element = syd.find_one(self._db[real_table_name], id=e[rid]) # special case for some type if isinstance(real_element[real_col_name], datetime): real_element[real_col_name] = syd.str_to_date(value) else: real_element[real_col_name] = value # update the db try: syd.update_one(db[real_table_name], real_element) # if this is a view, update view if real_table_name != table_name: self._data = syd.find_all(db[table_name]) # other views/tables may be updated self.table_should_reload.emit(table_name, real_table_name) except: # FIXME signal to warn user (status) print('Cannot update ERROR') self._data[index.row()] = previous return False
def nearest_acquisition(db, date, patient, **kwargs): tmp = syd.find_one(db['Acquisition'], date=date) if tmp: # if an acquisition already exist no need to find or return tmp else: t = kwargs.get('t', None) modality = kwargs.get('modality', None) content_type = kwargs.get('content_type', None) injection = syd.nearest_injection(db, date, patient) if t == 'Listmode': dicom = syd.find(db['DicomSeries'], injection_id=injection['id']) if dicom != []: for d in dicom: if d['modality'] == modality and d[ 'content_type'] == content_type: acquisition = syd.find_one(db['Acquisition'], id=d['acquisition_id']) return acquisition else: # when no dicom are in the database result = None try: acq = syd.find(db['Acquisition'], injection_id=injection['id']) except: tqdm.write('Cannot find acquisition') if acq != []: minnimum = np.abs(date - acq[0]['date']) for tmp in acq: m = np.abs(date - tmp['date']) if m <= timedelta(1.0 / 24.0 / 60.0 * 1.0): # timedelta usefull for multiple listmode for example tomo + wholebody if m <= minnimum: minnimum = m result = tmp return result elif t == 'Dicom': result = None # try: acq = syd.find(db['Acquisition'], injection_id=injection['id']) # except: # tqdm.write('Cannot find acquisition') if acq: minnimum = np.abs(date - acq[0]['date']) for tmp in acq: m = np.abs(date - tmp['date']) if m <= timedelta(1.0 / 24.0 / 60.0 * 10.0): # timedelta usefull for multiple listmode for example tomo + wholebody if m < minnimum: minnimum = m result = tmp return result
def update_nested_one(db, element): ''' Consider an input element having nested element. Update them. For example, if patient is {id:'1', injection:{id:12, ...}, injection_id:12, ...} the nested injection will be updated ''' m = {} for k in element: if not k[-3:] == '_id': continue field = k[:-3] table = syd.guess_table_name(db, field) if table == None: # may append for xample with dicom_id continue eid = element[k] nested_elem = syd.find_one(db[table], id=eid) if nested_elem == None: continue m[field] = nested_elem for f in m: update_nested_one(db, m[f]) element[f] = m[f]
def get_image_filename(db, image): ''' Retrieve the filename associated with the image ''' file_mhd = syd.find_one(db['File'], id=image['file_mhd_id']) filepath = get_file_absolute_filename(db, file_mhd) return filepath
def find_patient(db, patient_name): patient = syd.find_one(db['Patient'], name=patient_name) if patient == None: s = f'Cannot find patient with name {patient_name}' syd.raise_except(s) return patient
def build_image_folder(db, image): ''' Create the file folder of an Image ''' pname = syd.find_one(db['Patient'], id=image['patient_id'])['name'] # date = image['acquisition_date'].strftime('%Y-%m-%d') # modality = image['modality'] # folder = build_folder(db, pname, date, modality) folder = pname return folder
def get_ct_path(self, db, d): path = None e = syd.syd_find_ct(db, d['id']) if len(e) < 1: return path else: im = None dicom_id = e[0][0] image_id = e[0][1] ct = syd.find_one(db['DicomSeries'], id=dicom_id) path = self.get_file_path(db, ct) if image_id != 0: im = syd.find_one(db['Image'], id=image_id) file_mhd_id = im['file_mhd_id'] file = syd.find_one(db['File'], id=file_mhd_id) path = db.absolute_data_folder + '/' + file[ 'folder'] + '/' + file['filename'] return path return path
def guess_fov(db, acquisition): same_study = [] same_modality = [] same_date = [] frame_of_reference_study = [] same_for_dicom = [] study = syd.find(db['DicomSeries'], acquisition_id=acquisition['id']) for s in study: # Accessing the frame of reference uid directly from the file for all dicom in the acquisition frame_of_reference_study.append(s['frame_of_reference_uid']) acq = syd.find(db['Acquisition'], injection_id=acquisition['injection_id']) acq = [i for i in acq if (acquisition['id'] != i['id']) ] # Removing the acquisition given in the parameter for a in acq: dicom_series = syd.find_one(db['DicomSeries'], acquisition_id=a['id']) if dicom_series is not None: try: if dicom_series['dicom_study_id'] == study[0][ 'dicom_study_id']: same_study.append(a) except: continue for a in same_study: if acquisition['modality'] == a['modality']: same_modality.append(a) for a in same_modality: if np.abs(acquisition['date'] - a['date']) < timedelta(1.0 / 24.0): same_date.append(a) for a in same_date: dicom_series = syd.find(db['DicomSeries'], acquisition_id=a['id']) for d in dicom_series: if d['frame_of_reference_uid'] in frame_of_reference_study: # taking the FOR from the dico same_for = a same_for_dicom.append(d) break # stoping at the first dicom found for d in same_for_dicom: str = d['series_description'] if str.find('FOV1') != -1 or str.find('FOV 1') != -1: acquisition['fov'] = 2 syd.update_one(db['Acquisition'], acquisition) tqdm.write(f'Update of acquisition :{acquisition}') return {} elif str.find('FOV2') != -1 or str.find('FOV 2') != -1: acquisition['fov'] = 1 syd.update_one(db['Acquisition'], acquisition) tqdm.write(f'Update of acquisition :{acquisition}') return {} elif str.find('MFOV') != -1: print('') else: s = f'Cannot update acquisition {acquisition}' syd.raise_except(s)
def insert_roi_from_file(db, filename, dicom_series): ''' Insert a ROI from a filename ''' struct = Box() # if Path(filename).suffix != 'mha' or Path(filename).suffix != 'mhd': # tqdm.write('Ignoring {}: not an Image'.format(Path(filename).name)) # return {} # else: injection_id = dicom_series['injection_id'] acquisition_id = dicom_series['acquisition_id'] acquisition = syd.find_one(db['Acquisition'], id=acquisition_id) injection = syd.find_one(db['Injection'], id=acquisition['injection_id']) patient = syd.find_one(db['Patient'], id=injection['patient_id']) im = { 'patient_id': patient['id'], 'injection_id': injection_id, 'acquisition_id': acquisition_id, 'frame_of_reference_uid': dicom_series['frame_of_reference_uid'], 'modality': 'RTSTRUCT', 'labels': None } e = syd.insert_write_new_image(db, im, itk.imread(filename)) try: struct = syd.find_one(db['DicomStruct'], dicom_series_id=dicom_series['id']) except: tqdm.write(f'Cannot find DicomStruct matching {filename}') roi = { 'dicom_struct_id': struct['id'], 'image_id': e['id'], 'name': struct['names'], 'frame_of_reference_uid': dicom_series['frame_of_reference_uid'], 'labels': None } e = syd.insert_one(db['Roi'], roi) return e
def update_roi_characteristics(db, r, background=0): ''' Update roi volume, density and mass ''' im_roi = syd.find_one(db['Image'], roi_id=r['id']) dicom_struct = syd.find_one(db['DicomStruct'], id=r['dicom_struct_id']) if dicom_struct is not None: im_ct = syd.find_one(db['Image'], dicom_series_id=dicom_struct['dicom_series_id']) else: im_ct = syd.find_one( db['Image'], frame_of_reference_uid=r['frame_of_reference_uid'], modality='CT') file_img = syd.find_one(db['File'], id=im_roi['file_mhd_id']) if im_ct is not None: file_img_ct = syd.find_one(db['File'], id=im_ct['file_mhd_id']) else: print(f'Could not find the CT file image for the roi {r.id}') return 0 filename_im = os.path.join( db.absolute_data_folder, os.path.join(file_img['folder'], file_img['filename'])) filename_ct = os.path.join( db.absolute_data_folder, os.path.join(file_img_ct['folder'], file_img_ct['filename'])) roi = itk.imread(filename_im) ct = itk.imread(filename_ct) array_im = itk.array_from_image(roi) spacing = roi.GetSpacing() ### Volume ### e = np.count_nonzero(array_im != background) volume_elem = spacing[0] * spacing[1] * spacing[2] # spacing is in mm volume_elem = volume_elem * 0.001 # convert mm3 to cm3 (/1000) volume = e * volume_elem r['volume'] = volume syd.update_one(db['Roi'], r) ### Density ### mask = gt.applyTransformation(input=roi, like=ct, force_resample=True, interpolation_mode='NN') stats = gt.imageStatistics(input=ct, mask=mask) HU_mean = stats['mean'] density = 1 + (HU_mean / 1000) r['density'] = density syd.update_one(db['Roi'], r) ### Mass ### mass = np.multiply(volume, density) r['mass'] = mass syd.update_one(db['Roi'], r) return 1
def slot_on_view(self): data = [] path = [] rows = set(index.row() for index in self.table_view.selectedIndexes()) for row in rows: data.append(self._data[row]) self.w = SydCTWindow(data, self._filename, self._table_name) self.w.button_ct_on.setEnabled(False) db = syd.open_db(self._filename) for d in data: e = self.w.get_ct_path(db, d) if e is not None and len(rows) == 1 and d['modality'] != 'CT': self.w.button_ct_on.setEnabled(True) self.w.show() else: if self._table_name == 'DicomSeries' or self._table_name == 'DicomSeries_default': db = syd.open_db(self._filename) dicom_file = syd.find_one(db['DicomFile'], dicom_series_id=d['id']) file = syd.find_one(db['File'], id=dicom_file['file_id']) tmp = db.absolute_data_folder + '/' + file[ 'folder'] + '/' + file['filename'] path.append(tmp) elif self._table_name == 'Image' or self._table_name == 'Image_default': db = syd.open_db(self._filename) file = syd.find_one(db['File'], id=d['file_mhd_id']) path.append(db.absolute_data_folder + '/' + file['folder'] + '/' + file['filename']) else: print('La table séléctionnée ne correspond pas') if path != []: path = ' '.join(path) cmd = f'vv {path}' os.system(cmd) else: print('Path to image has no corresponding file')
def search_injection_from_info(db, dicom_study, rad_info): patient_id = dicom_study.patient_id all_rad = syd.find(db['Radionuclide']) rad_names = [n.name for n in all_rad] if len(rad_info.code) != 1: tqdm.write('Error: several radionuclide found. Dont know what to do') return None # look for radionuclide name and date rad_code = rad_info.code[0] rad_date = datetime.strptime(rad_info.date[0], '%Y%m%d%H%M%S') s = [str_match(rad_code, n) for n in rad_names] s = np.array(s) i = np.argmax(s) rad_name = rad_names[i] # search if injections exist for this patient and this rad radionuclide = syd.find_one(db['Radionuclide'], name=rad_name) rad_info.radionuclide_id = radionuclide.id inj_candidates = syd.find(db['Injection'], radionuclide_id=radionuclide.id, patient_id=patient_id) if len(inj_candidates) == 0: return None # check date and activity max_time_days = timedelta( 1.0) # 1 day # FIXME <------------------------ options found = None for ic in inj_candidates: d = ic.date if d > rad_date: t = d - rad_date else: t = rad_date - d if t <= max_time_days: act_diff = np.fabs(ic.activity_in_mbq - rad_info.total_dose) found = ic tqdm.write('Timedelta superior to 10 minutes') if found: tqdm.write(f'Injection found : {found}') return found else: return None
def guess_or_create_patient(db, ds): # try to retrieve patient from PatientID tag patient_dicom_id = ds.data_element("PatientID").value patient = syd.find_one(db['Patient'], dicom_id=patient_dicom_id) # create if not exist if patient is None: patient = Box() patient.dicom_id = patient_dicom_id try: patient.name = str(ds.data_element("PatientName").value) patient.sex = ds.data_element("PatientSex").value except: pass patient.num = 0 # FIXME --> to complete patient = syd.insert_one(db['Patient'], patient) tqdm.write('Insert new Patient {}'.format(patient)) return patient
def data(self, index, role): element = self._data[index.row()] c = index.column() h = self._col_names[c] v = element[h] if role == Qt.DisplayRole: if v is None: return '' # what if date ? if type(v) is int or type(v) is float: return v return str(v) if role == Qt.EditRole: table = self._db[self._table] # update first in case something changed element = syd.find_one(table, id=element['id']) v = element[h] if v is None: return '' # what if date -> FIXME later with delegate if type(v) is int: return v return str(v)
def slot_ct_off(self): if len(self._data) < 1: print("Aucun élément sélectionné") else: path = [] for d in self._data: if self.table_name == 'DicomSeries' or self.table_name == 'DicomSeries_default': db = syd.open_db(self._filename) path.append(self.get_file_path(db, d)) elif self.table_name == 'Image' or self.table_name == 'Image_default': db = syd.open_db(self._filename) file = syd.find_one(db['File'], id=d['file_mhd_id']) path.append(db.absolute_data_folder + '/' + file['folder'] + '/' + file['filename']) else: print('La table séléctionnée ne correspond pas') if path != []: path = ' '.join(path) cmd = f'vv {path}' os.system(cmd) else: print('Path to image has no corresponding file') self.hide()
def insert_file(db, ds, filename, struct): ''' Insert or update a dicom from a file ''' dicom_file = Box() dicom_file.sop_uid = ds.data_element('SOPInstanceUID').value dicom_file.dicom_series_id = struct['dicom_series_id'] dicom_file.dicom_struct_id = struct['id'] dicom_series = syd.find_one(db['DicomSeries'], id=struct['dicom_series_id']) try: dicom_file.instance_number = int(ds.InstanceNumber) except: dicom_file.instance_number = None # insert file in folder base_filename = os.path.basename(filename) afile = Box() afile.folder = dicom_series.folder afile.filename = base_filename afile = syd.insert_one(db['File'], afile) # copy the file src = filename dst_folder = os.path.join(db.absolute_data_folder, dicom_series.folder) dst = os.path.join(dst_folder, base_filename) if not os.path.exists(dst_folder): os.makedirs(dst_folder) # if not do_it_later: copyfile(src, dst) dicom_file.file_id = afile.id dicom_file = syd.insert_one(db['DicomFile'], dicom_file) return dicom_file
def guess_stitch(db, acquisition): if acquisition['fov'] == '1': tmp = syd.find(db['Acquisition'], fov='2') elif acquisition['fov'] == '2': tmp = syd.find(db['Acquisition'], fov='1') else: tqdm.write(f'Cannot determnied the fov of {acquisition}') return {} injection = syd.find_one(db['Injection'], id=acquisition['injection_id']) patient = syd.find_one(db['Patient'], id=injection['patient_id']) dicom1 = syd.find(db['DicomSeries'], acquisition_id=acquisition['id']) res = [] epsilon = 0.1 delta = timedelta(1.0 / 24.0 * 2.0) for t in tmp: diff = np.abs(t['date'] - acquisition['date']) if diff < delta: dicom2 = syd.find(db['DicomSeries'], acquisition_id=t['id']) max = 0.0 for d1 in dicom1: for d2 in dicom2: ratio = difflib.SequenceMatcher( None, d1['series_description'], d2['series_description']).ratio() if max - ratio < epsilon: max = ratio r = [d1, d2] res.append(r) for r in res: image1 = syd.find_one(db['Image'], dicom_series_id=r[0]['id']) file1 = syd.find_one(db['File'], id=image1['file_mhd_id']) image2 = syd.find_one(db['Image'], dicom_series_id=r[1]['id']) file2 = syd.find_one(db['File'], id=image2['file_mhd_id']) path1 = os.path.join(db.absolute_data_folder, os.path.join(file1['folder'], file1['filename'])) path2 = os.path.join(db.absolute_data_folder, os.path.join(file2['folder'], file2['filename'])) im1 = itk.imread(path1) im2 = itk.imread(path2) result = sti.stitch_image(im1, im2, 2, 0) itk.imwrite(result, './tmp.mhd') if acquisition['fov'] == '1': im = { 'patient_id': patient['id'], 'injection_id': injection['id'], 'acquisition_id': acquisition['id'], 'pixel_type': 'float', 'pixel_unit': 'counts', 'modality': acquisition['modality'], 'frame_of_reference_uid': r[0]['frame_of_reference_uid'], 'acquisition_date': acquisition['date'] } else: im = { 'patient_id': patient['id'], 'injection_id': injection['id'], 'acquisition_id': tmp['id'], 'pixel_type': 'float', 'pixel_unit': 'counts', 'modality': tmp['modality'], 'frame_of_reference_uid': r[0]['frame_of_reference_uid'], 'acquisition_date': tmp['date'] } e = syd.insert_write_new_image(db, im, itk.imread('./tmp.mhd')) os.remove('./tmp.mhd') os.remove('./tmp.raw') return res
def get_roi_file_absolute_filename(db, e): image = syd.find_one(db['Image'], id=e['image_id']) filepath = syd.get_image_filename(db, image) return filepath
def insert_listmode_from_file(db, filename, patient): patient_folder = os.path.join(db.absolute_data_folder, patient['name']) e = check_type(filename) ftype, end = e.split('.') if ftype != 'Listmode': tqdm.write('Ignoring {}: it is not a Listmode'.format(filename)) return None if end == 'dat': date = return_date(filename.name) elif end == 'I': ds = pydicom.read_file(str(filename)) try: acquisition_date = ds.AcquisitionDate acquisition_time = ds.AcquisitionTime date = syd.dcm_str_to_date(acquisition_date + acquisition_time) except: date = return_date_str(ds[0x0008, 0x002a].value) else: tqdm.write('Date not found on DICOM') return None try: modality, content_type = syd.guess_content_type(filename) except: s = f'Cannot guess content_type' syd.raise_except(s) # Check if the listmode is already in the file with date and name listmode = syd.find(db['Listmode'], date=date, modality=modality) if listmode is not None: for l in listmode: file = syd.find_one(db['File'], id=l['file_id']) if file['filename'].endswith(filename.name): tqdm.write('Ignoring {} : Listmode already in the db'.format( filename)) return None # Check if the acquisition exists or not res = syd.nearest_acquisition(db, date, patient, t="Listmode", modality=modality, content_type=content_type) if res is not None: # When an acquisition is found a1 = res try: syd.guess_fov(db, a1) except: tqdm.write(f'Cannot guess fov for acquisition : {a1}') else: # Creation of the acquisition if it does not exist d1 = syd.nearest_injection(db, date, patient) a0 = {'injection_id': d1['id'], 'modality': modality, 'date': date} syd.insert_one(db['Acquisition'], a0) a1 = syd.find_one(db['Acquisition'], date=a0['date']) try: syd.guess_fov(db, a1) except: tqdm.write(f'Cannot guess fov for acquisition : {a1}') # Listmode creation then insertion l0 = { 'acquisition_id': a1['id'], 'date': date, 'modality': modality, 'content_type': content_type } syd.insert_one(db['Listmode'], l0) l1 = syd.find(db['Listmode'], acquisition_id=a1['id']) acqui_folder = os.path.join(patient_folder, 'acqui_' + str(a1['id'])) base_filename = 'LM_' + str(l1[len(l1) - 1]['id']) + '_' + str( filename.name) if not os.path.exists(acqui_folder): os.makedirs(acqui_folder) # File creation for the file table afile = Box() afile.folder = os.path.join(patient['name'], 'acqui_' + str(a1['id'])) afile.filename = base_filename syd.insert_one(db['File'], afile) # Update of listmode to account for the file_id f0 = syd.find_one(db['File'], filename=afile.filename) l2 = { 'id': l1[len(l1) - 1]['id'], 'acquisition_id': a1['id'], 'file_id': f0['id'] } syd.update_one(db['Listmode'], l2) # Moving the file copy(filename, acqui_folder) old_filename = os.path.join(acqui_folder, filename.name) new_filename = os.path.join(acqui_folder, base_filename) move(old_filename, new_filename) # return create listmode return l2
def insert_view(db, name, table, view_format): """ Create a SQL view and a description in the table FormatView (used for printing) """ # get the list of columns table = syd.guess_table_name(db, table) columns_format = syd.parse_columns_view_format(db, view_format) # check column id # needed because sqlite do not consider up/low case while Box yes for col in columns_format: c = columns_format[col] if len(c.tables) == 0: t = table else: t = c.tables[-1] if c.id not in db[t].columns: # special case: add column labels if does not exist if c.id == 'labels': print("(Add a 'labels' column)") db[t].create_column('labels', db.types.text) if c.id not in db[t].columns: s = f"Error, cannot find the column '{c.id}' in the table {t}\n" s += f'Columns are {db[t].columns}' syd.raise_except(s) # TODO check if view already exist ? name = table + '_' + name s = f'DROP VIEW IF EXISTS {name} ;' db.query(s) # create sql query to create the view s = syd.create_view_query_from_format(name, table, columns_format) # create the view db.query(s) # test the view ts = f"SELECT * from {name}" txt = '' try: db.query(ts) n = db[name].count() txt = f'View {name} has been created with {n} elements' except exc.OperationalError as e: a = f'Error : view error with {ts}\n' a += f'The initial query was \n{s}\n' a += str(e) syd.raise_except(a) # create/update element in the table FormatView view = syd.find_one(db['FormatView'], view_name=name) updated = True if not view: updated = False view = Box() view.view_name = name view.table_name = table view.format = view_format if updated: syd.update_one(db['FormatView'], view) else: syd.insert_one(db['FormatView'], view) return txt
def get_file_path(self, db, d): dicom_file = syd.find_one(db['DicomFile'], dicom_series_id=d['id']) file = syd.find_one(db['File'], id=dicom_file['file_id']) return db.absolute_data_folder + '/' + file['folder'] + '/' + file[ 'filename']
def insert_image_from_dicom(db, dicom_series, dicom_path): ''' Convert one Dicom image to MHD image ''' # modality modality = dicom_series['modality'] #Try guessing pixel unit from dicom try: ds = pydicom.read_file(dicom_path) unit = ds[0x0054, 0x1001].value if unit == "BQML": pixel_unit = 'Bq/mL' else: pixel_unit = unit except: # guess pixel unit FIXME --> check dicom tag ? pixel_unit = 'undefined' if modality == 'CT': pixel_unit = 'HU' if modality == 'NM': pixel_unit = 'counts' if modality == 'RTDOSE': pixel_unit = 'Gy' # get dicom files files = syd.get_dicom_series_files(db, dicom_series) if len(files) == 0: s = 'Error, no file associated with this dicom serie' syd.raise_except(s) # get folder folder = dicom_series['folder'] folder = os.path.join(db.absolute_data_folder, folder) acquisition_id = int( os.path.basename(os.path.dirname(folder)).split('_')[1]) suid = dicom_series['series_uid'] PixelType = itk.ctype('float') Dimension = 3 namesGenerator = itk.GDCMSeriesFileNames.New() namesGenerator.SetUseSeriesDetails(False) namesGenerator.AddSeriesRestriction("0008|0021") namesGenerator.SetGlobalWarningDisplay(False) namesGenerator.SetDirectory(folder) seriesUID = namesGenerator.GetSeriesUIDs() fileNames = namesGenerator.GetFileNames(seriesUID[0]) # read dicom image if len(fileNames) > 1: itk_image = gt.read_dicom(fileNames) else: itk_image = gt.read_3d_dicom(fileNames) # pixel_type (ignored) # pixel_type = image.GetPixelIDTypeAsString() # GetNumberOfComponentsPerPixel # convert: assume only 2 type short for CT and float for everything else pixel_type = 'float' if modality == 'CT': pixel_type = 'signed_short' InputImageType = itk.Image[itk.F, Dimension] OutputImageType = itk.Image[itk.SS, Dimension] castImageFilter = itk.CastImageFilter[InputImageType, OutputImageType].New() castImageFilter.SetInput(itk_image) castImageFilter.Update() itk_image = castImageFilter.GetOutput() # else: # pixel_type = 'float' # try: # itk_image = sitk.Cast(itk_image, sitk.sitkFloat32) # except: # s = 'Cannot cast image. Ignoring '+str(dicom_series) # warning(s) # return None # injection ? injid = None if 'injection_id' in dicom_series: injid = dicom_series.injection_id # create Image #syd.update_nested_one(db, dicom_series) labels = '' if 'labels' in dicom_series: labels = dicom_series.labels dicom_study = syd.find_one(db['DicomStudy'], id=dicom_series.dicom_study_id) patient = syd.find_one(db['Patient'], id=dicom_study.patient_id) img = { 'patient_id': patient.id, 'injection_id': injid, 'dicom_series_id': dicom_series.id, 'acquisition_id': acquisition_id, 'pixel_type': pixel_type, 'pixel_unit': pixel_unit, 'frame_of_reference_uid': dicom_series.frame_of_reference_uid, 'modality': modality, 'acquisition_date': dicom_series.acquisition_date, 'labels': labels } # insert the image in the db img = syd.insert_new_image(db, img, itk_image) # write the mhd file p = syd.get_image_filename(db, img) itk.imwrite(itk_image, p) return img
def insert_roi_from_struct(db, struct, crop): """ Insert an ROI from a DicomStruct file """ roi = Box() res = [] series_id = struct['dicom_series_id'] dicom_series = syd.find_one(db['DicomSeries'], id=series_id) acquisition = syd.find_one(db['Acquisition'], id=dicom_series['acquisition_id']) injection_id = acquisition['injection_id'] acquisition_id = dicom_series['acquisition_id'] injection = syd.find_one(db['Injection'], id=injection_id) patient = syd.find_one(db['Patient'], id=injection['patient_id']) ### Getting the CT image path ### image_ct = syd.find_one(db['Image'], dicom_series_id=series_id) try: file_img = syd.find_one(db['File'], id=image_ct['file_mhd_id']) except: print('Could not find the CT image in the database') filename_img_ct = db.absolute_data_folder + '/' + file_img[ 'folder'] + '/' + file_img['filename'] ### Getting the DicomStruct dicom path ### dicom_file = syd.find_one(db['DicomFile'], dicom_struct_id=struct['id']) file_struct = syd.find_one(db['File'], id=dicom_file['file_id']) filename_struct = db.absolute_data_folder + '/' + file_struct[ 'folder'] + '/' + file_struct['filename'] ### Verifying if the ROI already exists in the table ### e = syd.find(db['Roi'], dicom_struct_id=struct['id']) if e != []: return {} ### Using GateTools to extract the image from the Dicom File ### structset = pydicom.read_file(filename_struct) img_ct = itk.imread(filename_img_ct, itk.F) base_filename, extension = os.path.splitext(filename_img_ct) roi_names = gt.list_roinames(structset) roi_objs = list() npbar = 0 pbar = None for r in roi_names: try: aroi = gt.region_of_interest(structset, r) if not aroi.have_mask(): tqdm.write(f'Mask for {r} not possible') roi_objs.append(aroi) except: tqdm.write(f'Something is wrong with ROI {r}') roi.remove(r) if npbar > 0: pbar = tqdm(total=npbar, leave=False) for roiname, aroi in zip(roi_names, roi_objs): try: mask = aroi.get_mask(img_ct, corrected=False, pbar=pbar) if crop: mask = gt.image_auto_crop(mask, bg=0) output_filename = base_filename + '_' + ''.join( e for e in roiname if e.isalnum()) + '.mhd' im = { 'patient_id': patient['id'], 'injection_id': injection_id, 'acquisition_id': acquisition_id, 'pixel_unit': 'binary', 'pixel_type': 'float', 'frame_of_reference_uid': dicom_series['frame_of_reference_uid'], 'modality': 'RTSTRUCT', 'labels': roiname } im = syd.insert_write_new_image(db, im, mask) roi = { 'dicom_struct_id': struct['id'], 'image_id': im['id'], 'frame_of_reference_uid': struct['frame_of_reference_uid'], 'name': roiname, 'labels': None } roi = syd.insert_one(db['Roi'], roi) im['roi_id'] = roi['id'] res.append(roi) syd.update_one(db['Image'], im) syd.update_roi_characteristics(db, roi) except: tqdm.write(f'Error in {roiname, aroi}') if npbar > 0: pbar.close() return res
def insert_struct_from_file(db, filename): """ Insert a DicomStruct from a filename """ struct = Box() try: ds = pydicom.read_file(filename) except: tqdm.write('Ignoring {}: not a Structure'.format(Path(filename).name)) return {} if ds.Modality != 'RTSTRUCT': return {} try: sop_uid = ds.data_element("SOPInstanceUID").value except: tqdm.write('Ignoring {}: cannot read UIDs'.format(filename)) return {} # check if the file already exist in the db dicom_file = syd.find_one(db['DicomFile'], sop_uid=sop_uid) if dicom_file is not None: tqdm.write('Ignoring {}: Dicom SOP Instance already in the db'.format( Path(filename))) return {} try: frame_of_ref = ds.ReferencedFrameOfReferenceSequence[0] study = frame_of_ref.RTReferencedStudySequence[0] series_uid = study.RTReferencedSeriesSequence[0].SeriesInstanceUID except: tqdm.write('Ignoring {}: Cannot read SeriesInstanceUID'.format( Path(filename).name)) return {} try: creation_date = ds.StudyDate creation_time = ds.StudyDate except: try: creation_date = ds.StructureSetDate creation_time = ds.StructureSetTime except: print(f'Could not find date for the file : {filename}') creation_date = dcm_str_to_date(creation_date + ' ' + creation_time) try: dicom_serie = syd.find_one(db['DicomSeries'], series_uid=series_uid) except: tqdm.write('Ignoring {} : Cannot read DicomSeries'.format( Path(filename).name)) if dicom_serie is not None: struct_names = [ str(ssroi.ROIName) for ssroi in ds.StructureSetROISequence ] separator = ';' struct_names = separator.join(struct_names) struct = { 'dicom_series_id': dicom_serie['id'], 'names': struct_names, 'series_uid': series_uid, 'frame_of_reference_uid': dicom_serie['frame_of_reference_uid'], 'creation_date': creation_date, 'sop_uid': sop_uid } struct = syd.insert_one(db['DicomStruct'], struct) dicom_file = insert_file(db, ds, filename, struct) return struct else: tqdm.write('Ignoring {} : Cannot find matching DicomSeries'.format( Path(filename).name)) return {}
def get_image_patient(db, image): ''' Retrieve the patient associated with the image ''' patient = syd.find_one(db['Patient'], id=image['patient_id']) return patient