Exemplo n.º 1
0
def calculate_zeropoint(filter_name,verbose=False):
	cmd = sim.UserCommands("../notebooks/metis_image_NQ.config")
	cmd["ATMO_USE_ATMO_BG"] = "yes"
	cmd["SCOPE_USE_MIRROR_BG"] = "yes"
	cmd["SIM_VERBOSE"]="no"
	cmd["FPA_QE"]="../data/TC_detector_METIS_NQ_no_losses.dat"
	cmd["INST_FILTER_TC"]="../data/TC_filter_"+filter_name+".dat"

	opt = sim.OpticalTrain(cmd)
	fpa = sim.Detector(cmd, small_fov=False)

	## generate a source with 0 mag
	lam, spec = sim.source.flat_spectrum(0, "../data/TC_filter_"+filter_name+".dat")
	src = sim.Source(lam=lam, spectra=np.array([spec]), ref=[0], x=[0], y=[0])
	src.apply_optical_train(opt, fpa)
	exptime=1
	##
	## noise-free image before applying Poisson noise
	photonflux = fpa.chips[0].array.T
	clean_image = photonflux * exptime
	##
	## detector image with Poisson noise
	hdu = fpa.read_out(OBS_EXPTIME=exptime)

	bg_counts = np.min(clean_image)
	source_minus_bg_counts = np.sum(clean_image - np.min(clean_image))

	if verbose:
		print("Background counts/s: {0:.2E}".format(bg_counts))
		print("Background-subtracted source counts/s: {0:.2E}".format(source_minus_bg_counts))
	return(bg_counts,source_minus_bg_counts)
Exemplo n.º 2
0
def run_simmetis():
    import simmetis as sim
    import os
    cmd = sim.UserCommands()
    cmd["OBS_EXPTIME"] = 3600
    cmd["OBS_NDIT"] = 1
    cmd["INST_FILTER_TC"] = "J"

    src = sim.source.source_1E4_Msun_cluster()
    opt = sim.OpticalTrain(cmd)
    fpa = sim.Detector(cmd)

    src.apply_optical_train(opt, fpa)
    fpa.read_out("my_output.fits")

    is_there = os.path.exists("my_output.fits")
    os.remove("my_output.fits")

    return is_there
Exemplo n.º 3
0
def calculate_zeropoint(filter_id, filter_path, verbose=False):
    ##
    ## find out if we have the LM or NQ band camera
    filter_data = ascii.read(filter_path)
    if filter_data["col1"][0] < 6:
        cmd = sim.UserCommands("../notebooks/metis_image_LM.config")
        cmd["FPA_QE"] = "../data/TC_detector_METIS_LM_no_losses.dat"
    else:
        cmd = sim.UserCommands("../notebooks/metis_image_NQ.config")
        cmd["FPA_QE"] = "TC_detector_METIS_NQ_no_losses.dat"

    cmd["INST_FILTER_TC"] = "../data/TC_filter_" + filter_id + ".dat"

    opt = sim.OpticalTrain(cmd)
    fpa = sim.Detector(cmd, small_fov=False)

    ## generate a source with 0 mag
    lam, spec = sim.source.flat_spectrum(0, filter_path)
    src = sim.Source(lam=lam, spectra=np.array([spec]), ref=[0], x=[0], y=[0])
    src.apply_optical_train(opt, fpa)
    exptime = 1
    ##
    ## noise-free image before applying Poisson noise
    photonflux = fpa.chips[0].array.T
    clean_image = photonflux * exptime
    ##
    ## detector image with Poisson noise
    hdu = fpa.read_out(OBS_EXPTIME=exptime)

    bg_counts = np.min(clean_image)
    source_minus_bg_counts = np.sum(clean_image - np.min(clean_image))

    if verbose:
        print("Background counts/s: {0:.2E}".format(bg_counts))
        print("Background-subtracted source counts/s: {0:.2E}".format(
            source_minus_bg_counts))
    return (bg_counts, source_minus_bg_counts)
