示例#1
0
def _ecliptic_obliquity(epoch):
    # Routine to return the obliquity of the ecliptic for a given date.
    # We need to figure out the time in Julian centuries from J2000 for this epoch.
    t = (epoch - 2000.) / 100.
    # Then we use the last (most recent) formula listed under
    # http://en.wikipedia.org/wiki/Ecliptic#Obliquity_of_the_ecliptic, from
    # JPL's 2010 calculations.
    ep = galsim.DMS_Angle('23:26:21.406')
    ep -= galsim.DMS_Angle('00:00:46.836769') * t
    ep -= galsim.DMS_Angle('00:00:0.0001831') * (t**2)
    ep += galsim.DMS_Angle('00:00:0.0020034') * (t**3)
    # There are even higher order terms, but they are really not important for any reasonable
    # calculation we could ever do with GalSim.
    return ep
示例#2
0
def read_image_header(row, img_file):
    """Read some information from the image header and write into the df row.
    """
    hdu = 0

    # Note: The next line usually works, but fitsio doesn't support CONTINUE lines, which DES
    #       image headers sometimes include.
    #h = fitsio.read_header(img_file, hdu)
    # I don't  care about any of the lines the sometimes use CONITNUE (e.g. OBSERVER), so I
    # just remove them and make the header with the rest of the entries.
    f = fitsio.FITS(img_file)
    header_list = f[hdu].read_header_list()
    header_list = [ d for d in header_list if 'CONTINUE' not in d['name'] ]
    h = fitsio.FITSHDR(header_list)
    try:
        date = h['DATE-OBS']
        date, time = date.strip().split('T',1)

        filter = h['FILTER']
        filter = filter.split()[0]

        sat = h['SATURATE']
        fwhm = h['FWHM']

        ccdnum = int(h['CCDNUM'])
        detpos = h['DETPOS'].strip()

        telra = h['TELRA']
        teldec = h['TELDEC']
        telha = h['HA']
        if galsim.__version__ >= '1.5.1':
            telra = galsim.Angle.from_hms(telra) / galsim.degrees
            teldec = galsim.Angle.from_dms(teldec) / galsim.degrees
            telha = galsim.Angle.from_hms(telha) / galsim.degrees
        else:
            telra = galsim.HMS_Angle(telra) / galsim.degrees
            teldec = galsim.DMS_Angle(teldec) / galsim.degrees
            telha = galsim.HMS_Angle(telha) / galsim.degrees

        airmass = float(h.get('AIRMASS',-999))
        sky = float(h.get('SKYBRITE',-999))
        sigsky = float(h.get('SKYSIGMA',-999))

        tiling = int(h.get('TILING',0))
        hex = int(h.get('HEX',0))

    except Exception as e:
        logger.info("Caught %s",e)
        logger.info("Cannot read header information from %s", img_file)
        raise

    row['date'] = date
    row['time'] = time
    row['sat'] = sat
    row['fits_filter'] = filter
    row['fits_fwhm'] = fwhm
    row['fits_ccdnum'] = ccdnum
    row['telra'] = telra
    row['teldec'] = teldec
    row['telha'] = telha
    row['airmass'] = airmass
    row['sky'] = sky
    row['sigsky'] = sigsky
    row['tiling'] = tiling
    row['hex'] = hex
