Example #1
0
    def test_pixsim_cosmics(self):
        night = '20150105'
        expid = 124
        camera = 'r0'
        obs.new_exposure('arc', night=night, expid=expid, nspec=3)
        pixsim.simulate(night, expid, camera, nspec=3, trimxy=True, cosmics=self.cosmics)

        self.assertTrue(os.path.exists(io.findfile('simspec', night, expid)))
        simspec = io.read_simspec(io.findfile('simspec', night, expid))
        self.assertTrue(os.path.exists(io.findfile('simpix', night, expid, camera)))
        self.assertTrue(os.path.exists(io.findfile('pix', night, expid, camera)))
Example #2
0
    def test_main_defaults(self):
        night = self.night
        expid = self.expid
        camera = 'r0'
        nspec = 3
        ncpu = 3
        obs.new_exposure('arc', night=night, expid=expid, nspec=nspec)

        #- run pixsim
        opts = ['--night', night, '--expid', expid]
        if ncpu is not None:
            opts.extend( ['--ncpu', ncpu] )
            
        log.debug('testing pixsim.main({})'.format(opts))
        pixsimargs = desisim.scripts.pixsim.parse(opts)
        desisim.scripts.pixsim.main(pixsimargs)

        #- verify outputs
        simpixfile = io.findfile('simpix', night, expid)
        self.assertTrue(os.path.exists(simpixfile))
        rawfile = desispec.io.findfile('raw', night, expid)
        self.assertTrue(os.path.exists(rawfile))
        fx = fits.open(rawfile)

        self.assertTrue('B0' in fx)
        self.assertTrue('R0' in fx)
        self.assertTrue('Z0' in fx)
        fx.close()

        #- cleanup as we go
        os.remove(simpixfile)
        os.remove(rawfile)
Example #3
0
 def tearDown(self):
     rawfile = desispec.io.findfile('raw', self.night, self.expid)
     if os.path.exists(rawfile):
         os.remove(rawfile)
     fibermap = desispec.io.findfile('fibermap', self.night, self.expid)
     if os.path.exists(fibermap):
         os.remove(fibermap)
     simspecfile = io.findfile('simspec', self.night, self.expid)
     if os.path.exists(simspecfile):
         os.remove(simspecfile)
     simpixfile = io.findfile('simpix', self.night, self.expid)
     if os.path.exists(simpixfile):
         os.remove(simpixfile)
     for camera in ('b0', 'r0', 'z0'):
         pixfile = desispec.io.findfile('preproc', self.night, self.expid, camera=camera)
         if os.path.exists(pixfile):
             os.remove(pixfile)
Example #4
0
    def test_pixsim_cosmics(self):
        night = self.night
        expid = self.expid
        cameras = ['r0']
        obs.new_exposure('arc', night=night, expid=expid, nspec=3)
        simspecfile = io.findfile('simspec', night, expid)
        rawfile = desispec.io.findfile('desi', night, expid)
        simpixfile = io.findfile('simpix', night, expid, cameras)

        self.assertFalse(os.path.exists(simpixfile))
        self.assertFalse(os.path.exists(rawfile))

        pixsim.simulate_exposure(simspecfile, rawfile, cameras,
                addcosmics=True, ccdshape=self.ccdshape)

        self.assertTrue(os.path.exists(rawfile))

        #- No simpixfile option, shouldn't exist
        self.assertFalse(os.path.exists(simpixfile))
Example #5
0
 def tearDown(self):
     rawfile = desispec.io.findfile('raw', self.night, self.expid)
     if os.path.exists(rawfile):
         os.remove(rawfile)
     fibermap = desispec.io.findfile('fibermap', self.night, self.expid)
     if os.path.exists(fibermap):
         os.remove(fibermap)
     simspecfile = io.findfile('simspec', self.night, self.expid)
     if os.path.exists(simspecfile):
         os.remove(simspecfile)
     simpixfile = io.findfile('simpix', self.night, self.expid)
     if os.path.exists(simpixfile):
         os.remove(simpixfile)
     for camera in ('b0', 'r0', 'z0'):
         pixfile = desispec.io.findfile('preproc',
                                        self.night,
                                        self.expid,
                                        camera=camera)
         if os.path.exists(pixfile):
             os.remove(pixfile)
Example #6
0
    def test_parse(self):
        night = self.night
        expid = self.expid

        opts = ['--night', night, '--expid', expid, '--cameras', 'b0,r1']
        args = desisim.scripts.pixsim.parse(opts)
        self.assertEqual(args.rawfile, desispec.io.findfile('raw', night, expid))
        self.assertEqual(args.simspec, io.findfile('simspec', night, expid))
        self.assertEqual(args.cameras, ['b0','r1'])

        with self.assertRaises(ValueError):
            desisim.scripts.pixsim.parse([])
Example #7
0
    def test_main_override(self):
        night = self.night
        expid = self.expid
        camera = 'r0'
        nspec = 3
        ncpu = 3
        obs.new_exposure('arc', night=night, expid=expid, nspec=nspec)

        #- derive night from simspec input while overriding expid
        #- Include wavelengths covering z, but only ask for b and r
        simspecfile = io.findfile('simspec', night, expid)
        altexpid = expid+1
        altrawfile = desispec.io.findfile('raw', night, altexpid) + '.blat'
        opts = [
            '--simspec', simspecfile,
            '--expid', altexpid,
            '--rawfile', altrawfile,
            '--cameras', 'b0,r0',
            '--wavemin', 5500, '--wavemax', 7000.0,
            '--ccd_npix_x', 2000,
            ]
        if ncpu is not None:
            opts.extend( ['--ncpu', ncpu] )

        log.debug('testing pixsim.main({})'.format(opts))
        pixsimargs = desisim.scripts.pixsim.parse(opts)
        desisim.scripts.pixsim.main(pixsimargs)
        simpixfile = io.findfile('simpix', night, altexpid)

        self.assertTrue(os.path.exists(simpixfile))
        self.assertTrue(os.path.exists(altrawfile))
        fx = fits.open(altrawfile)
        self.assertTrue('B0' in fx)
        self.assertTrue('R0' in fx)
        self.assertTrue('Z0' not in fx)
        fx.close()

        #- cleanup as we go
        os.remove(simpixfile)
        os.remove(altrawfile)
