Exemple #1
0
def get_source_distribution(fwhm, uniform, sersic):
    if uniform:
        return None

    # Build the source surface brightness distribution with unity
    # integral; intrinsic is set to 1 for a point source
    intrinsic = 1. if sersic is None \
                    else source.OnSkySersic(1.0, sersic[0], sersic[1], ellipticity=sersic[2],
                                            position_angle=sersic[3], unity_integral=True)

    # Set the size of the map used to render the source
    size = fwhm * 5 if sersic is None else max(fwhm * 5, sersic[0] * 5)
    sampling = fwhm / 10 if sersic is None else min(fwhm / 10, sersic[0] / 10 /
                                                    sersic[1])

    # Check the rendering of the Sersic profile
    if sersic is not None:
        intrinsic.make_map(sampling=sampling, size=size)
        r, theta = intrinsic.semi.polar(intrinsic.X, intrinsic.Y)
        flux_ratio = 2 * numpy.sum(intrinsic.data[r < intrinsic.r_eff.value]) \
                        * numpy.square(sampling) / intrinsic.get_integral()
        if numpy.absolute(numpy.log10(flux_ratio)) > numpy.log10(1.05):
            warnings.warn(
                'Difference in expected vs. map-rendered flux is larger than '
                '5%: {0}%.'.format((flux_ratio - 1) * 100))

    # Construct the on-sky source distribution
    return source.OnSkySource(fwhm, intrinsic, sampling=sampling, size=size)
Exemple #2
0
def main():

    # Assume slit is perfectly aligned with center of object

    # TODO: Introduce wavelength dependent seeing?
    mag = 22.  # g-band magnitude
    seeing = 0.6  # arcsec
    slitwidth = 0.75  # arcsec
    slitlength = 5.  # arcsec
    slitrotation = 0.  # degrees

    # Define the slit aperture
    slit = aperture.SlitAperture(0.,
                                 0.,
                                 slitwidth,
                                 slitlength,
                                 rotation=slitrotation)

    # Sample the source at least 5 times per seeing disk FWHM
    sampling = seeing / 5
    # Set the size of the map to be the maximum of 3 seeing disks, or
    # 1.5 times the size of the slit in the cartesian coordinates.
    # First, find the width of the slit shape in x and y (including any
    # rotation).
    dslitx, dslity = numpy.diff(numpy.asarray(slit.bounds).reshape(2, -1),
                                axis=0).ravel()
    size = max(seeing * 3, 1.5 * dslitx, 1.5 * dslity)

    # Use a point source with unity integral (integral of mapped
    # profile will not necessarily be unity)
    star = source.OnSkySource(seeing, 1.0, sampling=sampling, size=size)
    print('Fraction of star flux in mapped image: {0:.3f}'.format(
        numpy.sum(star.data) * numpy.square(sampling)))

    slit_img = slit.response(star.x, star.y)
    print('Slit area: {0:.2f} (arcsec^2)'.format(slit.area))

    print('Aperture efficiency: {0:.2f}'.format(
        numpy.sum(slit_img * star.data) * numpy.square(sampling)))

    # Use a reference spectrum that's constant; units are 1e-17 erg/s/cm^2/angstrom
    wave = numpy.linspace(3000., 10000., num=7001)
    spec = spectrum.ABReferenceSpectrum(wave)
    g = efficiency.FilterResponse()
    # Rescale to a specified magnitude
    spec.rescale_magnitude(mag, band=g)
    print('Star Magnitude (AB mag): {0:.2f}'.format(spec.magnitude(g)))

    # Sky Spectrum; units are 1e-17 erg/s/cm^2/angstrom/arcsec^2
    sky = spectrum.MaunakeaSkySpectrum()
    sky_mag = sky.magnitude(g)
    print('Sky Surface Brightness (AB mag/arcsec^2): {0:.2f}'.format(sky_mag))