示例#3
0
def main(argv):
    # Where to find and output data
    path, filename = os.path.split(__file__)
    datapath = os.path.abspath(os.path.join(path, "data/"))
    outpath = os.path.abspath(os.path.join(path, "output/"))

    # In non-script code, use getLogger(__name__) at module scope instead.
    logging.basicConfig(format="%(message)s",
                        level=logging.INFO,
                        stream=sys.stdout)
    logger = logging.getLogger("demo12")

    # initialize (pseudo-)random number generator
    random_seed = 1234567
    rng = galsim.BaseDeviate(random_seed)

    # read in SEDs
    SED_names = ['CWW_E_ext', 'CWW_Sbc_ext', 'CWW_Scd_ext', 'CWW_Im_ext']
    SEDs = {}
    for SED_name in SED_names:
        SED_filename = os.path.join(galsim.meta_data.share_dir,
                                    '{0}.sed'.format(SED_name))
        # Here we create some galsim.SED objects to hold star or galaxy spectra.  The most
        # convenient way to create realistic spectra is to read them in from a two-column ASCII
        # file, where the first column is wavelength and the second column is flux. Wavelengths in
        # the example SED files are in Angstroms, flux in flambda.  We use a set of files that are
        # distributed with GalSim in the share/ directory.
        SED = galsim.SED(SED_filename, wave_type='Ang', flux_type='flambda')
        # The normalization of SEDs affects how many photons are eventually drawn into an image.
        # One way to control this normalization is to specify the flux density in photons per nm
        # at a particular wavelength.  For example, here we normalize such that the photon density
        # is 1 photon per nm at 500 nm.
        SEDs[SED_name] = SED.withFluxDensity(target_flux_density=1.0,
                                             wavelength=500)
    logger.debug('Successfully read in SEDs')

    # read in the LSST filters
    filter_names = 'ugrizy'
    filters = {}
    for filter_name in filter_names:
        filter_filename = os.path.join(datapath,
                                       'LSST_{0}.dat'.format(filter_name))
        # Here we create some galsim.Bandpass objects to represent the filters we're observing
        # through.  These include the entire imaging system throughput including the atmosphere,
        # reflective and refractive optics, filters, and the CCD quantum efficiency.  These are
        # also conveniently read in from two-column ASCII files where the first column is
        # wavelength and the second column is dimensionless throughput. The example filter files
        # units of nanometers for the wavelength type, so we specify that using the required
        # `wave_type` argument.
        filters[filter_name] = galsim.Bandpass(filter_filename, wave_type='nm')
        # For speed, we can thin out the wavelength sampling of the filter a bit.
        # In the following line, `rel_err` specifies the relative error when integrating over just
        # the filter (however, this is not necessarily the relative error when integrating over the
        # filter times an SED).
        filters[filter_name] = filters[filter_name].thin(rel_err=1e-4)
    logger.debug('Read in filters')

    pixel_scale = 0.2  # arcseconds

    #-----------------------------------------------------------------------------------------------
    # Part A: chromatic de Vaucouleurs galaxy

    # Here we create a chromatic version of a de Vaucouleurs profile using the Chromatic class.
    # This class lets one create chromatic versions of any galsim GSObject class.  The first
    # argument is the GSObject instance to be chromaticized, and the second argument is the
    # profile's SED.

    logger.info('')
    logger.info('Starting part A: chromatic De Vaucouleurs galaxy')
    redshift = 0.8
    mono_gal = galsim.DeVaucouleurs(half_light_radius=0.5)
    SED = SEDs['CWW_E_ext'].atRedshift(redshift)
    gal = galsim.Chromatic(mono_gal, SED)

    # You can still shear, shift, and dilate the resulting chromatic object.
    gal = gal.shear(g1=0.5, g2=0.3).dilate(1.05).shift((0.0, 0.1))
    logger.debug('Created Chromatic')

    # convolve with PSF to make final profile
    PSF = galsim.Moffat(fwhm=0.6, beta=2.5)
    final = galsim.Convolve([gal, PSF])
    logger.debug('Created final profile')

    # draw profile through LSST filters
    gaussian_noise = galsim.GaussianNoise(rng, sigma=0.1)
    for filter_name, filter_ in filters.iteritems():
        img = galsim.ImageF(64, 64, scale=pixel_scale)
        final.drawImage(filter_, image=img)
        img.addNoise(gaussian_noise)
        logger.debug('Created {0}-band image'.format(filter_name))
        out_filename = os.path.join(outpath,
                                    'demo12a_{0}.fits'.format(filter_name))
        galsim.fits.write(img, out_filename)
        logger.debug('Wrote {0}-band image to disk'.format(filter_name))
        logger.info('Added flux for {0}-band image: {1}'.format(
            filter_name, img.added_flux))

    logger.info(
        'You can display the output in ds9 with a command line that looks something like:'
    )
    logger.info(
        'ds9 output/demo12a_*.fits -match scale -zoom 2 -match frame image &')

    #-----------------------------------------------------------------------------------------------
    # Part B: chromatic bulge+disk galaxy

    logger.info('')
    logger.info('Starting part B: chromatic bulge+disk galaxy')
    redshift = 0.8
    # make a bulge ...
    mono_bulge = galsim.DeVaucouleurs(half_light_radius=0.5)
    bulge_SED = SEDs['CWW_E_ext'].atRedshift(redshift)
    # The `*` operator can be used as a shortcut for creating a chromatic version of a GSObject:
    bulge = mono_bulge * bulge_SED
    bulge = bulge.shear(g1=0.12, g2=0.07)
    logger.debug('Created bulge component')
    # ... and a disk ...
    mono_disk = galsim.Exponential(half_light_radius=2.0)
    disk_SED = SEDs['CWW_Im_ext'].atRedshift(redshift)
    disk = mono_disk * disk_SED
    disk = disk.shear(g1=0.4, g2=0.2)
    logger.debug('Created disk component')
    # ... and then combine them.
    bdgal = 1.1 * (
        0.8 * bulge + 4 * disk
    )  # you can add and multiply ChromaticObjects just like GSObjects
    bdfinal = galsim.Convolve([bdgal, PSF])
    # Note that at this stage, our galaxy is chromatic but our PSF is still achromatic.  Part C)
    # below will dive into chromatic PSFs.
    logger.debug('Created bulge+disk galaxy final profile')

    # draw profile through LSST filters
    gaussian_noise = galsim.GaussianNoise(rng, sigma=0.02)
    for filter_name, filter_ in filters.iteritems():
        img = galsim.ImageF(64, 64, scale=pixel_scale)
        bdfinal.drawImage(filter_, image=img)
        img.addNoise(gaussian_noise)
        logger.debug('Created {0}-band image'.format(filter_name))
        out_filename = os.path.join(outpath,
                                    'demo12b_{0}.fits'.format(filter_name))
        galsim.fits.write(img, out_filename)
        logger.debug('Wrote {0}-band image to disk'.format(filter_name))
        logger.info('Added flux for {0}-band image: {1}'.format(
            filter_name, img.added_flux))

    logger.info(
        'You can display the output in ds9 with a command line that looks something like:'
    )
    logger.info(
        'ds9 -rgb -blue -scale limits -0.2 0.8 output/demo12b_r.fits -green -scale limits'
        +
        ' -0.25 1.0 output/demo12b_i.fits -red -scale limits -0.25 1.0 output/demo12b_z.fits'
        + ' -zoom 2 &')

    #-----------------------------------------------------------------------------------------------
    # Part C: chromatic PSF

    logger.info('')
    logger.info('Starting part C: chromatic PSF')
    redshift = 0.0
    mono_gal = galsim.Exponential(half_light_radius=0.5)
    SED = SEDs['CWW_Im_ext'].atRedshift(redshift)
    # Here's another way to set the normalization of the SED.  If we want 50 counts to be drawn
    # when observing an object with this SED through the LSST g-band filter, for instance, then we
    # can do:
    SED = SED.withFlux(50.0, filters['g'])
    # The flux drawn through other bands, which sample different parts of the SED and have different
    # throughputs, will, of course, be different.
    gal = mono_gal * SED
    gal = gal.shear(g1=0.5, g2=0.3)
    logger.debug('Created `Chromatic` galaxy')

    # For a ground-based PSF, two chromatic effects are introduced by the atmosphere:
    # (i) differential chromatic refraction (DCR), and (ii) wavelength-dependent seeing.
    #
    # DCR shifts the position of the PSF as a function of wavelength.  Blue light is shifted
    # toward the zenith slightly more than red light.
    #
    # Kolmogorov turbulence in the atmosphere leads to a seeing size (e.g., FWHM) that scales with
    # wavelength to the (-0.2) power.
    #
    # The ChromaticAtmosphere function will attach both of these effects to a fiducial PSF at
    # some fiducial wavelength.

    # First we define a monochromatic PSF to be the fiducial PSF.
    PSF_500 = galsim.Moffat(beta=2.5, fwhm=0.5)
    # Then we use ChromaticAtmosphere to manipulate this fiducial PSF as a function of wavelength.
    # ChromaticAtmosphere also needs to know the wavelength of the fiducial PSF, and the location
    # and orientation of the object with respect to the zenith.  This final piece of information
    # can be specified in several ways (see the ChromaticAtmosphere docstring for all of them).
    # Here are a couple ways: let's pretend our object is located near M101 on the sky, we observe
    # it 1 hour before it transits and we're observing from Mauna Kea.
    ra = galsim.HMS_Angle("14:03:13")  # hours : minutes : seconds
    dec = galsim.DMS_Angle("54:20:57")  # degrees : minutes : seconds
    m101 = galsim.CelestialCoord(ra, dec)
    latitude = 19.8207 * galsim.degrees  # latitude of Mauna Kea
    HA = -1.0 * galsim.hours  # Hour angle = one hour before transit

    # Then we can compute the zenith angle and parallactic angle (which is is the position angle
    # of the zenith measured from North through East) of this object:
    za, pa = galsim.dcr.zenith_parallactic_angles(m101,
                                                  HA=HA,
                                                  latitude=latitude)
    # And then finally, create the chromatic PSF
    PSF = galsim.ChromaticAtmosphere(PSF_500,
                                     500.0,
                                     zenith_angle=za,
                                     parallactic_angle=pa)
    # We could have also just passed `m101`, `latitude` and `HA` to ChromaticAtmosphere directly:
    PSF = galsim.ChromaticAtmosphere(PSF_500,
                                     500.0,
                                     obj_coord=m101,
                                     latitude=latitude,
                                     HA=HA)
    # and proceed like normal.

    # convolve with galaxy to create final profile
    final = galsim.Convolve([gal, PSF])
    logger.debug('Created chromatic PSF finale profile')

    # Draw profile through LSST filters
    gaussian_noise = galsim.GaussianNoise(rng, sigma=0.03)
    for filter_name, filter_ in filters.iteritems():
        img = galsim.ImageF(64, 64, scale=pixel_scale)
        final.drawImage(filter_, image=img)
        img.addNoise(gaussian_noise)
        logger.debug('Created {0}-band image'.format(filter_name))
        out_filename = os.path.join(outpath,
                                    'demo12c_{0}.fits'.format(filter_name))
        galsim.fits.write(img, out_filename)
        logger.debug('Wrote {0}-band image to disk'.format(filter_name))
        logger.info('Added flux for {0}-band image: {1}'.format(
            filter_name, img.added_flux))

    logger.info(
        'You can display the output in ds9 with a command line that looks something like:'
    )
    logger.info(
        'ds9 output/demo12c_*.fits -match scale -zoom 2 -match frame image -blink &'
    )
示例#4
0
def setup_wcs(config, ndim, nu_axis=False):

    pixel_scale = config.getfloat('skymodel', 'pixel_scale') * galsim.arcsec
    fov = config.getfloat('skymodel', 'field_of_view') * galsim.arcmin
    image_size = int((fov / galsim.arcmin) / (pixel_scale / galsim.arcmin))

    ra_field = config.get('field', 'field_ra')
    ra_field_gs = galsim.HMS_Angle(ra_field)
    dec_field = config.get('field', 'field_dec')
    dec_field_gs = galsim.DMS_Angle(dec_field)

    n_ifs = config.getint('observation', 'n_IFs')
    bw = config.getfloat('observation', 'total_bandwidth')
    base_freq = config.getfloat('observation', 'lowest_frequency')
    n_chan = config.getint('observation', 'n_channels')
    msname = config.get('pipeline', 'project_name') + '.ms'
    msname = config.get('pipeline', 'data_path') + msname
    imagename = msname + '.image'

    channel_width = bw / (n_chan * n_ifs)
    if_width = bw / n_ifs

    w = wcs.WCS(naxis=ndim)
    if ndim == 4:
        if nu_axis:
            '''
      w.wcs.naxis = [float(image_size),
                     float(image_size),
                     1,
                     n_chan*n_ifs]
      '''
            w.wcs.crpix = [float(image_size) / 2, float(image_size) / 2, 1, 1]
            w.wcs.cdelt = [
                pixel_scale / galsim.degrees, pixel_scale / galsim.degrees, bw,
                1
            ]
            w.wcs.crval = [
                ra_field_gs / galsim.degrees, dec_field_gs / galsim.degrees,
                base_freq + bw / 2, 1
            ]
            w.wcs.ctype = ['RA---SIN', 'DEC--SIN', 'FREQ', 'STOKES']
            w.wcs.cunit = ['deg', 'deg', 'Hz', '']

        else:
            '''
      w.wcs.naxis = [float(image_size),
                     float(image_size),
                     1,
                     1]
      '''
            w.wcs.crpix = [float(image_size) / 2, float(image_size) / 2, 1, 1]
            w.wcs.cdelt = [
                pixel_scale / galsim.degrees, pixel_scale / galsim.degrees, bw,
                1
            ]
            w.wcs.crval = [
                ra_field_gs / galsim.degrees, dec_field_gs / galsim.degrees,
                base_freq + bw / 2, 1
            ]
            w.wcs.ctype = ['RA---SIN', 'DEC--SIN', 'FREQ', 'STOKES']
            w.wcs.cunit = ['deg', 'deg', 'Hz', '']
    elif ndim == 2:
        w.wcs.crpix = [float(image_size) / 2, float(image_size) / 2]
        w.wcs.cdelt = [
            pixel_scale / galsim.degrees, pixel_scale / galsim.degrees
        ]
        w.wcs.crval = [
            ra_field_gs / galsim.degrees, dec_field_gs / galsim.degrees
        ]
        w.wcs.ctype = ['RA---SIN', 'DEC--SIN']
        w.wcs.cunit = ['deg', 'deg']

    return w
