예제 #1
0
def make_emission_from_emissivity(temp, emiss_src_spec):
    """
    Create an emission SourceSpectrum using a blackbody and an emissivity curve

    Parameters
    ----------
    temp : float, Quantity
        [Kelvin] If float, then must be in Kelvin
    emiss_src_spec : synphot.SpectralElement
        An emissivity response curve in the range [0..1]

    Returns
    -------
    flux : synphot.SourceSpectrum

    """

    if isinstance(temp, u.Quantity):
        temp = temp.to(u.Kelvin, equivalencies=u.temperature()).value

    if emiss_src_spec is None:
        logging.warning("Either emission or emissivity must be set")
        flux = None
    else:
        flux = SourceSpectrum(BlackBody1D, temperature=temp)
        flux.meta["solid_angle"] = u.sr**-1
        flux = flux * emiss_src_spec
        flux.meta["history"] = [
            "Created from Blackbody curve. Units are to be"
            " understood as per steradian"
        ]

    return flux
예제 #2
0
def convert_to_list_of_spectra(spectra, lam):
    spectra_list = []
    if isinstance(spectra, SourceSpectrum):
        spectra_list += [spectra]

    elif lam is None and\
            isinstance(spectra, (tuple, list)) and \
            isinstance(spectra[0], SourceSpectrum):
        spectra_list += spectra

    elif lam is not None and len(spectra.shape) == 1 and \
            isinstance(spectra, np.ndarray) and \
            isinstance(lam, np.ndarray):
        spec = SourceSpectrum(Empirical1D, points=lam, lookup_table=spectra)
        spectra_list += [spec]

    elif ((isinstance(spectra, np.ndarray) and
           len(spectra.shape) == 2) or
          (isinstance(spectra, (list, tuple)) and
           isinstance(spectra[0], np.ndarray))) and \
            isinstance(lam, np.ndarray):

        for sp in spectra:
            spec = SourceSpectrum(Empirical1D, points=lam, lookup_table=sp)
            spectra_list += [spec]

    return spectra_list
예제 #3
0
    def add_abs_lines(self, center, ew, fwhm):
        """
        TODO: accept different profiles (Lorentz1D, Voigt1D, etc)
        Add a absorption line of to a spectrum with center, fwhm and equivalent width specified by the user
        It also supports emission lines if ew is negative

        Parameters
        ----------
        center: float, list, np.ndarray, u.Quantity
            The center of the line

        fwhm:  float, list, np.ndarray, u.Quantity
            The FWHM of the line
        ew: float, list, np.ndarray, u.Quantity
            The Equivalent Width of the line

        Returns
        -------
        Spextrum
        """
        if isinstance(center, u.Quantity) is True:
            center = center.to(u.AA).value
        if isinstance(ew, u.Quantity) is True:
            ew = ew.to(u.AA).value
        if isinstance(fwhm, u.Quantity) is True:
            fwhm = fwhm.to(u.AA).value

        centers = np.array([center]).flatten()
        ews = np.array([ew]).flatten()
        fwhms = np.array([fwhm]).flatten()
        sp = self  #  .__class__(modelclass=self.model)

        sp.meta.update({"em_lines": {"center": list(centers),
                                     "ew": list(ews),
                                     "fwhm": list(fwhms)}})

        for c, e, f in zip(centers, ews, fwhms):
            sign = -1 * np.sign(e)  # to keep the convention that EL are negative and ABS are positive
            left, right = c - np.abs(e / 2), c + np.abs(e / 2)
            wavelengths = self.waveset[(self.waveset.value >= left) & (self.waveset.value <= right)]
            fluxes = units.convert_flux(wavelengths=wavelengths,
                                        fluxes=self(wavelengths),
                                        out_flux_unit=units.FLAM)
            flux = np.trapz(fluxes.value, wavelengths.value)
            line = GaussianFlux1D(mean=c, total_flux=sign * flux, fwhm=f)
            lam = line.sampleset(factor_step=0.35)  # bit better than Nyquist
            g_abs = SourceSpectrum(Empirical1D, points=lam, lookup_table=line(lam))

            sp = sp + g_abs

            if (sp(wavelengths).value < 0).any():
                warnings.warn("Warning: Flux<0 for specified EW and FHWM, setting it to Zero")
                waves = sp.waveset[sp(sp.waveset) < 0]
                zero_sp = SourceSpectrum(Empirical1D, points=waves, lookup_table=-1 * sp(waves).value)
                sp = sp + zero_sp  # Spextrum(modelclass=sp.model + zero_sp.model)

        sp = self._restore_attr(Spextrum(modelclass=sp))

        return sp
