Example #1
0
def Photutils_Fit(IMG, results, options):
    """
    Function to run the photutils automated isophote analysis on an image.
    """

    dat = IMG - results['background']
    geo = EllipseGeometry(x0=results['center']['x'],
                          y0=results['center']['y'],
                          sma=results['init R'] / 2,
                          eps=results['init ellip'],
                          pa=results['init pa'])
    ellipse = Photutils_Ellipse(dat, geometry=geo)

    isolist = ellipse.fit_image(fix_center=True, linear=False)
    res = {
        'fit R': isolist.sma[1:],
        'fit ellip': isolist.eps[1:],
        'fit ellip_err': isolist.ellip_err[1:],
        'fit pa': isolist.pa[1:],
        'fit pa_err': isolist.pa_err[1:],
        'auxfile fitlimit':
        'fit limit semi-major axis: %.2f pix' % isolist.sma[-1]
    }

    if 'ap_doplot' in options and options['ap_doplot']:
        ranges = [[
            max(0, int(results['center']['y'] - res['fit R'][-1] * 1.2)),
            min(dat.shape[1],
                int(results['center']['y'] + res['fit R'][-1] * 1.2))
        ],
                  [
                      max(0,
                          int(results['center']['x'] -
                              res['fit R'][-1] * 1.2)),
                      min(dat.shape[0],
                          int(results['center']['x'] + res['fit R'][-1] * 1.2))
                  ]]
        LSBImage(dat[ranges[1][0]:ranges[1][1], ranges[0][0]:ranges[0][1]],
                 results['background noise'])
        for i in range(len(res['fit R'])):
            plt.gca().add_patch(
                Ellipse(
                    (int(res['fit R'][-1] * 1.2), int(res['fit R'][-1] * 1.2)),
                    2 * res['fit R'][i],
                    2 * res['fit R'][i] * (1. - res['fit ellip'][i]),
                    res['fit pa'][i] * 180 / np.pi,
                    fill=False,
                    linewidth=0.5,
                    color='r'))
        if not ('ap_nologo' in options and options['ap_nologo']):
            AddLogo(plt.gcf())
        plt.savefig(
            '%sfit_ellipse_%s.jpg' %
            (options['ap_plotpath'] if 'ap_plotpath' in options else '',
             options['ap_name']),
            dpi=300)
        plt.close()

    return IMG, res
Example #2
0
def _fit_ellipse(burst_npy, acf, geometry, aper, sigma_t, sigma_f, plot=True):

    #Fit Ellipse to 2D ACF
    try:
        ellipse = Ellipse(acf, geometry)
        isolist = ellipse.fit_image()
        model_image = build_ellipse_model(acf.shape, isolist)
        residual = acf - model_image

        if plot == True:
            fig = plt.figure()
            smas = np.linspace(0, int(sigf3), 8)
            for sma in smas:
                iso = isolist.get_closest(sma)
                x, y, = iso.sampled_coordinates()
                plt.imshow(acf, aspect='auto')
                plt.plot(x, y, color='white')
            plt.show()
            fig.savefig(str(burst_npy) + '_ellipse_fit.png')
    except OverflowError:
        print('Note: Overflow Error')
        pass
    except ValueError:
        print('Note: Value Error')
        pass
    except IndexError:
        print('Ellipse Fit Failed!')
        pass

    print('Fit completed!')

    slope = np.tan(np.max(isolist.pa))
    std_sma_dr_unround = np.tan(np.std(isolist.pa))
    std_sma_dr = '%s' % float('%.2g' % std_sma_dr_unround)
    drift_rate_unround = -1 * (slope * (subfres / tres))  #MHz/ms
    drift_rate = '%s' % float('%.4g' % drift_rate_unround)  #MHz/ms
    print('Drift Slope: ',
          str(drift_rate) + ' +/- ' + str(std_sma_dr) + ' MHz/ms')

    return drift_rate
Example #3
0
plt.colorbar(im)
aperture.plot(color='#d62728')
box.plot(color='#d62728')
print(bkg_mean,bkg_rms,bkg_mean - 1*bkg_rms,bkg_mean + 1*bkg_rms,bkg_mean - 3*bkg_rms,bkg_mean + 3*bkg_rms)
#data = data - (bkg_mean+3*bkg_rms)#(bkg_mean - 1*bkg_rms) 
### np.median(data[box_cutout.data==0]) # == 15.167292
### np.std(data[box_cutout.data==0]) #== 10.078673
# ----------------------------------------------------------------------------
#datamask = deepcopy(data)
#datamask[mask>0]=0

geometry = EllipseGeometry(x0=cat.xcentroid, y0=cat.ycentroid, sma=a, eps=1-b/a,
                            pa=(theta+90)*np.pi/180.)


ellipse = Ellipse(ma.masked_where(mask > 0, data), geometry)
#isolist = ellipse.fit_image(integrmode='median', step=5, linear=True, 
#                                  maxsma=nsize/2, fflag=0.3, sclip=3, nclip=3)
isolist = ellipse.fit_image(integrmode='median', step=.1, linear=False, 
                                  maxsma=nsize/2, fflag=0.3, sclip=3, nclip=3)


# Try to fit further more (from the last ellipse) with larger step to increase S/N
# and capture outer parts of the galaxy
#geometry = EllipseGeometry(x0=cat.xcentroid, y0=cat.ycentroid, sma=np.max(isolist.sma), 
#                           eps=1-b/a, pa=(theta+90)*np.pi/180.)
#ellipse = Ellipse(data, geometry)
#isolist_outer = ellipse.fit_image(integrmode='median', step=0.3, minsma=isolist.sma[-1],
#                                  maxsma=nsize/2, fflag=0.3, sclip=3.0, nclip=3)