示例#5
0
def test_ecliptic():
    """Test the conversion from equatorial to ecliptic coordinates."""
    # Use locations of ecliptic poles from http://en.wikipedia.org/wiki/Ecliptic_pole
    north_pole = galsim.CelestialCoord(galsim.HMS_Angle('18:00:00.00'),
                                       galsim.DMS_Angle('66:33:38.55'))
    el, b = north_pole.ecliptic()
    # North pole should have b=90 degrees, with el being completely arbitrary.
    numpy.testing.assert_almost_equal(b.rad(), pi / 2, decimal=6)

    south_pole = galsim.CelestialCoord(galsim.HMS_Angle('06:00:00.00'),
                                       galsim.DMS_Angle('-66:33:38.55'))
    el, b = south_pole.ecliptic()
    # South pole should have b=-90 degrees, with el being completely arbitrary.
    numpy.testing.assert_almost_equal(b.rad(), -pi / 2, decimal=6)

    # Also confirm that positions that should be the same in equatorial and ecliptic coordinates are
    # actually the same:
    vernal_equinox = galsim.CelestialCoord(0. * galsim.radians,
                                           0. * galsim.radians)
    el, b = vernal_equinox.ecliptic()
    numpy.testing.assert_almost_equal(b.rad(), 0., decimal=6)
    numpy.testing.assert_almost_equal(el.rad(), 0., decimal=6)
    autumnal_equinox = galsim.CelestialCoord(pi * galsim.radians,
                                             0. * galsim.radians)
    el, b = autumnal_equinox.ecliptic()
    numpy.testing.assert_almost_equal(el.rad(), pi, decimal=6)
    numpy.testing.assert_almost_equal(b.rad(), 0., decimal=6)

    # Finally, test the results of using a date to get ecliptic coordinates with respect to the sun,
    # instead of absolute ones. For this, use dates and times of vernal and autumnal equinox
    # in 2014 from
    # http://wwp.greenwichmeantime.com/longest-day/
    # and the conversion to Julian dates from
    # http://www.aavso.org/jd-calculator
    import datetime
    vernal_eq_date = datetime.datetime(2014, 3, 20, 16, 57, 0)
    el, b = vernal_equinox.ecliptic(epoch=2014)
    el_rel, b_rel = vernal_equinox.ecliptic(epoch=2014, date=vernal_eq_date)
    # Vernal equinox: should have (el, b) = (el_rel, b_rel) = 0.0
    numpy.testing.assert_almost_equal(el_rel.rad(), el.rad(), decimal=3)
    numpy.testing.assert_almost_equal(b_rel.rad(), b.rad(), decimal=6)
    # Now do the autumnal equinox: should have (el, b) = (pi, 0) = (el_rel, b_rel) when we look at
    # the time of the vernal equinox.
    el, b = autumnal_equinox.ecliptic(epoch=2014)
    el_rel, b_rel = autumnal_equinox.ecliptic(epoch=2014, date=vernal_eq_date)
    numpy.testing.assert_almost_equal(el_rel.rad(), el.rad(), decimal=3)
    numpy.testing.assert_almost_equal(b_rel.rad(), b.rad(), decimal=6)
    # And check that if it's the date of the autumnal equinox (sun at (180, 0)) but we're looking at
    # the position of the vernal equinox (0, 0), then (el_rel, b_rel) = (-180, 0)
    autumnal_eq_date = datetime.datetime(2014, 9, 23, 2, 29, 0)
    el_rel, b_rel = vernal_equinox.ecliptic(epoch=2014, date=autumnal_eq_date)
    numpy.testing.assert_almost_equal(el_rel.rad(), -pi, decimal=3)
    numpy.testing.assert_almost_equal(b_rel.rad(), 0., decimal=6)
    # And check that if it's the date of the vernal equinox (sun at (0, 0)) but we're looking at
    # the position of the autumnal equinox (180, 0), then (el_rel, b_rel) = (180, 0)
    el_rel, b_rel = autumnal_equinox.ecliptic(epoch=2014, date=vernal_eq_date)
    numpy.testing.assert_almost_equal(el_rel.rad(), pi, decimal=3)
    numpy.testing.assert_almost_equal(b_rel.rad(), 0., decimal=6)

    # Check round-trips: go from CelestialCoord to ecliptic back to equatorial, and make sure
    # results are the same.  This includes use of a function that isn't available to users, but we
    # use it for a few things so we should still make sure it's working properly.
    from galsim.celestial import _ecliptic_to_equatorial
    north_pole_2 = _ecliptic_to_equatorial(north_pole.ecliptic(epoch=2014),
                                           2014)
    numpy.testing.assert_almost_equal(north_pole.ra.rad(),
                                      north_pole_2.ra.rad(),
                                      decimal=6)
    numpy.testing.assert_almost_equal(north_pole.dec.rad(),
                                      north_pole_2.dec.rad(),
                                      decimal=6)
    south_pole_2 = _ecliptic_to_equatorial(south_pole.ecliptic(epoch=2014),
                                           2014)
    numpy.testing.assert_almost_equal(south_pole.ra.rad(),
                                      south_pole_2.ra.rad(),
                                      decimal=6)
    numpy.testing.assert_almost_equal(south_pole.dec.rad(),
                                      south_pole_2.dec.rad(),
                                      decimal=6)
    vernal_equinox_2 = _ecliptic_to_equatorial(
        vernal_equinox.ecliptic(epoch=2014), 2014)
    numpy.testing.assert_almost_equal(vernal_equinox.ra.rad(),
                                      vernal_equinox_2.ra.rad(),
                                      decimal=6)
    numpy.testing.assert_almost_equal(vernal_equinox.dec.rad(),
                                      vernal_equinox_2.dec.rad(),
                                      decimal=6)
    autumnal_equinox_2 = _ecliptic_to_equatorial(
        autumnal_equinox.ecliptic(epoch=2014), 2014)
    numpy.testing.assert_almost_equal(autumnal_equinox.ra.rad(),
                                      autumnal_equinox_2.ra.rad(),
                                      decimal=6)
    numpy.testing.assert_almost_equal(autumnal_equinox.dec.rad(),
                                      autumnal_equinox_2.dec.rad(),
                                      decimal=6)

# In[4]:

#define the components of galaxies

sed1 = galsim.SED(spec="wave",wave_type='nm',flux_type='fphotons')
sed1 = sed1.withFlux(gal1_flux_thru_r,filters['r'])

sed2 = galsim.SED(spec="300-wave",wave_type = 'nm',flux_type = 'fphotons')
sed2 = sed1.withFlux(gal2_flux_thru_r,filters['r'])

gal1 = galsim.Gaussian(flux=1.,sigma=gal1_sigma)
psf1 = galsim.Moffat(beta=2.5,fwhm=0.5)
ra = galsim.HMS_Angle("14:03:13")
dec = galsim.DMS_Angle("54:20:57")
m101 = galsim.CelestialCoord(ra,dec)
latitude = 19.8207*galsim.degrees
HA=-1.0*galsim.hours
za,pa = galsim.dcr.zenith_parallactic_angles(m101,HA=HA,latitude=latitude)
chrom_psf1 = galsim.ChromaticAtmosphere(psf1,500.,obj_coord=m101,latitude=latitude,HA=HA)