Example #8
0
    def test_pixsim_cosmics(self):
        night = self.night
        expid = self.expid
        cameras = ['r0']
        obs.new_exposure('arc', night=night, expid=expid, nspec=3)
        simspecfile = io.findfile('simspec', night, expid)
        rawfile = desispec.io.findfile('desi', night, expid)
        simpixfile = io.findfile('simpix', night, expid, cameras)

        self.assertFalse(os.path.exists(simpixfile))
        self.assertFalse(os.path.exists(rawfile))

        pixsim.simulate_exposure(simspecfile,
                                 rawfile,
                                 cameras,
                                 addcosmics=True,
                                 ccdshape=self.ccdshape)

        self.assertTrue(os.path.exists(rawfile))

        #- No simpixfile option, shouldn't exist
        self.assertFalse(os.path.exists(simpixfile))
Example #9
0
    def test_parse(self):
        night = self.night
        expid = self.expid

        opts = ['--night', night, '--expid', expid, '--cameras', 'b0,r1']
        args = desisim.scripts.pixsim.parse(opts)
        self.assertEqual(args.rawfile,
                         desispec.io.findfile('raw', night, expid))
        self.assertEqual(args.simspec, io.findfile('simspec', night, expid))
        self.assertEqual(args.cameras, ['b0', 'r1'])

        with self.assertRaises(ValueError):
            desisim.scripts.pixsim.parse([])
Example #10
0
def expand_args(args):
    '''expand camera string into list of cameras
    '''
    if args.simspec is None:
        if args.night is None or args.expid is None:
            msg = 'Must set --simspec or both --night and --expid'
            log.error(msg)
            raise ValueError(msg)
        args.simspec = io.findfile('simspec', args.night, args.expid)

    #- expand camera list
    if args.cameras is not None:
        args.cameras = args.cameras.split(',')

    #- write to same directory as simspec
    if args.rawfile is None:
        rawfile = os.path.basename(desispec.io.findfile('raw', args.night, args.expid))
        args.rawfile = os.path.join(os.path.dirname(args.simspec), rawfile)

    if args.simpixfile is None:
        outdir = os.path.dirname(os.path.abspath(args.rawfile))
        args.simpixfile = io.findfile(
            'simpix', night=args.night, expid=args.expid, outdir=outdir)
Example #11
0
    def test_main_override(self):
        night = self.night
        expid = self.expid
        camera = 'r0'
        nspec = 3
        ncpu = 3
        obs.new_exposure('arc', night=night, expid=expid, nspec=nspec)

        #- derive night from simspec input while overriding expid
        simspecfile = io.findfile('simspec', night, expid)
        altrawfile = desispec.io.findfile('raw', night, expid) + '.blat'
        opts = [
            '--simspec', simspecfile,
            '--expid', expid+1,
            '--rawfile', altrawfile,
            '--cameras', 'b0,r0',
            '--preproc',
            '--wavemin', 5000, '--wavemax', 7000.0,
            '--ccd_npix_x', 2000,
            ]
        if ncpu is not None:
            opts.extend( ['--ncpu', ncpu] )

        log.debug('testing pixsim.main({})'.format(opts))
        desisim.scripts.pixsim.main(opts)
        simpixfile = io.findfile('simpix', night, expid+1)
        self.assertTrue(os.path.exists(simpixfile))
        self.assertTrue(os.path.exists(altrawfile))
        fx = fits.open(altrawfile)
        self.assertTrue('B0' in fx)
        self.assertTrue('R0' in fx)
        self.assertTrue('Z0' not in fx)
        fx.close()

        #- cleanup as we go
        os.remove(simpixfile)
        os.remove(altrawfile)
Example #12
0
    def test_simulate(self):
        import desispec.image
        night = self.night
        expid = self.expid
        camera = 'r0'
        nspec = 3
        obs.new_exposure('arc', night=night, expid=expid, nspec=nspec)
        simspec = io.read_simspec(io.findfile('simspec', night, expid))
        psf = desimodel.io.load_psf(camera[0])
        psf.npix_y, psf.npix_x = self.ccdshape

        image, rawpix, truepix = pixsim.simulate(camera, simspec, psf, nspec=nspec)

        self.assertTrue(isinstance(image, desispec.image.Image))
        self.assertTrue(isinstance(rawpix, np.ndarray))
        self.assertTrue(isinstance(truepix, np.ndarray))
        self.assertEqual(image.pix.shape, truepix.shape)
        self.assertEqual(image.pix.shape[0], rawpix.shape[0])
        self.assertLess(image.pix.shape[1], rawpix.shape[1])  #- raw has overscan