# Join two list excluding the last solution from the outer fit since stop_code=4    
Example #4
0
def _Generate_Profile(IMG, results, R, E, Ee, PA, PAe, options):

    # Create image array with background and mask applied
    try:
        if np.any(results['mask']):
            mask = results['mask']
        else:
            mask = None
    except:
        mask = None
    dat = IMG - results['background']
    zeropoint = options['ap_zeropoint'] if 'ap_zeropoint' in options else 22.5

    sb = []
    sbE = []
    cogdirect = []
    sbfix = []
    sbfixE = []

    count_neg = 0
    medflux = np.inf
    end_prof = None
    for i in range(len(R)):
        isobandwidth = R[i] * (options['ap_isoband_width']
                               if 'ap_isoband_width' in options else 0.025)
        if medflux > (results['background noise'] *
                      (options['ap_isoband_start'] if 'ap_isoband_start'
                       in options else 2)) or isobandwidth < 0.5:
            isovals = _iso_extract(
                dat,
                R[i],
                E[i],
                PA[i],
                results['center'],
                mask=mask,
                rad_interp=(options['ap_iso_interpolate_start']
                            if 'ap_iso_interpolate_start' in options else 5) *
                results['psf fwhm'],
                sigmaclip=options['ap_isoclip']
                if 'ap_isoclip' in options else False,
                sclip_iterations=options['ap_isoclip_iterations']
                if 'ap_isoclip_iterations' in options else 10,
                sclip_nsigma=options['ap_isoclip_nsigma']
                if 'ap_isoclip_nsigma' in options else 5)
            isovalsfix = _iso_extract(
                dat,
                R[i],
                results['init ellip'],
                results['init pa'],
                results['center'],
                mask=mask,
                rad_interp=(options['ap_iso_interpolate_start']
                            if 'ap_iso_interpolate_start' in options else 5) *
                results['psf fwhm'],
                sigmaclip=options['ap_isoclip']
                if 'ap_isoclip' in options else False,
                sclip_iterations=options['ap_isoclip_iterations']
                if 'ap_isoclip_iterations' in options else 10,
                sclip_nsigma=options['ap_isoclip_nsigma']
                if 'ap_isoclip_nsigma' in options else 5)
        else:
            isovals = _iso_between(
                dat,
                R[i] - isobandwidth,
                R[i] + isobandwidth,
                E[i],
                PA[i],
                results['center'],
                mask=mask,
                sigmaclip=options['ap_isoclip']
                if 'ap_isoclip' in options else False,
                sclip_iterations=options['ap_isoclip_iterations']
                if 'ap_isoclip_iterations' in options else 10,
                sclip_nsigma=options['ap_isoclip_nsigma']
                if 'ap_isoclip_nsigma' in options else 5)
            isovalsfix = _iso_between(
                dat,
                R[i] - isobandwidth,
                R[i] + isobandwidth,
                results['init ellip'],
                results['init pa'],
                results['center'],
                mask=mask,
                sigmaclip=options['ap_isoclip']
                if 'ap_isoclip' in options else False,
                sclip_iterations=options['ap_isoclip_iterations']
                if 'ap_isoclip_iterations' in options else 10,
                sclip_nsigma=options['ap_isoclip_nsigma']
                if 'ap_isoclip_nsigma' in options else 5)
        isotot = np.sum(
            _iso_between(dat,
                         0,
                         R[i],
                         E[i],
                         PA[i],
                         results['center'],
                         mask=mask))
        medflux = _average(
            isovals, options['ap_isoaverage_method']
            if 'ap_isoaverage_method' in options else 'median')
        scatflux = _scatter(
            isovals, options['ap_isoaverage_method']
            if 'ap_isoaverage_method' in options else 'median')
        medfluxfix = _average(
            isovalsfix, options['ap_isoaverage_method']
            if 'ap_isoaverage_method' in options else 'median')
        scatfluxfix = _scatter(
            isovalsfix, options['ap_isoaverage_method']
            if 'ap_isoaverage_method' in options else 'median')

        sb.append(
            flux_to_sb(medflux, options['ap_pixscale'], zeropoint
                       ) if medflux > 0 else 99.999)
        sbE.append((2.5 * scatflux / (np.sqrt(len(isovals)) * medflux *
                                      np.log(10))) if medflux > 0 else 99.999)
        sbfix.append(
            flux_to_sb(medfluxfix, options['ap_pixscale'], zeropoint
                       ) if medfluxfix > 0 else 99.999)
        sbfixE.append((2.5 * scatfluxfix /
                       (np.sqrt(len(isovalsfix)) * np.median(isovalsfix) *
                        np.log(10))) if medfluxfix > 0 else 99.999)
        cogdirect.append(
            flux_to_mag(isotot, zeropoint) if isotot > 0 else 99.999)
        if medflux <= 0:
            count_neg += 1
        if 'ap_truncate_evaluation' in options and options[
                'ap_truncate_evaluation'] and count_neg >= 2:
            end_prof = i + 1
            break

    # Compute Curve of Growth from SB profile
    cog, cogE = SBprof_to_COG_errorprop(R[:end_prof] * options['ap_pixscale'],
                                        np.array(sb),
                                        np.array(sbE),
                                        1. - E[:end_prof],
                                        Ee[:end_prof],
                                        N=100,
                                        method=0,
                                        symmetric_error=True)
    cogE[cog > 99] = 99.999
    cogfix, cogfixE = SBprof_to_COG_errorprop(R[:end_prof] *
                                              options['ap_pixscale'],
                                              np.array(sbfix),
                                              np.array(sbfixE),
                                              1. - E[:end_prof],
                                              Ee[:end_prof],
                                              N=100,
                                              method=0,
                                              symmetric_error=True)
    cogfixE[cogfix > 99] = 99.999

    # For each radius evaluation, write the profile parameters
    params = [
        'R', 'SB', 'SB_e', 'totmag', 'totmag_e', 'ellip', 'ellip_e', 'pa',
        'pa_e', 'totmag_direct', 'SB_fix', 'SB_fix_e', 'totmag_fix',
        'totmag_fix_e'
    ]

    SBprof_data = dict((h, None) for h in params)
    SBprof_units = {
        'R': 'arcsec',
        'SB': 'mag*arcsec^-2',
        'SB_e': 'mag*arcsec^-2',
        'totmag': 'mag',
        'totmag_e': 'mag',
        'ellip': 'unitless',
        'ellip_e': 'unitless',
        'pa': 'deg',
        'pa_e': 'deg',
        'totmag_direct': 'mag',
        'SB_fix': 'mag*arcsec^-2',
        'SB_fix_e': 'mag*arcsec^-2',
        'totmag_fix': 'mag',
        'totmag_fix_e': 'mag'
    }
    SBprof_format = {
        'R': '%.4f',
        'SB': '%.4f',
        'SB_e': '%.4f',
        'totmag': '%.4f',
        'totmag_e': '%.4f',
        'ellip': '%.3f',
        'ellip_e': '%.3f',
        'pa': '%.2f',
        'pa_e': '%.2f',
        'totmag_direct': '%.4f',
        'SB_fix': '%.4f',
        'SB_fix_e': '%.4f',
        'totmag_fix': '%.4f',
        'totmag_fix_e': '%.4f'
    }

    SBprof_data['R'] = list(R[:end_prof] * options['ap_pixscale'])
    SBprof_data['SB'] = list(sb)
    SBprof_data['SB_e'] = list(sbE)
    SBprof_data['totmag'] = list(cog)
    SBprof_data['totmag_e'] = list(cogE)
    SBprof_data['ellip'] = list(E[:end_prof])
    SBprof_data['ellip_e'] = list(Ee[:end_prof])
    SBprof_data['pa'] = list(PA[:end_prof] * 180 / np.pi)
    SBprof_data['pa_e'] = list(PAe[:end_prof] * 180 / np.pi)
    SBprof_data['totmag_direct'] = list(cogdirect)
    SBprof_data['SB_fix'] = list(sbfix)
    SBprof_data['SB_fix_e'] = list(sbfixE)
    SBprof_data['totmag_fix'] = list(cogfix)
    SBprof_data['totmag_fix_e'] = list(cogfixE)

    if 'ap_doplot' in options and options['ap_doplot']:
        CHOOSE = np.logical_and(
            np.array(SBprof_data['SB']) < 99,
            np.array(SBprof_data['SB_e']) < 1)
        errscale = 1.
        if np.all(np.array(SBprof_data['SB_e'])[CHOOSE] < 0.5):
            errscale = 1 / np.max(np.array(SBprof_data['SB_e'])[CHOOSE])
        lnlist = []
        lnlist.append(
            plt.errorbar(np.array(SBprof_data['R'])[CHOOSE],
                         np.array(SBprof_data['SB'])[CHOOSE],
                         yerr=errscale * np.array(SBprof_data['SB_e'])[CHOOSE],
                         elinewidth=1,
                         linewidth=0,
                         marker='.',
                         markersize=5,
                         color='r',
                         label='Surface Brightness (err$\\cdot$%.1f)' %
                         errscale))
        plt.errorbar(np.array(SBprof_data['R'])[np.logical_and(
            CHOOSE,
            np.arange(len(CHOOSE)) % 4 == 0)],
                     np.array(SBprof_data['SB'])[np.logical_and(
                         CHOOSE,
                         np.arange(len(CHOOSE)) % 4 == 0)],
                     yerr=np.array(SBprof_data['SB_e'])[np.logical_and(
                         CHOOSE,
                         np.arange(len(CHOOSE)) % 4 == 0)],
                     elinewidth=1,
                     linewidth=0,
                     marker='.',
                     markersize=5,
                     color='limegreen')
        # plt.errorbar(np.array(SBprof_data['R'])[CHOOSE], np.array(SBprof_data['totmag'])[CHOOSE], yerr = np.array(SBprof_data['totmag_e'])[CHOOSE],
        #              elinewidth = 1, linewidth = 0, marker = '.', markersize = 5, color = 'orange', label = 'Curve of Growth')
        plt.xlabel('Semi-Major-Axis [arcsec]', fontsize=16)
        plt.ylabel('Surface Brightness [mag arcsec$^{-2}$]', fontsize=16)
        bkgrdnoise = -2.5 * np.log10(
            results['background noise']) + zeropoint + 2.5 * np.log10(
                options['ap_pixscale']**2)
        lnlist.append(
            plt.axhline(
                bkgrdnoise,
                color='purple',
                linewidth=0.5,
                linestyle='--',
                label='1$\\sigma$ noise/pixel: %.1f mag arcsec$^{-2}$' %
                bkgrdnoise))
        plt.gca().invert_yaxis()
        plt.tick_params(labelsize=14)
        # ax2 = plt.gca().twinx()
        # lnlist += ax2.plot(np.array(SBprof_data['R'])[CHOOSE], np.array(SBprof_data['pa'])[CHOOSE]/180, color = 'b', label = 'PA/180')
        # lnlist += ax2.plot(np.array(SBprof_data['R'])[CHOOSE], np.array(SBprof_data['ellip'])[CHOOSE], color = 'orange', linestyle = '--', label = 'ellipticity')
        labs = [l.get_label() for l in lnlist]
        plt.legend(lnlist, labs, fontsize=11)
        # ax2.set_ylabel('Position Angle, Ellipticity', fontsize = 16)
        # ax2.tick_params(labelsize = 14)
        plt.tight_layout()
        if not ('ap_nologo' in options and options['ap_nologo']):
            AddLogo(plt.gcf())
        plt.savefig(
            '%sphotometry_%s.jpg' %
            (options['ap_plotpath'] if 'ap_plotpath' in options else '',
             options['ap_name']),
            dpi=options['ap_plotdpi'] if 'ap_plotdpi' in options else 300)
        plt.close()

        useR = np.array(SBprof_data['R'])[CHOOSE] / options['ap_pixscale']
        useE = np.array(SBprof_data['ellip'])[CHOOSE]
        usePA = np.array(SBprof_data['pa'])[CHOOSE]
        ranges = [[
            max(0, int(results['center']['x'] - useR[-1] * 1.2)),
            min(dat.shape[1], int(results['center']['x'] + useR[-1] * 1.2))
        ],
                  [
                      max(0, int(results['center']['y'] - useR[-1] * 1.2)),
                      min(dat.shape[0],
                          int(results['center']['y'] + useR[-1] * 1.2))
                  ]]
        LSBImage(dat[ranges[1][0]:ranges[1][1], ranges[0][0]:ranges[0][1]],
                 results['background noise'])
        for i in range(len(useR)):
            plt.gca().add_patch(
                Ellipse(
                    (results['center']['x'] - ranges[0][0],
                     results['center']['y'] - ranges[1][0]),
                    2 * useR[i],
                    2 * useR[i] * (1. - useE[i]),
                    usePA[i],
                    fill=False,
                    linewidth=((i + 1) / len(useR))**2,
                    color='limegreen' if (i % 4 == 0) else 'r',
                    linestyle='-' if useR[i] < results['fit R'][-1] else '--'))
        if not ('ap_nologo' in options and options['ap_nologo']):
            AddLogo(plt.gcf())
        plt.savefig(
            '%sphotometry_ellipse_%s.jpg' %
            (options['ap_plotpath'] if 'ap_plotpath' in options else '',
             options['ap_name']),
            dpi=options['ap_plotdpi'] if 'ap_plotdpi' in options else 300)
        plt.close()

    return {
        'prof header': params,
        'prof units': SBprof_units,
        'prof data': SBprof_data,
        'prof format': SBprof_format
    }