gal2 = galsim.Gaussian(flux=1.,sigma=gal2_sigma)
psf2 = galsim.Gaussian(flux=1.,sigma = psf2_sigma)
ra = galsim.HMS_Angle("14:13:13")
dec = galsim.DMS_Angle("54:50:57")
rand_thing_next_to_m101 = galsim.CelestialCoord(ra,dec)
latitude_seoul = 37.5665*galsim.degrees #seoul
za,pa = galsim.dcr.zenith_parallactic_angles(rand_thing_next_to_m101,HA=HA,latitude=latitude)
chrom_psf2 = galsim.ChromaticAtmosphere(psf2,500.,obj_coord=rand_thing_next_to_m101,latitude=latitude_seoul,HA=HA)
示例#7
0
def runSkyModel(config):
    # image properties
    data_path = config.get('pipeline', 'data_path')
    pixel_scale = config.getfloat('skymodel', 'pixel_scale') * galsim.arcsec
    fov = config.getfloat('skymodel', 'field_of_view') * galsim.arcmin
    image_size = int((fov / galsim.arcmin) / (pixel_scale / galsim.arcmin))

    ra_field = config.get('field', 'field_ra')
    ra_field_gs = galsim.HMS_Angle(ra_field)
    dec_field = config.get('field', 'field_dec')
    dec_field_gs = galsim.DMS_Angle(dec_field)

    cat_file_name = config.get('field', 'catalogue')
    print('Loading catalogue from {0} ...'.format(cat_file_name))
    cat = fits.getdata(cat_file_name)
    nobj = len(cat)

    cat_wcs = ast_wcs.WCS(naxis=2)
    cat_wcs.wcs.crpix = [image_size / 2, image_size / 2]
    cat_wcs.wcs.cdelt = [
        pixel_scale / galsim.degrees, pixel_scale / galsim.degrees
    ]
    cat_wcs.wcs.crval = [0.e0, 0.e0]
    cat_wcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']

    gal_ra = cat['latitude']
    gal_dec = cat['longitude']
    gal_e1 = cat['e1']
    gal_e2 = cat['e2']
    gal_flux = cat['I1400']  #mjy
    gal_r0 = cat['size'] / 2.
    g1 = 0
    g2 = 0
    print('...done.')

    full_image = galsim.ImageF(image_size, image_size, scale=pixel_scale)
    im_center = full_image.bounds.trueCenter()
    sky_center = galsim.CelestialCoord(ra=ra_field_gs, dec=dec_field_gs)

    # - on dx's since the ra axis is flipped.
    dudx = -pixel_scale / galsim.arcsec
    dudy = 0.
    dvdx = 0.
    dvdy = pixel_scale / galsim.arcsec
    image_center = full_image.trueCenter()
    affine = galsim.AffineTransform(dudx,
                                    dudy,
                                    dvdx,
                                    dvdy,
                                    origin=full_image.trueCenter())
    wcs = galsim.TanWCS(affine, sky_center, units=galsim.arcsec)
    full_image.wcs = wcs

    tstart = time.time()

    nobj = 200

    for i in range(nobj):

        sys.stdout.write('\rAdding source {0} of {1} to skymodel...'.format(
            i + 1, nobj))

        gal = galsim.Exponential(scale_radius=gal_r0[i], flux=gal_flux[i])

        ellipticity = galsim.Shear(e1=gal_e1[i], e2=gal_e2[i])
        shear = galsim.Shear(g1=g1[i], g2=g2[i])
        total_shear = ellipticity + shear

        gal = gal.shear(total_shear)

        x, y = cat_wcs.wcs_world2pix(gal_ra[i], gal_dec[i], 0)
        x = float(x)
        y = float(y)

        # Account for the fractional part of the position:
        ix = int(np.floor(x + 0.5))
        iy = int(np.floor(y + 0.5))
        offset = galsim.PositionD(x - ix, y - iy)

        stamp = gal.drawImage(scale=pixel_scale / galsim.arcsec, offset=offset)
        stamp.setCenter(ix, iy)

        bounds = stamp.bounds & full_image.bounds
        full_image[bounds] += stamp[bounds]
        sys.stdout.flush()

    tend = time.time()
    print('\n...done in {0} seconds.'.format(tend - tstart))
    all_gals_fname = data_path + config.get('field', 'fitsname')
    print('Writing image data to {0} ...'.format(all_gals_fname))
    image_data = full_image.array
    write4dImage(all_gals_fname,
                 image_data,
                 pixel_scale / galsim.degrees,
                 obs_ra=ra_field_gs / galsim.degrees,
                 obs_dec=dec_field_gs / galsim.degrees,
                 obs_freq=config.getfloat('observation', 'lowest_frequency'))
    print('...done.')

    print('runSkyModel complete.')