Example #13
0
    def test_simulate(self):
        import desispec.image
        night = self.night
        expid = self.expid
        camera = 'r0'
        nspec = 3
        obs.new_exposure('arc', night=night, expid=expid, nspec=nspec)
        simspec = io.read_simspec(io.findfile('simspec', night, expid))
        psf = desimodel.io.load_psf(camera[0])
        psf.npix_y, psf.npix_x = self.ccdshape

        image, rawpix, truepix = pixsim.simulate(camera, simspec, psf, nspec=nspec)

        self.assertTrue(isinstance(image, desispec.image.Image))
        self.assertTrue(isinstance(rawpix, np.ndarray))
        self.assertTrue(isinstance(truepix, np.ndarray))
        self.assertEqual(image.pix.shape, truepix.shape)
        self.assertEqual(image.pix.shape[0], rawpix.shape[0])
        self.assertLess(image.pix.shape[1], rawpix.shape[1])  #- raw has overscan
Example #14
0
import os
import desimodel
import fitsio
import numpy as np
import pylab as pl
import astropy.io.fits as fits

from astropy.table import Table, vstack
from desimodel.io import findfile
from desitarget.geomask import circles
from desimodel.focalplane import get_tile_radius_deg

tiles_file = findfile('footprint/desi-tiles.fits')

print(tiles_file)

tiles = Table(fits.open(tiles_file)[1].data)
tiles.pprint(max_width=-1)

extra_gray = Table(tiles[tiles['PASS'] == 8], copy=True)
extra_dark = Table(tiles[tiles['PASS'] == 9], copy=True)
extra_brt = Table(tiles[tiles['PASS'] == 8], copy=True)

example_gray = Table(tiles[tiles['PASS'] == 0], copy=True)
example_dark = Table(tiles[tiles['PASS'] == 1], copy=True)
example_brt = Table(tiles[tiles['PASS'] == 5], copy=True)

extra_gray['PASS'] = 8
extra_gray['PROGRAM'] = example_gray['PROGRAM'][0]
extra_gray['OBSCONDITIONS'] = example_gray['OBSCONDITIONS'][0]
Example #15
0
def simulate(night, expid, camera, nspec=None, verbose=False, ncpu=None,
    trimxy=False, cosmics=None):
    """
    Run pixel-level simulation of input spectra
    
    Args:
        night (string) : YEARMMDD
        expid (integer) : exposure id
        camera (str) : e.g. b0, r1, z9
        nspec (int) : number of spectra to simulate
        verbose (boolean) : if True, print status messages
        ncpu (int) : number of CPU cores to use in parallel
        trimxy (boolean) : trim image to just pixels with input signal
        cosmics (str) : filename with dark images with cosmics to add

    Reads:
        $DESI_SPECTRO_SIM/$PIXPROD/{night}/simspec-{expid}.fits
        
    Writes:
        $DESI_SPECTRO_SIM/$PIXPROD/{night}/simpix-{camera}-{expid}.fits
        $DESI_SPECTRO_SIM/$PIXPROD/{night}/pix-{camera}-{expid}.fits
    """
    if verbose:
        print "Reading input files"

    channel = camera[0].lower()
    ispec = int(camera[1])
    assert channel in 'brz'
    assert 0 <= ispec < 10

    #- Load DESI parameters
    params = desimodel.io.load_desiparams()
    nfibers = params['spectro']['nfibers']

    #- Load simspec file
    simfile = io.findfile('simspec', night=night, expid=expid)
    simspec = io.read_simspec(simfile)
    wave = simspec.wave[channel]
    if simspec.skyphot is not None:
        phot = simspec.phot[channel] + simspec.skyphot[channel]
    else:
        phot = simspec.phot[channel]

    if ispec*nfibers >= simspec.nspec:
        print "ERROR: camera {} not in the {} spectra in {}/{}".format(
            camera, simspec.nspec, night, os.path.basename(simfile))
        return

    #- Load PSF
    psf = desimodel.io.load_psf(channel)

    #- Trim to just the spectra for this spectrograph
    if nspec is None:
        ii = slice(nfibers*ispec, nfibers*(ispec+1))
    else:
        ii = slice(nfibers*ispec, nfibers*ispec + nspec)

    phot = phot[ii]

    #- check if simulation has less than 500 input spectra
    if phot.shape[0] < nspec:
        nspec = phot.shape[0]

    #- Project to image and append that to file
    if verbose:
        print "Projecting photons onto CCD"
        
    img = parallel_project(psf, wave, phot, ncpu=ncpu)
    
    if trimxy:
        xmin, xmax, ymin, ymax = psf.xyrange((0,nspec), wave)
        img = img[0:ymax, 0:xmax]
        # img = img[ymin:ymax, xmin:xmax]
        # hdr['CRVAL1'] = xmin+1
        # hdr['CRVAL2'] = ymin+1

    #- Prepare header
    hdr = simspec.header
    tmp = '/'.join(simfile.split('/')[-3:])  #- last 3 elements of path
    hdr['SIMFILE'] = (tmp, 'Input simulation file')

    #- Strip unnecessary keywords
    for key in ('EXTNAME', 'LOGLAM', 'AIRORVAC', 'CRVAL1', 'CDELT1'):
        if key in hdr:
            del hdr[key]

    #- Write noiseless output
    simpixfile = io.findfile('simpix', night=night, expid=expid, camera=camera)
    io.write_simpix(simpixfile, img, meta=hdr)

    #- Add cosmics from library of dark images
    #- in this case, don't add readnoise since the dark image already has it
    if cosmics is not None:
        cosmics = io.read_cosmics(cosmics, expid, shape=img.shape)
        pix = np.random.poisson(img) + cosmics.pix
        readnoise = cosmics.meta['RDNOISE']
        ivar = 1.0/(pix.clip(0) + readnoise**2)
        mask = cosmics.mask
    #- Or just add noise
    else:
        params = desimodel.io.load_desiparams()
        channel = camera[0].lower()
        readnoise = params['ccd'][channel]['readnoise']
        pix = np.random.poisson(img) + np.random.normal(scale=readnoise, size=img.shape)
        ivar = 1.0/(pix.clip(0) + readnoise**2)
        mask = np.zeros(img.shape, dtype=np.uint16)
    
    #- Metadata to be included in pix file header is in the fibermap header
    #- TODO: this is fragile; consider updating fibermap to use astropy Table
    #- that includes the header rather than directly assuming FITS as the
    #- underlying format.
    fibermapfile = desispec.io.findfile('fibermap', night=night, expid=expid)
    fm, fmhdr = desispec.io.read_fibermap(fibermapfile, header=True)
    meta = dict()
    try:
        meta['TELRA']  = simspec.header['TELRA']
        meta['TELDEC'] = simspec.header['TELDEC']
    except KeyError:  #- temporary backwards compatibilty
        meta['TELRA']  = fmhdr['TELERA']
        meta['TELDEC'] = fmhdr['TELEDEC']
        
    meta['TILEID'] = simspec.header['TILEID']
    meta['DATE-OBS'] = simspec.header['DATE-OBS']
    meta['FLAVOR'] = simspec.header['FLAVOR']
    meta['EXPTIME'] = simspec.header['EXPTIME']
    meta['AIRMASS'] = simspec.header['AIRMASS']

    image = Image(pix, ivar, mask, readnoise=readnoise, camera=camera, meta=meta)
    pixfile = desispec.io.findfile('pix', night=night, camera=camera, expid=expid)
    desispec.io.write_image(pixfile, image)

    if verbose:
        print "Wrote "+pixfile