Example #5
0
def imod2snrconvseries(magdata, bandmod, frac=0.5):
	from scipy import signal
	from photutils.isophote import EllipseGeometry
	from photutils.isophote import Ellipse
	from photutils.isophote import build_ellipse_model
	
	cr = csstpkg.mag2cr(magdata['MOD_' + bandmod], band=bandmod)
	cr300poiss = poisson.rvs(cr * texp, size=1)[0]
	
	agalaxy = csstpkg.galser(lumtot=cr300poiss, reff=magdata['reff'], nser=magdata['nser'], ellip=1 - magdata['Eab'])
	# agalaxy.plotmodel()
	
	# Generating convolution image:
	apsf = csstpkg.psfgauss()
	normpsf = apsf.gauss()[2] / np.sum(apsf.gauss()[2])
	agalconv = signal.fftconvolve(agalaxy.sermod()[2], normpsf, mode='same')
	
	# FITS file generating:
	# hduagalaxy = fits.PrimaryHDU(agalaxy.sermod()[2])
	# hduagalaxy.writeto('test_agalaxy.fits',overwrite=True)
	# hduapsf = fits.PrimaryHDU(normpsf)
	# hduapsf.writeto('test_apsf.fits', overwrite=True)
	
	# hdr = fits.Header()
	# hdr['UVUDFID']=magdata['ID']
	# hduagalconv = fits.PrimaryHDU(data=agalconv,header=hdr)
	# hduagalconv.writeto('test_agalconv.fits', overwrite=True)
	
	# build ellipse model and fit to convolved:
	ellipgeo = EllipseGeometry(x0=agalaxy.orig0[0], y0=agalaxy.orig0[1], sma=agalaxy.a, eps=agalaxy.ellip, pa=0)
	# aper = agalaxy.aperture0
	ellipseinst = Ellipse(agalconv, geometry=ellipgeo)
	isophlist = ellipseinst.fit_image(minsma=1., maxsma=5*agalaxy.a)
	
	# print cr300poiss, isophlist.tflux_e[-1]
	
	if len(isophlist.valid) > 0:
		# model_image = build_ellipse_model(agalconv.shape, isophlist)
		# print 'sum of model:', np.sum(model_image)
		# residual = agalconv - model_image
		
		# # plot data, model and residual
		# fig, (ax1, ax2, ax3) = plt.subplots(figsize=(14, 5), nrows=1, ncols=3)
		# fig.subplots_adjust(left=0.04, right=0.98, bottom=0.02, top=0.98)
		# ax1.imshow(agalconv, origin='lower')
		# ax1.set_title('A Galaxy')
		# agalaxy.apers().plot(color='white',ax=ax1, lw=1)
		# ax2.imshow(model_image, origin='lower')
		# ax2.set_title('Ellipse Model')
		# ax3.imshow(residual, origin='lower')
		# ax3.set_title('Residual')
		
		# fig = plt.figure()
		# ax = fig.add_subplot(111, projection='3d')
		# ax.plot_wireframe(agalaxy.x, agalaxy.y, agalconv, color='blue', lw=1)
		# ax.plot_wireframe(agalaxy.x, agalaxy.y, model_image, color='red', lw=1)
		# plt.show()
	
		isophlist.fracflux = isophlist.tflux_e/cr300poiss
		# print isophlist.fracflux
		idx = find_nearest_idx(isophlist.fracflux, frac)
		# print isophlist[idx]
		snr = isolistsnr(isophlist[idx], bandmod='g')
		return snr
	else:
		return 'nan'
