Source code for astrobase.services.trilegal

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# trilegal - Waqas Bhatti (wbhatti@astro.princeton.edu) - Dec 2017
# License: MIT. See the LICENSE file for more details.

'''
This downloads and interacts with galaxy models generated by the TRILEGAL
web-form by Prof. Leo Girardi. This module requires the `requests` and `astropy`
packages only and can be used without astrobase if the accompanying `dust.py`
module is located in the same directory as this module.

If you use this, please cite the TRILEGAL papers:

http://stev.oapd.inaf.it/~webmaster/trilegal_1.6/papers.html

and link to the TRILEGAL website:

http://stev.oapd.inaf.it/cgi-bin/trilegal

The extinction coefficient Av_at_infinity for the requested coordinates is
automatically obtained from the 2MASS DUST service at:

http://irsa.ipac.caltech.edu/applications/DUST/

'''

#############
## LOGGING ##
#############

import logging
from astrobase import log_sub, log_fmt, log_date_fmt

DEBUG = False
if DEBUG:
    level = logging.DEBUG
else:
    level = logging.INFO
LOGGER = logging.getLogger(__name__)
logging.basicConfig(
    level=level,
    style=log_sub,
    format=log_fmt,
    datefmt=log_date_fmt,
)

LOGDEBUG = LOGGER.debug
LOGINFO = LOGGER.info
LOGWARNING = LOGGER.warning
LOGERROR = LOGGER.error
LOGEXCEPTION = LOGGER.exception


#############
## IMPORTS ##
#############

import os
import os.path
import gzip
import hashlib
import time
import re
from datetime import datetime
import copy

import numpy as np

# to do the queries
import requests
import requests.exceptions

# to convert to/from galactic coords
from astropy.coordinates import SkyCoord
from astropy import units as u


###################
## LOCAL IMPORTS ##
###################

from . import dust


############################
## TRILEGAL FORM SETTINGS ##
############################

# URL of the POST form target
TRILEGAL_POSTURL = 'http://stev.oapd.inaf.it/cgi-bin/trilegal_{formversion}'

# BASE URL for the results
TRILEGAL_BASEURL = 'http://stev.oapd.inaf.it'

# regex to get the result file name
TRILEGAL_REGEX = re.compile(r'a href\S*.dat')

# these are the params that the user will probably interact with the most
TRILEGAL_INPUT_PARAMS = {
    'binary_kind':'1',
    'extinction_infty':'0.0398',
    'extinction_sigma':'0.1',
    'gc_b':'60.0',
    'gc_l':'90.0',
    'field':'1.0',
    'icm_lim':'4',
    'mag_lim':'26.0',
    'photsys_file':'tab_mag_odfnew/tab_mag_sloan_2mass.dat',
    'trilegal_version':'1.6',
}