Example #16
0
def expand_args(args):
    '''expand camera string into list of cameras
    '''
    # if simspec:
    #     if not night:
    #         get night from simspec
    #     if not expid:
    #         get expid from simspec
    # else:
    #     assert night and expid are set
    #     get simspec from (night, expid)
    #
    # if not outrawfile:
    #     get outrawfile from (night, expid)
    #
    # if outpixfile or outsimpixfile:
    #     assert len(cameras) == 1

    if args.simspec is None:
        if args.night is None or args.expid is None:
            msg = 'Must set --simspec or both --night and --expid'
            log.error(msg)
            raise ValueError(msg)
        args.simspec = io.findfile('simspec', args.night, args.expid)

    if (args.cameras is None) and (args.spectrographs is None):
        from astropy.io import fits
        try:
            data = fits.getdata(args.simspec, 'B')
            nspec = data['PHOT'].shape[1]
        except KeyError:
            #- Try old specsim format instead
            hdr = fits.getheader(args.simspec, 'PHOT_B')
            nspec = hdr['NAXIS2']

        nspectrographs = (nspec - 1) // 500 + 1
        args.spectrographs = list(range(nspectrographs))

    if (args.night is None) or (args.expid is None):
        from astropy.io import fits
        hdr = fits.getheader(args.simspec)
        if args.night is None:
            args.night = str(hdr['NIGHT'])
        if args.expid is None:
            args.expid = int(hdr['EXPID'])

    if isinstance(args.spectrographs, str):
        args.spectrographs = [int(x) for x in args.spectrographs.split(',')]

    #- expand camera list
    if args.cameras is None:
        args.cameras = list()
        for arm in args.arms.split(','):
            for ispec in args.spectrographs:
                args.cameras.append(arm + str(ispec))
    else:
        args.cameras = args.cameras.split(',')

    #- write to same directory as simspec
    if args.rawfile is None:
        rawfile = os.path.basename(
            desispec.io.findfile('raw', args.night, args.expid))
        args.rawfile = os.path.join(os.path.dirname(args.simspec), rawfile)

    if args.preproc:
        if args.preproc_dir is None:
            args.preproc_dir = os.path.dirname(args.rawfile)

    if args.simpixfile is None:
        args.simpixfile = io.findfile('simpix',
                                      night=args.night,
                                      expid=args.expid,
                                      outdir=os.path.dirname(
                                          os.path.abspath(args.rawfile)))