Example #6
0
def fit_ellipse_for_source(
    friendid=None,
    detectid=None,
    coords=None,
    shotid=None,
    subcont=True,
    convolve_image=False,
    pixscale=pixscale,
    imsize=imsize,
    wave_range=None,
):

    if detectid is not None:

        global deth5

        detectid_obj = detectid

        if detectid_obj <= 2190000000:
            det_info = deth5.root.Detections.read_where("detectid == detectid_obj")[0]
            linewidth = det_info["linewidth"]
            wave_obj = det_info["wave"]
            redshift = wave_obj / (1216) - 1
        else:
            det_info = conth5.root.Detections.read_where("detectid == detectid_obj")[0]
            redshift = 0
            wave_obj = 4500

        coords_obj = SkyCoord(det_info["ra"], det_info["dec"], unit="deg")

        shotid_obj = det_info["shotid"]
        fwhm = surveyh5.root.Survey.read_where("shotid == shotid_obj")["fwhm_virus"][0]
        amp = det_info["multiframe"]

        if wave_range is not None:
            wave_range_obj = wave_range
        else:
            if detectid_obj <= 2190000000:
                wave_range_obj = [wave_obj - 2 * linewidth, wave_obj + 2 * linewidth]
            else:
                wave_range_obj = [4100, 4200]

        if coords is not None:
            coords_obj = coords

        if shotid is not None:
            shotid_obj = shotid
            fwhm = surveyh5.root.Survey.read_where("shotid == shotid_obj")[
                "fwhm_virus"
            ][0]

        try:
            hdu = make_narrowband_image(
                coords=coords_obj,
                shotid=shotid_obj,
                wave_range=wave_range_obj,
                imsize=imsize * u.arcsec,
                pixscale=pixscale * u.arcsec,
                subcont=subcont,
                convolve_image=convolve_image,
                include_error=True,
            )

        except:
            print("Could not make narrowband image for {}".format(detectid))
            return np.nan, np.nan

    elif friendid is not None:

        global friend_cat

        sel = friend_cat["friendid"] == friendid
        group = friend_cat[sel]
        coords_obj = SkyCoord(ra=group["icx"][0] * u.deg, dec=group["icy"][0] * u.deg)
        wave_obj = group["icz"][0]
        redshift = wave_obj / (1216) - 1
        linewidth = group["linewidth"][0]
        shotid_obj = group["shotid"][0]
        fwhm = group["fwhm"][0]
        amp = group["multiframe"][0]

        if wave_range is not None:
            wave_range_obj = wave_range
        else:
            wave_range_obj = [wave_obj - 2 * linewidth, wave_obj + 2 * linewidth]

        if shotid is not None:
            shotid_obj = shotid
            fwhm = surveyh5.root.Survey.read_where("shotid == shotid_obj")[
                "fwhm_virus"
            ][0]

        try:
            hdu = make_narrowband_image(
                coords=coords_obj,
                shotid=shotid_obj,
                wave_range=wave_range_obj,
                imsize=imsize * u.arcsec,
                pixscale=pixscale * u.arcsec,
                subcont=subcont,
                convolve_image=convolve_image,
                include_error=True,
            )
        except:
            print("Could not make narrowband image for {}".format(friendid))
            return None

    elif coords is not None:
        coords_obj = coords

        if wave_range is not None:
            wave_range_obj = wave_range
        else:
            print(
                "You need to supply wave_range=[wave_start, wave_end] for collapsed image"
            )

        if shotid is not None:
            shotid_obj = shotid
            fwhm = surveyh5.root.Survey.read_where("shotid == shotid_obj")[
                "fwhm_virus"
            ][0]
        else:
            print("Enter the shotid to use (eg. 20200123003)")

        hdu = make_narrowband_image(
            coords=coords_obj,
            shotid=shotid_obj,
            wave_range=wave_range_obj,
            imsize=imsize * u.arcsec,
            pixscale=pixscale * u.arcsec,
            subcont=subcont,
            convolve_image=convolve_image,
            include_error=True,
        )
    else:
        print("You must provide a detectid, friendid or coords/wave_range/shotid")
        return np.nan, np.nan

    w = wcs.WCS(hdu[0].header)

    if friendid is not None:

        sel_friend_group = friend_cat["friendid"] == friendid
        group = friend_cat[sel_friend_group]
        eps = 1 - group["a2"][0] / group["b2"][0]
        pa = group["pa"][0] * np.pi / 180.0 - 90
        sma = group["a"][0] * 3600 / pixscale

        coords = SkyCoord(ra=group["icx"][0] * u.deg, dec=group["icy"][0] * u.deg)
        wave_obj = group["icz"][0]
        redshift = wave_obj / (1216) - 1
        linewidth = np.nanmedian(group["linewidth"])
        shotid_obj = group["shotid"][0]
        fwhm = group["fwhm"][0]

        geometry = EllipseGeometry(
            x0=w.wcs.crpix[0], y0=w.wcs.crpix[0], sma=sma, eps=eps, pa=pa
        )
    else:
        geometry = EllipseGeometry(
            x0=w.wcs.crpix[0], y0=w.wcs.crpix[0], sma=20, eps=0.2, pa=20.0
        )

    geometry = EllipseGeometry(
        x0=w.wcs.crpix[0], y0=w.wcs.crpix[0], sma=20, eps=0.2, pa=20.0
    )
    # geometry.find_center(hdu.data)
    # aper = EllipticalAperture((geometry.x0, geometry.y0), geometry.sma,
    #                          geometry.sma*(1 - geometry.eps), geometry.pa)

    # plt.imshow(hdu.data, origin='lower')
    # aper.plot(color='white')

    ellipse = Ellipse(hdu[0].data)
    isolist = ellipse.fit_image()
    iso_tab = isolist.to_table()

    if len(iso_tab) == 0:
        geometry.find_center(hdu[0].data, verbose=False, threshold=0.5)
        ellipse = Ellipse(hdu[0].data, geometry)
        isolist = ellipse.fit_image()
        iso_tab = isolist.to_table()

    if len(iso_tab) == 0:
        return np.nan, np.nan, np.nan

        try:
            # compute iso's manually in steps of 3 pixels
            ellipse = Ellipse(hdu[0].data)  # reset ellipse
            iso_list = []
            for sma in np.arange(1, 60, 2):
                iso = ellipse.fit_isophote(sma)
                if np.isnan(iso.intens):
                    # print('break at {}'.format(sma))
                    break
                else:
                    iso_list.append(iso)
            isolist = IsophoteList(iso_list)
            iso_tab = isolist.to_table()
        except:
            return np.nan, np.nan, np.nan

    try:
        model_image = build_ellipse_model(hdu[0].data.shape, isolist)
        residual = hdu[0].data - model_image
    except:
        return np.nan, np.nan, np.nan

    sma = iso_tab["sma"] * pixscale
    const_arcsec_to_kpc = cosmo.kpc_proper_per_arcmin(redshift).value / 60.0

    def arcsec_to_kpc(sma):
        dist = const_arcsec_to_kpc * sma
        return dist

    def kpc_to_arcsec(dist):
        sma = dist / const_arcsec_to_kpc
        return sma

    dist_kpc = (
        sma * u.arcsec.to(u.arcmin) * u.arcmin * cosmo.kpc_proper_per_arcmin(redshift)
    )
    dist_arcsec = kpc_to_arcsec(dist_kpc)

    # print(shotid_obj, fwhm)
    # s_exp1d = models.Exponential1D(amplitude=0.2, tau=-50)

    alpha = 3.5
    s_moffat = models.Moffat1D(
        amplitude=1,
        gamma=(0.5 * fwhm) / np.sqrt(2 ** (1.0 / alpha) - 1.0),
        x_0=0.0,
        alpha=alpha,
        fixed={"amplitude": False, "x_0": True, "gamma": True, "alpha": True},
    )

    s_init = models.Exponential1D(amplitude=0.2, tau=-50)

    fit = fitting.LevMarLSQFitter()
    s_r = fit(s_init, dist_kpc, iso_tab["intens"])

    # Fitting can be done using the uncertainties as weights.
    # To get the standard weighting of 1/unc^2 for the case of
    # Gaussian errors, the weights to pass to the fitting are 1/unc.
    # fitted_line = fit(line_init, x, y, weights=1.0/yunc)

    # s_r = fit(s_init, dist_kpc, iso_tab['intens'])#, weights=iso_tab['intens']/iso_tab['intens_err'] )

    print(s_r)
    try:
        r_n = -1.0 * s_r.tau  # _0 #* const_arcsec_to_kpc
    except:
        r_n = np.nan  # r_n = -1. * s_r.tau_0
    try:
        sel_iso = np.where(dist_kpc >= 2 * r_n)[0][0]
    except:
        sel_iso = -1

    aper = EllipticalAperture(
        (isolist.x0[sel_iso], isolist.y0[sel_iso]),
        isolist.sma[sel_iso],
        isolist.sma[sel_iso] * (1 - isolist.eps[sel_iso]),
        isolist.pa[sel_iso],
    )

    phottable = aperture_photometry(hdu[0].data, aper, error=hdu[1].data)
    flux = phottable["aperture_sum"][0] * 10 ** -17 * u.erg / (u.cm ** 2 * u.s)
    flux_err = phottable["aperture_sum_err"][0] * 10 ** -17 * u.erg / (u.cm ** 2 * u.s)

    lum_dist = cosmo.luminosity_distance(redshift).to(u.cm)
    lum = flux * 4.0 * np.pi * lum_dist ** 2
    lum_err = flux_err * 4.0 * np.pi * lum_dist ** 2

    if detectid:
        name = detectid
    elif friendid:
        name = friendid

    # Get Image data from Elixer
    catlib = catalogs.CatalogLibrary()
    try:
        cutout = catlib.get_cutouts(
            position=coords_obj,
            side=imsize,
            aperture=None,
            dynamic=False,
            filter=["r", "g", "f606W"],
            first=True,
            allow_bad_image=False,
            allow_web=True,
        )[0]
    except:
        print("Could not get imaging for " + str(name))

    zscale = ZScaleInterval(contrast=0.5, krej=1.5)
    vmin, vmax = zscale.get_limits(values=hdu[0].data)

    fig = plt.figure(figsize=(20, 12))
    fig.suptitle(
        "{}  ra={:3.2f}, dec={:3.2f}, wave={:5.2f}, z={:3.2f}, mf={}".format(
            name, coords_obj.ra.value, coords_obj.dec.value, wave_obj, redshift, amp
        ),
        fontsize=22,
    )

    ax1 = fig.add_subplot(231, projection=w)
    plt.imshow(hdu[0].data, vmin=vmin, vmax=vmax)
    plt.xlabel("RA")
    plt.ylabel("Dec")
    plt.colorbar()
    plt.title("Image summed across 4*linewidth")

    ax2 = fig.add_subplot(232, projection=w)
    plt.imshow(model_image, vmin=vmin, vmax=vmax)
    plt.xlabel("RA")
    plt.ylabel("Dec")
    plt.colorbar()
    plt.title("model")

    ax3 = fig.add_subplot(233, projection=w)
    plt.imshow(residual, vmin=vmin, vmax=vmax)
    plt.xlabel("RA")
    plt.ylabel("Dec")
    plt.colorbar()
    plt.title("residuals (image-model)")
    # fig = plt.figure(figsize=(10,5))

    im_zscale = ZScaleInterval(contrast=0.5, krej=2.5)
    im_vmin, im_vmax = im_zscale.get_limits(values=cutout["cutout"].data)

    ax4 = fig.add_subplot(234, projection=cutout["cutout"].wcs)

    plt.imshow(
        cutout["cutout"].data,
        vmin=im_vmin,
        vmax=im_vmax,
        origin="lower",
        cmap=plt.get_cmap("gray"),
        interpolation="none",
    )

    plt.text(
        0.8,
        0.9,
        cutout["instrument"] + cutout["filter"],
        transform=ax4.transAxes,
        fontsize=20,
        color="w",
    )
    plt.contour(hdu[0].data, transform=ax4.get_transform(w))
    plt.xlabel("RA")
    plt.ylabel("Dec")
    aper.plot(
        color="white", linestyle="dashed", linewidth=2, transform=ax4.get_transform(w)
    )

    ax5 = fig.add_subplot(235)
    plt.errorbar(
        dist_kpc.value,
        iso_tab["intens"],
        yerr=iso_tab["intens_err"] * iso_tab["intens"],
        linestyle="none",
        marker="o",
        label="Lya SB profile",
    )

    plt.plot(dist_kpc, s_r(dist_kpc), color="r", label="Lya exp SB model", linewidth=2)

    plt.xlabel("Semi-major axis (kpc)")
    # plt.xlabel('Semi-major axis (arcsec)')
    plt.ylabel("Flux ({})".format(10 ** -17 * (u.erg / (u.s * u.cm ** 2))))
    plt.text(0.4, 0.7, "r_n={:3.2f}".format(r_n), transform=ax5.transAxes, fontsize=16)
    plt.text(
        0.4, 0.6, "L_lya={:3.2e}".format(lum), transform=ax5.transAxes, fontsize=16
    )
    secax = ax5.secondary_xaxis("top", functions=(kpc_to_arcsec, kpc_to_arcsec))
    secax.set_xlabel("Semi-major axis (arcsec)")
    # secax.set_xlabel('Semi-major axis (kpc)')
    plt.xlim(0, 100)

    # plt.plot(sma, s_r(sma), label='moffat psf')

    # plt.plot(dist_kpc.value, s1(kpc_to_arcsec(dist_kpc.value)),
    #        linestyle='dashed', linewidth=2,
    #         color='green', label='PSF seeing:{:3.2f}'.format(fwhm))

    # These two are the exact same
    # s1 = models.Moffat1D()
    # s1.amplitude = iso_tab['intens'][0]
    # alpha=3.5
    # s1.gamma = 0.5*(fwhm*const_arcsec_to_kpc)/ np.sqrt(2 ** (1.0 / alpha) - 1.0)
    # s1.alpha = alpha
    # plt.plot(r_1d, moffat_1d, color='orange')

    #    plt.plot(dist_kpc.value, (s1(dist_kpc.value)),
    #            linestyle='dashed', linewidth=2,
    #             color='blue', label='PSF seeing:{:3.2f}'.format(fwhm))

    E = Extract()
    E.load_shot(shotid_obj)
    moffat_psf = E.moffat_psf(seeing=fwhm, boxsize=imsize, scale=pixscale)
    moffat_shape = np.shape(moffat_psf)
    xcen = int(moffat_shape[1] / 2)
    ycen = int(moffat_shape[2] / 2)
    moffat_1d = (
        moffat_psf[0, xcen:-1, ycen] / moffat_psf[0, xcen, ycen] * iso_tab["intens"][0]
    )
    r_1d = moffat_psf[1, xcen:-1, ycen]
    E.close()

    plt.plot(
        arcsec_to_kpc(pixscale * np.arange(80)),
        iso_tab["intens"][0] * (moffat_psf[0, 80:-1, 80] / moffat_psf[0, 80, 80]),
        linestyle="dashed",
        color="green",
        label="PSF seeing:{:3.2f}".format(fwhm),
    )
    plt.legend()

    if friendid is not None:
        ax6 = fig.add_subplot(236, projection=cutout["cutout"].wcs)
        plot_friends(friendid, friend_cat, cutout, ax=ax6, label=False)
    plt.savefig("fit2d_{}.png".format(name))

    # filename = 'param_{}.txt'.format(name)
    # np.savetxt(filename, (r_n.value, lum.value))

    return r_n, lum, lum_err