Exemple #3
0
def direct():

    seeing = 0.6  # arcsec
    wave_ref = 5500  # Reference wavelength in angstrom
    slitwidth = 0.75  # arcsec
    slitlength = 5.  # arcsec
    slitrotation = 0.  # degrees

    sky_spec = spectrum.MaunakeaSkySpectrum()
    #    pyplot.plot(sky_spec.wave, sky_spec.flux)
    #    pyplot.show()

    psf = source.OnSkyGaussian(seeing)

    sky_reference_flux = sky_spec.interp([wave_ref])[0]
    sky = source.OnSkySource(psf, source.OnSkyConstant(sky_reference_flux))

    slit = aperture.SlitAperture(0.,
                                 0.,
                                 slitwidth,
                                 slitlength,
                                 rotation=slitrotation)

    lowres_wfos = spectrographs.TMTWFOS(setting='lowres')
    off_slit_img = lowres_wfos.monochromatic_image(sky, slit, arm='blue')

    #    pyplot.imshow(off_slit_img, origin='lower', interpolation='nearest')
    #    pyplot.show()

    nspec, nspat = off_slit_img.shape
    #    pyplot.plot(off_slit_img[:,nspat//2])
    #    pyplot.show()

    test_twod = observe.rectilinear_twod_spectrum(
        sky_spec, off_slit_img, lowres_wfos.arms['blue'].dispscale)
    print('finished')

    pyplot.imshow(test_twod,
                  origin='lower',
                  interpolation='nearest',
                  aspect='auto')
    pyplot.show()
Exemple #4
0
def twod_spec():

    mag = 23.  # g-band AB magnitude
    seeing = 0.6  # arcsec
    wave_ref = 5500  # Reference wavelength in angstrom
    slitwidth = 0.75  # arcsec
    slitlength = 5.  # arcsec
    slitrotation = 0.  # degrees

    #    wave = numpy.linspace(3100., 10000., num=6901, dtype=float)
    #    star_spec = spectrum.ABReferenceSpectrum(wave)
    star_spec = spectrum.BlueGalaxySpectrum()

    star_spec.show()

    g = efficiency.FilterResponse()
    star_spec.rescale_magnitude(mag, band=g)

    sky_spec = spectrum.MaunakeaSkySpectrum()

    psf = source.OnSkyGaussian(seeing)
    star_reference_flux = star_spec.interp([wave_ref])[0]
    star = source.OnSkySource(psf, star_reference_flux)

    sky_reference_flux = sky_spec.interp([wave_ref])[0]
    sky = source.OnSkySource(psf, source.OnSkyConstant(sky_reference_flux))

    slit = aperture.SlitAperture(0.,
                                 0.,
                                 slitwidth,
                                 slitlength,
                                 rotation=slitrotation)

    lowres_wfos = spectrographs.TMTWFOS(setting='lowres')

    wave_lim = star_spec.wave[[0, -1]]

    arm = 'red'

    print('Building off-slit rectilinear spectrum')
    off_slit_spectrum = lowres_wfos.twod_spectrum(sky_spec,
                                                  slit,
                                                  wave_lim=wave_lim,
                                                  arm=arm,
                                                  rectilinear=True)

    #    print(numpy.median(off_slit_spectrum))
    #    pyplot.imshow(off_slit_spectrum, origin='lower', interpolation='nearest', aspect='auto',
    #                  vmax=10)
    #    pyplot.show()

    print('Building on-slit rectilinear spectrum')
    on_slit_spectrum = lowres_wfos.twod_spectrum(sky_spec,
                                                 slit,
                                                 source_distribution=star,
                                                 source_spectrum=star_spec,
                                                 wave_lim=wave_lim,
                                                 arm=arm,
                                                 rectilinear=True)
    #    pyplot.imshow(on_slit_spectrum, origin='lower', interpolation='nearest', aspect='auto',
    #                  vmax=10)
    #    pyplot.show()

    print('Writing rectilinear spectra to disk.')
    fits.HDUList([fits.PrimaryHDU(data=off_slit_spectrum)
                  ]).writeto('offslit_test.fits', overwrite=True)
    fits.HDUList([fits.PrimaryHDU(data=on_slit_spectrum)
                  ]).writeto('onslit_test.fits', overwrite=True)

    # Field coordinates in arcsec
    field_coo = numpy.array([-4., 1.2]) * 60.

    print('Building off-slit projected spectrum.')
    off_slit_projected_spectrum, spec0, spat0 \
            = lowres_wfos.twod_spectrum(sky_spec, slit, wave_lim=wave_lim, arm=arm,
                                        field_coo=field_coo)

    #    from IPython import embed
    #    embed()

    print('Building on-slit projected spectrum.')
    on_slit_projected_spectrum, spec0, spat0 \
            = lowres_wfos.twod_spectrum(sky_spec, slit, source_distribution=star,
                                        source_spectrum=star_spec, wave_lim=wave_lim, arm=arm,
                                        field_coo=field_coo)

    #    embed()
    print(on_slit_projected_spectrum.shape)

    fits.HDUList([fits.PrimaryHDU(data=off_slit_projected_spectrum)
                  ]).writeto('offslit_projected_test.fits', overwrite=True)
    fits.HDUList([fits.PrimaryHDU(data=on_slit_projected_spectrum)
                  ]).writeto('onslit_projected_test.fits', overwrite=True)