示例#8
0
def runSkyModel(config):
  '''Simulate a sky model from a T-RECS catalogue.

  Parameters
  ----------
  config : configparser
    ConfigParser configuration containing necessary sections.

  '''
  data_path = config.get('pipeline', 'data_path')

  # Set some image properties
  pixel_scale = config.getfloat('skymodel', 'pixel_scale')*galsim.arcsec
  fov = config.getfloat('skymodel', 'field_of_view')*galsim.arcmin
  image_size = int((fov/galsim.arcmin)/(pixel_scale/galsim.arcmin))

  ra_field = config.get('field', 'field_ra')
  ra_field_gs = galsim.HMS_Angle(ra_field)
  dec_field = config.get('field', 'field_dec')
  dec_field_gs = galsim.DMS_Angle(dec_field)
  
  w_twod = setup_wcs(config, ndim=2)
  w_fourd = setup_wcs(config, ndim=4)
  header_twod = w_twod.to_header()
  header_fourd = w_fourd.to_header()
  
  # Load the catalogue
  cat_file_name = config.get('field', 'catalogue')
  print('Loading catalogue from {0} ...'.format(cat_file_name))
  cat = Table()
  if config.get('skymodel', 'catalogue_origin') == 'trecs':
    cat_read =  Table.read(cat_file_name, format='ascii')
    
    cat['ra_offset'] = cat_read['lon'] # deg
    cat['ra_offset'].unit = 'deg'
    
    cat['dec_offset'] = cat_read['lat'] # deg
    cat['dec_offset'].unit = 'deg'

    
    cat['dec_abs'] = dec_field_gs / galsim.degrees + cat['dec_offset']
    dec_abs_radians = cat['dec_abs']*galsim.degrees / galsim.radians
    cat['ra_abs'] = ra_field_gs / galsim.degrees + cat['ra_offset']/np.cos(np.asarray(dec_abs_radians, dtype=float))

    cat['integrated_flux'] = cat_read['flux']*1.e-3 # Jy
    cat['integrated_flux'].unit = 'Jy'

    cat['size'] = cat_read['size'] # arcsec
    cat['size'].unit = 'arcsec'

    cat['peak_flux'] = cat['integrated_flux'] / (2.*cat['size']*arcsectorad)
    cat['peak_flux'].unit = 'Jy'

    cat['e1'] = cat_read['e1']
    cat['e2'] = cat_read['e2']

    cat['g1'] = cat_read['gamma1'] # 0
    cat['g2'] = cat_read['gamma2'] # 0

  elif config.get('skymodel', 'catalogue_origin') == 'pybdsm':
    cat_read =  Table.read(cat_file_name, format='fits')

    cat['ra_abs'] = cat_read['RA'] # deg
    cat['dec_abs'] = cat_read['DEC'] # deg

    cat['dec_offset'] = cat['dec_abs'] - dec_field_gs / galsim.degrees
    dec_abs_radians = cat['dec_abs']*galsim.degrees / galsim.radians
    cat['ra_offset'] = (cat['ra_abs'] - ra_field_gs / galsim.degrees)*np.cos(np.asarray(dec_abs_radians, dtype=float))
    
    cat['integrated_flux'] = cat_read['Total_flux'] # Jy

    cat['size'] = cat_read['Maj']*degtoarcsec # deg
    cat['size'].unit = 'arcsec'

    cat['peak_flux'] = cat_read['Peak_flux'] # Jy

    cat['q'] = cat_read['Min']/cat_read['Maj']
    cat['position_angle'] = np.arctan2(cat_read['Min'], cat_read['Maj'])
    cat['mod_e'] = (1. - cat['q']**2.)/(1. + cat['q']**2.)

    cat['e1'] = cat['mod_e']*np.cos(2.*cat['position_angle'])
    cat['e2'] = cat['mod_e']*np.sin(2.*cat['position_angle'])

    cat['g1'] = 0.e0
    cat['g2'] = 0.e0

  # fov cut
  ra_offset_max = 0.9*(fov/2) / galsim.degrees
  dec_offset_max = 0.9*(fov/2) / galsim.degrees
  
  fov_cut = (abs(cat['ra_offset']) < ra_offset_max)*(abs(cat['dec_offset']) < dec_offset_max)
  cat = cat[fov_cut]
  
  # flux cuts
  if config.getboolean('skymodel', 'highfluxcut'):
    highflux_cut = cat['peak_flux'] < config.getfloat('skymodel', 'highfluxcut_value')
    cat = cat[highflux_cut]
  
  if config.getboolean('skymodel', 'lowfluxcut'):
    lowflux_cut = cat['peak_flux'] > config.getfloat('skymodel', 'lowfluxcut_value')
    cat = cat[lowflux_cut]
  
  if config.getboolean('skymodel', 'highsizecut'):
    highsize_cut = cat['size'] < config.getfloat('skymodel', 'highsizecut_value')
    cat = cat[highsize_cut]
  
  if config.getboolean('skymodel', 'lowsizecut'):
    lowsize_cut = cat['size'] > config.getfloat('skymodel', 'lowsizecut_value')
    cat = cat[lowsize_cut]
    
  if config.get('skymodel', 'sizescale')=='constant':
    cat['size'] = np.ones_like(cat['size'])*config.getfloat('skymodel', 'sizescale_constant_value')

  # number of sources, on grid if requested
  if config.getboolean('skymodel', 'grid'):
    nobj = int(np.sqrt(config.getint('skymodel', 'ngals')))**2.
    cat['ra_offset'] = np.linspace(-ra_offset_max, ra_offset_max, nobj)
    cat['dec_offset'] = np.linspace(-ra_offset_max, ra_offset_max, nobj)
  else:
    nobj = len(cat)
    if config.getint('skymodel', 'ngals') > -1:
      nobj = config.getint('skymodel', 'ngals')
      cat = cat[:nobj]
  
  # flux range
  if config.get('skymodel', 'fluxscale')=='constant':
    cat['integrated_flux'] = np.ones_like(cat['integrated_flux'])*config.getfloat('skymodel', 'fluxscale_constant_value')
    cat['peak_flux'] = cat['integrated_flux'] / (2.*cat['size']*arcsectorad)
    
  # scale flux
  cat['integrated_flux'] = cat['integrated_flux']*config.getfloat('skymodel', 'flux_factor')
  cat['peak_flux'] = cat['peak_flux']*config.getfloat('skymodel', 'flux_factor')
  
  # write out catalogue
  cat.write(config.get('pipeline', 'data_path')+config.get('pipeline', 'project_name')+'_truthcat.txt', format='ascii')
  
  ix_arr = np.ones(nobj)
  iy_arr = np.ones(nobj)
  print('...done.')
  
  # Create the galsim image
  full_image = galsim.ImageF(image_size, image_size, scale=pixel_scale/galsim.arcsec)
  im_center = full_image.bounds.trueCenter()
  sky_center = galsim.CelestialCoord(ra=ra_field_gs, dec=dec_field_gs)

  # Create a WCS for the galsim image
  full_image.wcs, origin = galsim.wcs.readFromFitsHeader(header_twod)

  tstart=time.time()
  
  # Draw the galaxies onto the galsim image
  for i,cat_gal in enumerate(cat):
    
    sys.stdout.write('\rAdding source {0} of {1} to skymodel...'.format(i+1, nobj))
    
    # choose the profile
    if config.get('skymodel', 'galaxy_profile')=='exponential':
      gal = galsim.Exponential(scale_radius=cat_gal['size']/2., flux=cat_gal['integrated_flux'], gsparams=big_fft_params)
    
    elif config.get('skymodel', 'galaxy_profile')=='gaussian':
      gal = galsim.Gaussian(fwhm=cat_gal['size'], flux=cat_gal['integrated_flux'], gsparams=big_fft_params)
    
    elif config.get('skymodel', 'galaxy_profile')=='matched-exponential':
      gauss_gal = galsim.Gaussian(fwhm=cat_gal['size'], flux=cat_gal['integrated_flux'])
      gal = galsim.Exponential(half_light_radius=gauss_gal.getHalfLightRadius(), flux=cat_gal['integrated_flux'], gsparams=big_fft_params)
      del gauss_gal

    # calculate the total ellipticity
    ellipticity = galsim.Shear(e1=cat_gal['e1'],e2=cat_gal['e2'])
    shear = galsim.Shear(g1=cat_gal['g1'],g2=cat_gal['g2'])
    if config.getboolean('skymodel', 'doshear'):
      total_shear = ellipticity + shear
    else:
      total_shear = ellipticity

    gal = gal.shear(total_shear)
    
    x, y = w_twod.wcs_world2pix(cat_gal['ra_abs'], cat_gal['dec_abs'], 0,)
    x = float(x)
    y = float(y)
    
    # Account for the fractional part of the position:
    ix = int(np.floor(x+0.5))
    iy = int(np.floor(y+0.5))
    ix_arr[i] = ix
    iy_arr[i] = iy
    offset = galsim.PositionD(x-ix, y-iy)
    
    # Create the sub-image for this galaxy
    stamp = gal.drawImage(scale=pixel_scale/galsim.arcsec, offset=offset)
    stamp.setCenter(ix, iy)
    
    # Add the sub-image to the full iamge
    bounds = stamp.bounds & full_image.bounds
    full_image[bounds] += stamp[bounds]
    sys.stdout.flush()
  
  if config.getboolean('skymodel', 'doagn'):
    # Load the catalogue
    cat_file_name = config.get('field', 'agncatalogue')
    print('Loading catalogue from {0} ...'.format(cat_file_name))
    cat =  Table.read(cat_file_name, format='ascii')

    ra_offset = cat['lon(deg)']
    dec_offset = cat['lat(deg)']
    
    ra_offset_max = 0.9*(fov/2) / galsim.degrees
    dec_offset_max = 0.9*(fov/2) / galsim.degrees
    
    fov_cut = (abs(ra_offset) < ra_offset_max)*(abs(dec_offset) < dec_offset_max)
    #pdb.set_trace()
    cat = cat[fov_cut]
    
    if config.getboolean('skymodel', 'highfluxcut'):
      highflux_cut = cat['flux(mJy)']*1.e-3 < 100.e-6
      cat = cat[highflux_cut]
    if config.getboolean('skymodel', 'lowfluxcut'):
      lowflux_cut = cat['flux(mJy)']*1.e-3 > 25.e-6
      cat = cat[lowflux_cut]
    if config.getboolean('skymodel', 'highsizecut'):
      highsize_cut = cat['size(arcsec)']/2. < 10
      cat = cat[highsize_cut]
    if config.getboolean('skymodel', 'lowsizecut'):
      lowsize_cut = cat['size(arcsec)']/2. > 0.75
      cat = cat[lowsize_cut]
    
    if config.getboolean('skymodel', 'grid'):
      nobj = int(np.sqrt(config.getint('skymodel', 'ngals')))**2.
      
      gal_ra_offset = np.linspace(-ra_offset_max, ra_offset_max, nobj)
      gal_dec_offset = np.linspace(-ra_offset_max, ra_offset_max, nobj)
    else:
      gal_ra_offset = cat['lon(deg)']
      gal_dec_offset = cat['lat(deg)']
      nobj = len(cat)
      if config.getint('skymodel', 'ngals') > -1:
        nobj = config.getint('skymodel', 'ngals')
    
    gal_dec = dec_field_gs / galsim.degrees + gal_dec_offset
    gal_dec_radians = (gal_dec*galsim.degrees) / galsim.radians
    gal_ra = ra_field_gs / galsim.degrees + gal_ra_offset/np.cos(np.asarray(gal_dec_radians, dtype=float))
    
    gal_e1 = cat['e1']
    gal_e2 = cat['e2']
    gal_flux = cat['flux(mJy)']*1.e-3 #mjy convert to Jy
    gal_size = cat['size(arcsec)']/(2.)
    g1 = cat['gamma1']
    g2 = cat['gamma2']
    rs = cat['Rs']
    
    if config.get('skymodel', 'fluxscale')=='constant':
      gal_flux = np.ones_like(gal_flux)*100e-6
    
    ra_abs, dec_abs = w_twod.wcs_world2pix(gal_ra, gal_dec, 0,)
    truthcat = np.column_stack([gal_ra, gal_dec, ra_abs, dec_abs, gal_e1, gal_e2, gal_flux, gal_size, g1, g2])
    np.savetxt(config.get('pipeline', 'data_path')+config.get('pipeline', 'project_name')+'-agn_truthcat.txt', truthcat[:nobj])
    
    ix_arr = np.ones(nobj)
    iy_arr = np.ones(nobj)
    posang = random.uniform(0,2.*np.pi, nobj)
    print('...done.')
    
    # Draw the galaxies onto the galsim image
    for i in range(nobj):
    
      sys.stdout.write('\rAdding agn source {0} of {1} to skymodel...'.format(i+1, nobj))
      
      if (rs[i] < 0.01) or (cat_gal['size'] < config.getfloat('skymodel', 'pixel_scale')/2):
        x, y = w_twod.wcs_world2pix(cat_gal['ra_abs'], cat_gal['dec_abs'], 0,)
        x = float(x)
        y = float(y)
        
        # Account for the fractional part of the position:
        ix = int(np.floor(x+0.5))
        iy = int(np.floor(y+0.5))
        ix_arr[i] = ix
        iy_arr[i] = iy
        offset = galsim.PositionD(x-ix, y-iy)
        
        # Create the sub-image for this galaxy
        stamp = gal.drawImage(scale=pixel_scale/galsim.arcsec, offset=offset)
        stamp.setCenter(ix, iy)
        
        cen = stamp.array.shape
        # Add the hotspots as single pixel point sources
        stamp.array[cen[0]/2, cen[1]/2] += cat_gal['integrated_flux']
        
        # Add the sub-image to the full iamge
        bounds = stamp.bounds & full_image.bounds
        full_image[bounds] += stamp[bounds]
      
      else:
        lobe_flux = cat_gal['integrated_flux']*0.99
        hs_flux = cat_gal['integrated_flux'] - lobe_flux
        hs1_flux = hs_flux/3.
        hs2_flux = hs_flux/3.
        hs3_flux = hs_flux/3.
              
        hs_offset = rs[i]*cat_gal['size']
        lobe_offset = cat_gal['size']*0.6
        
        lobe1 = galsim.Gaussian(sigma=cat_gal['size']*0.25, flux=lobe_flux/2., gsparams=big_fft_params)
        lobe2 = galsim.Gaussian(sigma=cat_gal['size']*0.25, flux=lobe_flux/2., gsparams=big_fft_params)

        lobe1 = lobe1.shear(e1=0.3,e2=0)
        lobe2 = lobe2.shear(e1=0.3,e2=0)

        lobe1 = lobe1.shift(-lobe_offset,0)
        lobe2 = lobe2.shift(lobe_offset,0)

        gal = lobe1 + lobe2

        gal = gal.rotate(posang[i]*galsim.radians)      

        total_shear = galsim.Shear(g1=cat_gal['g1'], g2=cat_gal['g2'])      
              
        gal = gal.shear(total_shear)
        
        x, y = w_twod.wcs_world2pix(cat_gal['ra_abs'], cat_gal['dec_abs'], 0,)
        x = float(x)
        y = float(y)
        
        # Account for the fractional part of the position:
        ix = int(np.floor(x+0.5))
        iy = int(np.floor(y+0.5))
        ix_arr[i] = ix
        iy_arr[i] = iy
        offset = galsim.PositionD(x-ix, y-iy)
        hs_offset_pixels = hs_offset*pixel_scale/galsim.arcsec
        hs_ix_offset = hs_offset*np.sin(posang[i]) / (pixel_scale/galsim.arcsec)
        hs_iy_offset = hs_offset*np.cos(posang[i]) / (pixel_scale/galsim.arcsec)
        
        # Create the sub-image for this galaxy
        stamp = gal.drawImage(scale=pixel_scale/galsim.arcsec, offset=offset)
        stamp.setCenter(ix, iy)
        
        cen = stamp.array.shape
        # Add the hotspots as single pixel point sources
        stamp.array[cen[0]/2, cen[1]/2] += hs1_flux
        stamp.array[cen[0]/2+hs_ix_offset, cen[1]/2+hs_iy_offset] += hs2_flux
        stamp.array[cen[0]/2-hs_ix_offset, cen[1]/2-hs_iy_offset] += hs3_flux
        
        if config.getboolean('skymodel', 'pickleagn'):
          pickle.dump(stamp.array, open('agn_{0}.p'.format(i), 'wb'))
        
        # Add the sub-image to the full iamge
        bounds = stamp.bounds & full_image.bounds
        full_image[bounds] += stamp[bounds]
      
      sys.stdout.flush()
  
  tend = time.time()
  print('\n...done in {0} seconds.'.format(tend-tstart))
  all_gals_fname = data_path+config.get('field', 'fitsname')
  print('Writing image data to {0} ...'.format(all_gals_fname))

  # Extract the numpy array from the galsim image
  image_data = full_image.array

  # Write out the image with the 4D FITS header correct for e.g. casa simulation
  #write4dImage(all_gals_fname, image_data,
  #             pixel_scale / galsim.degrees,
  #             obs_ra=ra_field_gs / galsim.degrees,
  #             obs_dec=dec_field_gs / galsim.degrees,
  #             obs_freq=config.getfloat('observation', 'lowest_frequency'))
  
  if config.getboolean('primarybeam', 'dopb'):
    
    nstokes = config.getint('primarybeam', 'nstokes')
    nfreq = config.getint('primarybeam', 'nfreq')
    bw = config.getfloat('observation', 'total_bandwidth')
    base_freq = config.getfloat('observation', 'lowest_frequency')
    freq_width = bw / nfreq
  
    image_cube = np.empty((nstokes,nfreq)+image_data.shape)    
        
    stokes_list = ['I', 'Q', 'U'][:nstokes]
    freq_list = base_freq + np.arange(nfreq)*freq_width
    
    for i_stokes, stokes in enumerate(stokes_list):
      for i_freq, freq in enumerate(freq_list):
        image_cube[i_stokes,i_freq] = image_data*primary_beam(config, freq)

    hdu = fits.PrimaryHDU(image_cube, header=header_fourd)

  else:
    hdu = fits.PrimaryHDU(np.expand_dims(np.expand_dims(image_data, axis=0), axis=0), header=header_fourd)
  
  hdulist = fits.HDUList([hdu])
  hdulist.writeto(all_gals_fname, clobber=True)
  
  print('...done.')
  
  if config.getboolean('skymodel', 'im3cat'):
    np.savetxt(config.get('pipeline', 'data_path')+config.get('pipeline', 'project_name')+'_im3cat.txt', np.column_stack([np.arange(nobj), ix_arr, iy_arr]))
    
  # Write out the image with the 4D FITS header correct for e.g. casa simulation
  write4dImage(all_gals_fname, image_data,
              pixel_scale / galsim.degrees,
               obs_ra=ra_field_gs / galsim.degrees,
               obs_dec=dec_field_gs / galsim.degrees,
               obs_freq=config.getfloat('observation', 'lowest_frequency'))
  
  print('runSkyModel complete.')