Example #7
0
def ellipsefit_multiband(objid, objdir, data, sample, mgefit,
                         nowrite=False, verbose=False):
    """Ellipse-fit the multiband data.

    See
    https://github.com/astropy/photutils-datasets/blob/master/notebooks/isophote/isophote_example4.ipynb

    """
    from photutils.isophote import (EllipseGeometry, Ellipse, EllipseSample,
                                    Isophote, IsophoteList)
    from photutils.isophote.sample import CentralEllipseSample
    from photutils.isophote.fitter import CentralEllipseFitter

    band, refband, pixscale = data['band'], data['refband'], data['pixscale']

    ellipsefit = dict()
    ellipsefit['success'] = False
    ellipsefit['redshift'] = sample['z']
    ellipsefit['band'] = band
    ellipsefit['refband'] = refband
    ellipsefit['pixscale'] = pixscale
    for filt in band:
        ellipsefit['psfsigma_{}'.format(filt)] = sample['psfsize_{}'.format(filt)]

    # Default parameters
    integrmode, sclip, nclip, step, fflag = 'bilinear', 3, 0, 0.1, 0.5
    #integrmode, sclip, nclip, step, fflag = 'median', 3, 0, 0.1, 0.5

    # http://photutils.readthedocs.io/en/stable/isophote_faq.html#isophote-faq
    # Note: position angle in photutils is measured counter-clockwise from the
    # x-axis, while .pa in MGE measured counter-clockwise from the y-axis.
    geometry = EllipseGeometry(x0=mgefit['xpeak'], y0=mgefit['ypeak'],
                               eps=mgefit['eps'],
                               #sma=0.5*mgefit['majoraxis'], 
                               sma=10,
                               pa=np.radians(mgefit['pa']-90))
    ellipsefit['geometry'] = geometry

    def _sky(data, ellipsefit, diameter=2.0):
        """Estimate the sky brightness in each band."""
        #area = diameter**2 # arcsec^2
        for filt in band:
            img = data['{}_masked'.format(filt)]
            #ellipsefit['{}_sky'.format(filt)] = 22.5 - 2.5 * np.log10( ma.std(img) )
            #ellipsefit['mu_{}_sky'.format(filt)] = ellipsefit['{}_sky'.format(filt)] # + 2.5 * np.log10(area)
            ellipsefit['mu_{}_sky'.format(filt)] = 22.5 - 2.5 * np.log10( ma.std(img) )

    _sky(data, ellipsefit)

    # Fit in the reference band...
    if verbose:
        print('Ellipse-fitting the reference {}-band image.'.format(refband))
        
    img = data['{}_masked'.format(refband)]
    ellipse = Ellipse(img, geometry=geometry)

    # First fit with the default parameters.
    try:
        t0 = time.time()
        with warnings.catch_warnings():
            warnings.simplefilter('ignore')
            for minsma in (10, 1, 5): # try a few different starting minor axes
                print('  Trying minimum sma = {:.1f} pixels.'.format(minsma))
                isophot = ellipse.fit_image(minsma=minsma, maxsma=1.5*mgefit['majoraxis'],
                                            integrmode=integrmode, sclip=sclip, nclip=nclip,
                                            step=step, fflag=fflag)
                if len(isophot) > 0:
                    break
        if verbose:
            print('Time = {:.3f} sec'.format( (time.time() - t0) / 1))

        if len(isophot) == 0:
            print('Ellipse-fitting failed, likely due to complex morphology or poor initial geometry.')
        else:
            ellipsefit['success'] = True
            ellipsefit[refband] = isophot

            tall = time.time()
            for filt in band:
                t0 = time.time()
                if filt == refband: # we did it already!
                    continue

                if verbose:
                    print('Ellipse-fitting {}-band image.'.format(filt))

                img = data['{}_masked'.format(filt)]

                # Loop on the reference band isophotes but skip the first isophote,
                # which is a CentralEllipseSample object (see below).
                isobandfit = []
                for iso in isophot:
                #for iso in isophot[1:]:
                    g = iso.sample.geometry # fixed geometry

                    # Use the same integration mode and clipping parameters.
                    sample = EllipseSample(img, g.sma, geometry=g, integrmode=integrmode,
                                           sclip=sclip, nclip=nclip)
                    sample.update()

                    # Create an Isophote instance with the sample.
                    isobandfit.append(Isophote(sample, 0, True, 0))

                # Now deal with the central pixel; see
                # https://github.com/astropy/photutils-datasets/blob/master/notebooks/isophote/isophote_example4.ipynb
                #import pdb ; pdb.set_trace()
                #g = EllipseGeometry(x0=geometry.x0, y0=geometry.y0, eps=mgefit['eps'], sma=1.0)
                #g.find_center(img)

                ## Use the same integration mode and clipping parameters.
                #sample = CentralEllipseSample(img, g.sma, geometry=g, integrmode=integrmode,
                #                              sclip=sclip, nclip=nclip)
                #cen = CentralEllipseFitter(sample).fit()
                #isobandfit.append(cen)
                #isobandfit.sort()

                # Build the IsophoteList instance with the result.
                ellipsefit[filt] = IsophoteList(isobandfit)
                if verbose:
                    print('Time = {:.3f} sec'.format( (time.time() - t0) / 1))

            if verbose:
                print('Time for all images = {:.3f} sec'.format( (time.time() - tall) / 1))
                
    except:
        print('Ellipse-fitting failed, likely due to too many masked pixels.')

    # Write out
    if not nowrite:
        legacyhalos.io.write_ellipsefit(objid, objdir, ellipsefit, verbose=verbose)

    return ellipsefit
