コード例 #1
0
ファイル: syd_guess.py プロジェクト: OpenSyd/syd
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
コード例 #2
0
ファイル: syd_guess.py プロジェクト: OpenSyd/syd
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)
コード例 #3
0
def find_series(db, patient_id, grep):

    # select study from this patient
    studies = syd.find(db['DicomStudy'], patient_id=patient_id)
    study_ids = [s.id for s in studies]

    # series
    elements = syd.find(db['DicomSeries'], dicom_study_id=study_ids)

    # select series
    grep.append('%ignore')
    elements, s = syd.grep(db, 'DicomSeries', elements, grep=grep)

    return elements, s
コード例 #4
0
def tabular_add_abs_filename(db, table_name, elements):
    # only for image, dicomstudy, dicomseries, dicomfile
    # image  -> file_mhd_id file_raw_id => file
    # study  -> NO
    # series -> => dicomfile => file_id ; several so only first one or all ?

    if table_name == 'DicomSeries':
        ids = [e.id for e in elements]
        dicomfiles = syd.find(db['DicomFile'], dicom_series_id=ids)

        ids = [df.file_id for df in dicomfiles]
        files = syd.find(db['File'], id=ids)

        map_df = {df.dicom_series_id: df for df in dicomfiles}  # keep only one
        map_f = {f.id: f for f in files}  # keep only one

        for e in elements:
            try:
                df = map_df[e.id]
                f = map_f[df.id]
                e['abs_filename'] = syd.get_file_absolute_filename(db, f)
            except:
                e['abs_filename'] = 'file_does_not_exist'
                # print('warning, cannot find', e.id, df.id)

    if table_name == 'DicomFile':
        ids = [e.file_id for e in elements]
        files = syd.find(db['File'], id=ids)
        map_f = {f.id: f for f in files}
        for e in elements:
            try:
                f = map_f[e.file_id]
                e['abs_filename'] = syd.get_file_absolute_filename(db, f)
            except:
                e['abs_filename'] = 'file_does_not_exist'
                # print('warning, cannot find', e.id, df.id)

    if table_name == 'Image':
        ids = [e.file_mhd_id for e in elements]
        files = syd.find(db['File'], id=ids)
        map_f = {f.id: f for f in files}

        for e in elements:
            try:
                f = map_f[e.file_mhd_id]
                e['abs_filename'] = syd.get_file_absolute_filename(db, f)
            except:
                e['abs_filename'] = 'file_does_not_exist'
コード例 #5
0
def tabular_add_nb_dicom_files(db, table_name, elements):
    if table_name != 'DicomSeries':
        return

    for e in elements:
        dicomfiles = syd.find(db['DicomFile'], dicom_series_id=e.id)
        e['nb_dicom_files'] = len(dicomfiles)
コード例 #6
0
def tabular_get_line_format(db, table_name, format_name, element):
    '''
    Retrieve the line format from the format name to build a tabluar
    '''

    table_name = syd.guess_table_name(db, table_name)
    formats = syd.find(db['PrintFormat'], table_name=table_name)

    df = None
    ff = None
    for f in formats:
        if f.name == format_name:
            df = f.format
            ff = f

    if df == None and format_name != 'raw':
        s = "Cannot find the format '" + format_name + "' in table '" + table_name + "' using 'raw'"
        syd.warning(s)
        format_name = 'raw'

    if format_name == 'raw':
        df = ''
        for k in element:
            df += '{' + str(k) + '} '

    sorting_key = ''
    if ff:
        if 'sorting_key' in ff:
            sorting_key = ff.sorting_key

    return df, sorting_key
コード例 #7
0
ファイル: syd_guess.py プロジェクト: OpenSyd/syd
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
コード例 #8
0
ファイル: syd_acquisition.py プロジェクト: OpenSyd/syd
def find_acquisition(db, injection):
    acquisition = syd.find(db['Acquisition'], injection_id=injection['id'])
    acquisition = syd.sort_elements(acquisition, 'date')
    struct = []
    elements = []
    for tmp in acquisition:
        listmode = syd.find(db['Listmode'], acquisition_id=tmp['id'])
        dicom_series = syd.find(db['DicomSeries'], acquisition_id=tmp['id'])
        for d in dicom_series:
            dicom_struct = syd.find(db['DicomStruct'], dicom_series_id=d['id'])
            struct = struct + dicom_struct
        el = {
            'acquisition': tmp,
            'listmode': listmode,
            'dicom_serie': dicom_series,
            'dicom_struct': struct
        }
        elements.append(el)
    return elements