# these are taken from get_trilegal.pm, a Perl script from Prof. Leo Girardi
# a version of this is at T. D. Morton's VESPA github repository:
# https://github.com/timothydmorton/VESPA/blob/master/scripts/get_trilegal
TRILEGAL_DEFAULT_PARAMS = {
    'binary_frac': '0.3',
    'binary_kind': '${use_binaries}',
    'binary_mrinf': '0.7',
    'binary_mrsup': '1',
    'bulge_a': '1',
    'bulge_a0': '95',
    'bulge_am': '2500',
    'bulge_b': '-2.0e9',
    'bulge_csi': '0.31',
    'bulge_cutoffmass': '0.01',
    'bulge_eta': '0.68',
    'bulge_file': 'tab_sfr/file_sfr_bulge_zoccali_p03.dat',
    'bulge_kind': '2',
    'bulge_phi0': '15',
    'bulge_rho_central': '406.0',
    'eq_alpha': '0',
    'eq_delta': '0',
    'extinction_h_r': '100000',
    'extinction_h_z': '110',
    'extinction_infty': '${avextinction}',
    'extinction_kind': '2',
    'extinction_rho_sun': '0.00015',
    'extinction_sigma': '${sigmaav_av}',
    'field': '${area}',
    'gal_coord': '1',  # 1 -> set to gl_deg, gb_deg, 2 -> set to ra_hr, decl_deg
    'gc_b': '${gal_b}',
    'gc_l': '${gal_l}',
    'halo_a': '1',
    'halo_b': '0',
    'halo_file': 'tab_sfr/file_sfr_halo.dat',
    'halo_kind': '2',
    'halo_q': '0.65',
    'halo_r_eff': '2800',
    'halo_rho_sun': '0.00015',
    'icm_lim': '${icmlim}',
    'imf_file': 'tab_imf/imf_chabrier_lognormal.dat',
    'mag_lim': '${maglim}',
    'mag_res': '0.1',
    'object_a': '1',
    'object_av': '1.504',
    'object_avkind': '1',
    'object_b': '0',
    'object_cutoffmass': '0.8',
    'object_dist': '1658',
    'object_file': 'tab_sfr/file_sfr_m4.dat',
    'object_kind': '0',
    'object_mass': '1280',
    'output_kind': '1',
    'photsys_file': 'tab_mag_odfnew/tab_mag_${system}.dat',
    'r_sun': '8700',
    'submit_form': 'Submit',
    'thickdisk_a': '1',
    'thickdisk_b': '0',
    'thickdisk_file': 'tab_sfr/file_sfr_thickdisk.dat',
    'thickdisk_h_r': '2800',
    'thickdisk_h_z': '800',
    'thickdisk_kind': '0',
    'thickdisk_r_max': '15000',
    'thickdisk_r_min': '0',
    'thickdisk_rho_sun': '0.0015',
    'thindisk_a': '0.8',
    'thindisk_b': '0',
    'thindisk_file': 'tab_sfr/file_sfr_thindisk_mod.dat',
    'thindisk_h_r': '2800',
    'thindisk_h_z0': '95',
    'thindisk_hz_alpha': '1.6666',
    'thindisk_hz_tau0': '4400000000',
    'thindisk_kind': '3',
    'thindisk_r_max': '15000',
    'thindisk_r_min': '0',
    'thindisk_rho_sun': '59',
    'trilegal_version': '${version}',
    'z_sun': '24.2'
}


