Beispiel #1
0
def new_acquisition(db, dicom_series, date, injection):
    acquisition = Box()
    acquisition.injection_id = injection['id']
    acquisition.date = date
    acquisition.modality = dicom_series.modality

    syd.insert_one(db['Acquisition'], acquisition)
    tqdm.write(f'Insert new Acquisition {acquisition}')
    return acquisition
Beispiel #2
0
def new_injection(db, dicom_study, rad_info):
    injection = Box()
    injection.radionuclide_id = rad_info.radionuclide_id
    injection.patient_id = dicom_study.patient_id
    injection.activity_in_mbq = rad_info.total_dose / 1e6
    injection.date = datetime.strptime(rad_info.date[0], '%Y%m%d%H%M%S')

    syd.insert_one(db['Injection'], injection)
    tqdm.write(f'Insert new injection {injection}')
    return injection
Beispiel #3
0
def insert_new_image(db, img, itk_image):
    '''
    Create a new image in the database: DO NOT COPY itk_image in the db.
    Should be performed after:
               p = syd.get_image_filename(db, img)
               itk.imwrite(itk_image, p)
    img : dict
    itk_image : image itk
    '''

    # set the id to None to force a new image
    img['id'] = None

    # insert Image to get the id
    img = syd.insert_one(db['Image'], img)

    # create file mhd/raw
    folder = build_image_folder(db, img)
    if not os.path.exists(os.path.join(db.absolute_data_folder, folder)):
        os.makedirs(os.path.join(db.absolute_data_folder, folder))
    modality = img['modality']
    id = img['id']
    file_mhd = syd.new_file(db, folder, str(id) + '_' + modality + '.mhd')
    file_raw = syd.new_file(db, folder, str(id) + '_' + modality + '.raw')

    # FIXME check and set image_type

    # update files in img
    img['file_mhd_id'] = file_mhd['id']
    img['file_raw_id'] = file_raw['id']
    syd.update_one(db['Image'], img)

    return img
Beispiel #4
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
Beispiel #5
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
Beispiel #6
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
Beispiel #7
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
Beispiel #8
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 {}
Beispiel #9
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
Beispiel #10
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