Example #17
0
def simulate(night,
             expid,
             camera,
             nspec=None,
             verbose=False,
             ncpu=None,
             trimxy=False,
             cosmics=None):
    """
    Run pixel-level simulation of input spectra
    
    Args:
        night (string) : YEARMMDD
        expid (integer) : exposure id
        camera (str) : e.g. b0, r1, z9
        nspec (int) : number of spectra to simulate
        verbose (boolean) : if True, print status messages
        ncpu (int) : number of CPU cores to use in parallel
        trimxy (boolean) : trim image to just pixels with input signal
        cosmics (str) : filename with dark images with cosmics to add

    Reads:
        $DESI_SPECTRO_SIM/$PIXPROD/{night}/simspec-{expid}.fits
        
    Writes:
        $DESI_SPECTRO_SIM/$PIXPROD/{night}/simpix-{camera}-{expid}.fits
        $DESI_SPECTRO_SIM/$PIXPROD/{night}/pix-{camera}-{expid}.fits
    """
    if verbose:
        print "Reading input files"

    channel = camera[0].lower()
    ispec = int(camera[1])
    assert channel in 'brz'
    assert 0 <= ispec < 10

    #- Load DESI parameters
    params = desimodel.io.load_desiparams()
    nfibers = params['spectro']['nfibers']

    #- Load simspec file
    simfile = io.findfile('simspec', night=night, expid=expid)
    simspec = io.read_simspec(simfile)
    wave = simspec.wave[channel]
    if simspec.skyphot is not None:
        phot = simspec.phot[channel] + simspec.skyphot[channel]
    else:
        phot = simspec.phot[channel]

    if ispec * nfibers >= simspec.nspec:
        print "ERROR: camera {} not in the {} spectra in {}/{}".format(
            camera, simspec.nspec, night, os.path.basename(simfile))
        return

    #- Load PSF
    psf = desimodel.io.load_psf(channel)

    #- Trim to just the spectra for this spectrograph
    if nspec is None:
        ii = slice(nfibers * ispec, nfibers * (ispec + 1))
    else:
        ii = slice(nfibers * ispec, nfibers * ispec + nspec)

    phot = phot[ii]

    #- check if simulation has less than 500 input spectra
    if phot.shape[0] < nspec:
        nspec = phot.shape[0]

    #- Project to image and append that to file
    if verbose:
        print "Projecting photons onto CCD"

    img = parallel_project(psf, wave, phot, ncpu=ncpu)

    if trimxy:
        xmin, xmax, ymin, ymax = psf.xyrange((0, nspec), wave)
        img = img[0:ymax, 0:xmax]
        # img = img[ymin:ymax, xmin:xmax]
        # hdr['CRVAL1'] = xmin+1
        # hdr['CRVAL2'] = ymin+1

    #- Prepare header
    hdr = simspec.header
    tmp = '/'.join(simfile.split('/')[-3:])  #- last 3 elements of path
    hdr['SIMFILE'] = (tmp, 'Input simulation file')

    #- Strip unnecessary keywords
    for key in ('EXTNAME', 'LOGLAM', 'AIRORVAC', 'CRVAL1', 'CDELT1'):
        if key in hdr:
            del hdr[key]

    #- Write noiseless output
    simpixfile = io.findfile('simpix', night=night, expid=expid, camera=camera)
    io.write_simpix(simpixfile, img, meta=hdr)

    #- Add cosmics from library of dark images
    #- in this case, don't add readnoise since the dark image already has it
    if cosmics is not None:
        cosmics = io.read_cosmics(cosmics, expid, shape=img.shape)
        pix = np.random.poisson(img) + cosmics.pix
        readnoise = cosmics.meta['RDNOISE']
        ivar = 1.0 / (pix.clip(0) + readnoise**2)
        mask = cosmics.mask
    #- Or just add noise
    else:
        params = desimodel.io.load_desiparams()
        channel = camera[0].lower()
        readnoise = params['ccd'][channel]['readnoise']
        pix = np.random.poisson(img) + np.random.normal(scale=readnoise,
                                                        size=img.shape)
        ivar = 1.0 / (pix.clip(0) + readnoise**2)
        mask = np.zeros(img.shape, dtype=np.uint16)

    #- Metadata to be included in pix file header is in the fibermap header
    #- TODO: this is fragile; consider updating fibermap to use astropy Table
    #- that includes the header rather than directly assuming FITS as the
    #- underlying format.
    fibermapfile = desispec.io.findfile('fibermap', night=night, expid=expid)
    fm, fmhdr = desispec.io.read_fibermap(fibermapfile, header=True)
    meta = dict()
    try:
        meta['TELRA'] = simspec.header['TELRA']
        meta['TELDEC'] = simspec.header['TELDEC']
    except KeyError:  #- temporary backwards compatibilty
        meta['TELRA'] = fmhdr['TELERA']
        meta['TELDEC'] = fmhdr['TELEDEC']

    meta['TILEID'] = simspec.header['TILEID']
    meta['DATE-OBS'] = simspec.header['DATE-OBS']
    meta['FLAVOR'] = simspec.header['FLAVOR']
    meta['EXPTIME'] = simspec.header['EXPTIME']
    meta['AIRMASS'] = simspec.header['AIRMASS']

    image = Image(pix,
                  ivar,
                  mask,
                  readnoise=readnoise,
                  camera=camera,
                  meta=meta)
    pixfile = desispec.io.findfile('pix',
                                   night=night,
                                   camera=camera,
                                   expid=expid)
    desispec.io.write_image(pixfile, image)

    if verbose:
        print "Wrote " + pixfile