Exemplo n.º 4
0
def background_increases_consistently_with_exptime():
    """
    Run an empty source for exposure time: (1,2,4,8,16,32,64) mins
    If true the background level increases linearly and the stdev increases as sqrt(exptime)
    """

    import numpy as np
    import simmetis as sim

    cmd = sim.UserCommands()
    cmd["OBS_REMOVE_CONST_BG"] = "no"

    opt = sim.OpticalTrain(cmd)
    fpa = sim.Detector(cmd)

    stats = []

    for t in [2**i for i in range(7)]:
        src = sim.source.empty_sky()
        src.apply_optical_train(opt, fpa)
        hdu = fpa.read_out(OBS_EXPTIME=60 * t, FPA_LINEARITY_CURVE=None)
        im = hdu[0].data
        stats += [[t, np.sum(im), np.median(im), np.std(im)]]

    stats = np.array(stats)

    factors = stats / stats[0, :]
    bg_stats = [
        i == np.round(l**2) == np.round(j) == np.round(k)
        for i, j, k, l in factors
    ]

    return_val = np.all(bg_stats)
    if not return_val:
        print(factors)

    return return_val
Exemplo n.º 5
0
    def transmission_emission(self, conditions='median', plot=False):
        '''
        Apply transission to src_cube and calculate emission spectrum
        '''
        print()
        print("--------------------Transmission and Emission--------------------")
        if plot:
            plt.plot(self.wavelen, self.src_cube[:, self.plotpix[0], self.plotpix[1]])
            plt.title("Pixel ["+str(self.plotpix[0])+","+str(self.plotpix[1])+"] in source cube")
            plt.xlabel("Wavelength [micron]")
            plt.ylabel("Flux [Jy/arcsec2]")
            plt.show()

        # calculate wavelens of detector, needed for emission
        #
        det_wavelen = (self.det_velocities
                       * u.m/u.s).to(u.um, equivalencies=u.doppler_optical(self.restcoo))

        #############################################################################
        # Read in trans-/emission from skycal
        #
        if conditions == 'best':
            skyfile = 'skycal_R308296_best_conditions.fits'
            self.cmds["SCOPE_TEMPERATURE"] = 258. - 273.
            self.cmds["SCOPE_MIRROR_LIST"] = "EC_mirrors_EELT_SCAO_best.tbl"
        elif conditions == 'median':
            skyfile = 'skycal_R308296_median_conditions.fits'
            self.cmds["SCOPE_TEMPERATURE"] = 282. - 273.
            self.cmds["SCOPE_MIRROR_LIST"] = "EC_mirrors_EELT_SCAO_median.tbl"
        elif conditions == 'poor':
            skyfile = 'skycal_R308296_poor_conditions.fits'
            self.cmds["SCOPE_TEMPERATURE"] = 294. - 273.
            self.cmds["SCOPE_MIRROR_LIST"] = "EC_mirrors_EELT_SCAO_poor.tbl"
        else:
            raise ValueError('Undefined conditions "' + conditions +
                             '", only "best", "median", and "poor" are defined')

        skyfile = sm.utils.find_file(skyfile)
        skytransfits = fits.open(skyfile)
        print("Reading ", skyfile)

        skytrans = skytransfits[1].data

        skylam = skytrans['LAMBDA']
        skytran = skytrans['TRANS']
        skyemis = skytrans['EMIS']

        #plt.plot(skylam, skytran)
        #plt.show()

        idx = (np.where((skylam >= np.min(self.wavelen)) &
                        (skylam <= np.max(self.wavelen))))[0]
        if self.verbose:
            print("wavelen:", np.min(self.wavelen), "...", np.max(self.wavelen))
            print("skylam: ", np.min(skylam), "...", np.max(skylam))
            print("Index skytran to src-wave:", idx[0], "...", idx[-1])
        #
        # interpolate transmission/emission onto source-grid
        #
        self.transmission = np.interp(self.wavelen, skylam, skytran) # dimensionless, [0...1]

        sky_emission = (np.interp(det_wavelen.value, skylam, skyemis)
                        * (self.det_pixscale/1000.)**2)
        # emission in data file is photons/s/um/m^2/arcsec2, convert to photons/s/um/m^2

        if plot:
            plt.figure(num=1, figsize=self.wide_figsize)
            plt.subplots_adjust(left=0.1, right=0.75)
            plt.plot(skylam[idx], skytran[idx], "+", label='Sky transmission')
            plt.plot(self.wavelen, self.transmission, label='Sky tr. interpolated')
            plt.xlabel("Wavelength [micron]")
            plt.ylabel("Transmission")
            #plt.show()

        #############################################################################
        # get trans-/emission from SimMETIS
        #
        if self.verbose:
            print("Steaming up optical train")
            print("Telescope temperature:", self.cmds["SCOPE_TEMPERATURE"])

        # Create transmission curve.
        opttrain = sm.OpticalTrain(self.cmds)

        # Some comments about the OpticalTrain in SimMumble:
        #
        # For MICADO, AO means MAORY
        # For METIS, this should be configured to do nothing
        #
        # tc_ao = 	 transmission of everything after first mirror in AO system
        #		 (n-1 AO mirrors, entrance window, dichroic, instrument...)
        # tc_mirror= transmission of everything after the telescope
        #		 (tc_ao + one AO mirror, but not M1)
        # tc_atmo =	 transmission of telescope and instrument
        #		 (i.e. _without_ the atmosphere)
        # tc_source= transmission seen by light from the source
        #		 (including atmosphere)
        #
        # ph_ao    = blackbody @ INST_AO_TEMPERATURE * 0.1 * tc_ao
        # ph_mirror= _gen_thermal_emission (based on SCOPE_MIRROR_LIST) * tc_mirror
        # ph_atmo  = atmospheric emission * tc_atmo
        #
        tc_trans = interp1d(opttrain.tc_atmo.lam, opttrain.tc_atmo.val,
                            kind='linear', bounds_error=False, fill_value=0.)

        if plot:
            plt.plot(self.wavelen, tc_trans(self.wavelen), label='Tel. transmission')
            plt.title("Sky & Telescope Transmission")
            plt.xlabel("Wavelength [micron]")
            plt.legend(loc='upper left', bbox_to_anchor=(1.02, 1.0))
            plt.show()

        # combine transmission of atmosphere, telescope, and LMS (the Roy factor)
        self.transmission *= tc_trans(self.wavelen) * 0.712599

        #############################################################################
        #
        # transmit the source cube!
        #
        self.target_cube = self.src_cube * self.transmission[:, np.newaxis, np.newaxis]
        self.add_cmds_to_header(self.target_hdr)

        # do not add skycal-file to self.cmds!
        # the optical train will be confused if we try to re-run it.
        if len(skyfile) > 50:
            self.target_hdr['SKYCAL_FILE'] = "... " + skyfile[-50:]
        else:
            self.target_hdr['SKYCAL_FILE'] = skyfile

        if plot:
            plt.plot(self.wavelen, self.target_cube[:, self.plotpix[0],
                                                    self.plotpix[1]])
            plt.title("Pixel [" + str(self.plotpix[0]) + "," +
                      str(self.plotpix[1]) + "] in transmitted cube")
            plt.xlabel("Wavelength [micron]")
            plt.ylabel("Flux [Jy/arcsec2]")
            plt.show()

        #############################################################################
        # let there be emitted light!
        #
        # this is the code in spectral.py/BlackbodyCurve to compute the bin width
        lam = opttrain.ph_mirror.lam
        lam_res = lam[1] - lam[0]
        edges = np.append(lam - 0.5 * lam_res, lam[-1] + 0.5 * lam_res)
        lam_res = edges[1:] - edges[:-1]

        # lam_res is now (approximately) the bin width in um
        #
        # calculate emission in photons/s/um/pixel

        ph_mirr_um = opttrain.ph_mirror.val / lam_res

        if opttrain.ph_ao is not None:
            ph_mirr_um += opttrain.ph_ao.val / lam_res

        ph_mirror = interp1d(lam, ph_mirr_um,
                             kind='linear', bounds_error=False, fill_value=0.)

        mirr_list = self.cmds.mirrors_telescope
        mirr_area = np.pi / 4 * np.sum(mirr_list["Outer"]**2 - \
                                       mirr_list["Inner"]**2)
        if self.verbose:
            print("Pix_res: ", opttrain.cmds.pix_res)
            print("Mirror area: ", mirr_area, "[m^2]")

        ph_atmo_um = sky_emission * mirr_area * tc_trans(det_wavelen)
        ph_mirrors = ph_mirror(det_wavelen) * 1.25
        # Leo's fudge-factor to account for spiders and entrance window

        if plot:
            plt.figure(num=1, figsize=self.wide_figsize)
            plt.subplots_adjust(right=0.8)
            plt.plot(det_wavelen, ph_atmo_um, '+', label='Atmosphere')
            plt.plot(det_wavelen, ph_mirrors, label='Telescope')
            plt.plot(det_wavelen, ph_atmo_um+ph_mirrors, label='total')
            plt.title("Sky & Mirror Emission")
            plt.xlabel("Wavelength [micron]")
            plt.ylabel("Background Flux [photons/s/um/pixel]")
            plt.legend(loc='upper left', bbox_to_anchor=(1.02, 1.0))
            plt.show()

        self.background = (ph_atmo_um + ph_mirrors) * 0.712599 	# photons/s/um/pixel
        # apply Roy factor for transmission of LMS

        if self.verbose:
            print("Final telescope temperature:", opttrain.cmds["SCOPE_TEMPERATURE"])
