Exemplo n.º 1
0
def mmrinit():
    # get the constants for the mMR
    Cnt = resources.get_mmr_constants()

    # transaxial look up tables
    txLUT = transaxial_lut(Cnt)
    Cnt['Naw'] = txLUT['Naw']

    # axial look up tables
    axLUT = axial_lut(Cnt)

    return Cnt, txLUT, axLUT
Exemplo n.º 2
0
def check_constants():
    '''get the constants for the mMR from the resources file before
    getting the path to the local resources.py (on Linux machines it is in ~/.niftypet)'''
    path_resources = path_niftypet_local()
    # import resource
    sys.path.append(path_resources)
    try:
        import resources
    except ImportError as ie:
        print '----------------------------'
        print 'e> Import Error: NiftyPET' 's resources file <resources.py> could not be imported.  It should be in ' '~/.niftypet/resources.py' ' but likely it does not exists.'
        print '----------------------------'
        raise ImportError('Could not find resources.py')
    #===========================
    Cnt = resources.get_mmr_constants()

    sct_compile = chck_sct_h(Cnt)
    def_compile = chck_vox_h(Cnt)
    print '----------------------------'
    print 'changed sct.h:', sct_compile
    print 'changed def.h:', def_compile
    print '----------------------------'
    if sct_compile or def_compile:
        print 'i> NiftyPET constants were changed: needs CUDA compilation.'
Exemplo n.º 3
0
def fwhm2sig(fwhm):
    Cnt = resources.get_mmr_constants()
    return (fwhm / Cnt['SZ_VOXY']) / (2 * (2 * np.log(2))**.5)