示例#9
0
def runSkyModel(config):
  '''Simulate a sky model from a T-RECS catalogue.

  Parameters
  ----------
  config : configparser
    ConfigParser configuration containing necessary sections.

  '''

  data_path = config.get('pipeline', 'data_path')

  # Set some image properties
  pixel_scale = config.getfloat('skymodel', 'pixel_scale')*galsim.arcsec
  fov = config.getfloat('skymodel', 'field_of_view')*galsim.arcmin
  image_size = int((fov/galsim.arcmin)/(pixel_scale/galsim.arcmin))

  ra_field = config.get('field', 'field_ra')
  ra_field_gs = galsim.HMS_Angle(ra_field)
  dec_field = config.get('field', 'field_dec')
  dec_field_gs = galsim.DMS_Angle(dec_field)
  
  # Load the catalogue
  cat_file_name = config.get('field', 'catalogue')
  print('Loading catalogue from {0} ...'.format(cat_file_name))
  cat =  fits.getdata(cat_file_name)

  
  # Set up a WCS for the catalogue
  cat_wcs = ast_wcs.WCS(naxis=2)
  cat_wcs.wcs.crpix = [image_size/2, image_size/2]
  cat_wcs.wcs.cdelt = [pixel_scale/galsim.degrees, pixel_scale/galsim.degrees]
  cat_wcs.wcs.crval = [0.e0, 0.e0]
  cat_wcs.wcs.ctype = ['RA---TAN', 'DEC--TAN']
  
  cat_fov_max = float(fov/galsim.arcmin)/(2.*60.) # cat is generated on 1 degsq
  fov_cut = (abs(cat['latitude']) < cat_fov_max)*(abs(cat['longitude']) < cat_fov_max)
  
  #pdb.set_trace()
  
  cat = cat[fov_cut]
  if config.getboolean('skymodel', 'highfluxcut'):
    highflux_cut = cat['I1400']*1.e-3 < 500.e-6
    cat = cat[highflux_cut]
  if config.getboolean('skymodel', 'lowfluxcut'):
    lowflux_cut = cat['I1400']*1.e-3 > 25.e-6
    cat = cat[lowflux_cut]
  if config.getboolean('skymodel', 'highsizecut'):
    highsize_cut = cat['size']/2. < 10
    cat = cat[highsize_cut]
  if config.getboolean('skymodel', 'lowsizecut'):
    lowsize_cut = cat['size']/2. > 0.75
    cat = cat[lowsize_cut]
  
  gal_ra = cat['latitude']
  gal_dec = cat['longitude']
  gal_e1 = cat['e1']
  gal_e2 = cat['e2']
  gal_flux = cat['I1400']*1.e-3 #mjy convert to Jy
  gal_r0 = cat['size']/2.# ????? Factor of 2?
  g1 = 0
  g2 = 0
  
  if config.get('skymodel', 'fluxscale')=='constant':
    gal_flux = np.ones_like(gal_flux)*100e-6
  
  nobj = len(cat)
  if config.getint('skymodel', 'ngals') > -1:
    nobj = config.getint('skymodel', 'ngals')
  
  ix_arr = np.ones(nobj)
  iy_arr = np.ones(nobj)
  print('...done.')
  
  # Create the galsim image
  full_image = galsim.ImageF(image_size, image_size, scale=pixel_scale)
  im_center = full_image.bounds.trueCenter()
  sky_center = galsim.CelestialCoord(ra=ra_field_gs, dec=dec_field_gs)

  # Create a WCS for the galsim image
  dudx = -pixel_scale / galsim.arcsec # - on dx's since the ra axis is flipped.
  dudy = 0.
  dvdx = 0.
  dvdy = pixel_scale / galsim.arcsec
  image_center = full_image.trueCenter()
  affine = galsim.AffineTransform(dudx, dudy, dvdx, dvdy, origin=full_image.trueCenter())
  wcs = galsim.TanWCS(affine, sky_center, units=galsim.arcsec)
  full_image.wcs = wcs

  tstart=time.time()
  
  # Draw the galaxies onto the galsim image
  for i in range(nobj):
  
    sys.stdout.write('\rAdding source {0} of {1} to skymodel...'.format(i+1, nobj))
    
    gal = galsim.Exponential(scale_radius=gal_r0[i], flux=gal_flux[i])

    ellipticity = galsim.Shear(e1=gal_e1[i],e2=gal_e2[i])
    shear = galsim.Shear(g1=g1[i],g2=g2[i])
    total_shear = ellipticity + shear

    gal = gal.shear(total_shear)
    
    x, y = cat_wcs.wcs_world2pix(gal_ra[i], gal_dec[i], 0)
    x = float(x)
    y = float(y)
    
    # Account for the fractional part of the position:
    ix = int(np.floor(x+0.5))
    iy = int(np.floor(y+0.5))
    ix_arr[i] = ix
    iy_arr[i] = iy
    offset = galsim.PositionD(x-ix, y-iy)
    
    # Create the sub-image for this galaxy
    stamp = gal.drawImage(scale=pixel_scale/galsim.arcsec, offset=offset)
    stamp.setCenter(ix, iy)
    
    # Add the sub-image to the full iamge
    bounds = stamp.bounds & full_image.bounds
    full_image[bounds] += stamp[bounds]
    sys.stdout.flush()
  
  tend = time.time()
  print('\n...done in {0} seconds.'.format(tend-tstart))
  all_gals_fname = data_path+config.get('field', 'fitsname')
  print('Writing image data to {0} ...'.format(all_gals_fname))

  # Extract the numpy array from the galsim image
  image_data = full_image.array

  # Write out the image with the 4D FITS header correct for e.g. casa simulation
  write4dImage(all_gals_fname, image_data,
               pixel_scale / galsim.degrees,
               obs_ra=ra_field_gs / galsim.degrees,
               obs_dec=dec_field_gs / galsim.degrees,
               obs_freq=config.getfloat('observation', 'lowest_frequency'))
  print('...done.')
  
  if config.getboolean('skymodel', 'im3cat'):
    np.savetxt(config.get('pipeline', 'data_path')+'im3cat.txt', np.column_stack([np.arange(nobj), ix_arr, iy_arr]))
  
  print('runSkyModel complete.')