# these were extracted from the TRILEGAL HTML form at:
# http://stev.oapd.inaf.it/cgi-bin/trilegal
TRILEGAL_FILTER_SYSTEMS = {
    '2mass': {
        'desc': '2MASS JHKs',
        'table': 'tab_mag_odfnew/tab_mag_2mass.dat'
    },
    '2mass_spitzer_wise': {
        'desc': '2MASS + Spitzer (IRAC+MIPS) + WISE',
        'table': 'tab_mag_odfnew/tab_mag_2mass_spitzer_wise.dat'
    },
    '2mass_spitzer_wise_washington_ddo51': {
        'desc': '2MASS+Spitzer+WISE+Washington+DDO51',
        'table': ('tab_mag_odfnew/'
                  'tab_mag_2mass_spitzer_wise_washington_ddo51.dat')
    },
    'TESS_2mass_kepler': {
        'desc': ('TESS + 2MASS (Vegamags) + Kepler + SDSS griz + '
                 'DDO51 (in ABmags)'),
        'table': 'tab_mag_odfnew/tab_mag_TESS_2mass_kepler.dat'
    },
    'UVbright': {
        'desc': 'HST+GALEX+Swift/UVOT UV filters',
        'table': 'tab_mag_odfnew/tab_mag_UVbright.dat'
    },
    'acs_hrc': {
        'desc': 'HST/ACS HRC',
        'table': 'tab_mag_odfnew/tab_mag_acs_hrc.dat'
    },
    'acs_wfc': {
        'desc': 'HST/ACS WFC',
        'table': 'tab_mag_odfnew/tab_mag_acs_wfc.dat'
    },
    'akari': {
        'desc': 'AKARI',
        'table': 'tab_mag_odfnew/tab_mag_akari.dat'
    },
    'batc': {
        'desc': 'BATC',
        'table': 'tab_mag_odfnew/tab_mag_batc.dat'
    },
    'bessell': {
        'desc': 'UBVRIJHKLMN (cf. Bessell 1990 + Bessell & Brett 1988)',
        'table': 'tab_mag_odfnew/tab_mag_bessell.dat'
    },
    'ciber': {
        'desc': 'CIBER',
        'table': 'tab_mag_odfnew/tab_mag_ciber.dat'
    },
    'dcmc': {
        'desc': 'DCMC',
        'table': 'tab_mag_odfnew/tab_mag_dcmc.dat'
    },
    'decam': {
        'desc': 'DECAM (ABmags)',
        'table': 'tab_mag_odfnew/tab_mag_decam.dat'
    },
    'decam_vista': {
        'desc': 'DECAM ugrizY (ABmags) + VISTA ZYJHKs (Vegamags)',
        'table': 'tab_mag_odfnew/tab_mag_decam_vista.dat'
    },
    'denis': {
        'desc': 'DENIS',
        'table': 'tab_mag_odfnew/tab_mag_denis.dat'
    },
    'dmc14': {
        'desc': 'DMC 14 filters',
        'table': 'tab_mag_odfnew/tab_mag_dmc14.dat'
    },
    'dmc15': {
        'desc': 'DMC 15 filters',
        'table': 'tab_mag_odfnew/tab_mag_dmc15.dat'
    },
    'eis': {
        'desc': 'ESO/EIS (WFI UBVRIZ + SOFI JHK)',
        'table': 'tab_mag_odfnew/tab_mag_eis.dat'
    },
    'gaia': {
        'desc': "Gaia's G, G_BP and G_RP (Vegamags)",
        'table': 'tab_mag_odfnew/tab_mag_gaia.dat'
    },
    'galex': {
        'desc': "GALEX FUV+NUV (Vegamag) + Johnson's UBV",
        'table': 'tab_mag_odfnew/tab_mag_galex.dat'
    },
    'galex_sloan': {
        'desc': 'GALEX FUV+NUV + SDSS ugriz (all ABmags)',
        'table': 'tab_mag_odfnew/tab_mag_galex_sloan.dat'
    },
    'int_wfc': {
        'desc': 'INT/WFC (Vegamag)',
        'table': 'tab_mag_odfnew/tab_mag_int_wfc.dat'
    },
    'iphas': {
        'desc': 'IPHAS',
        'table': 'tab_mag_odfnew/tab_mag_iphas.dat'
    },
    'jwst_wide': {
        'desc': 'planned JWST wide filters',
        'table': 'tab_mag_odfnew/tab_mag_jwst_wide.dat'
    },
    'kepler': {
        'desc': 'Kepler + SDSS griz + DDO51 (in ABmags)',
        'table': 'tab_mag_odfnew/tab_mag_kepler.dat'
    },
    'kepler_2mass': {
        'desc': ('Kepler + SDSS griz + DDO51 (in ABmags) + 2MASS '
                 '(~Vegamag)'),
        'table': 'tab_mag_odfnew/tab_mag_kepler_2mass.dat'
    },
    'lbt_lbc': {
        'desc': 'LBT/LBC (Vegamag)',
        'table': 'tab_mag_odfnew/tab_mag_lbt_lbc.dat'
    },
    'lsst': {
        'desc': ('LSST ugrizY, March 2012 total filter throughputs (all '
                 'ABmags)'),
        'table': 'tab_mag_odfnew/tab_mag_lsst.dat'
    },
    'megacam': {
        'desc': "CFHT/Megacam u*g'r'i'z'",
        'table': 'tab_mag_odfnew/tab_mag_megacam.dat'
    },
    'megacam_wircam': {
        'desc': 'CFHT Megacam + Wircam (all ABmags)',
        'table': 'tab_mag_odfnew/tab_mag_megacam_wircam.dat'
    },
    'nicmosab': {
        'desc': 'HST/NICMOS AB',
        'table': 'tab_mag_odfnew/tab_mag_nicmosab.dat'
    },
    'nicmosst': {
        'desc': 'HST/NICMOS ST',
        'table': 'tab_mag_odfnew/tab_mag_nicmosst.dat'
    },
    'nicmosvega': {
        'desc': 'HST/NICMOS vega',
        'table': 'tab_mag_odfnew/tab_mag_nicmosvega.dat'
    },
    'noao_ctio_mosaic2': {
        'desc': 'NOAO/CTIO/MOSAIC2 (Vegamag)',
        'table': 'tab_mag_odfnew/tab_mag_noao_ctio_mosaic2.dat'
    },
    'ogle': {
        'desc': 'OGLE-II',
        'table': 'tab_mag_odfnew/tab_mag_ogle.dat'
    },
    'ogle_2mass_spitzer': {
        'desc': 'OGLE + 2MASS + Spitzer (IRAC+MIPS)',
        'table': 'tab_mag_odfnew/tab_mag_ogle_2mass_spitzer.dat'
    },
    'panstarrs1': {
        'desc': 'Pan-STARRS1',
        'table': 'tab_mag_odfnew/tab_mag_panstarrs1.dat'
    },
    'sloan': {
        'desc': 'SDSS ugriz',
        'table': 'tab_mag_odfnew/tab_mag_sloan.dat'
    },
    'sloan_2mass': {
        'desc': 'SDSS ugriz + 2MASS JHKs',
        'table': 'tab_mag_odfnew/tab_mag_sloan_2mass.dat'
    },
    'sloan_ukidss': {
        'desc': 'SDSS ugriz + UKIDSS ZYJHK',
        'table': 'tab_mag_odfnew/tab_mag_sloan_ukidss.dat'
    },
    'spitzer': {
        'desc': 'Spitzer IRAC+MIPS',
        'table': 'tab_mag_odfnew/tab_mag_spitzer.dat'
    },
    'stis': {
        'desc': 'HST/STIS imaging mode',
        'table': 'tab_mag_odfnew/tab_mag_stis.dat'
    },
    'stroemgren': {
        'desc': 'Stroemgren-Crawford',
        'table': 'tab_mag_odfnew/tab_mag_stroemgren.dat'
    },
    'suprimecam': {
        'desc': 'Subaru/Suprime-Cam (ABmags)',
        'table': 'tab_mag_odfnew/tab_mag_suprimecam.dat'
    },
    'swift_uvot': {
        'desc': 'SWIFT/UVOT UVW2, UVM2, UVW1,u (Vegamag)',
        'table': 'tab_mag_odfnew/tab_mag_swift_uvot.dat'
    },
    'tycho2': {
        'desc': 'Tycho VTBT',
        'table': 'tab_mag_odfnew/tab_mag_tycho2.dat'
    },
    'ubvrijhk': {
        'desc': 'UBVRIJHK (cf. Maiz-Apellaniz 2006 + Bessell 1990)',
        'table': 'tab_mag_odfnew/tab_mag_ubvrijhk.dat'
    },
    'ukidss': {
        'desc': 'UKIDSS ZYJHK (Vegamag)',
        'table': 'tab_mag_odfnew/tab_mag_ukidss.dat'
    },
    'vilnius': {
        'desc': 'Vilnius',
        'table': 'tab_mag_odfnew/tab_mag_vilnius.dat'
    },
    'visir': {
        'desc': 'VISIR',
        'table': 'tab_mag_odfnew/tab_mag_visir.dat'
    },
    'vista': {
        'desc': 'VISTA ZYJHKs (Vegamag)',
        'table': 'tab_mag_odfnew/tab_mag_vista.dat'
    },
    'vphas': {
        'desc': 'VPHAS+ (ABmags)',
        'table': 'tab_mag_odfnew/tab_mag_vphas.dat'
    },
    'vst_omegacam': {
        'desc': 'VST/OMEGACAM (ABmag)',
        'table': 'tab_mag_odfnew/tab_mag_vst_omegacam.dat'
    },
    'washington': {
        'desc': 'Washington CMT1T2',
        'table': 'tab_mag_odfnew/tab_mag_washington.dat'
    },
    'washington_ddo51': {
        'desc': 'Washington CMT1T2 + DDO51',
        'table': 'tab_mag_odfnew/tab_mag_washington_ddo51.dat'
    },
    'wfc3_medium': {
        'desc': ('HST/WFC3 medium filters (UVIS1+IR, final '
                 'throughputs)'),
        'table': 'tab_mag_odfnew/tab_mag_wfc3_medium.dat'
    },
    'wfc3_verywide': {
        'desc': ('HST/WFC3 long-pass and extremely wide filters '
                 '(UVIS1, final throughputs)'),
        'table': 'tab_mag_odfnew/tab_mag_wfc3_verywide.dat'
    },
    'wfc3_wide': {
        'desc': 'HST/WFC3 wide filters (UVIS1+IR, final throughputs)',
        'table': 'tab_mag_odfnew/tab_mag_wfc3_wide.dat'
    },
    'wfc3_wideverywide': {
        'desc': ('HST/WFC3 all W+LP+X filters (UVIS1+IR, final '
                 'throughputs)'),
        'table': 'tab_mag_odfnew/tab_mag_wfc3_wideverywide.dat'
    },
    'wfc3ir': {
        'desc': 'HST/WFC3 IR channel (final throughputs)',
        'table': 'tab_mag_odfnew/tab_mag_wfc3ir.dat'
    },
    'wfc3uvis1': {
        'desc': 'HST/WFC3 UVIS channel, chip 1 (final throughputs)',
        'table': 'tab_mag_odfnew/tab_mag_wfc3uvis1.dat'
    },
    'wfc3uvis2': {
        'desc': 'HST/WFC3 UVIS channel, chip 2 (final throughputs)',
        'table': 'tab_mag_odfnew/tab_mag_wfc3uvis2.dat'
    },
    'wfi': {
        'desc': 'ESO/WFI',
        'table': 'tab_mag_odfnew/tab_mag_wfi.dat'
    },
    'wfi2': {
        'desc': 'ESO/WFI2',
        'table': 'tab_mag_odfnew/tab_mag_wfi2.dat'
    },
    'wfi_sofi': {
        'desc': 'ESO/WFI+SOFI',
        'table': 'tab_mag_odfnew/tab_mag_wfi_sofi.dat'
    },
    'wfpc2': {
        'desc': 'HST/WFPC2 (Vegamag, cf. Holtzman et al. 1995)',
        'table': 'tab_mag_odfnew/tab_mag_wfpc2.dat'
    },
    'wircam': {
        'desc': 'CFHT Wircam',
        'table': 'tab_mag_odfnew/tab_mag_wircam.dat'
    }
}