Exemplo n.º 4
0
def align_mumap(
        datain,
        scanner_params={},
        outpath='',
        use_stored=False,
        hst=[],
        t0=0, t1=0,
        itr=2,
        faff='',
        fpet='',
        fcomment='',
        store=False,
        store_npy=False,
        petopt='ac',
        musrc='ute', # another option is pct for mu-map source
        ute_name='UTE2',
        del_auxilary=True,
        verbose=True,
    ):
    '''
    Align the a pCT or MR-derived mu-map to a PET image reconstructed to chosen
    specifications (e.g., with/without attenuation and scatter corrections)

    use_sotred only works if hst or t0/t1 given but not when faff.
    '''


    #> output folder
    if outpath=='':
        opth = os.path.join( datain['corepath'], 'mumap-obj' )
    else:
        opth = os.path.join( outpath, 'mumap-obj' )

    #> create the folder, if not existent
    nimpa.create_dir(opth)

    #> get the timing of PET if affine not given
    if faff!='' and 't0' in hst:
        t0 = hst['t0']
        t1 = hst['t1']

    #> file name for the output mu-map
    fnm = 'mumap-' + musrc.upper()

    #> output dictionary
    mu_dct = {}

    #---------------------------------------------------------------------------
    #> used stored if requested
    if use_stored and affine!='':
        fmu_stored = fnm + '-aligned-to_t'\
                     + str(hst['t0'])+'-'+str(hst['t1'])+'_'+petopt.upper()\
                     + fcomment
        fmupath = os.path.join(opth, fmu_stored)
        if os.path.isfile( fmupath ):
            mudct_stored = nimpa.getnii(fmupath, output='all')
            #> create output dictionary
            mu_dct['im'] = mudct_stored['im']
            mu_dct['affine'] = mudct_stored['affine']
            #mu_dct['faff'] = faff
            return mu_dct
    #---------------------------------------------------------------------------

    #> three ways of passing scanner constants <Cnt> are here decoded
    if 'Cnt' in scanner_params:
        Cnt = scanner_params['Cnt']
    elif 'SO_IMZ' in scanner_params:
        Cnt = scanner_params
    else:
        Cnt = rs.get_mmr_constants()
    Cnt   = scanner_params['Cnt']

    #> if affine not provided histogram the LM data for recon and registration
    if not os.path.isfile(faff):
        from niftypet.nipet.prj import mmrrec
        #-histogram the list data if needed
        if not hst:
            from niftypet.nipet import mmrhist
            if 'txLUT' in scanner_params:
                hst = mmrhist(datain, scanner_params, t0=t0, t1=t1)
            else:
                raise ValueError(
                    'e> full scanner parameters not provided\
                     but required for histogramming.')

    #=========================================================
    #-get hardware mu-map
    if 'hmumap' in datain and os.path.isfile(datain['hmumap']):
        muh, _, _ = np.load(datain['hmumap'], allow_pickle=True)
        if verbose: print 'i> loaded hardware mu-map from file:', datain['hmumap']
    elif outpath!='':
        hmupath = os.path.join( os.path.join(outpath,'mumap-hdw'), 'hmumap.npy')
        if os.path.isfile( hmupath ):
            muh, _, _ = np.load(hmupath, allow_pickle=True)
            datain['hmumap'] = hmupath
        else:
            raise IOError('Invalid path to the hardware mu-map')
    else:
        print 'e> obtain the hardware mu-map first.'
        raise IOError('Could not find the hardware mu-map.  Have you run the routine for hardware mu-map?')
    #=========================================================
    #-check if T1w image is available
    if not 'MRT1W#' in datain and not 'T1nii' in datain and not 'T1bc' in datain \
    and not 'T1N4' in datain:
        print 'e> no MR T1w images required for co-registration!'
        raise IOError('T1w image could not be obtained')
    #=========================================================

    #-if the affine is not given,
    #-it will be generated by reconstructing PET image, with some or no corrections
    if not os.path.isfile(faff):
        # first recon pet to get the T1 aligned to it
        if petopt=='qnt':
            # ---------------------------------------------
            # OPTION 1 (quantitative recon with all corrections using MR-based mu-map)
            # get UTE object mu-map (may not be in register with the PET data)
            mudic = obj_mumap(
                        datain,
                        Cnt,
                        del_auxilary=del_auxilary)
            muo = mudic['im']
            # reconstruct PET image with UTE mu-map to which co-register T1w
            recout = mmrrec.osemone(
                datain, [muh, muo],
                hst, scanner_params,
                recmod=3, itr=itr, fwhm=0.,
                fcomment=fcomment+'_QNT-UTE',
                outpath=os.path.join(outpath, 'PET', 'positioning'),
                store_img=True)
        elif petopt=='nac':
            # ---------------------------------------------
            # OPTION 2 (recon without any corrections for scatter and attenuation)
            # reconstruct PET image with UTE mu-map to which co-register T1w
            muo = np.zeros(muh.shape, dtype=muh.dtype)
            recout = mmrrec.osemone(
                datain, [muh, muo],
                hst, scanner_params,
                recmod=1, itr=itr, fwhm=0.,
                fcomment=fcomment+'_NAC',
                outpath=os.path.join(outpath,'PET', 'positioning'),
                store_img=True)
        elif petopt=='ac':
            # ---------------------------------------------
            # OPTION 3 (recon with attenuation correction only but no scatter)
            # reconstruct PET image with UTE mu-map to which co-register T1w
            mudic = obj_mumap(
                    datain,
                    Cnt,
                    del_auxilary=del_auxilary)
            muo = mudic['im']

            recout = mmrrec.osemone(
                datain, [muh, muo],
                hst, scanner_params,
                recmod=1, itr=itr, fwhm=0.,
                fcomment=fcomment+'_AC-UTE',
                outpath=os.path.join(outpath,'PET', 'positioning'),
                store_img=True)

        fpet = recout.fpet
        mu_dct['fpet'] = fpet

        #------------------------------
        if musrc=='ute' and ute_name in datain and os.path.exists(datain[ute_name]):
            # change to NIfTI if the UTE sequence is in DICOM files (folder)
            if os.path.isdir(datain[ute_name]):
                fnew =  os.path.basename(datain[ute_name])
                call( [ Cnt['DCM2NIIX'], '-f', fnew, datain[ute_name] ] )
                fute = glob.glob(os.path.join(datain[ute_name], fnew+'*nii*'))[0]
            elif os.path.isfile(datain[ute_name]):
                fute = datain[ute_name]

            # get the affine transformation
            try:
                regdct = nimpa.coreg_spm(
                    fpet,
                    fute,
                    outpath=os.path.join(outpath,'PET', 'positioning')
                )
            except:
                regdct = nimpa.affine_niftyreg(
                    fpet,
                    fute,
                    outpath=os.path.join(outpath,'PET', 'positioning'),
                    #fcomment=fcomment,
                    executable = Cnt['REGPATH'],
                    omp = multiprocessing.cpu_count()/2,
                    rigOnly = True,
                    affDirect = False,
                    maxit=5,
                    speed=True,
                    pi=50, pv=50,
                    smof=0, smor=0,
                    rmsk=True,
                    fmsk=True,
                    rfwhm=15., #millilitres
                    rthrsh=0.05,
                    ffwhm = 15., #millilitres
                    fthrsh=0.05,
                    verbose=verbose
                )

            faff_mrpet = regdct['faff']

        elif musrc=='pct':

            ft1w = nimpa.pick_t1w(datain)

            try:
                regdct = nimpa.coreg_spm(
                    fpet,
                    ft1w,
                    outpath=os.path.join(outpath,'PET', 'positioning')
                )
            except:
                regdct = nimpa.affine_niftyreg(
                    fpet,
                    ft1w,
                    outpath=os.path.join(outpath,'PET', 'positioning'),
                    executable = Cnt['REGPATH'],
                    omp = multiprocessing.cpu_count()/2,
                    rigOnly = True,
                    affDirect = False,
                    maxit=5,
                    speed=True,
                    pi=50, pv=50,
                    smof=0, smor=0,
                    rmsk=True,
                    fmsk=True,
                    rfwhm=15., #millilitres
                    rthrsh=0.05,
                    ffwhm = 15., #millilitres
                    fthrsh=0.05,
                    verbose=verbose
                )

            faff_mrpet = regdct['faff']

        else:
            raise IOError('Floating MR image not provided or is invalid.')

    else:
        faff_mrpet = faff
        regdct = {}
        if not os.path.isfile(fpet):
            raise IOError('e> the reference PET should be supplied with the affine.')

    #> output file name for the aligned mu-maps
    if musrc=='pct':
        freg = os.path.join(opth, 'pCT-res-tmp'+fcomment+'.nii.gz')
        fflo = datain['pCT']

    elif musrc=='ute':
        freg = os.path.join(opth, 'UTE-res-tmp'+fcomment+'.nii.gz')
        if 'UTE' not in datain:
            fnii = 'converted-from-DICOM_'
            tstmp = nimpa.time_stamp(simple_ascii=True)
            # convert the DICOM mu-map images to nii
            if 'mumapDCM' not in datain:
                raise IOError('DICOM with the UTE mu-map are not given.')
            call( [ Cnt['DCM2NIIX'], '-f', fnii+tstmp, '-o', opth, datain['mumapDCM'] ] )
            #files for the T1w, pick one:
            fflo = glob.glob( os.path.join(opth, '*'+fnii+tstmp+'*.nii*') )[0]
        else:
            if os.path.isfile(datain['UTE']):
                fflo = datain['UTE']
            else:
                raise IOError('The provided NIfTI UTE path is not valid.')

    #> call the resampling routine to get the pCT/UTE in place
    if 'matlab_eng' in regdct:
        nimpa.resample_spm(
            fpet,
            fflo,
            faff_mrpet,
            matlab_eng=regdct['matlab_eng'],
            fimout=freg,
            del_ref_uncmpr=True,
            del_flo_uncmpr=True,
            del_out_uncmpr=True
        )
    else:
        nimpa.resample_niftyreg(
            fpet,
            fflo,
            faff_mrpet,
            fimout = freg,
            executable = Cnt['RESPATH'],
            verbose = True)


    #-get the NIfTI of registered image
    nim = nib.load(freg)
    A   = nim.affine
    imreg = np.float32( nim.get_data() )
    imreg = imreg[:,::-1,::-1]
    imreg = np.transpose(imreg, (2, 1, 0))

    #-convert to mu-values; sort out the file name too.
    if musrc=='pct':
        mu = hu2mu(imreg)
    elif musrc=='ute':
        mu = np.float32(imreg)/1e4
        #-remove the converted file from DICOMs
        os.remove(fflo)
    else:
        raise NameError('Confused o_O.')

    # get rid of negatives
    mu[mu<0] = 0
    # return image dictionary with the image itself and other parameters
    mu_dct['im'] = mu
    mu_dct['affine'] = A
    mu_dct['faff'] = faff

    if store or store_npy:

        nimpa.create_dir(opth)
        if faff=='':
            fname = fnm + '-aligned-to_t'\
                    + str(hst['t0'])+'-'+str(hst['t1'])+'_'+petopt.upper()\
                    + fcomment
        else:
            fname = fnm + '-aligned-to-given-affine' + fcomment

    if store_npy:
        #> Numpy
        if store_to_npy:
            fnp = os.path.join(opth, fname + '.npy')
            np.save(fnp, (mu, A, fnp))


    if store:
        #> NIfTI
        fmu = os.path.join(opth, fname + '.nii.gz')
        nimpa.array2nii(mu[::-1,::-1,:], A, fmu)
        mu_dct['fim'] = fmu

    if del_auxilary:
        os.remove(freg)
        if not os.path.isfile(faff):
            os.remove(fute)

    return mu_dct