예제 #4
0
def get_normalized_star_spectrum(spectral_type, magnitude, filter_name):
    """
    spec_data = get_normalized_star_spectrum(spectral_type, magnitude, filter_name)

    Returns a structure containing the synthetic spectrum of the star having the spectral type and magnitude 
    in the specified input filter. Magnitude is in VEGAMAG-F(lambda) system.
    Spectra are from PICKLES, PASP, 110, 863 (1998)
    Absolute flux spectra, no effect of atmospheric and instrument transmission


    Parameters
    ----------
        r0AtZenith: float
                    overall r0 at zenith [m]

        spectral_type:  string.
                        spectral type and luminosity class (e.g. G2V or M4III) or 'vega'
        magnitude:  float.
                    magnitude in the filter_name filter
        filter_name: string.
                     Name of the filter. See Filters.get() for the list of available filters

    Returns
    -------
        spectrum: synphot.SourceSpectrum object defining the spectrum

    Examples
    --------
    Plot the spectrum of a vega, A0V, G2V stars of mag=8 defined on JohnsonR filter

    >>> sp= get_normalized_star_spectrum('vega', 8, Filters.JOHNSON_R)
    >>> spA0V= get_normalized_star_spectrum('A0V', 8, Filters.JOHNSON_R)
    >>> spG2V= get_normalized_star_spectrum('G2V', 8, Filters.JOHNSON_R)
    >>> plt.plot(sp.waveset, sp(sp.waveset), label='Vega')
    >>> plt.plot(spA0V.waveset, spA0V(spA0V.waveset), label='A0V')
    >>> plt.plot(spG2V.waveset, spG2V(spG2V.waveset), label='G2V')
    >>> plt.grid(True)
    >>> plt.xlabel('nm')
    >>> plt.ylabel('FLAM')
    >>> plt.xlim(0, 10000)
    >>> plt.legend()
"""
    # read the sourcespectrum
    if spectral_type == 'vega':
        spectrum = SourceSpectrum.from_vega()
    else:
        spectrum = SourceSpectrum.from_file(
            PickelsLibrary.filename(spectral_type))

    bandpass = Filters.get(filter_name)

    spectrum_norm = spectrum.normalize(
        magnitude * synphot.units.VEGAMAG,
        bandpass,
        vegaspec=SourceSpectrum.from_vega())

    return spectrum_norm
예제 #5
0
def test_round_trip_snr_limmag(snr, exptime, ra, dec, time, night):
    """Test round trip: get_snr(get_limmag(...))"""
    kwargs = dict(
        exptime=exptime * u.s,
        coord=SkyCoord(ra * u.deg, dec * u.deg),
        time=time, night=night)

    limmag = get_limmag(
        SourceSpectrum(ConstFlux1D, amplitude=0*u.ABmag), snr=snr, **kwargs)
    snr_2 = get_snr(SourceSpectrum(ConstFlux1D, amplitude=limmag), **kwargs)
    assert snr_2 == approx(snr)