Exemplo n.º 6
0
def mimic_image(hdu,
                catalogue,
                cmds=None,
                hdu_ext=0,
                sim_chip_n=0,
                return_stamps=False,
                cat_ra_name="RA",
                cat_dec_name="DE",
                cat_filter_name="J",
                **kwargs):
    """
    Create a SimMETIS image to mimic a real FITS file

    Parameters
    ----------
    hdu : str, astropy.HDUList
        The original FITS object- either a filename or an astropy.HDUList object

    catalogue : str, astropy.Table
        A catalogue of stars - either a filename or an astropy.Table object

    cmds : str, simmetis.UserCommands
        Commands by which to simulate the image - a filename to a .config file or a UserCommands object

    hdu_ext : int
        The extension in the original FITS file which should be simulated

    sim_chip_n : int
        Which chip in the FPA_LAYOUT to simulate. Passed to apply_optical_train() and read_out()

    return_stamps : bool
        If True, returns two PostageStamps object for the original HDU and the generated HDU

    cat_ra_name, cat_dec_name, cat_filter_name : str
        The names of the column in catalogue which point to the RA, Dec and filter magnitudes for the stars


    Optional Parameters
    -------------------
    As passed to a PostageStamps object

    "dx"           : 0,
    "dy "          : 0,
    "bg_tile_size" : 24,
    "stamp_width"  : 24,
    "hot_pixel_threshold" : 3000


    Returns
    -------
    hdu_sim, src [, post_real, post_sim]
        If return_stamps is True, post_real and post_sim are returned


    Examples
    --------
    ::

        >>> hdu_real = fits.open("HAWKI.2008-11-05T04_08_55.552.fits")
        >>> cat = ascii.read("ngc362_cohen.dat")
        >>>
        >>> dx, dy = -5, 15
        >>>
        >>> cmd = sim.UserCommands("hawki_ngc362.config")
        >>> cmd["INST_FILTER_TC"] = "J"
        >>> cmd["OBS_EXPTIME"] = 10
        >>>
        >>> out = mimic_image(hdu=hdu_real, catalogue=cat, cmds=cmd, hdu_ext=3,
        ...                   sim_chip_n=3, return_stamps=True,
        ...                   dx=dx, dy=dy)
        >>> hdu_sim, src, post_real, post_sim = out
        >>> len(out)
        4

    """

    if isinstance(hdu, str) and os.path.exists(hdu):
        hdu = fits.open(hdu)[hdu_ext]
    elif isinstance(hdu, fits.HDUList):
        hdu = hdu[hdu_ext]
    else:
        raise ValueError("hdu must be a filename or an astropy HDU object: " +
                         type(hdu))

    if isinstance(catalogue, str) and os.path.exists(catalogue):
        cat = ascii.read(catalogue)
    elif isinstance(catalogue, Table):
        cat = catalogue
    else:
        raise ValueError(
            "catalogue must be a filename or an astropy.Table object: " +
            type(catalogue))

    if isinstance(cmds, str) and os.path.exists(cmds):
        cmds = sim.UserCommands(cmds)
    elif isinstance(cmds, sim.UserCommands):
        pass
    else:
        raise ValueError(
            "cmds must be a filename or an simmetis.UserCommands object: " +
            type(cmds))

    fig = plt.figure(figsize=(0.1, 0.1))
    apl_fig = aplpy.FITSFigure(hdu, figure=fig)

    # get the RA DEC position of the centre of the HAWKI FoV
    xc, yc = hdu.header["CRPIX1"], hdu.header["CRPIX2"]
    ra_cen, dec_cen = apl_fig.pixel2world(xc, yc)

    # get the x,y positions in arcsec from the HAWKI FoV centre
    y = (cat[cat_dec_name] - dec_cen) * 3600
    x = -(cat[cat_ra_name] - ra_cen) * 3600 * np.cos(cat[cat_dec_name] / 57.3)
    mag = cat[cat_filter_name]

    # make a Source object with the x,y positions in arcsec from the HAWKI FoV centre
    src = sim.source.stars(mags=mag, filter_name=cat_filter_name, x=x, y=y)

    opt = sim.OpticalTrain(cmds)
    fpa = sim.Detector(cmds, small_fov=False)

    print(sim_chip_n)

    src.apply_optical_train(opt, fpa, chips=sim_chip_n)
    hdu_sim = fpa.read_out(chips=sim_chip_n)

    ## Get the Postage Stamps
    if return_stamps:

        params = {
            "dx": 0,
            "dy ": 0,
            "bg_tile_size": 24,
            "stamp_width": 24,
            "hot_pixel_threshold": 3000
        }
        params.update(**kwargs)

        w, h = hdu_sim[0].data.shape
        mask = (src.x_pix > 0) * (src.x_pix < w) * (src.y_pix > 0) * (src.y_pix
                                                                      < h)

        xw = cat[cat_ra_name][mask]
        yw = cat[cat_dec_name][mask]
        mag = cat[cat_filter_name][mask]

        # get the x,y pixel positions of the stars in the simulated image
        xps = src.x_pix[mask]
        yps = src.y_pix[mask]

        # get the x,y pixel positions of the stars in the real image, include offset if needed
        xpr, ypr = apl_fig.world2pixel(xw, yw)
        xpr += params["dx"]
        ypr += params["dy"]

        # get the images from the FITS objects
        im_sim = np.copy(hdu_sim[0].data)
        im_sim -= np.median(im_sim)
        post_sim = PostageStamps(im_sim, x=xps, y=yps, **params)

        im_real = np.copy(hdu.data)
        im_real -= np.median(im_real)
        post_real = PostageStamps(im_real, x=xpr, y=ypr, **params)

        return hdu_sim, src, post_real, post_sim

    else:
        return hdu_sim, src