Example #18
0
def new_exposure(program, nspec=5000, night=None, expid=None, tileid=None,
                 nproc=None, seed=None, obsconditions=None, 
                 specify_targets=dict(), testslit=False, exptime=None,
                 arc_lines_filename=None, flat_spectrum_filename=None):
    """
    Create a new exposure and output input simulation files.
    Does not generate pixel-level simulations or noisy spectra.

    Args:
        program: 'arc', 'flat', 'bright', 'dark', 'bgs', 'mws', ...

    Options:
        * nspec : integer number of spectra to simulate
        * night : YEARMMDD string
        * expid : positive integer exposure ID
        * tileid : integer tile ID
        * seed : random seed
        * obsconditions: str or dict-like; see options below
        * specify_targets: (dict of dicts)  Define target properties like magnitude and redshift
                                 for each target class. Each objtype has its own key,value pair
                                 see simspec.templates.specify_galparams_dict() 
                                 or simsepc.templates.specify_starparams_dict()
        * exptime: float exposure time [seconds], overrides obsconditions['EXPTIME']
        * testslit : simulate test slit if True, default False; only for arc/flat
        * arc_lines_filename : use alternate arc lines filename (used if program="arc")
        * flat_spectrum_filename : use alternate flat spectrum filename (used if program="flat")

    Writes:
        * $DESI_SPECTRO_SIM/$PIXPROD/{night}/fibermap-{expid}.fits
        * $DESI_SPECTRO_SIM/$PIXPROD/{night}/simspec-{expid}.fits

    Returns:
        * science: sim, fibermap, meta, obsconditions

    input obsconditions can be a string 'dark', 'gray', 'bright', or dict-like
    observation metadata with keys SEEING (arcsec), EXPTIME (sec), AIRMASS,
    MOONFRAC (0-1), MOONALT (deg), MOONSEP (deg).  Output obsconditions is
    is expanded dict-like structure.

    program is used to pick the sky brightness, and is propagated to
    desisim.targets.sample_objtype() to get the correct distribution of
    targets for a given program, e.g. ELGs, LRGs, QSOs for program='dark'.

    if program is 'arc' or 'flat', then `sim` is truth table with keys
    FLUX and WAVE; and meta=None and obsconditions=None.

    Also see simexp.simarc(), .simflat(), and .simscience(), the last of
    which simulates a science exposure given surveysim obsconditions input,
    fiber assignments, and pre-generated mock target spectra.
    """
    if expid is None:
        expid = get_next_expid()

    if tileid is None:
        tileid = get_next_tileid()

    if night is None:
        #- simulation obs time = now, even if sun is up
        dateobs = time.gmtime()
        night = get_night(utc=dateobs)
    else:
        #- 10pm on night YEARMMDD
        night = str(night)  #- just in case we got an integer instead of string
        dateobs = time.strptime(night+':22', '%Y%m%d:%H')

    outsimspec = desisim.io.findfile('simspec', night, expid)
    outfibermap = desisim.io.findfile('simfibermap', night, expid)
    
    program = program.lower()
    log.debug('Generating {} targets'.format(nspec))
    
    header = dict(NIGHT=night, EXPID=expid, PROGRAM=program)
    if program in ('arc', 'flat'):
        header['FLAVOR'] = program
    else:
        header['FLAVOR'] = 'science'

    #- ISO 8601 DATE-OBS year-mm-ddThh:mm:ss
    header['DATE-OBS'] = time.strftime('%FT%T', dateobs)
    
    if program == 'arc':
        if arc_lines_filename is None :
            infile = os.getenv('DESI_ROOT')+'/spectro/templates/calib/v0.3/arc-lines-average-in-vacuum.fits'
        else :
            infile = arc_lines_filename
        arcdata = fits.getdata(infile, 1)
        if exptime is None:
            exptime = 5
        wave, phot, fibermap = desisim.simexp.simarc(arcdata, nspec=nspec, testslit=testslit)

        header['EXPTIME'] = exptime
        desisim.io.write_simspec_arc(outsimspec, wave, phot, header, fibermap=fibermap)

        fibermap.meta['NIGHT'] = night
        fibermap.meta['EXPID'] = expid
        fibermap.write(outfibermap)
        truth = dict(WAVE=wave, PHOT=phot, UNITS='photon')
        return truth, fibermap, None, None
    
    elif program == 'flat':
        if flat_spectrum_filename is None :
            infile = os.getenv('DESI_ROOT')+'/spectro/templates/calib/v0.3/flat-3100K-quartz-iodine.fits'
        else :
            infile = flat_spectrum_filename

        if exptime is None:
            exptime = 10
        sim, fibermap = desisim.simexp.simflat(infile, nspec=nspec, exptime=exptime, testslit=testslit)

        header['EXPTIME'] = exptime
        header['FLAVOR'] = 'flat'
        desisim.io.write_simspec(sim, truth=None, fibermap=fibermap, obs=None,
            expid=expid, night=night, header=header)

        fibermap.meta['NIGHT'] = night
        fibermap.meta['EXPID'] = expid
        fibermap.write(outfibermap)
        # fluxunits = 1e-17 * u.erg / (u.s * u.cm**2 * u.Angstrom)
        fluxunits = '1e-17 erg/(s * cm2 * Angstrom)'
        flux = sim.simulated['source_flux'].to(fluxunits)
        wave = sim.simulated['wavelength'].to('Angstrom')
        truth = dict(WAVE=wave, FLUX=flux, UNITS=str(fluxunits))
        return truth, fibermap, None, None

    #- all other programs
    fibermap, (flux, wave, meta) = get_targets_parallel(nspec, program,
        tileid=tileid, nproc=nproc, seed=seed, specify_targets=specify_targets)

    if obsconditions is None:
        if program in ['dark', 'lrg', 'qso']:
            obsconditions = desisim.simexp.reference_conditions['DARK']
        elif program in ['elg', 'gray', 'grey']:
            obsconditions = desisim.simexp.reference_conditions['GRAY']
        elif program in ['mws', 'bgs', 'bright']:
            obsconditions = desisim.simexp.reference_conditions['BRIGHT']
        else:
            raise ValueError('unknown program {}'.format(program))
    elif isinstance(obsconditions, str):
        try:
            obsconditions = desisim.simexp.reference_conditions[obsconditions.upper()]
        except KeyError:
            raise ValueError('obsconditions {} not in {}'.format(
                obsconditions.upper(),
                list(desisim.simexp.reference_conditions.keys())))

    if exptime is not None:
        obsconditions['EXPTIME'] = exptime

    sim = simulate_spectra(wave, flux, fibermap=fibermap, obsconditions=obsconditions)

    #- Override $DESI_SPECTRO_DATA in order to write to simulation area
    datadir_orig = os.getenv('DESI_SPECTRO_DATA')
    simbase = os.path.join(os.getenv('DESI_SPECTRO_SIM'), os.getenv('PIXPROD'))
    os.environ['DESI_SPECTRO_DATA'] = simbase

    #- Write fibermap
    telera, teledec = io.get_tile_radec(tileid)
    hdr = dict(
        NIGHT = (night, 'Night of observation YEARMMDD'),
        EXPID = (expid, 'DESI exposure ID'),
        TILEID = (tileid, 'DESI tile ID'),
        PROGRAM = (program, 'program [dark, bright, ...]'),
        FLAVOR = ('science', 'Flavor [arc, flat, science, zero, ...]'),
        TELRA = (telera, 'Telescope pointing RA [degrees]'),
        TELDEC = (teledec, 'Telescope pointing dec [degrees]'),
        AIRMASS = (obsconditions['AIRMASS'], 'Airmass at middle of exposure'),
        EXPTIME = (obsconditions['EXPTIME'], 'Exposure time [sec]'),
        SEEING = (obsconditions['SEEING'], 'Seeing FWHM [arcsec]'),
        MOONFRAC = (obsconditions['MOONFRAC'], 'Moon illumination fraction 0-1; 1=full'),
        MOONALT  = (obsconditions['MOONALT'], 'Moon altitude [degrees]'),
        MOONSEP  = (obsconditions['MOONSEP'], 'Moon:tile separation angle [degrees]'),
        )
    hdr['DATE-OBS'] = (time.strftime('%FT%T', dateobs), 'Start of exposure')

    simfile = io.write_simspec(sim, meta, fibermap, obsconditions, expid, night, header=hdr)

    #- Write fibermap to $DESI_SPECTRO_SIM/$PIXPROD not $DESI_SPECTRO_DATA
    fiberfile = io.findfile('simfibermap', night, expid)
    desispec.io.write_fibermap(fiberfile, fibermap, header=hdr)
    log.info('Wrote '+fiberfile)

    update_obslog(obstype='science', program=program, expid=expid, dateobs=dateobs, tileid=tileid)

    #- Restore $DESI_SPECTRO_DATA
    if datadir_orig is not None:
        os.environ['DESI_SPECTRO_DATA'] = datadir_orig
    else:
        del os.environ['DESI_SPECTRO_DATA']

    return sim, fibermap, meta, obsconditions