예제 #6
0
def misc():
    # get_vega() downloads this one
    synphot.specio.read_remote_spec(
        'http://ssb.stsci.edu/cdbs/calspec/alpha_lyr_stis_008.fits')

    # G5V of UVKLIB subset of Pickles library
    # see http://www.stsci.edu/hst/instrumentation/reference-data-for-calibration-and-tools/astronomical-catalogs/pickles-atlas.html
    synphot.specio.read_remote_spec(
        'http://ssb.stsci.edu/cdbs/grid/pickles/dat_uvk/pickles_uk_27.fits')

    # read the sourcespectrum
    spG5V = SourceSpectrum.from_file(
        'http://ssb.stsci.edu/cdbs/grid/pickles/dat_uvk/pickles_uk_27.fits')
    spG2V = SourceSpectrum.from_file(
        'http://ssb.stsci.edu/cdbs/grid/pickles/dat_uvk/pickles_uk_26.fits')

    filtR = SpectralElement.from_filter('johnson_r')
    spG2V_19r = spG2V.normalize(19 * synphot.units.VEGAMAG,
                                filtR,
                                vegaspec=SourceSpectrum.from_vega())

    bp = SpectralElement(Box1D, x_0=700 * u.nm, width=600 * u.nm)
    obs = Observation(spG2V_19r, bp)
    obs.countrate(area=50 * u.m**2)

    bp220 = SpectralElement(Box1D, x_0=800 * u.nm, width=400 * u.nm)
    bpCRed = SpectralElement(Box1D, x_0=1650 * u.nm, width=300 * u.nm) * 0.8

    Observation(spG2V_19r, bp220).countrate(area=50 * u.m**2)
    Observation(spG2V_19r, bpCRed).countrate(area=50 * u.m**2)

    spM0V_8R = get_normalized_star_spectrum('M0V', 8.0, 'johnson_r')

    uPhotonSecM2Micron = u.photon / (u.s * u.m**2 * u.micron)

    spG2V_8R = get_normalized_star_spectrum("G2V", 8.0, 'johnson_r')
    plt.plot(spG2V_8R.waveset,
             spG2V_8R(spG2V_8R.waveset).to(uPhotonSecM2Micron))

    # compare with Armando's
    spG2V_19R = get_normalized_star_spectrum("G2V", 19, 'johnson_r')
    bp = SpectralElement(Box1D, x_0=700 * u.nm, width=600 * u.nm)
    obs = Observation(spG2V_19R, bp)
    obs.countrate(area=50 * u.m**2)

    # zeropoint in filtro r in erg/s/cm2/A
    Observation(get_normalized_star_spectrum('A0V', 0, 'johnson_r'),
                SpectralElement.from_filter('johnson_r')).effstim('flam')
    # zeropoint in ph/s/m2
    Observation(get_normalized_star_spectrum('A0V', 0, 'johnson_r'),
                SpectralElement.from_filter('johnson_r')).countrate(area=1 *
                                                                    u.m**2)
예제 #7
0
def make_emission_from_array(flux, wave, meta):
    """
    Create an emission SourceSpectrum using array.

    Takes care of bins and solid angles. The solid_angle is kept in the returned
    SourceSpectrum meta dictionary under self.meta["solid_angle"]

    Parameters
    ----------
    flux : array-like, Quantity
        if flux is not an array, the ``emission_unit`` must be in meta dict
    wave : array-like, Quantity
        if flux is not an array, the ``wavelength_unit`` must be in meta dict
    meta : dict

    Returns
    -------
    flux : synphot.SourceSpectrum

    """

    if not isinstance(flux, u.Quantity):
        if "emission_unit" in meta:
            flux = quantify(flux, meta["emission_unit"])
        else:
            logging.warning("emission_unit must be set in self.meta, "
                            "or emission must be an astropy.Quantity")
            flux = None

    if isinstance(wave, u.Quantity) and isinstance(flux, u.Quantity):
        flux_unit, angle = extract_type_from_unit(flux.unit, "solid angle")
        flux = flux / angle

        if is_flux_binned(flux.unit):
            flux = normalise_binned_flux(flux, wave)

        orig_unit = flux.unit
        flux = SourceSpectrum(Empirical1D, points=wave, lookup_table=flux)
        flux.meta["solid_angle"] = angle
        flux.meta["history"] = [
            "Created from emission array with units {}"
            "".format(orig_unit)
        ]
    else:
        logging.warning("wavelength and emission must be "
                        "astropy.Quantity py_objects")
        flux = None

    return flux
예제 #8
0
    def from_arrays(cls,
                    waves,
                    flux,
                    meta=None,
                    wave_unit=u.AA,
                    flux_unit=units.FLAM):
        """
        Create a ``Passband`` directly from from arrays (lists, numpy.arrays, etc)
        Parameters
        ----------
        waves: list-like
        flux: list-like
        meta: dictionary containing the metadata
        wave_unit: u.Quantity, defaulted to angstroms
        flux_unit: u.Quantiy, defaulted to FLAM

        Returns
        -------
        Passband
        """
        if isinstance(waves, u.Quantity) is False:
            waves = waves * wave_unit
        if isinstance(flux, (u.Quantity, u.core.Unit)) is False:
            flux = flux * flux_unit

        modelclass = SourceSpectrum(Empirical1D,
                                    points=waves,
                                    lookup_table=flux,
                                    meta=meta)

        sp = cls(modelclass=modelclass)
        sp.repr = repr(sp.model)
        return sp