示例#10
0
def makeThumbnails(config):

    # read in catalogue
    # extract thumbnails at all points in catalogue

    data_path = config.get('pipeline', 'data_path')

    # Set some image properties
    pixel_scale = config.getfloat('skymodel', 'pixel_scale') * galsim.arcsec
    fov = config.getfloat('skymodel', 'field_of_view') * galsim.arcmin
    image_size = int((fov / galsim.arcmin) / (pixel_scale / galsim.arcmin))

    ra_field = config.get('field', 'field_ra')
    ra_field_gs = galsim.HMS_Angle(ra_field)
    dec_field = config.get('field', 'field_dec')
    dec_field_gs = galsim.DMS_Angle(dec_field)

    # Load the wcs
    header = fits.getheader(
        config.get('pipeline', 'data_path') + config.get('field', 'fitsname'))
    w_twod = ast_wcs.WCS(header)

    # Load the catalogue
    cat_file_name = config.get('field', 'catalogue')
    print('Loading catalogue from {0} ...'.format(cat_file_name))
    cat = fits.getdata(cat_file_name)
    ra_offset = cat['longitude']
    dec_offset = cat['latitude']

    ra_offset_max = 0.9 * (fov / 2) / galsim.degrees
    dec_offset_max = 0.9 * (fov / 2) / galsim.degrees

    fov_cut = (abs(ra_offset) < ra_offset_max) * (abs(dec_offset) <
                                                  dec_offset_max)
    #pdb.set_trace()
    cat = cat[fov_cut]

    if config.getboolean('skymodel', 'highfluxcut'):
        highflux_cut = cat['I1400'] * 1.e-3 < 500.e-6
        cat = cat[highflux_cut]
    if config.getboolean('skymodel', 'lowfluxcut'):
        lowflux_cut = cat['I1400'] * 1.e-3 > 25.e-6
        cat = cat[lowflux_cut]
    if config.getboolean('skymodel', 'highsizecut'):
        highsize_cut = cat['size'] / 2. < 10
        cat = cat[highsize_cut]
    if config.getboolean('skymodel', 'lowsizecut'):
        lowsize_cut = cat['size'] / 2. > 0.75
        cat = cat[lowsize_cut]

    gal_ra_offset = cat[' longitude']
    gal_dec_offset = cat['latitude']

    gal_dec = dec_field_gs / galsim.degrees + gal_dec_offset
    gal_dec_radians = (gal_dec * galsim.degrees) / galsim.radians
    gal_ra = ra_field_gs / galsim.degrees + gal_ra_offset / np.cos(
        np.asarray(gal_dec_radians, dtype=float))

    gal_e1 = cat['e1']
    gal_e2 = cat['e2']
    gal_flux = cat['I1400'] * 1.e-3  #mjy convert to Jy
    gal_r0 = cat['size'] / 2.  # ????? Factor of 2?
    g1 = 0
    g2 = 0

    if config.get('skymodel', 'fluxscale') == 'constant':
        gal_flux = np.ones_like(gal_flux) * np.median(gal_flux) * 1.e4

    nobj = len(cat)
    if config.getint('skymodel', 'ngals') > 0:
        nobj = config.getint('skymodel', 'ngals')

    print('...done.')

    #pdb.set_trace()

    for i in range(nobj):

        plt.close('all')

        sys.stdout.write(
            '\rCreating thumbnail for source {0} of {1}...'.format(
                i + 1, nobj))

        npix_stamp = 10 * int((gal_r0[i]) / (pixel_scale / galsim.arcsec))
        x, y, _, _ = w_twod.wcs_world2pix(gal_ra[i], gal_dec[i], 0, 0, 0)
        x = float(x)
        y = float(y)

        # Account for the fractional part of the position:
        ix = int(np.floor(x + 0.5))
        iy = int(np.floor(y + 0.5))

        plt.figure(i, figsize=(9, 7.5))

        plt.subplot(221)
        im = fits.getdata(
            config.get('pipeline', 'data_path') +
            config.get('field', 'fitsname'))
        im = im[0, 0]

        stamp = im[iy - npix_stamp / 2:iy + npix_stamp / 2,
                   ix - npix_stamp / 2:ix + npix_stamp / 2]
        plt.imshow(stamp,
                   cmap='afmhot',
                   origin='lower',
                   interpolation='nearest')

        plt.subplot(222)
        im = fits.getdata(
            config.get('pipeline', 'data_path') +
            config.get('pipeline', 'project_name') + '.wsclean-dirty.fits')

        im = im[0, 0, :, ::-1]
        stamp = im[iy - npix_stamp / 2:iy + npix_stamp / 2,
                   ix - npix_stamp / 2:ix + npix_stamp / 2]
        plt.imshow(stamp,
                   cmap='afmhot',
                   origin='lower',
                   interpolation='nearest')
        #pdb.set_trace()
        plt.subplot(223)
        if config.get('imager', 'type') == 'wsclean':
            im = fits.getdata(config.get('pipeline', 'data_path')+\
                      config.get('pipeline', 'project_name')+'.wsclean-image.fits')
            im = im[0, 0, :, ::-1]
        elif config.get('imager', 'type') == 'casa':
            im = fits.getdata(config.get('pipeline', 'data_path')+\
                      config.get('pipeline', 'project_name')+'.casa-cs.image.fits')
            im = im[0, 0, :, ::-1]
            size_diff = im.shape[0] - image_size
            im = im[size_diff / 2:-size_diff / 2, size_diff / 2:-size_diff / 2]

        stamp = im[iy - npix_stamp / 2:iy + npix_stamp / 2,
                   ix - npix_stamp / 2:ix + npix_stamp / 2]
        plt.imshow(stamp,
                   cmap='afmhot',
                   origin='lower',
                   interpolation='nearest')
        plt.subplot(224)
        if config.get('imager', 'type') == 'wsclean':
            im = fits.getdata(config.get('pipeline', 'data_path')+\
                      config.get('pipeline', 'project_name')+'.wsclean-model.fits')
            im = im[0, 0, :, ::-1]
        elif config.get('imager', 'type') == 'casa':
            im = fits.getdata(config.get('pipeline', 'data_path')+\
                      config.get('pipeline', 'project_name')+'.casa-cs.model.fits')
            im = im[0, 0, :, ::-1]
            size_diff = im.shape[0] - image_size
            im = im[size_diff / 2:-size_diff / 2, size_diff / 2:-size_diff / 2]

        stamp = im[iy - npix_stamp / 2:iy + npix_stamp / 2,
                   ix - npix_stamp / 2:ix + npix_stamp / 2]
        plt.imshow(stamp,
                   cmap='afmhot',
                   origin='lower',
                   interpolation='nearest')
        plt.savefig(config.get('pipeline', 'data_path') +
                    config.get('pipeline', 'project_name') +
                    'source_{0}.png'.format(i),
                    bbox_inches='tight',
                    dpi=160)

        sys.stdout.flush()

    print('\n...done.')