Example #19
0
def main(args, comm=None):
    if args.verbose:
        import logging
        log.setLevel(logging.DEBUG)
    #we do this so we can use operator.itemgetter
    import operator
    #we do this so our print statements can have timestamps
    import time

    rank = 0
    nproc = 1
    if comm is not None:
        import mpi4py
        rank = comm.rank
        nproc = comm.size

    if rank == 0:
        log.info('Starting pixsim at {}'.format(asctime()))

    #no preflight check here, too complicated.   
    #we'll assume the user knows what he or she is doing...

    # Determine which nights we are using
    nights = None
    if args.nights is not None:
        nights = args.nights.split(",")
    else:
        rawdir = os.path.abspath(specio.rawdata_root())
        nights = []
        nightpat = re.compile(r"\d{8}")
        for root, dirs, files in os.walk(rawdir, topdown=True):
            for d in dirs:
                nightmat = nightpat.match(d)
                if nightmat is not None:
                    nights.append(d)

    # Get the list of exposures for each night
    night_expid = {}
    all_expid = []
    exp_to_night = {}
    for nt in nights:
        night_expid[nt] = specio.get_exposures(nt, raw=True)

    #get a list of tuples of (night,expid) that we can evenly divide between communicators
    night_exposure_list=list()
    if comm is None or comm.rank == 0:
        for nt in nights:
            for exp in night_expid[nt]:
                rawfile = desispec.io.findfile('raw', nt, exp)
                if not os.path.exists(rawfile):
                    night_exposure_list.append([nt,exp])
                elif args.overwrite:
                    log.warning('Overwriting pre-existing {}'.format(os.path.basename(rawfile)))
                    os.remove(rawfile)
                    night_exposure_list.append([nt,exp])
                else:
                    log.info('Skipping pre-existing {}'.format(os.path.basename(rawfile)))

        if args.nexp is not None:
            night_exposure_list = night_exposure_list[0:args.nexp]

    if comm is not None:
        night_exposure_list = comm.bcast(night_exposure_list, root=0)

    if len(night_exposure_list) == 0:
        if comm is None or comm.rank == 0:
            log.error('No exposures to process')
        sys.exit(1)

    # Get the list of cameras and make sure it's in the right format
    cams = []
    if args.cameras is not None:
        entry = args.cameras.split(',')
        for i in entry:
            cams.append(i)
    else:
        #do this with band first so we can avoid re-broadcasting cosmics
        for band in ['b', 'r', 'z']:
            for spec in range(10):
                cams.append('{}{}'.format(band, spec)) 

    #are we using cosmics?
    if args.cosmics is not None:
        addcosmics = True
    else:
        addcosmics = False

    ncameras=len(cams)
    nexposures=len(night_exposure_list)
    #call ultity function to figure out how many nodes we have
    nnodes=mpi_count_nodes(comm)

    #call utility functions to divide our workload
    if args.nodes_per_exp is not None:
        user_specified_nodes=args.nodes_per_exp
    else:
        user_specified_nodes=None

    nodes_per_comm_exp=get_nodes_per_exp(nnodes,nexposures,ncameras,user_specified_nodes)    
    #also figure out how many exposure communicators we have
    num_exp_comm = nnodes // nodes_per_comm_exp 
 
    #split the communicator into exposure communicators
    comm_exp, node_index_exp, num_nodes_exp = mpi_split_by_node(comm, nodes_per_comm_exp)
    #further splitting will happen automatically in simulate_exposure

    #based on this, figure out which simspecfiles and rawfiles are assigned to each communicator
    #find all specfiles
    #find all rawfiles
    rawfile_list=[]
    simspecfile_list=[]
    night_list=[]
    expid_list=[]
    for i in range(len(night_exposure_list)):
        night_list.append(night_exposure_list[i][0])
        expid_list.append(night_exposure_list[i][1])
        rawfile_list.append(desispec.io.findfile('raw', night_list[i], expid_list[i]))
        simspecfile_list.append(io.findfile('simspec', night_list[i], expid_list[i]))
 
    #now divy the rawfiles and specfiles between node communicators
    #there is onerawfile and one specfile for each exposure
    rawfile_comm_exp=[]
    simspecfile_comm_exp=[]
    for i in range(num_exp_comm):
        if node_index_exp == i: #assign rawfile, simspec file to one communicator at a time
            rawfile_comm_exp=rawfile_list[i::num_exp_comm]
            simspecfile_comm_exp=simspecfile_list[i::num_exp_comm] 
            night_comm_exp=night_list[i::num_exp_comm]
            expid_comm_exp=expid_list[i::num_exp_comm]
    
    comm.Barrier()

    #now wrap pixsim.simulate_exposure for each exposure (in desisim.pixsim)
    if comm_exp.rank == 0:
        log.info("Starting simulate_exposure for night {} expid {}".format(night_comm_exp, expid_comm_exp))
    for i in range(len(rawfile_comm_exp)):
        simulate_exposure(simspecfile_comm_exp[i], rawfile_comm_exp[i], cameras=cams,
            ccdshape=None, simpixfile=None, addcosmics=addcosmics, comm=comm_exp)


    comm.Barrier()

    if rank == 0:
        log.info('Finished pixsim nights {}'.format(args.nights, asctime()))