Example #8
0
def get_amplitude_at_r(r, image, x0, y0, ellip, theta):
    """
    Finds the amplitude at an isophotal radius `r`.

    Parameters
    ----------

    r : float or int
        Isophotal radius in pixels.

    image : CCDData or array
        Image to of the source.

    x0, y0 : float
        The center pixel coordinate of the ellipse.

    ellip : ellipticity
        The ellipticity of the ellipse.

    theta : float
        The position angle (in radians) of the semimajor axis in
        relation to the positive x axis of the image array (rotating
        towards the positive y axis). Position angles are defined in the
        range :math:`0 < PA <= \pi`. Avoid using as starting position
        angle of 0., since the fit algorithm may not work properly.
        When the ellipses are such that position angles are near either
        extreme of the range, noise can make the solution jump back and
        forth between successive isophotes, by amounts close to 180
        degrees.

    Returns
    -------

    amplitude_at_r : float or np.nan

    """

    if isinstance(image, CCDData) or isinstance(image, Cutout2D):
        image = image.data

    r = float(r)

    try:
        # Define EllipseGeometry using ellip and theta
        g = EllipseGeometry(x0, y0, 1., ellip, theta)

        # Create Ellipse model
        ellipse = Ellipse(image, geometry=g)

        # Fit isophote at r_eff
        iso = ellipse.fit_isophote(r)

        # Get flux at r_eff
        amplitude = iso.intens

    except Exception as exception:
        import warnings
        warnings.warn("Amplitude could not be computed, returning np.nan. Exception: {}".format(str(exception)), Warning)
        amplitude = np.nan

    return amplitude
Example #9
0
def Isophote_Extract_Photutils(IMG, results, options):
    """Wrapper of photutils method for extracting SB profiles.

    This simply gives users access to the photutils isophote
    extraction methods. The one exception is that SB values are taken
    as the median instead of the mean, as recomended in the photutils
    documentation. See: `photutils
    <https://photutils.readthedocs.io/en/stable/isophote.html>`_ for
    more information.

    Parameters
    ----------
    ap_zeropoint : float, default 22.5
      Photometric zero point. For converting flux to mag units.

    ap_fluxunits : str, default "mag"
      units for outputted photometry. Can either be "mag" for log
      units, or "intensity" for linear units.
    
    ap_plot_sbprof_ylim : tuple, default None
      Tuple with axes limits for the y-axis in the SB profile
      diagnostic plot. Be careful when using intensity units
      since this will change the ideal axis limits.
    
    ap_plot_sbprof_xlim : tuple, default None
      Tuple with axes limits for the x-axis in the SB profile
      diagnostic plot.
    
    ap_plot_sbprof_set_errscale : float, default None
      Float value by which to scale errorbars on the SB profile
      this makes them more visible in cases where the statistical
      errors are very small.
    
    Notes
    ----------
    :References:
    - 'background'
    - 'background noise'
    - 'psf fwhm'
    - 'center'
    - 'init R' (optional)
    - 'init ellip' (optional)
    - 'init pa' (optional)
    - 'fit R' (optional)
    - 'fit ellip' (optional)
    - 'fit pa' (optional)
    - 'fit photutils isolist' (optional)

    Returns
    -------
    IMG : ndarray
      Unaltered galaxy image

    results : dict
      .. code-block:: python

        {'prof header': , # List object with strings giving the items in the header of the final SB profile (list)
         'prof units': , # dict object that links header strings to units (given as strings) for each variable (dict)
         'prof data': # dict object linking header strings to list objects containing the rows for a given variable (dict)

        }

    """

    zeropoint = options["ap_zeropoint"] if "ap_zeropoint" in options else 22.5
    fluxunits = options["ap_fluxunits"] if "ap_fluxunits" in options else "mag"

    if fluxunits == "intensity":
        params = [
            "R",
            "I",
            "I_e",
            "totflux",
            "totflux_e",
            "ellip",
            "ellip_e",
            "pa",
            "pa_e",
            "a3",
            "a3_e",
            "b3",
            "b3_e",
            "a4",
            "a4_e",
            "b4",
            "b4_e",
        ]
        SBprof_units = {
            "R": "arcsec",
            "I": "flux*arcsec^-2",
            "I_e": "flux*arcsec^-2",
            "totflux": "flux",
            "totflux_e": "flux",
            "ellip": "unitless",
            "ellip_e": "unitless",
            "pa": "deg",
            "pa_e": "deg",
            "a3": "unitless",
            "a3_e": "unitless",
            "b3": "unitless",
            "b3_e": "unitless",
            "a4": "unitless",
            "a4_e": "unitless",
            "b4": "unitless",
            "b4_e": "unitless",
        }
    else:
        params = [
            "R",
            "SB",
            "SB_e",
            "totmag",
            "totmag_e",
            "ellip",
            "ellip_e",
            "pa",
            "pa_e",
            "a3",
            "a3_e",
            "b3",
            "b3_e",
            "a4",
            "a4_e",
            "b4",
            "b4_e",
        ]
        SBprof_units = {
            "R": "arcsec",
            "SB": "mag*arcsec^-2",
            "SB_e": "mag*arcsec^-2",
            "totmag": "mag",
            "totmag_e": "mag",
            "ellip": "unitless",
            "ellip_e": "unitless",
            "pa": "deg",
            "pa_e": "deg",
            "a3": "unitless",
            "a3_e": "unitless",
            "b3": "unitless",
            "b3_e": "unitless",
            "a4": "unitless",
            "a4_e": "unitless",
            "b4": "unitless",
            "b4_e": "unitless",
        }
    SBprof_data = dict((h, []) for h in params)
    res = {}
    dat = IMG - results["background"]
    if not "fit R" in results and not "fit photutils isolist" in results:
        logging.info(
            "%s: photutils fitting and extracting image data" % options["ap_name"]
        )
        geo = EllipseGeometry(
            x0=results["center"]["x"],
            y0=results["center"]["y"],
            sma=results["init R"] / 2,
            eps=results["init ellip"],
            pa=results["init pa"],
        )
        ellipse = Photutils_Ellipse(dat, geometry=geo)

        isolist = ellipse.fit_image(fix_center=True, linear=False)
        res.update(
            {
                "fit photutils isolist": isolist,
                "auxfile fitlimit": "fit limit semi-major axis: %.2f pix"
                % isolist.sma[-1],
            }
        )
    elif not "fit photutils isolist" in results:
        logging.info("%s: photutils extracting image data" % options["ap_name"])
        list_iso = []
        for i in range(len(results["fit R"])):
            if results["fit R"][i] <= 0:
                continue
            # Container for ellipse geometry
            geo = EllipseGeometry(
                sma=results["fit R"][i],
                x0=results["center"]["x"],
                y0=results["center"]["y"],
                eps=results["fit ellip"][i],
                pa=results["fit pa"][i],
            )
            # Extract the isophote information
            ES = EllipseSample(dat, sma=results["fit R"][i], geometry=geo)
            ES.update(fixed_parameters=None)
            list_iso.append(Isophote(ES, niter=30, valid=True, stop_code=0))

        isolist = IsophoteList(list_iso)
        res.update(
            {
                "fit photutils isolist": isolist,
                "auxfile fitlimit": "fit limit semi-major axis: %.2f pix"
                % isolist.sma[-1],
            }
        )
    else:
        isolist = results["fit photutils isolist"]

    for i in range(len(isolist.sma)):
        SBprof_data["R"].append(isolist.sma[i] * options["ap_pixscale"])
        if fluxunits == "intensity":
            SBprof_data["I"].append(
                np.median(isolist.sample[i].values[2]) / options["ap_pixscale"] ** 2
            )
            SBprof_data["I_e"].append(isolist.int_err[i])
            SBprof_data["totflux"].append(isolist.tflux_e[i])
            SBprof_data["totflux_e"].append(isolist.rms[i] / np.sqrt(isolist.npix_e[i]))
        else:
            SBprof_data["SB"].append(
                flux_to_sb(
                    np.median(isolist.sample[i].values[2]),
                    options["ap_pixscale"],
                    zeropoint,
                )
            )
            SBprof_data["SB_e"].append(
                2.5 * isolist.int_err[i] / (isolist.intens[i] * np.log(10))
            )
            SBprof_data["totmag"].append(flux_to_mag(isolist.tflux_e[i], zeropoint))
            SBprof_data["totmag_e"].append(
                2.5
                * isolist.rms[i]
                / (np.sqrt(isolist.npix_e[i]) * isolist.tflux_e[i] * np.log(10))
            )
        SBprof_data["ellip"].append(isolist.eps[i])
        SBprof_data["ellip_e"].append(isolist.ellip_err[i])
        SBprof_data["pa"].append(isolist.pa[i] * 180 / np.pi)
        SBprof_data["pa_e"].append(isolist.pa_err[i] * 180 / np.pi)
        SBprof_data["a3"].append(isolist.a3[i])
        SBprof_data["a3_e"].append(isolist.a3_err[i])
        SBprof_data["b3"].append(isolist.b3[i])
        SBprof_data["b3_e"].append(isolist.b3_err[i])
        SBprof_data["a4"].append(isolist.a4[i])
        SBprof_data["a4_e"].append(isolist.a4_err[i])
        SBprof_data["b4"].append(isolist.b4[i])
        SBprof_data["b4_e"].append(isolist.b4_err[i])
        for k in SBprof_data.keys():
            if not np.isfinite(SBprof_data[k][-1]):
                SBprof_data[k][-1] = 99.999
    res.update(
        {"prof header": params, "prof units": SBprof_units, "prof data": SBprof_data}
    )

    if "ap_doplot" in options and options["ap_doplot"]:
        if fluxunits == "intensity":
            Plot_I_Profile(
                dat,
                np.array(SBprof_data["R"]),
                np.array(SBprof_data["I"]),
                np.array(SBprof_data["I_e"]),
                np.array(SBprof_data["ellip"]),
                np.array(SBprof_data["pa"]),
                results,
                options,
            )
        else:
            Plot_SB_Profile(
                dat,
                np.array(SBprof_data["R"]),
                np.array(SBprof_data["SB"]),
                np.array(SBprof_data["SB_e"]),
                np.array(SBprof_data["ellip"]),
                np.array(SBprof_data["pa"]),
                results,
                options,
            )

    return IMG, res