##############################
## TRILEGAL QUERY FUNCTIONS ##
##############################

[docs]def list_trilegal_filtersystems(): ''' This just lists all the filter systems available for TRILEGAL. ''' print('%-40s %s' % ('FILTER SYSTEM NAME','DESCRIPTION')) print('%-40s %s' % ('------------------','-----------')) for key in sorted(TRILEGAL_FILTER_SYSTEMS.keys()): print('%-40s %s' % (key, TRILEGAL_FILTER_SYSTEMS[key]['desc']))
[docs]def query_galcoords(gal_lon, gal_lat, filtersystem='sloan_2mass', field_deg2=1.0, usebinaries=True, extinction_sigma=0.1, magnitude_limit=26.0, maglim_filtercol=4, trilegal_version=1.6, extraparams=None, forcefetch=False, cachedir='~/.astrobase/trilegal-cache', verbose=True, timeout=60.0, refresh=150.0, maxtimeout=700.0): '''This queries the TRILEGAL model form, downloads results, and parses them. Parameters ---------- gal_lon,gal_lat : float These are the center galactic longitude and latitude in degrees. filtersystem : str This is a key in the TRILEGAL_FILTER_SYSTEMS dict. Use the function :py:func:`astrobase.services.trilegal.list_trilegal_filtersystems` to see a nicely formatted table with the key and description for each of these. field_deg2 : float The area of the simulated field in square degrees. usebinaries : bool If this is True, binaries will be present in the model results. extinction_sigma : float This is the applied std dev around the `Av_extinction` value for the galactic coordinates requested. magnitude_limit : float This is the limiting magnitude of the simulation in the `maglim_filtercol` band index of the filter system chosen. maglim_filtercol : int The index in the filter system list of the magnitude limiting band. trilegal_version : float This is the the version of the TRILEGAL form to use. This can usually be left as-is. extraparams : dict or None This is a dict that can be used to override parameters of the model other than the basic ones used for input to this function. All parameters are listed in `TRILEGAL_DEFAULT_PARAMS` above. See: http://stev.oapd.inaf.it/cgi-bin/trilegal for explanations of these parameters. forcefetch : bool If this is True, the query will be retried even if cached results for it exist. cachedir : str This points to the directory where results will be downloaded. verbose : bool If True, will indicate progress and warn of any issues. timeout : float This sets the amount of time in seconds to wait for the service to respond to our initial request. refresh : float This sets the amount of time in seconds to wait before checking if the result file is available. If the results file isn't available after `refresh` seconds have elapsed, the function will wait for `refresh` seconds continuously, until `maxtimeout` is reached or the results file becomes available. maxtimeout : float The maximum amount of time in seconds to wait for a result to become available after submitting our query request. Returns ------- dict This returns a dict of the form:: {'params':the input param dict used, 'extraparams':any extra params used, 'provenance':'cached' or 'new download', 'tablefile':the path on disk to the downloaded model text file} ''' # these are the default parameters inputparams = copy.deepcopy(TRILEGAL_INPUT_PARAMS) # update them with the input params inputparams['binary_kind'] = '1' if usebinaries else '0' inputparams['extinction_sigma'] = '%.2f' % extinction_sigma inputparams['field'] = '%.2f' % field_deg2 inputparams['icm_lim'] = str(maglim_filtercol) inputparams['mag_lim'] = '%.2f' % magnitude_limit inputparams['trilegal_version'] = str(trilegal_version) # get the coordinates inputparams['gc_l'] = '%.3f' % gal_lon inputparams['gc_b'] = '%.3f' % gal_lat # check if the area is less than 10 deg^2 if field_deg2 > 10.0: LOGERROR("can't have an area > 10 square degrees") return None # get the extinction parameter. this is by default A[inf] in V. we'll use # the value from SF11 generated by the 2MASS DUST service extinction_info = dust.extinction_query(gal_lon, gal_lat, coordtype='galactic', forcefetch=forcefetch, verbose=verbose, timeout=timeout) try: Av_infinity = extinction_info['Amag']['CTIO V']['sf11'] inputparams['extinction_infty'] = '%.5f' % Av_infinity except Exception: LOGEXCEPTION( 'could not get A_V_SF11 from 2MASS DUST ' 'for Galactic coords: (%.3f, %.3f), ' 'using default value of %s' % (gal_lon, gal_lat, inputparams['extinction_infty']) ) # get the filter system table if filtersystem in TRILEGAL_FILTER_SYSTEMS: inputparams['photsys_file'] = ( TRILEGAL_FILTER_SYSTEMS[filtersystem]['table'] ) else: LOGERROR('filtersystem name: %s is not in the table of known ' 'filter systems.\n' 'Try the trilegal.list_trilegal_filtersystems() function ' 'to see all available filter systems.' % filtersystem) return None # override the complete form param dict now with our params trilegal_params = copy.deepcopy(TRILEGAL_DEFAULT_PARAMS) trilegal_params.update(inputparams) # override the final params with any extraparams if extraparams and isinstance(extraparams, dict): trilegal_params.update(extraparams) # see if the cachedir exists if '~' in cachedir: cachedir = os.path.expanduser(cachedir) if not os.path.exists(cachedir): os.makedirs(cachedir) # generate the cachefname and look for it cachekey = repr(inputparams) cachekey = hashlib.sha256(cachekey.encode()).hexdigest() cachefname = os.path.join(cachedir, '%s.txt.gz' % cachekey) provenance = 'cache' lockfile = os.path.join(cachedir, 'LOCK-%s' % cachekey) # run the query if results not found in the cache if forcefetch or (not os.path.exists(cachefname)): # first, check if a query like this is running already if os.path.exists(lockfile): with open(lockfile,'r') as infd: lock_contents = infd.read() lock_contents = lock_contents.replace('\n','') LOGERROR('this query appears to be active since %s' 'in another instance, not running it again' % lock_contents) return None else: with open(lockfile,'w') as outfd: outfd.write(datetime.utcnow().isoformat()) provenance = 'new download' try: if verbose: LOGINFO('submitting TRILEGAL request for input params: %s' % repr(inputparams)) posturl = TRILEGAL_POSTURL.format(formversion=trilegal_version) req = requests.post(posturl, data=trilegal_params, timeout=timeout) resp = req.text # get the URL of the result file resultfile = TRILEGAL_REGEX.search(resp) if resultfile: resultfile = resultfile[0] waitdone = False timeelapsed = 0.0 resultfileurl = '%s/%s' % ( TRILEGAL_BASEURL, resultfile.replace('a href=..','') ) if verbose: LOGINFO( 'request submitted sucessfully, waiting for results...' ) # wait for 2 minutes, then try to download the result file while not waitdone: if timeelapsed > maxtimeout: LOGERROR('TRILEGAL timed out after waiting for results,' ' request was: ' '%s' % repr(inputparams)) # remove the lock file if os.path.exists(lockfile): os.remove(lockfile) return None time.sleep(refresh) timeelapsed = timeelapsed + refresh try: resreq = requests.get(resultfileurl) resreq.raise_for_status() if verbose: LOGINFO('TRILEGAL completed, retrieving results...') # stream the response to the output cache file with gzip.open(cachefname,'wb') as outfd: for chunk in resreq.iter_content(chunk_size=65536): outfd.write(chunk) tablefname = cachefname waitdone = True if verbose: LOGINFO('done.') except Exception: if verbose: LOGINFO('elapsed time: %.1f, result file: %s ' 'not ready yet...' % (timeelapsed, resultfileurl)) continue else: LOGERROR('no result file URL found in TRILEGAL output, ' 'this is probably an error with the input. ' 'HTML of error page follows:\n') LOGINFO(resp) # remove the lock file if os.path.exists(lockfile): os.remove(lockfile) return None except requests.exceptions.Timeout: LOGERROR('TRILEGAL submission timed out, ' 'site is probably down. Request was: ' '%s' % repr(inputparams)) return None except Exception: LOGEXCEPTION('TRILEGAL request failed for ' '%s' % repr(inputparams)) return None finally: # remove the lock file if os.path.exists(lockfile): os.remove(lockfile) # otherwise, get the file from the cache else: if verbose: LOGINFO('getting cached TRILEGAL model result for ' 'request: %s' % (repr(inputparams))) tablefname = cachefname # return a dict pointing to the result file # we'll parse this later resdict = {'params':inputparams, 'extraparams':extraparams, 'provenance':provenance, 'tablefile':tablefname} return resdict
[docs]def query_radecl(ra, decl, filtersystem='sloan_2mass', field_deg2=1.0, usebinaries=True, extinction_sigma=0.1, magnitude_limit=26.0, maglim_filtercol=4, trilegal_version=1.6, extraparams=None, forcefetch=False, cachedir='~/.astrobase/trilegal-cache', verbose=True, timeout=60.0, refresh=150.0, maxtimeout=700.0): '''This runs the TRILEGAL query for decimal equatorial coordinates. Parameters ---------- ra,decl : float These are the center equatorial coordinates in decimal degrees filtersystem : str This is a key in the TRILEGAL_FILTER_SYSTEMS dict. Use the function :py:func:`astrobase.services.trilegal.list_trilegal_filtersystems` to see a nicely formatted table with the key and description for each of these. field_deg2 : float The area of the simulated field in square degrees. This is in the Galactic coordinate system. usebinaries : bool If this is True, binaries will be present in the model results. extinction_sigma : float This is the applied std dev around the `Av_extinction` value for the galactic coordinates requested. magnitude_limit : float This is the limiting magnitude of the simulation in the `maglim_filtercol` band index of the filter system chosen. maglim_filtercol : int The index in the filter system list of the magnitude limiting band. trilegal_version : float This is the the version of the TRILEGAL form to use. This can usually be left as-is. extraparams : dict or None This is a dict that can be used to override parameters of the model other than the basic ones used for input to this function. All parameters are listed in `TRILEGAL_DEFAULT_PARAMS` above. See: http://stev.oapd.inaf.it/cgi-bin/trilegal for explanations of these parameters. forcefetch : bool If this is True, the query will be retried even if cached results for it exist. cachedir : str This points to the directory where results will be downloaded. verbose : bool If True, will indicate progress and warn of any issues. timeout : float This sets the amount of time in seconds to wait for the service to respond to our initial request. refresh : float This sets the amount of time in seconds to wait before checking if the result file is available. If the results file isn't available after `refresh` seconds have elapsed, the function will wait for `refresh` seconds continuously, until `maxtimeout` is reached or the results file becomes available. maxtimeout : float The maximum amount of time in seconds to wait for a result to become available after submitting our query request. Returns ------- dict This returns a dict of the form:: {'params':the input param dict used, 'extraparams':any extra params used, 'provenance':'cached' or 'new download', 'tablefile':the path on disk to the downloaded model text file} ''' # convert the ra/decl to gl, gb radecl = SkyCoord(ra=ra*u.degree, dec=decl*u.degree) gl = radecl.galactic.l.degree gb = radecl.galactic.b.degree return query_galcoords(gl, gb, filtersystem=filtersystem, field_deg2=field_deg2, usebinaries=usebinaries, extinction_sigma=extinction_sigma, magnitude_limit=magnitude_limit, maglim_filtercol=maglim_filtercol, trilegal_version=trilegal_version, extraparams=extraparams, forcefetch=forcefetch, cachedir=cachedir, verbose=verbose, timeout=timeout, refresh=refresh, maxtimeout=maxtimeout)
[docs]def read_model_table(modelfile): ''' This reads a downloaded TRILEGAL model file. Parameters ---------- modelfile : str Path to the downloaded model file to read. Returns ------- np.recarray Returns the model table as a Numpy record array. ''' infd = gzip.open(modelfile) model = np.genfromtxt(infd,names=True) infd.close() return model