示例#11
0
def read_image_header(img_file):
    """Read some information from the image header.

    Returns (date, time, filter, ccdnum, detpos, telra, teldec, ha, 
             airmass, sky, sigsky, fwhm, tiling, hex, wcs)
    """
    print 'Start read_image_header'
    print img_file
    import galsim
    import astropy.io.fits as pyfits

    if img_file.endswith('fz'):
        hdu = 1
    else:
        hdu = 0

    # fitsio is a bit faster here.  11 sec/exp rather than 12, so not a huge difference, but still.
    with pyfits.open(img_file) as pyf:
        #print pyf
        #print pyf[hdu]
        h = pyf[hdu].header
        #h = pyf[hdu].read_header()
        #print 'opened'
        # DATE-OBS looks like '2012-12-03T07:38:54.174780', so split on T.
        date = h['DATE-OBS']
        date, time = date.strip().split('T', 1)

        # FILTER looks like 'z DECam SDSS c0004 9260.0 1520.0', so split on white space
        filter = h['FILTER']
        filter = filter.split()[0]

        # CCDNUM is 1-62.  DETPOS is a string such as 'S29     '.  Strip off the whitespace.
        ccdnum = h['CCDNUM']
        ccdnum = int(ccdnum)
        detpos = h['DETPOS']
        detpos = detpos.strip()
        #print 'detpos = ',detpos

        # TELRA, TELDEC look like '-62:30:22.320'.  Use GalSim to convert to decimal degrees.
        telra = h['TELRA']
        teldec = h['TELDEC']
        telra = galsim.HMS_Angle(telra) / galsim.degrees
        teldec = galsim.DMS_Angle(teldec) / galsim.degrees
        #print 'telra, teldec = ',telra,teldec

        # HA looks like '03:12:02.70''.  Use GalSim to convert to decimal degrees.
        ha = h['HA']
        ha = galsim.HMS_Angle(ha) / galsim.degrees

        # A few more items to grab from the header, but allow default values for these:
        airmass = float(h.get('AIRMASS', -999))
        sky = float(h.get('SKYBRITE', -999))
        sigsky = float(h.get('SKYSIGMA', -999))
        fwhm = float(h.get('FWHM', -999))

        tiling = int(h.get('TILING', 0))
        hex = int(h.get('HEX', 0))

        # Use Galsim to read WCS
        wcs = galsim.FitsWCS(header=h)
        #print 'wcs = ',wcs

    return (date, time, filter, ccdnum, detpos, telra, teldec, ha, airmass,
            sky, sigsky, fwhm, tiling, hex, wcs)
示例#12
0
    def setPointing(self, logger=None):
        """Set the pointing attribute based on the input ra, dec (given in the initializer)

        There are a number of ways the pointing can be specified.
        Even this is probably not sufficiently generic for all applications, but it's a start.

        1. numerical values (in Hours, Degrees respective) for ra, dec
        2. hh:mm:ss.ssss, dd:mm:ss.ssss strings giving hours/degrees, minutes, seconds for each
        3. FITS header key words to read to get the ra, dec values
        4. None, which will attempt to find the spatial center of all the input images using the
           midpoint of the min/max ra and dec values of the image corners according to their
           individual WCS functions. [Not implemented currently.]
        """
        import fitsio
        import galsim

        ra = self.ra
        dec = self.dec
        if (ra is None) != (dec is None):
            raise ValueError("Only one of ra, dec was specified")

        if ra is None:
            if self.images[0].wcs.isCelestial():
                if len(self.images) == 1:
                    # Here we can just use the image center.
                    im = self.images[0]
                    self.pointing = im.wcs.toWorld(im.trueCenter())
                    if logger:
                        logger.info("Setting pointing to image center: %.3f h, %.3f d",
                                    self.pointing.ra / galsim.hours,
                                    self.pointing.dec / galsim.degrees)
                else:
                    raise NotImplemented("The automatic pointing calculation is not implemented yet.")
            else:
                self.pointing = None
        elif type(ra) in [float, int]:
            ra = float(ra) * galsim.hours
            dec = float(dec) * galsim.degrees
            self.pointing = galsim.CelestialCoord(ra,dec)
            if logger:
                logger.info("Setting pointing to: %.3f h, %.3f d",
                            self.pointing.ra / galsim.hours,
                            self.pointing.dec / galsim.degrees)
        elif str(ra) != ra:
            raise ValueError("Unable to parse input ra: %s"%ra)
        elif str(dec) != dec:
            raise ValueError("Unable to parse input dec: %s"%dec)
        elif ':' in ra and ':' in dec:
            ra = galsim.HMS_Angle(ra)
            dec = galsim.DMS_Angle(dec)
            self.pointing = galsim.CelestialCoord(ra,dec)
            if logger:
                logger.info("Setting pointing to: %.3f h, %.3f d",
                            self.pointing.ra / galsim.hours,
                            self.pointing.dec / galsim.degrees)
        else:
            file_name = self.image_files[0]
            if logger:
                if len(self.image_files) == 1:
                    logger.info("Setting pointing from keywords %s, %s", ra, dec)
                else:
                    logger.info("Setting pointing from keywords %s, %s in %s", ra, dec, file_name)
            fits = fitsio.FITS(file_name)
            hdu = 1 if file_name.endswith('.fz') else 0
            header = fits[hdu].read_header()
            self.ra = header[ra]
            self.dec = header[dec]
            # Recurse to do further parsing.
            self.setPointing(logger)