Example #10
0
import Messier33

with fits.open("/home/s1539878/data/mphys/ellipse/m33_i_mosaic.fits") as d:
    head = d[0].header
    data = d[0].data

x0 = head["CRPIX1"]
y0 = head["CRPIX2"]

#x1,y1 = np.unravel_index(np.argmax(data), data.shape)
x2, y2 = (3013, 2651)
PA = np.radians(112)
sma = 500
e = np.cos(inclination)
print(e, PA)
geometry = isophote.EllipseGeometry(x2, y2, sma, e, PA)
print(geometry.__dict__)
#aper=EllipticalAperture((x2,y2),sma, sma*(1-e), PA)
"""
fig,ax = plt.subplots(1)
plt.imshow(data)
plt.scatter(x2,y2)
aper.plot()
plt.show()
"""
ellipse = Ellipse(data, geometry, threshold=0.01)
#print(ellipse.fit_isophote(400))
isolist = ellipse.fit_image(300, 50, 2500, fix_pa=True)
print(isolist.sma)
isolist.to_table().to_pandas().to_csv("tmp")
Example #11
0
#!/usr/bin/env python

import fitsio
import numpy.ma as ma
from photutils.isophote import EllipseGeometry, Ellipse

img = fitsio.read('data/image.fits')
img = ma.masked_array(img, img == 0)

g = EllipseGeometry(x0=266, y0=266, eps=0.240, sma=110, pa=1.0558)
ell = Ellipse(img, geometry=g)
iso = ell.fit_image(3,
                    integrmode='median',
                    sclip=3,
                    nclip=2,
                    linear=False,
                    step=0.1)
Example #12
0
import numpy as np

from photutils.datasets import make_noise_image
from photutils.isophote import EllipseGeometry, Ellipse
from photutils import EllipticalAperture

g = Gaussian2D(100., 75, 75, 20, 12, theta=40. * np.pi / 180.)
ny = nx = 150
y, x = np.mgrid[0:ny, 0:nx]

noise = make_noise_image((ny, nx),
                         distribution='gaussian',
                         mean=0.,
                         stddev=2.,
                         random_state=12345)
data = g(x, y) + noise

#==========================================

geometry = EllipseGeometry(x0=75, y0=75, sma=20, eps=0.5, pa=20. * np.pi / 180)

aper = EllipticalAperture((geometry.x0, geometry.y0), geometry.sma,
                          geometry.sma * (1 - geometry.eps), geometry.pa)

plt.imshow(data, origin='lower')
aper.plot(color='white')
plt.show()

ellipse = Ellipse(data, geometry)
isolist = ellipse.fit_image()
Example #13
0
def Photutils_Fit(IMG, results, options):
    """Photutils elliptical isophote wrapper.

    This simply gives users access to the photutils isophote
    fitting method. See: `photutils
    <https://photutils.readthedocs.io/en/stable/isophote.html>`_ for
    more information.

    Notes
    ----------
    :References:
    - 'background'
    - 'center'
    - 'init R'
    - 'init ellip'
    - 'init pa'

    Returns
    -------
    IMG : ndarray
      Unaltered galaxy image

    results : dict
      .. code-block:: python

        {'fit ellip': , # array of ellipticity values (ndarray)
         'fit pa': , # array of PA values (ndarray)
         'fit R': , # array of semi-major axis values (ndarray)
         'fit ellip_err': , # optional, array of ellipticity error values (ndarray)
         'fit pa_err': , # optional, array of PA error values (ndarray)
         'auxfile fitlimit': # optional, auxfile message (string)

        }
    """

    dat = IMG - results["background"]
    geo = EllipseGeometry(
        x0=results["center"]["x"],
        y0=results["center"]["y"],
        sma=results["init R"] / 2,
        eps=results["init ellip"],
        pa=results["init pa"],
    )
    ellipse = Photutils_Ellipse(dat, geometry=geo)

    isolist = ellipse.fit_image(fix_center=True, linear=False)
    res = {
        "fit R":
        isolist.sma[1:],
        "fit ellip":
        isolist.eps[1:],
        "fit ellip_err":
        isolist.ellip_err[1:],
        "fit pa":
        isolist.pa[1:],
        "fit pa_err":
        isolist.pa_err[1:],
        "fit photutils isolist":
        isolist,
        "auxfile fitlimit":
        "fit limit semi-major axis: %.2f pix" % isolist.sma[-1],
    }

    if "ap_doplot" in options and options["ap_doplot"]:
        Plot_Isophote_Fit(
            dat,
            res["fit R"],
            res["fit ellip"],
            res["fit pa"],
            res["fit ellip_err"],
            res["fit pa_err"],
            results,
            options,
        )

    return IMG, res