Exemple #5
0
def gal_set_image():

    seeing = 0.6  # arcsec
    wave_ref = 5500  # Reference wavelength in angstrom
    slitwidth = 0.75  # arcsec
    slitlength = 5.  # arcsec
    slitrotation = 0.  # degrees

    slit_pos_file = 'slits.db'
    if not os.path.isfile(slit_pos_file):
        slit_x = numpy.arange(-4.2 * 60 + slitlength, 4.2 * 60,
                              slitlength + slitlength * 0.2)
        nslits = slit_x.size
        slit_y = numpy.random.uniform(size=nslits) * 3 - 1.5
        mag = 23 - numpy.random.uniform(size=nslits) * 2
        z = 0.1 + numpy.random.uniform(size=nslits) * 0.4
        numpy.savetxt(slit_pos_file,
                      numpy.array([slit_x, slit_y, mag, z]).T,
                      header='{0:>7} {1:>7} {2:>5} {3:>7}'.format(
                          'SLITX', 'SLITY', 'GMAG', 'Z'),
                      fmt=['%9.2f', '%7.2f', '%5.2f', '%7.5f'])
    else:
        slit_x, slit_y, mag, z = numpy.genfromtxt(slit_pos_file).T
        nslits = slit_x.size

    nspec = 18000
    nspat = 10800
    image = {
        'blue': numpy.zeros((nspec, nspat), dtype=numpy.float32),
        'red': numpy.zeros((nspec, nspat), dtype=numpy.float32)
    }

    psf = source.OnSkyGaussian(seeing)
    g = efficiency.FilterResponse()

    sky_spec = spectrum.MaunakeaSkySpectrum()
    sky_reference_flux = sky_spec.interp([wave_ref])[0]
    sky = source.OnSkyConstant(sky_reference_flux)

    slit = aperture.SlitAperture(0.,
                                 0.,
                                 slitwidth,
                                 slitlength,
                                 rotation=slitrotation)
    lowres_wfos = spectrographs.TMTWFOS(setting='lowres')
    wave_lim = numpy.array([3100, 10000])

    gal = source.OnSkySource(psf,
                             source.OnSkySersic(1.0,
                                                0.1,
                                                1,
                                                unity_integral=True),
                             sampling=lowres_wfos.arms['blue'].pixelscale)

    #    pyplot.imshow(gal.data, origin='lower', interpolation='nearest')
    #    pyplot.show()

    for i in range(nslits):
        gal_spec = spectrum.BlueGalaxySpectrum()
        gal_spec.redshift(z[i])
        gal_spec.rescale_magnitude(mag[i], band=g)

        field_coo = numpy.array([slit_x[i], slit_y[i]])

        for arm in ['blue', 'red']:
            print('Building on-slit projected spectrum.')
            slit_spectrum, spec0, spat0 \
                    = lowres_wfos.twod_spectrum(sky_spec, slit, source_distribution=gal,
                                                source_spectrum=gal_spec, wave_lim=wave_lim,
                                                arm=arm, field_coo=field_coo)
            sspec = int(spec0) + nspec // 2
            sspat = int(spat0) + nspat // 2

            image[arm][sspec:sspec+slit_spectrum.shape[0], sspat:sspat+slit_spectrum.shape[1]] \
                    += slit_spectrum

    fits.HDUList([fits.PrimaryHDU(data=image['blue'])
                  ]).writeto('gal_set_blue.fits', overwrite=True)
    fits.HDUList([fits.PrimaryHDU(data=image['red'])
                  ]).writeto('gal_set_red.fits', overwrite=True)