Example #20
0
def load_hardware(fiberpos_file=None,
                  gfa_file=None,
                  rundate=None,
                  status_file=None):
    """Create a hardware class representing properties of the telescope.

    Args:
        fiberpos_file (str):  Optional path to the fiber positioner FITS file.
            If not specified, desimodel is used to get the location of the
            default file.
        gfa_file (str):  Optional path to the GFA file.
        rundate (str):  ISO 8601 format time stamp as a string in the
            format YYYY-MM-DDTHH:MM:SS.  If None, uses current time.
        status_file (str):  Path to fiber status file.  If not specified, all
            fibers are assumed good.

    Returns:
        (Hardware):  The hardware object.

    """
    log = Logger.get()

    # Read the fiber positioner data
    if fiberpos_file is None:
        fiberpos_file = dmio.findfile('focalplane/fiberpos-all.fits')
    log.info("Reading fiber positions from {}".format(fiberpos_file))

    fpdata = fitsio.read(fiberpos_file, ext=1)
    pos_rows = np.where(fpdata["DEVICE_TYPE"] == b"POS")[0]
    etc_rows = np.where(fpdata["DEVICE_TYPE"] == b"ETC")[0]
    keep_rows = np.unique(np.concatenate((pos_rows, etc_rows)))

    nfiber = len(keep_rows)
    log.debug("  fiber position table keeping {} rows".format(nfiber))

    device_type = np.empty(nfiber, dtype="a8")
    device_type[:] = fpdata["DEVICE_TYPE"][keep_rows]

    # For non-science positioners, no fiber ID is assigned in the positioner
    # file.  This is a pain, since all our quantities are indexed by fiber ID.
    # Instead, we give every position a FIBER value which is unique and which
    # is sorted by LOCATION.  We start these fake FIBER values at 5000.
    fiber = np.copy(fpdata["FIBER"][keep_rows])
    location = np.copy(fpdata["LOCATION"][keep_rows])
    missing_fiber = [x for x, y in enumerate(fiber) if y < 0]
    if len(missing_fiber) > 0:
        missing_locsorted = np.sort(location[missing_fiber])
        locfiber = {y: x for x, y in enumerate(missing_locsorted)}
        fiber[missing_fiber] = [(5000 + locfiber[x])
                                for x in location[missing_fiber]]

    # Read the status file...
    status = np.empty(nfiber, dtype=np.int32)
    status[:] = FIBER_STATE_OK

    if status_file is not None:
        runtime = None
        if rundate is None:
            runtime = datetime.utcnow()
        else:
            runtime = datetime.strptime(rundate, "%Y-%m-%dT%H:%M:%S")
        locindx = {y: x for x, y in enumerate(location)}
        statdata = Table.read(status_file, format="ascii.ecsv")
        for row in statdata:
            loc = row["LOCATION"]
            broken = row["BROKEN"]
            stuck = row["STUCK"]
            start = datetime.strptime(row["START_DATE"], "%Y-%m-%dT%H:%M:%S")
            stop = datetime.strptime(row["END_DATE"], "%Y-%m-%dT%H:%M:%S")
            # Check if this row applies to our current run
            if (runtime >= start) and (runtime < stop):
                # yep...
                if broken > 0:
                    status[locindx[loc]] |= FIBER_STATE_BROKEN
                if stuck > 0:
                    status[locindx[loc]] |= FIBER_STATE_STUCK

    hw = Hardware(fiber, fpdata["PETAL"][keep_rows],
                  fpdata["SPECTRO"][keep_rows], location,
                  fpdata["SLIT"][keep_rows], fpdata["SLITBLOCK"][keep_rows],
                  fpdata["BLOCKFIBER"][keep_rows], fpdata["DEVICE"][keep_rows],
                  device_type, fpdata["X"][keep_rows], fpdata["Y"][keep_rows],
                  fpdata["Z"][keep_rows], fpdata["Q"][keep_rows],
                  fpdata["S"][keep_rows], status)
    return hw