Example #14
0
def burst_drift(npy, fslice=':', tslice=':'):

    #Load npy array
    burst = np.load(npy)

    #Subband in Frequency
    subfac = 16
    rb_sub = np.nanmean(R3H.reshape(-1, subfac, R3H.shape[1]), axis=1)

    rb_sub_zm = rb_sub[fslice, tslice]

    ynorm = (rb_sub_zm.sum(0) / np.max(rb_sub_zm.sum(0)))
    x = np.linspace(0, len(ynorm) - 1, len(ynorm))

    #Smooth

    sav = ss.savgol_filter(rb_sub_zm, 49, 6)

    #Calculate 2D ACF

    acf = ss.correlate(sav, sav)

    #Provide the initial Ellipse to be fitted
    #Calculate Ellipse Geometry
    geometry = EllipseGeometry(x0=acf.shape[1] / 2,
                               y0=acf.shape[0] / 2,
                               sma=20,
                               eps=0.4,
                               pa=60 * np.pi / 180.)
    #Show Initial Guess Ellipsee
    aper = EllipticalAperture((geometry.x0, geometry.y0), geometry.sma,
                              geometry.sma * (1 - geometry.eps), geometry.pa)

    #Plot Initial Guess Ellipse on ACF

    #plt.imshow(acf, aspect = 'auto')
    #aper.plot(color='white')

    #Fit Ellipse to 2D ACF

    ellipse = Ellipse(acf, geometry)
    isolist = ellipse.fit_image()
    model_image = build_ellipse_model(acf.shape, isolist)
    residual = acf - model_image

    fig = plt.figure(figsize=(40, 10))
    ax1 = fig.add_subplot(131)
    plt.gca().invert_yaxis()
    x = np.linspace(0, acf.shape[1] - 1, acf.shape[1])
    y = lambda x: (0.809) * x + 37.65

    plt.plot(x, y(x), color='white', label='Drift Rate = -33 MHz/ms')
    plt.imshow(sav, interpolation=None)
    plt.yticks(np.arange(0, sav.shape[0], 60), [1000, 900, 800, 700, 600])
    plt.xticks(np.arange(0, sav.shape[1], 48), [0, 2, 4, 6, 8, 10])
    plt.ylabel('Frequency (MHz)')
    plt.xlabel('Time (ms)')
    plt.title('Dynamic Spectrum R3H')
    plt.legend()

    ax2 = fig.add_subplot(132)

    plt.imshow(acf)  #, origin='lower')
    plt.ylabel('Frequency Shift (MHz)')
    plt.xlabel('Time Shfit (ms)')
    plt.yticks(np.arange(0, acf.shape[0], 79),
               [1000, 600, 200, 0, -200, -600, -1000])
    plt.xticks(np.arange(0, acf.shape[1], 49),
               [-10, -8, -6, -4, -3, 0, 2, 4, 6, 8, 10])

    #plt.plot(x, y(x))
    plt.title('2D ACF R3H')

    smas = np.linspace(10, 100, 8)
    for sma in smas:
        iso = isolist.get_closest(sma)
        x, y, = iso.sampled_coordinates()
        plt.plot(x, y, color='white')

    #ax3.imshow(model_image, origin='lower')
    #ax3.set_title('Ellipse Model')

    #ax3.imshow(residual, origin='lower')

    ax3 = fig.add_subplot(133)

    #plt.set_aspect('auto')
    x = np.linspace(0, len(ynorm) - 1, len(ynorm))
    plt.plot(x, ss.savgol_filter(ynorm, 19, 6))
    plt.title('Timeseries R3H')
    plt.ylabel('Normalized Intensity')
    plt.xlabel('Time (ms)')
    plt.xticks(np.arange(0, sav.shape[1], 48), [0, 2, 4, 6, 8, 10])
    #ax3.set_title('Residual')
    fig.savefig('Drift Rate R3H')
    return
Example #15
0
#The center pixel coordinates of the bulge
x0 = 98.5
y0 = 98.5
bulge_3D = abel.Transform(image,
                          direction='inverse',
                          method='three_point',
                          center=(y0, x0)).transform

#=======================
#Fitting ellipses to the 3D image in order to get its brigthness profile
#=======================

# geometry = EllipseGeometry(x0=98, y0=98, sma=15, eps=0.19, pa=(np.pi/180)*226)
geometry = EllipseGeometry(x0=98, y0=98, sma=15, eps=0.0, pa=0)

ellipse = Ellipse(bulge_3D, geometry)
isolist = ellipse.fit_image(fix_pa=True, fix_eps=True)

#========================
#Converting to mass profile
#========================

#Considering 2MASS H-band of course
magzp = 20.4107
distance = 38e+6  #pc
solar_abs_mag = 3.32
gamma = 1.0


def count2mass(image, magzp, d, solar_abs_mag, gamma):
    app_mag = magzp - (2.5 * np.log10(image))
Example #16
0
def isophote_data() :
    
    from photutils.isophote import EllipseGeometry
    from photutils import EllipticalAperture
    from photutils.isophote import Ellipse
    
    test = 'a2744/cutouts/a2744_ID_5830_f160w.fits'
    (data, dim, photfnu, R_e,
     redshift, sma, smb, pa) = open_cutout(test)
    (noise, _, _, _,
     _, _, _, _) = open_cutout('a2744/cutouts/a2744_ID_5830_f160w_noise.fits')
    plt.display_image_simple(data, cmap=cm.viridis)
    
    xlen, ylen = dim[1], dim[0]
    
    geometry = EllipseGeometry(x0=xlen/2, y0=ylen/2, sma=20, eps=0.5,
                               pa=70*np.pi/180)
    aper = EllipticalAperture((geometry.x0, geometry.y0), geometry.sma,
                               geometry.sma*(1 - geometry.eps), geometry.pa)
    
    # pyp.imshow(data, origin='lower')
    # aper.plot(color='white')
    
    ellipse = Ellipse(data, geometry)
    isolist = ellipse.fit_image()
    
    # print(isolist.tflux_e)
    
    isophotes = True
    if isophotes :
        plt.display_isophotes(data, isolist, cmap=cm.viridis)
        
        # from photutils.isophote import build_ellipse_model
        # model = build_ellipse_model(data.shape, isolist)
        # residual = data - model
        # plt.display_image_simple(residual, norm=None)
    
    annuli = True
    if annuli :
        from photutils import EllipticalAnnulus
        from photutils import aperture_photometry
        
        center = (isolist[0].x0, isolist[0].y0)
        # print(center)
        
        last = np.where(isolist.stop_code == 0)[0][-1]
        isolist = isolist[last]
        
        pa = isolist.pa
        # print(pa*180/np.pi)
        
        a_outs = np.arange(1e-5, isolist.sma, isolist.sma/11)
        b_outs = a_outs*(1-isolist.eps)
        
        for i in range(len(a_outs) - 1) :
            a_in = a_outs[i]
            a_out = a_outs[i+1]
            b_in = b_outs[i]
            b_out = b_outs[i+1]
            # print(a_in, a_out, b_in, b_out)
            aper = EllipticalAnnulus(center, a_in, a_out, b_out, b_in=b_in,
                                     theta=isolist.pa)
            phot_table = aperture_photometry(data, aper, error=noise)
            flux = phot_table['aperture_sum'][0]
            flux_err = phot_table['aperture_sum_err'][0]
            # print(flux)
            # print(flux_err)
            
            annulus_mask = aper.to_mask()
            
            annulus_data = annulus_mask.multiply(data)
            # plt.display_image_simple(annulus_data, cmap=cm.viridis, norm=None)
            # print(np.sum(annulus_data))
            
            err_table = aperture_photometry(noise, aper)
            flux_err_alt = err_table['aperture_sum'][0]
            # print(flux_err)
            
            err_data = annulus_mask.multiply(noise)
            # print(np.sum(err_data))
            
            # print(flux/flux_err)
            print(flux/flux_err_alt)
            # print()
            
    return
from photutils.isophote import EllipseGeometry, Ellipse
from photutils import EllipticalAperture

#===================================
#Reading fits file containing data to be fitted
#===================================

bulge = fits.getdata('/home/elismar/Documentos/Fisica/IC/imfit-1.7.1/ngc2992-93/images/NICMOS/n4sb08040/bulge.fits')

#===================================
#Fitting elliptical isophotes to bulge
#===================================

geometry = EllipseGeometry(x0=50, y0=65, sma=3, eps=0.1, pa=0)

ellipse = Ellipse(bulge, geometry)
isolist = ellipse.fit_image()

#===================================
#Plotting results
#===================================

fig = plt.figure()
axs = fig.add_subplot(111)
norm = plt.Normalize(-2, 10)
axs.imshow(bulge, origin='lower', norm=norm)
axs.set_title('Data')

smas = np.linspace(1, 10, 10)
for sma in smas:
    iso = isolist.get_closest(sma)