Exemple #6
0
def fiddles_model(mag,
                  telescope,
                  seeing,
                  exposure_time,
                  airmass=1.0,
                  fiddles_fratio=3.,
                  fiber_diameter=0.15,
                  dmag_sky=None):

    # Use a reference spectrum that's constant; units are 1e-17 erg/s/cm^2/angstrom
    wave = numpy.linspace(3000., 10000., num=7001)
    spec = spectrum.ABReferenceSpectrum(wave)
    g = efficiency.FilterResponse()

    # Rescale to a specified magnitude
    spec.rescale_magnitude(mag, band=g)
    print('Star Magnitude (AB mag): {0:.2f}'.format(spec.magnitude(g)))

    # Sky Spectrum; units are 1e-17 erg/s/cm^2/angstrom/arcsec^2
    sky = spectrum.MaunakeaSkySpectrum()
    sky_mag = sky.magnitude(g)
    print('Sky Surface Brightness (AB mag/arcsec^2): {0:.2f}'.format(sky_mag))
    if dmag_sky is not None:
        sky_mag += dmag_sky
        sky.rescale_magnitude(sky_mag, band=g)

    # Fiddles detector
    fiddles_pixel_size = 7.4e-3  # mm
    fiddles_fullwell = 18133  # Electrons (NOT ADU!)
    fiddles_platescale = telescope.platescale * fiddles_fratio / telescope.fratio
    qe_file = os.path.join(os.environ['ENYO_DIR'], 'data', 'efficiency',
                           'detectors', 'thor_labs_monochrome_qe.db')
    fiddles_det = efficiency.Detector(
        pixelscale=fiddles_pixel_size / fiddles_platescale,
        rn=6.45,
        dark=5.,
        qe=efficiency.Efficiency.from_file(qe_file, wave_units='nm'))
    print('FIDDLES pixelscale (arcsec/pixel): {0:.3f}'.format(
        fiddles_det.pixelscale))

    # On-sky fiber diameter
    on_sky_fiber_diameter = fiber_diameter / fiddles_platescale  # arcsec
    print('On-sky fiber diameter (arcsec): {0:.2f}'.format(
        on_sky_fiber_diameter))

    # Size for the fiber image
    upsample = 1 if fiddles_det.pixelscale < seeing / 5 else int(
        fiddles_det.pixelscale / (seeing / 5)) + 1
    print('Upsampling: {0}'.format(upsample))
    sampling = fiddles_det.pixelscale / upsample
    print('Pixel sampling of maps: {0:.3f} (arcsec/pixel)'.format(sampling))
    size = (int(numpy.ceil(on_sky_fiber_diameter * 1.2 / sampling)) // upsample
            + 1) * upsample * sampling
    print('Square map size : {0:.3f} (arcsec)'.format(size))

    # Use a point source with unity integral (integral of mapped
    # profile will not necessarily be unity)
    star = source.OnSkySource(seeing, 1.0, sampling=sampling, size=size)
    print('Fraction of star flux in mapped image: {0:.3f}'.format(
        numpy.sum(star.data) * numpy.square(sampling)))
    #    pyplot.imshow(star.data, origin='lower', interpolation='nearest')
    #    pyplot.show()

    # Define fiber aperture
    fiber = aperture.FiberAperture(0.,
                                   0.,
                                   on_sky_fiber_diameter,
                                   resolution=100)
    # Generate its response function
    fiber_response = fiber.response(star.x, star.y)
    print('Fiber area (mapped): {0:.2f} (arcsec^2)'.format(
        numpy.sum(fiber_response) * numpy.square(star.sampling)))
    print('Fiber area (nominal): {0:.2f} (arcsec^2)'.format(fiber.area))

    in_fiber = numpy.sum(star.data * fiber_response) * numpy.square(
        star.sampling)
    print('Aperture loss: {0:.3f}'.format(in_fiber))

    # This would assume that the fiber does NOT scramble the light...
    #    fiber_img = star.data*fiber_response

    # Instead scale the fiber response profile to produce a uniformly
    # scrambled fiber output beam
    scale = numpy.sum(star.data * fiber_response) / numpy.sum(fiber_response)
    source_fiber_img = scale * fiber_response

    # Down-sample to the detector size
    if upsample > 1:
        source_fiber_img = util.boxcar_average(source_fiber_img, upscale)
        fiber_response = util.boxcar_average(fiber_response, upscale)

    # Scale the spectra to be erg/angstrom (per arcsec^2 for sky)
    print('Exposure time: {0:.1f} (s)'.format(exposure_time))
    spec.rescale(telescope.area * exposure_time)
    sky.rescale(telescope.area * exposure_time)

    # Convert them to photons/angstrom (per arcsec^2 for sky)
    spec.photon_flux()
    sky.photon_flux()

    # Atmospheric Extinction
    atm = efficiency.AtmosphericThroughput(airmass=airmass)

    # Fiber throughput (10-m polymicro fiber run)
    fiber_throughput = efficiency.FiberThroughput()

    # TODO: assumes no fiber FRD or coupling losses

    # Integrate spectrally to get the total number of electrons at the
    # detector accounting for the g-band filter and the detector qe.
    flux = numpy.sum(spec.flux * atm(spec.wave) * fiber_throughput(spec.wave) *
                     g(spec.wave) * fiddles_det.qe(spec.wave) *
                     spec.wavelength_step())
    print('Object flux: {0:.3f} (electrons)'.format(flux))
    sky_flux = numpy.sum(sky.flux * fiber_throughput(sky.wave) * g(sky.wave) *
                         fiddles_det.qe(sky.wave) * sky.wavelength_step())
    print('Sky flux: {0:.3f} (electrons/arcsec^2)'.format(sky_flux))
    print('Sky flux: {0:.3f} (electrons)'.format(sky_flux * fiber.area))

    # Scale the source image by the expected flux (source_fiber_img was
    # constructed assuming unity flux)
    fiber_obj_img = source_fiber_img * flux
    # Scale the fiber response function by the sky surface brightness
    # (the integral of the sky image is then just the fiber area times
    # the uniform sky surface brightness)
    fiber_sky_img = fiber_response * sky_flux

    # Integrate spatially over the pixel size to get the number of
    # electrons in each pixel
    fiber_obj_img *= numpy.square(upsample * sampling)
    fiber_sky_img *= numpy.square(upsample * sampling)

    return fiber_obj_img, fiber_sky_img, fiddles_det, sky_mag