コード例 #9
0
def get_dicom_struct_files(db, struct):
    """
    Return the list of files associated with the struct
    """
    dicom_files = syd.find(db['DicomFile'], dicom_struct_id=struct['id'])

    # sort by instance_number
    dicom_files = sorted(
        dicom_files,
        key=lambda kv: (kv['instance_number'] is None, kv['instance_number']))

    # get all associated id of the files
    fids = [df['file_id'] for df in dicom_files]

    # find files
    res = syd.find(db['File'], id=fids)

    # FIXME sort res like fids (?)

    return res
コード例 #10
0
ファイル: syd_guess.py プロジェクト: OpenSyd/syd
def nearest_injection(db, date, patient):
    var = syd.find(db['Injection'], patient_id=patient['id'])
    min = np.abs(date - var[0]['date'])
    for tmp in var:
        if not tmp['date']:
            continue
        m = np.abs(date - tmp['date'])
        # if date < tmp['date']:
        #     tqdm.write(f'Injection {tmp["date"]} is after the wanted date {date}')

        if m <= min:
            min = m
            result = tmp
    return result
コード例 #11
0
def tabular_add_time_from_inj(db, table_name, elements):
    if table_name != 'DicomSeries' and table_name != 'Image':
        return

    ids = [e.injection_id for e in elements]
    injections = syd.find(db['Injection'], id=ids)
    map_inj = {inj.id: inj for inj in injections}  # keep only one
    for e in elements:
        if not e.injection_id in map_inj:
            continue
        inj = map_inj[e.injection_id]
        date1 = inj.date
        date2 = e.acquisition_date
        # print(date1, date2)
        e.time_from_inj = date2 - date1
コード例 #12
0
def get_sub_elements(db, elements, format_info, subelements):
    # format_info.field_format_name,      # study->patient->name
    # format_info.tables,                 # DicomStudy Patient
    # format_info.field_id_names,         # study_id patient_id
    # format_info.field_name)             # name

    # get al subelements
    current_table = format_info.tables[0]
    current_field_id_name = format_info.field_id_names[0]
    ids = [elem[current_field_id_name] for elem in subelements]  ## repetition, unique ? FIXME
    new_subelements = syd.find(current_table, id=ids)

    if len(format_info.tables) == 1:
        # correspondance current_id -> new_id
        subelements_map = {}
        for s in new_subelements:
            try:
                subelements_map[s.id] = s[format_info.field_name]
            except:
                subelements_map[s.id] = '?'
        for elem in elements:
            index = elem[format_info.field_format_name]
            if index:  # because can be None
                elem[format_info.field_format_name] = subelements_map[index]
            else:
                elem[format_info.field_format_name] = '?'
        return elements

    # correspondance current_id -> new_id
    subelements_map = {}
    for s in new_subelements:
        subelements_map[s.id] = s[format_info.field_id_names[1]]

    # change the id
    for elem in elements:
        index = elem[format_info.field_format_name]
        if index:
            elem[format_info.field_format_name] = subelements_map[index]

    # recurse removing the first
    format_info.tables = format_info.tables[1:]
    format_info.field_id_names = format_info.field_id_names[1:]
    return get_sub_elements(db, elements, format_info, new_subelements)
コード例 #13
0
ファイル: syd_guess.py プロジェクト: OpenSyd/syd
def search_injection(db, ds, dicom_study, dicom_series):
    patient_id = dicom_study.patient_id
    inj_candidates = syd.find(db['Injection'], patient_id=patient_id)
    dicom_date = dicom_series.acquisition_date

    # check date is before the dicom
    found = None
    for ic in inj_candidates:
        if not ic.date:
            continue
        if ic.date < dicom_date:
            if found:
                if ic.date > found.date:
                    found = ic
                    # tqdm.write('Several injections may be associated. Ignoring injection')
            else:
                found = ic

    if found:
        tqdm.write(f'Injection found : {found}')
        return found
    else:
        return None
コード例 #14
0
ファイル: syd_listmode.py プロジェクト: OpenSyd/syd
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
コード例 #15
0
def find_images(db, patient_id, grep):

    elements = syd.find(db['Image'], patient_id=patient_id)
    elements, s = syd.grep(db, 'Image', elements, grep=grep)

    return elements, s
コード例 #16
0
ファイル: syd_guess.py プロジェクト: OpenSyd/syd
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
コード例 #17
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