Example #1
0
    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
Example #2
0
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
Example #3
0
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]
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
    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
Example #8
0
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)
Example #9
0
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
Example #10
0
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
Example #11
0
 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')
Example #12
0
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
Example #13
0
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
Example #14
0
 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)
Example #15
0
 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()
Example #16
0
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
Example #17
0
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
Example #18
0
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
Example #19
0
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
Example #20
0
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
Example #21
0
 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']
Example #22
0
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
Example #23
0
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
Example #24
0
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 {}
Example #25
0
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