Exemple #7
0
def onsky_aperture_snr(telescope, mag, seeing, on_sky_fiber_diameter, dmag_sky=None,
                       detector_noise_ratio=1., sampling=0.1, size=5.0, re=None, sersicn=None,
                       exptime=1., quiet=False):

    # Use a reference spectrum that's constant; units are 1e-17 erg/s/cm^2/angstrom
    wave = numpy.linspace(3000., 10000., num=7001)
    spec = spectrum.ABReferenceSpectrum(wave)
    g = efficiency.FilterResponse()
    spec.rescale_magnitude(mag, band=g)

    # Sky Spectrum; units are 1e-17 erg/s/cm^2/angstrom/arcsec^2
    sky = spectrum.MaunakeaSkySpectrum()
    sky_mag = sky.magnitude(g)
    if dmag_sky is not None:
        sky_mag += dmag_sky
        sky.rescale_magnitude(sky_mag, band=g)

#    # For the image representation of the fiber and source, use a fixed
#    # sampling
#    size = (int(numpy.ceil(on_sky_fiber_diameter*1.2/sampling))+1)*sampling

    # Build the source
    intrinsic = 1.0 if re is None or sersicn is None \
                    else source.OnSkySersic(1.0, re, sersicn, sampling=sampling, size=size,
                                            unity_integral=True)
    src = source.OnSkySource(seeing, intrinsic, sampling=sampling, size=size)
    if numpy.absolute(numpy.log10(numpy.sum(src.data*numpy.square(src.sampling)))) > 0.1:
        raise ValueError('Bad source representation; image integral is {0:.3f}.'.format(
                            numpy.sum(src.data*numpy.square(src.sampling))))
    # Define fiber aperture
    fiber = aperture.FiberAperture(0., 0., on_sky_fiber_diameter, resolution=100)
    # Generate its response function
    fiber_response = fiber.response(src.x, src.y)
    in_fiber = numpy.sum(src.data*fiber_response)*numpy.square(src.sampling)

    # Scale the fiber response profile to produce a uniformly scrambled
    # fiber output beam
    scale = numpy.sum(src.data*fiber_response)/numpy.sum(fiber_response)
    source_fiber_img = scale*fiber_response

    # Convert them to photons/angstrom (per arcsec^2 for sky)
    spec.rescale(telescope.area*exptime)
    sky.rescale(telescope.area*exptime)
    spec.photon_flux()
    sky.photon_flux()

    # Get the total number of source and sky photons at
    # the detector integrated over the g-band filter
    flux = numpy.sum(spec.flux * g(spec.wave) * spec.wavelength_step())
    sky_flux = numpy.sum(sky.flux * g(sky.wave) * sky.wavelength_step())

    # Scale the source image by the expected flux (source_fiber_img was
    # constructed assuming unity flux)
    fiber_obj_img = source_fiber_img * flux
    # Scale the fiber response function by the sky surface brightness
    # (the integral of the sky image is then just the fiber area times
    # the uniform sky surface brightness)
    fiber_sky_img = fiber_response * sky_flux

    # Integrate spatially over the pixel size to get the number of
    # photons/s/cm^2 entering the fiber
    fiber_obj_flux = numpy.sum(fiber_obj_img * numpy.square(src.sampling))
    fiber_sky_flux = numpy.sum(fiber_sky_img * numpy.square(src.sampling))

    total_flux = fiber_obj_flux + fiber_sky_flux
    sky_var = fiber_sky_flux + detector_noise_ratio*total_flux
    total_var = fiber_obj_flux + sky_var
    total_snr = fiber_obj_flux/numpy.sqrt(total_var)
    skysub_snr = fiber_obj_flux/numpy.sqrt(total_var + sky_var)

    if not quiet:
        print('Star Magnitude (AB mag): {0:.2f}'.format(spec.magnitude(g)))
        print('Sky Surface Brightness (AB mag/arcsec^2): {0:.2f}'.format(sky_mag))
        print('On-sky fiber diameter (arcsec): {0:.2f}'.format(on_sky_fiber_diameter))
        print('Pixel sampling of maps: {0:.3f} (arcsec/pixel)'.format(sampling))
        print('Square map size : {0:.3f} (arcsec)'.format(size))
        print('Fraction of source flux in mapped image: {0:.3f}'.format(numpy.sum(src.data)
                                                                * numpy.square(sampling)))
        print('Fiber area (mapped): {0:.2f} (arcsec^2)'.format(numpy.sum(fiber_response)
                                                                * numpy.square(src.sampling)))
        print('Fiber area (nominal): {0:.2f} (arcsec^2)'.format(fiber.area))
        print('Aperture loss: {0:.3f}'.format(in_fiber))
        print('Object flux: {0:.3e} (g-band photons/s)'.format(fiber_obj_flux))
        print('Sky flux: {0:.3e} (g-band photons/s)'.format(fiber_sky_flux))
        print('Total S/N: {0:.3f}'.format(total_snr))
        print('Sky-subtracted S/N: {0:.3f}'.format(skysub_snr))

#    return fiber_obj_flux, fiber_sky_flux, total_snr, skysub_snr
    return total_snr, skysub_snr