예제 #9
0
def image_source():
    n = 50
    unit = u.Unit("ph s-1 m-2 um-1")
    wave = np.linspace(0.5, 2.5, n) * u.um
    specs = [
        SourceSpectrum(Empirical1D,
                       points=wave,
                       lookup_table=np.linspace(0, 4, n) * unit)
    ]

    n = 50
    im_wcs = wcs.WCS(naxis=2)
    im_wcs.wcs.cunit = [u.arcsec, u.arcsec]
    im_wcs.wcs.cdelt = [0.2, 0.2]
    im_wcs.wcs.crval = [0, 0]
    im_wcs.wcs.crpix = [n // 2, n // 2]
    im_wcs.wcs.ctype = ["RA---TAN", "DEC--TAN"]

    im = np.ones((n + 1, n + 1)) * 1E-11
    im[0, n] += 5
    im[n, 0] += 5
    im[n // 2, n // 2] += 10

    im_hdu = fits.ImageHDU(data=im, header=im_wcs.to_header())
    im_hdu.header["SPEC_REF"] = 0
    im_source = Source(image_hdu=im_hdu, spectra=specs)

    return im_source
예제 #10
0
def calcMagFromSpec(bp, specPath, redden=None):
    sp = SourceSpectrum.from_file(specPath)
    if redden:
        sp = sp * redden
    obs = Observation(sp, bp)
    counts = obs.countrate(1.0)
    return -2.5 * np.log10(counts.value)
예제 #11
0
파일: utils.py 프로젝트: talister/etc
def read_eso_spectra(filepath):

    try:
        hdul = fits.open(filepath)
    except FileNotFoundError:
        print("Cannot find file {}".format(filepath))
        return None

    data = hdul[0].data
    hdr = hdul[0].header

    yyy = data
    if hdr.get('NAXIS3') == 4:
        # FLOYDS merged data, slice/bandid 1 has the extracted spectrum
        yyy = data[0][0]
    warnings.simplefilter('ignore', category=FITSFixedWarning)
    w = WCS(hdr, naxis=1, relax=False, fix=False)
    lam = w.wcs_pix2world(np.arange(len(yyy)), 0)[0]

    wavelength = get_x_units(lam)
    flux = get_y_units(yyy, filepath, hdr)

    source_spec = SourceSpectrum(Empirical1D,
                                 points=wavelength,
                                 lookup_table=flux,
                                 keep_neg=True,
                                 meta={'header': hdr})
    return source_spec
예제 #12
0
def filter_vega_zp(filterfile, filterzero):
    '''
    ######################################################
    # Input                                              #
    # -------------------------------------------------- #
    # filterfile: file containing filter function        #
    # filterzero: flux corresponding to mag=0            #
    # -------------------------------------------------- #
    # Output                                             #
    # -------------------------------------------------- #
    # mag_0: magnitude of Vega in filter system.         #
    ######################################################
    '''
    from synphot import SourceSpectrum, SpectralElement, Observation
    
    #load Vega spectrum
    spec = SourceSpectrum.from_vega()
    #Load ascii filter function
    if filterfile.split('/')[-1][:6] == 'Bessel':
        filt = SpectralElement.from_file(filterfile, wave_unit='nm')
    else:
        filt = SpectralElement.from_file(filterfile, wave_unit='AA')
    wave = filt.waveset
    #Synthetic observation
    obs = Observation(spec, filt)
    flux = obs.effstim(flux_unit='jy', waverange=(wave[0],wave[-1]))
    #Calibrate to zero point (zp)
    mag_0 = -2.512*np.log10(flux/filterzero)
    return mag_0
예제 #13
0
    def from_specutils(cls, spectrum_object):
        """
        This function _tries_ to create a Spectrum from a ``specutils.Spectrum1D`` instance.

        ``specutils.Spectrum1D``  can read multiple file formats with the ``.read`` method.
        please read ``specutils`` documentation.

        Parameters
        ----------
        spectrum_object: specutils.Spectrum1D object

        Returns
        -------
        a Spextrum instance
        """
        meta = spectrum_object.meta
        lam = spectrum_object.spectral_axis
        flux = spectrum_object.flux
        modelclass = SourceSpectrum(Empirical1D,
                                    points=lam,
                                    lookup_table=flux,
                                    meta=meta)

        sp = cls(modelclass=modelclass)
        sp.repr = "Spextrum.from_specutils(%s)" % repr(spectrum_object)

        return sp
예제 #14
0
 def collapse(self, waveset):
     throughput = self.radiometry_table.throughput(waveset)
     self._throughput = SpectralElement(Empirical1D, points=waveset,
                                        lookup_table=throughput)
     emission = self.radiometry_table.emission(waveset)
     self._emission = SourceSpectrum(Empirical1D, points=waveset,
                                     lookup_table=emission)
예제 #15
0
def extract_range_from_spectrum(spectrum, waverange):
    if not isinstance(spectrum, SourceSpectrum):
        raise ValueError(f"spectrum must be of type synphot.SourceSpectrum: "
                         f"{type(spectrum)}")

    wave_min, wave_max = utils.quantify(waverange, u.um).to(u.AA).value
    spec_waveset = spectrum.waveset.to(u.AA).value
    mask = (spec_waveset > wave_min) * (spec_waveset < wave_max)

    if sum(mask) == 0:
        logging.warning(f"Waverange does not overlap with Spectrum waveset: "
                      f"{[wave_min, wave_max]} <> {spec_waveset} "
                      f"for spectrum {spectrum}")
    if wave_min < min(spec_waveset) or wave_max > max(spec_waveset):
        logging.warning(f"Waverange only partially overlaps with Spectrum waveset: "
                      f"{[wave_min, wave_max]} <> {spec_waveset} "
                      f"for spectrum {spectrum}")

    wave = np.r_[wave_min, spec_waveset[mask], wave_max]
    flux = spectrum(wave)

    new_spectrum = SourceSpectrum(Empirical1D, points=wave, lookup_table=flux)
    new_spectrum.meta.update(spectrum.meta)

    return new_spectrum
예제 #16
0
    def sso_to_source_spec(self, tax_type):
        """Returns a SourceSpectrum from the passed <tax_type> if it is found
        in the Bus-DeMeo taxonomy, otherwise None is returned.
        The spectrum is produced by multiplying the reflectance spectra by
        a Kurucz model for the Sun so will need to be normalized"""

        source_spec = None

        if tax_type.lower().startswith('sso::') is False:
            tax_type = 'sso::' + tax_type.strip()
        config_item = conf.source_mapping.get(tax_type, None)
        if config_item is not None:
            filename = config_item()
            file_path = os.path.expandvars(filename)
            if not os.path.exists(file_path):
                file_path = str(
                    pkg_resources.files('etc.data').joinpath(filename))
            # Flux unit for LSST throughputs (*almost* FLAM but nm not Angstroms)
            lsst_funit = u.erg / u.cm**2 / u.s / u.nm
            source_spec = SourceSpectrum.from_file(file_path,
                                                   wave_unit=u.nm,
                                                   flux_unit=lsst_funit,
                                                   header_start=1)
            source_spec.meta['header']['source'] = config_item.description
            source_spec.meta['header']['filename'] = filename

        return source_spec
예제 #17
0
def calculate_values(detector, filt, mjd, aper):
    # parameters can be removed from obsmode as needed
    obsmode = 'wfc3,{},{},mjd#{},aper#{}'.format(detector, filt, mjd, aper)
    bp = stsyn.band(obsmode)

    # STMag
    photflam = bp.unit_response(stsyn.conf.area)  # inverse sensitivity in flam
    stmag = -21.1 - 2.5 * log10(photflam.value)

    # Pivot Wavelength and bandwidth
    photplam = bp.pivot()  # pivot wavelength in angstroms
    bandwidth = bp.photbw()  # bandwidth in angstroms

    # ABMag
    abmag = stmag - 5 * log10(photplam.value) + 18.6921

    # Vegamag
    #for some reason stsyn.Vega doesn't load so we redefine it
    stsyn.Vega = SourceSpectrum.from_vega()
    obs = Observation(
        stsyn.Vega, bp, binset=bp.binset
    )  # synthetic observation of vega in bandpass using vega spectrum
    vegamag = -obs.effstim(flux_unit='obmag', area=stsyn.conf.area)

    return obsmode, photplam.value, bandwidth.value, photflam.value, stmag, abmag, vegamag.value
def get_phot(waves, exts, bands):
    """
    Compute the extinction in the requested bands

    Parameters
    ----------
    waves : numpy.ndarray
        The wavelengths

    exts : numpy.ndarray
        The extinction values at wavelengths "waves"

    bands: list of strings
        Bands requested

    Outputs
    -------
    band extinctions : numpy array
        Calculated band extinctions
    """
    # create a SourceSpectrum object from the extinction curve
    spectrum = SourceSpectrum(
        Empirical1D,
        points=waves * 1e4,
        lookup_table=exts,
    )

    # path for band response curves
    band_path = (
        "/Users/mdecleir/measure_extinction/measure_extinction/data/Band_RespCurves/"
    )

    # dictionary linking the bands to their response curves
    bandnames = {
        "J": "2MASSJ",
        "H": "2MASSH",
        "K": "2MASSKs",
        "IRAC1": "IRAC1",
        "IRAC2": "IRAC2",
        "WISE1": "WISE1",
        "WISE2": "WISE2",
        "L": "AAOL",
        "M": "AAOM",
    }

    # compute the extinction value in each band
    band_ext = np.zeros(len(bands))
    for k, band in enumerate(bands):
        # create the bandpass (as a SpectralElement object)
        bp = SpectralElement.from_file(
            "%s%s.dat" %
            (band_path,
             bandnames[band]))  # assumes wavelengths are in Angstrom!!
        # integrate the extinction curve over the bandpass, only if the bandpass fully overlaps with the extinction curve (this actually excludes WISE2)
        if bp.check_overlap(spectrum) == "full":
            obs = Observation(spectrum, bp)
            band_ext[k] = obs.effstim().value
        else:
            band_ext[k] = np.nan
    return band_ext
예제 #19
0
def _unity_source(dx=0, dy=0, angle=0, weight=1, n=100):
    unit = u.Unit("ph s-1 m-2 um-1")
    wave = np.linspace(0.5, 2.5, n) * u.um
    specs = [
        SourceSpectrum(Empirical1D,
                       points=wave,
                       lookup_table=np.ones(n) * unit)
    ]

    im_wcs = wcs.WCS(naxis=2)
    im_wcs.wcs.cunit = [u.arcsec, u.arcsec]
    im_wcs.wcs.cdelt = [1, 1]
    im_wcs.wcs.crval = [0, 0]
    im_wcs.wcs.crpix = [n / 2, n / 2]
    im_wcs.wcs.ctype = ["RA---TAN", "DEC--TAN"]

    im = np.ones((n, n))

    im_hdu = fits.ImageHDU(data=im, header=im_wcs.to_header())
    im_hdu.header["SPEC_REF"] = 0
    im_source = Source(image_hdu=im_hdu, spectra=specs)

    angle = angle * np.pi / 180
    im_source.fields[0].header["CRVAL1"] += dx * u.arcsec.to(u.deg)
    im_source.fields[0].header["CRVAL2"] += dy * u.arcsec.to(u.deg)
    im_source.fields[0].header["PC1_1"] = np.cos(angle)
    im_source.fields[0].header["PC1_2"] = np.sin(angle)
    im_source.fields[0].header["PC2_1"] = -np.sin(angle)
    im_source.fields[0].header["PC2_2"] = np.cos(angle)
    im_source.fields[0].data *= weight

    return im_source
예제 #20
0
def ab_spectrum(mag=0):
    # ..todo: the waves vector is a bit random, in particular its length, but sets the resolution of
    #         the final spectrum in scopesim. Can this be make more general?
    waves = np.geomspace(100, 300000, 50000)
    sp = ConstFlux1D(amplitude=mag * u.ABmag)

    return SourceSpectrum(Empirical1D, points=waves, lookup_table=sp(waves))
예제 #21
0
def get_phot(spec, bands):
    """
    Compute the fluxes in the requested bands.

    Parameters
    ----------
    spec : SpecData object
        the spectrum

    bands: list of strings
        bands requested

    Outputs
    -------
    band fluxes : numpy array
        calculated band fluxes
    """

    # create a SourceSpectrum object from the spectrum, excluding the bad regions
    spectrum = SourceSpectrum(
        Empirical1D,
        points=spec.waves.to(u.Angstrom)[spec.npts != 0],
        lookup_table=spec.fluxes[spec.npts != 0],
    )

    # path for band response curves
    band_path = pkg_resources.resource_filename("measure_extinction",
                                                "data/Band_RespCurves/")

    # dictionary linking the bands to their response curves
    bandnames = {
        "J": "2MASSJ",
        "H": "2MASSH",
        "K": "2MASSKs",
        "IRAC1": "IRAC1",
        "IRAC2": "IRAC2",
        "WISE1": "WISE1",
        "WISE2": "WISE2",
        "L": "AAOL",
        "M": "AAOM",
    }

    # define the units of the output fluxes
    funit = u.erg / (u.s * u.cm * u.cm * u.Angstrom)

    # compute the flux in each band
    fluxes = np.zeros(len(bands))
    for k, band in enumerate(bands):
        # create the bandpass (as a SpectralElement object)
        bp = SpectralElement.from_file(
            "%s%s.dat" %
            (band_path,
             bandnames[band]))  # assumes wavelengths are in Angstrom!!
        # integrate the spectrum over the bandpass, only if the bandpass fully overlaps with the spectrum (this actually excludes WISE2)
        if bp.check_overlap(spectrum) == "full":
            obs = Observation(spectrum, bp)
            fluxes[k] = obs.effstim(funit).value
        else:
            fluxes[k] = np.nan
    return fluxes
예제 #22
0
    def apply_to(self, obj):
        """
        obj == SourceBase - applies throughput
        obj == ImagePlaneBase - applies emission if Imager
        obj == FieldOfViewBase - applies emission if Spectrograph

        """
        if isinstance(obj, SourceBase) and not self.is_empty:
            self.meta = utils.from_currsys(self.meta)
            for ii in range(len(obj.spectra)):
                spec = obj.spectra[ii]
                wave_val = spec.waveset.value
                wave_unit = spec.waveset.unit  # angstrom
                wave_min = quantify(self.meta["wave_min"], u.um).to(u.AA)
                wave_max = quantify(self.meta["wave_max"], u.um).to(u.AA)
                mask = (wave_val > wave_min.value) * (wave_val < wave_max.value)

                wave = ([wave_min.value] + list(wave_val[mask]) +
                        [wave_max.value]) * wave_unit
                thru = self.throughput(wave)
                flux = spec(wave)
                flux *= thru
                new_source = SourceSpectrum(Empirical1D, points=wave,
                                            lookup_table=flux)
                obj.spectra[ii] = new_source

        elif isinstance(obj, ImagePlaneBase) and not self.is_empty:
            # by calling use_area, the surface area is taken into account, but
            # the units are stuck in PHOTLAM for synphot
            emission = self.get_emission(use_area=True)  # --> PHOTLAM * area
            if emission is not None:
                wave = emission.waveset  # angstrom
                flux = emission(wave)    # PHOTLAM --> ph s-1 cm-2 AA-1 * cm2
                phs = (np.trapz(flux, wave) * u.cm**2).to(u.Unit("ph s-1"))
            else:
                phs = 0 * (u.ph / u.s)

            obj.hdu.data += phs.value

        elif isinstance(obj, FieldOfViewBase) and not self.is_empty:
            # ..todo:: Super hacky, FIX THIS!!
            emission = self.get_emission(use_area=True)  # --> PHOTLAM * area
            if emission is not None:
                wave_val = emission.waveset.value
                wave_unit = emission.waveset.unit   # angstrom
                wave_min = quantify(obj.meta["wave_min"], u.um).to(wave_unit)
                wave_max = quantify(obj.meta["wave_max"], u.um).to(wave_unit)
                mask = (wave_val > wave_min.value) * (wave_val < wave_max.value)

                wave = ([wave_min.value] + list(wave_val[mask]) +
                        [wave_max.value]) * wave_unit
                flux = emission(wave)    # PHOTLAM --> ph s-1 cm-2 AA-1 * cm2
                phs = (np.trapz(flux, wave) * u.cm**2).to(u.Unit("ph s-1"))
            else:
                phs = 0 * (u.ph / u.s)

            obj.hdu.data += phs.value

        return obj
예제 #23
0
    def __init__(self, template_name=None, modelclass=None, **kwargs):

        if template_name is not None:
            if template_name in DEFAULT_SPECTRA:
                template_name = DEFAULT_SPECTRA[template_name]

            SpectrumContainer.__init__(self, template_name)
            meta, lam, flux = self._loader()
            SourceSpectrum.__init__(self, Empirical1D, points=lam, lookup_table=flux, meta=meta,  **kwargs)

            self.repr = "Spextrum(%s)" % self.template
        elif modelclass is not None:

            SourceSpectrum.__init__(self, modelclass=modelclass, **kwargs)

        else:
            raise ValueError("please define a spectra")
예제 #24
0
    def test_throws_error_if_only_partial_overlap_exists(self):
        wave = np.arange(0.7, 2.05, 0.1) * u.um
        flux = np.arange(len(wave)) * PHOTLAM
        spec = SourceSpectrum(Empirical1D, points=wave, lookup_table=flux)

        with pytest.raises(ValueError):
            waverange = [1.98, 2.12] * u.um
            new_spec = fov_utils.extract_range_from_spectrum(spec, waverange)
예제 #25
0
    def sky_spectrum_from_filter(self, filtername='V'):
        waveset = np.arange(3000, 12001, 1) * u.AA
        sky_flux = np.empty(len(waveset))
        sky_flux.fill(self._photon_rate(filtername))
        sky_flux = u.Quantity(sky_flux, unit=units.PHOTLAM)
        sky = SourceSpectrum(Empirical1D,
                             points=waveset,
                             lookup_table=sky_flux)

        return sky
예제 #26
0
파일: dust.py 프로젝트: rtanmay/sbpy
    def _planck(Tscale, T, eph):
        """Planck function and temperature for dust thermal emission."""
        if not synphot:
            raise AstropyWarning(
                'synphot is required for blackbody calculations')

        if T is None:
            T = Tscale * 278 / np.sqrt(eph['rh'] / u.au) * u.K
        # Does not include the factor of pi:
        return SourceSpectrum(BlackBody1D, temperature=T)
예제 #27
0
 def test_returns_correct_units_with_without_area_argument(
         self, area, expected_units):
     flux = np.ones(11) * u.Unit("ph s-1 m-2 um-1")
     wave = np.linspace(1, 2, 11) * u.um
     spec = SourceSpectrum(Empirical1D, points=wave, lookup_table=flux)
     counts = source_utils.photons_in_range([spec],
                                            1 * u.um,
                                            2 * u.um,
                                            area=area)
     assert counts.unit == expected_units
예제 #28
0
def test_round_trip_snr_exptime(snr, mag, ra, dec, time, night):
    """Test round trip: get_snr(get_limmag(...))"""
    source = SourceSpectrum(ConstFlux1D, amplitude=mag * u.ABmag)
    kwargs = dict(
        coord=SkyCoord(ra * u.deg, dec * u.deg),
        night=night, time=time)

    exptime = get_exptime(source, snr=snr, **kwargs)
    snr_2 = get_snr(source, exptime=exptime, **kwargs)
    assert snr_2 == approx(snr)
예제 #29
0
def Scorr_vega(filt1,filt2, zerof1,zerof2):
    from synphot import SourceSpectrum
    
    #load Vega spectrum
    spec = SourceSpectrum.from_vega()
    #Scorr = -2.5log(flux2/flux1) such that mag2 = mag1 + Scorr
    mag1 = filter_mag(filt1, zerof1, spec)
    mag2 = filter_mag(filt2, zerof2, spec)
    scorr = mag2 - mag1
    return scorr
예제 #30
0
    def test_extracts_the_wave_range_needed(self):
        wave = np.arange(0.7, 2.5, 0.1) * u.um
        flux = np.arange(len(wave)) * PHOTLAM
        spec = SourceSpectrum(Empirical1D, points=wave, lookup_table=flux)

        waverange = [1.98, 2.12] * u.um
        new_spec = fov_utils.extract_range_from_spectrum(spec, waverange)

        assert len(new_spec.waverange) == 2
        assert new_spec.waverange[0] == 1.98 * u.um
        assert new_spec(1.98 * u.um).value == approx(12.8)