Exemplo n.º 5
0
def obj_mumap(
        datain,
        params={},
        outpath='',
        comment='',
        store=False,
        store_npy=False,
        gantry_offset=True,
        del_auxilary=True,
        ):
    '''Get the object mu-map from DICOM images'''


    # three ways of passing scanner constants <Cnt> are here decoded
    if 'Cnt' in params:
        Cnt = params['Cnt']
    elif 'SO_IMZ' in params:
        Cnt = params
    else:
        Cnt = rs.get_mmr_constants()


    # output folder
    if outpath=='':
        fmudir = os.path.join( datain['corepath'], 'mumap-obj' )
    else:
        fmudir = os.path.join( outpath, 'mumap-obj' )
    nimpa.create_dir(fmudir)
    # ref file name
    fmuref = os.path.join(fmudir, 'muref.nii.gz')
    # ref affine
    B = image_affine(datain, Cnt, gantry_offset=gantry_offset)
    # ref image (blank)
    im = np.zeros((Cnt['SO_IMZ'], Cnt['SO_IMY'], Cnt['SO_IMX']), dtype=np.float32)
    # store ref image
    nimpa.array2nii(im, B, fmuref)

    # check if the object dicom files for MR-based mu-map exists
    if not 'mumapDCM' in datain or not os.path.isdir(datain['mumapDCM']):
        print 'e> DICOM forlder for the mu-map does not exist.'
        return None

    fnii = 'converted-from-object-DICOM_'
    tstmp = nimpa.time_stamp(simple_ascii=True)

    # find residual(s) from previous runs and delete them
    resdcm = glob.glob( os.path.join(fmudir, '*'+fnii+'*.nii*') )
    for d in resdcm:
        os.remove(d)

    # convert the DICOM mu-map images to nii
    call( [ Cnt['DCM2NIIX'], '-f', fnii+tstmp, '-o', fmudir, datain['mumapDCM'] ] )
    #files for the T1w, pick one:
    fmunii = glob.glob( os.path.join(fmudir, '*'+fnii+tstmp+'*.nii*') )[0]
    # fmunii = glob.glob( os.path.join(datain['mumapDCM'], '*converted*.nii*') )
    # fmunii = fmunii[0]

    # the converted nii image resample to the reference size
    fmu = os.path.join(fmudir, comment+'mumap_tmp.nii.gz')
    if os.path.isfile( Cnt['RESPATH'] ):
        cmd = [ Cnt['RESPATH'],
                    '-ref', fmuref,
                    '-flo', fmunii,
                    '-res', fmu,
                    '-pad', '0']
        if not Cnt['VERBOSE']: cmd.append('-voff')
        call(cmd)
    else:
        print 'e> path to resampling executable is incorrect!'
        sys.exit()

    nim = nib.load(fmu)
    # get the affine transform
    A = nim.get_sform()
    mu = nim.get_data()
    mu = np.transpose(mu[:,::-1,::-1], (2, 1, 0))
    # convert to mu-values
    mu = np.float32(mu)/1e4
    mu[mu<0] = 0

    #> return image dictionary with the image itself and some other stats
    mu_dct = {  'im':mu,
                'affine':A}
    if not del_auxilary: mu_dct['fmuref'] = fmuref

    # store the mu-map if requested
    if store_npy:
        # to numpy array
        fnp = os.path.join(fmudir, 'mumap-from-DICOM.npy' )
        np.save(fnp, (mu, A))

    if store:
        # with this file name
        fmumap = os.path.join(fmudir, 'mumap-from-DICOM_no-alignment'+comment+'.nii.gz')
        nimpa.array2nii(mu[::-1,::-1,:], A, fmumap)
        mu_dct['fim'] = fmumap

    if del_auxilary:
        os.remove(fmuref)
        os.remove(fmunii)
        os.remove(fmu)


    return mu_dct