Commit 8f399db2 authored by Monica Rainer's avatar Monica Rainer
Browse files

GOFIO v1.0

parents
This diff is collapsed.
This diff is collapsed.
import numpy as np
def idlMod(a, b):
"""
Emulate 'modulo' behavior of IDL.
Parameters
----------
a : float or array
Numerator
b : float
Denominator
Returns
-------
IDL modulo : float or array
The result of IDL modulo operation.
"""
if isinstance(a, np.ndarray):
s = np.sign(a)
m = np.mod(a, b)
m[(s < 0)] -= b
else:
m = a % b
if a < 0: m -= b
return m
from .pyaValErrs import *
from .pyaOtherErrors import *
from .warn import *
from __future__ import print_function
import copy
import six
import traceback
class PyaErrTemplate(Exception):
def __init__(self, what, errType, where=None, why=None, solution=None, addInfo=None, tbfe=None):
"""
The PyA error class template.
Parameters
----------
what : string
What has happened?
errType : string
Description of the type of error.
where : string
Where did it happen?
why : string
Why did it happen?
solution : string or list of strings
How can the problem be solved?
addInfo : string
Whatever additional information may be available.
tbfe : Exception
Saves trace back from a previously raised exception.
Of the parameters, only the first (what) and second (errType) are mandatory; the latter
should be provided by every more specialized exception class.
.. note:: The template should never be raised directly, but specialized derived classes
should be used.
"""
self.errorType = errType
self.what = what
self.where = where
self.why = why
# Check whether solution is iterable
self.solution = solution
if solution is not None:
if not isinstance(solution, six.string_types):
self.solution = copy.deepcopy(solution)
else:
self.solution = [solution]
self.addInfo = addInfo
# Check trace back
if not tbfe is None:
self.addTB(tbfe)
else:
self.tbfe = None
def addTB(self, e):
"""
Add trace back from another exception.
Parameters
----------
e : Exception
The exception from which to add.
"""
self.tbfe = [" - " + l for l in traceback.format_exc().splitlines(True)]
def __str__(self, head=True):
"""
Return error message as string.
Parameters:
- `head` - boolean, If True, a header will be printed says "PyA error". Setting False is, e.g.,
used in printing warnings.
"""
e = ""
if head:
e = "\n"
e += "---------------------\n"
e += "A PyA error occurred:\n"
e += "---------------------\n"
if not self.tbfe is None:
# Print information from trace back (add indentation)
e += "PyA trace back:\n"
for l in self.tbfe:
e += l
if head:
e += "Type of error: " + self.errorType + "\n"
e += "What happened?\n"
e += " " + self.what + "\n"
if not self.where is None:
e += "Where did it happen?\n"
e += " " + self.where + "\n"
if not self.why is None:
e += "Why did it happen?\n"
e += " " + self.why + "\n"
if not self.solution is None:
e += "What are possible solutions?\n"
for s in self.solution:
e += " - " + s + "\n"
if not self.addInfo is None:
e += "Additional information:\n"
e += " " + self.addInfo + "\n"
return e
from __future__ import absolute_import
from .pyaErrTemplate import PyaErrTemplate
class PyAOrderError(PyaErrTemplate):
def __init__(self, what, **keys):
"""
When to be raised?
Whenever operations seem to be carried out in the
wrong order.
"""
PyaErrTemplate.__init__(self, what, "PyA Order Error", **keys)
class PyAParameterConflict(PyaErrTemplate):
def __init__(self, what, **keys):
"""
When to be raised?
This exception should be raised when conflicting/mutually exclusive
parameters are received.
"""
PyaErrTemplate.__init__(self, what, "PyA Parameter Conflict", **keys)
class PyANetworkError(PyaErrTemplate):
def __init__(self, what, **keys):
"""
When to be raised?
This exception should be raised when an action through the network
has failed (e.g., a download).
"""
PyaErrTemplate.__init__(self, what, "PyA Network Error", **keys)
class PyANotImplemented(PyaErrTemplate):
def __init__(self, what, **keys):
"""
When to be raised?
This exception should be raised when the function/method called has not been implemented. \
Such a situation often occurs when a member is to be implemented in a derived class \
(abstract base class concept in c++).
"""
PyaErrTemplate.__init__(self, what, "PyA Not Implemented", **keys)
class PyAImportFailure(PyaErrTemplate, ImportError):
def __init__(self, what, **keys):
"""
When to be raised?
When an import fails. This may not be fatal.
"""
PyaErrTemplate.__init__(self, what, "PyA import failure", **keys)
class PyARequiredImport(PyaErrTemplate, ImportError):
def __init__(self, what, **keys):
"""
When to be raised?
If a definitely needed package (e.g., numpy) cannot be imported.
"""
PyaErrTemplate.__init__(self, what, "PyA import error", **keys)
class PyAUnclassifiedError(PyaErrTemplate):
def __init__(self, what, **keys):
"""
When to be raised?
If an error occurred that cannot or shall not be specified further.
"""
PyaErrTemplate.__init__(self, what, "PyA unclassified error", **keys)
class PyADownloadError(PyaErrTemplate):
def __init__(self, what, **keys):
"""
When to be raised?
A download could not successfully be carried out.
"""
PyaErrTemplate.__init__(self, what, "PyA download error", **keys)
class PyAFileError(PyaErrTemplate):
def __init__(self, fn, mode, **keys):
"""
When to be raised?
Whenever a file-related error is detected.
Parameters
----------
fn : string
Name of the file in question.
mode : string, {no, ne}
- "no": File could not be opened.
- "ne": File does not exist
"""
if mode == "no":
what = "File '" + str(fn) + "' could not be opened."
elif mode == "ne":
what = "File '" + str(fn) + "' does not exist."
PyaErrTemplate.__init__(self, what, "PyA file error", **keys)
class PyAAlgorithmFailure(PyaErrTemplate):
def __init__(self, what, **keys):
"""
When to be raised?
Whenever an algorithm fails in accomplishing its purpose.
"""
PyaErrTemplate.__init__(self, what, "PyA algorithm failure", **keys)
class PyADeprecationError(PyaErrTemplate):
def __init__(self, what, **keys):
"""
When to be raised?
Whenever a deprecated part of code is called.
"""
PyaErrTemplate.__init__(self, what, "PyA deprecation note", **keys)
from __future__ import absolute_import
from .pyaErrTemplate import PyaErrTemplate
class PyAValError(PyaErrTemplate):
def __init__(self, what, **keys):
"""
When to be raised?
Whenever an unexpected value is encountered.
"""
PyaErrTemplate.__init__(self, what, "PyA Value Error", **keys)
class PyANameClash(PyaErrTemplate):
def __init__(self, what, **keys):
"""
When to be raised?
Whenever an unexpected doubling of names (e.g., key values in a dictionary) is encountered.
"""
PyaErrTemplate.__init__(self, what, "PyA Name Clash", **keys)
class PyAFloatingPointError(PyaErrTemplate):
def __init__(self, what, **keys):
"""
When to be raised?
Whenever a floating point error is caught.
"""
PyaErrTemplate.__init__(self, what, "PyA Floating Point Error", **keys)
from __future__ import print_function
from __future__ import absolute_import
from .pyaErrTemplate import PyaErrTemplate
def warn(w):
"""
Parameters:
- `w` - Something which can be converted into a string.
This may especially be a PyA exception, which is treated as a warning here.
Warnings are printed to stdout.
"""
print("--------------------")
print("| PyA User warning |")
print("--------------------")
if isinstance(w, PyaErrTemplate):
print(w.__str__(head=False))
return
print(str(w))
"""
Last modified 2017-01-11
Written by Avet Harutyunyan for the old GIANO pipeline
Implemented in the GIANOB DRS by Monica Rainer
"""
import os, tempfile, datetime
from collections import OrderedDict
def getdate(date_time=None):
tlimit = datetime.time(9, 0, 0)
oneday = datetime.timedelta(days=1)
if date_time:
if isinstance(date_time, datetime.datetime):
pass
elif isinstance(date_time, basestring):
date_time = datetime.datetime.strptime(date_time, '%Y-%m-%dT%H:%M:%S.%f')
else:
date_time = datetime.datetime.utcnow()
date_, time_ = date_time.date(), date_time.time()
if time_ < tlimit:
date_ = date_ - oneday
return date_.strftime('%Y-%m-%d')
def read_usr_config(path):
f = open(path, 'r')
cntnt = f.readlines()
f.close()
usrconfig = {}
for aline in cntnt:
aline = aline.strip()
#print aline
if aline:
if aline[0] != '#':
key, value = aline.split(':::')
#print key
#print value
usrconfig[key.strip()] = eval(value.strip())
return usrconfig
usr_cfg_path = os.path.join(os.getcwd(), 'gofio.cfg')
if os.path.isfile(usr_cfg_path):
try:
USRCONFIG = read_usr_config(usr_cfg_path)
except:
USRCONFIG = {}
USRCONFIG['OFFLINE'] = False
else:
USRCONFIG ={}
USRCONFIG['OFFLINE'] = False
#
# pipeline configuration
#
CONFIG = {}
CONFIG['APPNAME'] = 'GOFIO'
CONFIG['VERSION'] = 1.0
CONFIG['DATE'] = getdate()
CONFIG['OFFLINE'] = False
#
# Directories
#
#CONFIG['BASE_RAW'] = '/mnt/nfs/RAW'
CONFIG['BASE_RAW'] = '/home/monica/Documenti/gianob/gianobdrs/varie/commissioning_marzo/raw'
CONFIG['BASE_RAMP'] = '/home/avet/gianorp/databases'
CONFIG['USR_DIR'] = os.environ.get('HOME')
CONFIG['TMP_DIR'] = tempfile.gettempdir()
CONFIG['APP_DIR'] = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CONFIG['BASE_RED_DIR'] = os.path.join(CONFIG['APP_DIR'],'reduced')
#CONFIG['BASE_RED_DIR'] = '/mnt/nfs/REDUCED'
CONFIG['RAW_DIR'] = os.path.join(CONFIG['BASE_RAW'],CONFIG['DATE'])
CONFIG['OFFLINE_DIR'] = False
CONFIG['RED_DIR'] = os.path.join(CONFIG['BASE_RED_DIR'],CONFIG['DATE'])
CONFIG['RED_CALIB'] = os.path.join(CONFIG['RED_DIR'],'CALIB')
CONFIG['RED_STR'] = os.path.join(CONFIG['RED_DIR'],'STR')
# Resources
CONFIG['RES_DIR'] = os.path.join(CONFIG['APP_DIR'], 'resources')
CONFIG['BADPIX_MASK'] = os.path.join(CONFIG['RES_DIR'], 'badpix_mask.fits')
CONFIG['LOG_FILE'] = os.path.join(CONFIG['RED_DIR'], 'drs.log')
CONFIG['STRAIGHT'] = os.path.join(CONFIG['RES_DIR'],'straight_giano_2D')
CONFIG['STRAIGHT_OPT'] = 'I=1'
CONFIG['BASE_CALIB_DIR'] = os.path.join(CONFIG['APP_DIR'], 'calibrations')
CONFIG['CALIB_DIR'] = os.path.join(CONFIG['BASE_CALIB_DIR'], 'calfiles')
CONFIG['CALIB_DB_DIR'] = os.path.join(CONFIG['BASE_CALIB_DIR'], 'database')
CONFIG['NIGHT_DB_DIR'] = os.path.join(CONFIG['APP_DIR'], 'databases')
#
# Header configuration
#
# Keywords used by the pipeline: change here if the keywords change
# If some keywords are added or removed, change varie/check_keywords accordingly.
CONFIG['KEYS'] = {'OBJECT' : 'OBJECT', 'OBSTYPE' : 'OBS-TYPE', 'OBSMODE' : 'OBSMODE' , 'IMANAME' : 'IMANAME', 'FILENAME' : 'FILENAME', 'NCOMBINE' : 'NCOMBINE', 'MJD' : 'MJD-OBS', 'EXPTIME' : 'EXPTIME', 'NODSTARE' : 'HIERARCH TNG CAT ACQTEMPL' , 'GROUPN' : 'GROUP_N', 'GROUPI' : 'GROUP_I', 'SLIT' : 'SLIT_POS' , 'STARE' : 'STAREPOS' , 'GROUPID' : 'GROUPID' , 'ID' : 'OBSID' , 'PID' : 'PAIRID' , 'NPAIRS' : 'HIERARCH TNG CAT EXP NPAIRS' ,'NREP' : 'HIERARCH TNG CAT EXP NREP' , 'EXTMODE' : 'HIERARCH TNG CAT DR SPEXTMODE' , 'RA' : 'HIERARCH TNG TEL TARG ALPHA' , 'DEC' : 'HIERARCH TNG TEL TARG DELTA' , 'PMA' : 'HIERARCH TNG TEL TARG PMA' , 'PMD' : 'HIERARCH TNG TEL TARG PMD' , 'EQUINOX' : 'HIERARCH TNG TEL TARG EQUINOX' , 'TARG_TYPE' : 'HIERARCH TNG CAT TARG TYPE' , 'AM' : 'AIRMASS' , 'RADVEL' : 'HIERARCH TNG TEL TARG RADVEL' }
# Values of the keyword:
# CONFIG['OBSTYPE'] keyword values to determine the nature of the files
CONFIG['DARK'] = 'DARK'
CONFIG['FLAT'] = 'FLAT'
CONFIG['WCAL_UNE'] = 'WCAL_UNE'
CONFIG['WCAL_FP'] = 'WCAL_FP'
CONFIG['SCIENCE'] = 'SCIENCE'
# CONFIG['NODSTARE'] keyword values to determine if stare or nodding
CONFIG['NODVALUE'] = 'GIANO_sci_nodding'
CONFIG['STAREVALUE'] = 'GIANO_sci_stare'
# CONFIG['SLIT'] keyword values to determine the slit position
CONFIG['A'] = 'A' # value of CONFIG['SLIT'] for A position
CONFIG['B'] = 'B' # value of CONFIG['SLIT'] for B position
CONFIG['C'] = 'C' # value of CONFIG['SLIT'] for C position
# CONFIG['STARE'] keyword values to determine the Obj-Sky position
CONFIG['OBJ'] = 'OBJ'
CONFIG['SKY'] = 'SKY'
# CONFIG['EXTMODE'] keyword values to determine to extraction mode
CONFIG['EXTPAIR'] = 'PAIR_EXT'
CONFIG['EXTAVG'] = 'GRPAVG_EXT'
CONFIG['EXTDEFAULT'] = CONFIG['EXTAVG']
# CONFIG['TARG_TYPE'] keyword values to determine type of object (science, telluric, ...)
CONFIG['TELLURIC'] = 'TELLURIC'
CONFIG['FASTROT'] = 'FASTROT'
CONFIG['TYPE_SCIENCE'] = 'SCIENCE'
#
# Keywords added by the DRS, with relative comments
#
CONFIG['KEY_DRS'] = 'HIERARCH TNG DRS'
CONFIG['RON_EFF'] = (' '.join((CONFIG['KEY_DRS'],'RON')),'Effective RON after image reduction')
CONFIG['GAIN_EFF'] = (' '.join((CONFIG['KEY_DRS'],'GAIN')),'Effective gain after image reduction')
CONFIG['TEXP_EFF'] = (' '.join((CONFIG['KEY_DRS'],'EXPTIME')),'Effective exposure time after image reduction')
CONFIG['WLFIT'] = (' '.join((CONFIG['KEY_DRS'],'CAL WLFUNC')),'Function used for wavelength calibration')
CONFIG['WLFIT_FUNC'] = 'l0 + k1*(x-xc) + k2*(x-xc)**2 + k3*(x-xc)**3'
CONFIG['WLCOEFFS'] = {'k1':(' '.join((CONFIG['KEY_DRS'],'CAL K1')),'k1 coefficient of the calibration function'),'k2':(' '.join((CONFIG['KEY_DRS'],'CAL K2')),'k2 coefficient of the calibration function'),'k3':(' '.join((CONFIG['KEY_DRS'],'CAL K3')),'k3 coefficient of the calibration function'),'l0':(' '.join((CONFIG['KEY_DRS'],'CAL L0')),'l0 coefficient of the calibration function'),'xc':(' '.join((CONFIG['KEY_DRS'],'CAL XC')),'xc coefficient of the calibration function'),'rms':(' '.join((CONFIG['KEY_DRS'],'CAL RMSE')),'[m/s] RMS error of the calibration')}
CONFIG['SPEC_USED'] = (' '.join((CONFIG['KEY_DRS'],'SPEC')),'Images combined')
CONFIG['SPEC_MJD'] = (' '.join((CONFIG['KEY_DRS'],'MJD')),'MJD of the relative image')
CONFIG['SNR'] = (' '.join((CONFIG['KEY_DRS'],'SNR')),'SNR in the middle of the order',)
CONFIG['STRAIGHT_PAR'] = OrderedDict([ ('P1',' '.join((CONFIG['KEY_DRS'],'STR2DP1'))), ('P2',' '.join((CONFIG['KEY_DRS'],'STR2DP2'))), ('P3',' '.join((CONFIG['KEY_DRS'],'STR2DP3'))), ('P4',' '.join((CONFIG['KEY_DRS'],'STR2DP4'))), ('P5',' '.join((CONFIG['KEY_DRS'],'STR2DP5'))), ('P6',' '.join((CONFIG['KEY_DRS'],'STR2DP6'))) ])
CONFIG['DRS_MJD'] = (' '.join((CONFIG['KEY_DRS'],'MJD')),'MJD of the combined image')
CONFIG['BERV'] = (' '.join((CONFIG['KEY_DRS'],'BERV')),'Barycentric correction [km/s]')
CONFIG['HJD'] = (' '.join((CONFIG['KEY_DRS'],'HJD')),'HJD of the combined image')
CONFIG['AIRMASS'] = (' '.join((CONFIG['KEY_DRS'],'AIRMASS')),'Airmass of the combined image')
#
# DB configuration
#
# Ramp processor database
CONFIG['RAMP_NAME'] = 'ramps' + CONFIG['DATE'] + '.db'
CONFIG['DB_RAMP'] = os.path.join(CONFIG['BASE_RAMP'],CONFIG['RAMP_NAME'])
CONFIG['DB_RAMP_TBL'] = 'reducedramps'
CONFIG['DB_RAMP_COLS'] = {'fpath':'FPATH' , 'obstype':'OBSTYPE' , 'dateobs':'DATEOBS' , 'object' : 'OBJECT' , 'exptime':'EXPTIME' , 'nodstare':'NODSTARE' , 'slitpos':'SLITPOS' , 'groupi':'GROUPI' , 'groupn':'GROUPN'}
# Calibration database
CONFIG['DB_CALIB'] = 'drs_calib.db'
CONFIG['DB_CALIB_PATH'] = os.path.join(CONFIG['CALIB_DB_DIR'], CONFIG['DB_CALIB'])
CONFIG['DB_CALIB_TBL'] = 'calibrations'
#CONFIG['DB_CALIB_COLS'] = {'01_data': 'date_calib', 'dark10': 'masterdark10', 'dark30': 'masterdark30', 'dark60': 'masterdark60', 'dark100': 'masterdark100', 'flat': 'masterflat', 'flatstr': 'masterflat_str', 'flatnor': 'masterflat_nor', 'une': 'wl_une', 'une_str': 'wl_une_str', 'une_calib':'wl_une_calib' ,'fp': 'wl_fp', 'fp_str': 'wl_fp_str', 'fp_calib':'wl_fp_calib'}
CONFIG['DB_CALIB_COLS'] = OrderedDict([('01_data', 'date_calib'), ('dark10', 'masterdark10'), ('dark30', 'masterdark30'), ('dark60', 'masterdark60'), ('dark100', 'masterdark100'), ('flat', 'masterflat'), ('flatstr', 'masterflat_str'), ('flatnor', 'masterflat_nor'), ('une', 'wl_une'), ('une_str', 'wl_une_str'), ('une_calib', 'wl_une_calib'), ('fp', 'wl_fp'), ('fp_str', 'wl_fp_str'), ('fp_calib','wl_fp_calib')])
CONFIG['DB_CALIB_DATATYPE'] = OrderedDict()
for colname in CONFIG['DB_CALIB_COLS']:
CONFIG['DB_CALIB_DATATYPE'][colname] = 'TEXT'
CONFIG['DB_CALIB_DATATYPE']['01_data'] = 'TEXT unique'
# Night reduction database
CONFIG['DB_NIGHT'] = ''.join(('drs_',CONFIG['DATE'],'.db'))
CONFIG['DB_NIGHT_PATH'] = os.path.join(CONFIG['NIGHT_DB_DIR'], CONFIG['DB_NIGHT'])
CONFIG['DB_NIGHT_TBL'] = 'reduced'
CONFIG['DB_NIGHT_COLS'] = {'fpath': 'FPATH'}
CONFIG['DB_NIGHT_DATATYPE'] = {}
for colname in CONFIG['DB_CALIB_COLS']:
CONFIG['DB_NIGHT_DATATYPE'][colname] = 'TEXT'
CONFIG['DB_NIGHT_DATATYPE']['fpath'] = 'TEXT unique'
#
# Extraction info
#
CONFIG['MASK_C'] = os.path.join(CONFIG['RES_DIR'], 'GIANOB_MASKC.fits')
CONFIG['A_POS'] = 8. # guess pixel position for A
CONFIG['B_POS'] = 23. # guess pixel position for B
CONFIG['C_POS'] = 15. # guess pixel position for C
CONFIG['HWTM'] = 6. # hwtm limit for contamination between A and B
#
# Wavelength calibration
#
CONFIG['WAVE_SELECT'] = os.path.join(CONFIG['RES_DIR'], 'UNe_lines_GIANO_selected.txt')
CONFIG['WAVE_ALL'] = os.path.join(CONFIG['RES_DIR'], 'UNe_observed_lines_GIANOB_18nov2016.txt')
CONFIG['WAVE_FIT'] = {'drift':0.0, 'low_fwhm':1.7, 'high_fwhm':4.0, 'wrange1':10, 'confidence1':3, 'wrange2':5, 'confidence2':1.5, 'xc_range':10}
CONFIG['XC_GUESS'] = {32:987, 33:984, 34:982, 35:980, 36:978, 37:976, 38:974, 39:972, 40:970, 41:968, 42:965, 43:963, 44:960, 45:957, 46:955, 47:952, 48:949, 49:946, 50:943, 51:940, 52:937, 53:933, 54:930, 55:927, 56:924, 57:921, 58:918, 59:914, 60:910, 61:907, 62:904, 63:901, 64:898, 65:895, 66:892, 67:889, 68:886, 69:883, 70:880, 71:877, 72:874, 73:871, 74:868, 75:865, 76:862, 77:859, 78:857, 79:855, 80:853, 81:851}
CONFIG['L0_GUESS'] = {32:2398.32, 33:2325.63, 34:2257.24, 35:2192.68, 36:2131.75, 37:2074.09, 38:2019.53, 39:1967.73, 40:1918.56, 41:1871.75, 42:1827.18, 43:1784.70, 44:1744.14, 45:1705.38, 46:1668.31, 47:1632.82, 48:1598.81, 49:1566.20, 50:1534.86, 51:1504.78, 52:1475.85, 53:1448.03, 54:1421.20, 55:1395.38, 56:1370.45, 57:1346.41, 58:1323.22, 59:1300.78, 60:1279.12, 61:1258.15, 62:1237.85, 63:1218.21, 64:1199.17, 65:1180.72, 66:1162.83, 67:1145.47, 68:1128.62, 69:1112.26, 70:1096.36, 71:1080.91, 72:1065.89, 73:1051.28, 74:1037.06, 75:1023.22, 76:1003.74, 77:996.61, 78:983.81, 79:971.34, 80:959.17, 81:947.30}
#
# Misc Calibrations
#
CONFIG['DO_CALIB'] = {'dark':True, 'flat':True, 'une':True, 'fp':True, 'only_calib':False}
#CONFIG['DO_CALIB'] = {'dark':False, 'flat':False, 'une':False, 'fp':False, 'only_calib':False}
CONFIG['FLAT_EXPT'] = 100.0
CONFIG['WLCAL_EXPT'] = 100.0
CONFIG['FP_EXPT'] = 60.0
CONFIG['DARKLIST'] = {10:[],30:[],60:[],100:[]} # exptime dei dark
CONFIG['NDARK'] = 4 # quanti tipi di dark (esempio: 10,30,60,100 sec = 4) meglio sovrastimare
CONFIG['RON'] = 5.0 # electrons
CONFIG['GAIN'] = 2.2 # e/ADU
CONFIG['XCCD'] = 2048
CONFIG['YCCD'] = 2048
CONFIG['DARK_MEAN'] = {10:[5.0,5.0,10.0,8.0],30:[15.0,12.0,25.0,18.0],60:[25.0,20.0,40.0,32.0],100:[30.0,25.0,65.0,45.0]} # Dark quality check: mean signal below this number (4 quadrant for 4 exposure time)
#CONFIG['FLATCHECK'] = [985,1030,575,590] # region x1:x2,y1:y2 for flats' quality check
CONFIG['FLATSIGNAL'] = 300 # lowest flat signal expected to pass quality check
CONFIG['SCIENCECHECK'] = [500,540,140,160] # region x1:x2,y1:y2 for images' quality check
#CONFIG['NODSIGNAL'] = 2*CONFIG['DARK_MEAN']['quadrant'][0] # lowest image signal expected to pass quality check
CONFIG['NODSIGNAL'] = 0.0 # lowest image signal expected to pass quality check
CONFIG['USE_FLAT'] = {'global':False, 'order':True, 'nor':False} # global: flat normalized by global mean value - order: flat normalized order by order by mean value - nor: flat normalized row by row by continuum fitting, removing the blaze function - No True value: no flat division
if USRCONFIG['OFFLINE']:
for key in USRCONFIG.keys():
CONFIG[key] = USRCONFIG[key]
CONFIG['RAW_DIR'] = os.path.join(CONFIG['BASE_RAW'],CONFIG['DATE'])
CONFIG['OFFLINE_DIR'] = os.path.join(CONFIG['BASE_RED_DIR'],CONFIG['DATE'])
CONFIG['RED_DIR'] = os.path.join(CONFIG['OFFLINE_DIR'],'offline')
CONFIG['RED_CALIB'] = os.path.join(CONFIG['RED_DIR'],'CALIB')
CONFIG['RED_STR'] = os.path.join(CONFIG['RED_DIR'],'STR')
CONFIG['LOG_FILE'] = os.path.join(CONFIG['RED_DIR'], 'drs.log')
CONFIG['RAMP_NAME'] = 'ramps' + CONFIG['DATE'] + '.db'
CONFIG['DB_RAMP'] = os.path.join(CONFIG['BASE_RAMP'],CONFIG['RAMP_NAME'])
"""
Last modified: 2017-03-07
Reduction of the flat-fields:
- check the exposure time
- check the mean flux in the four quadrants
- create the masterdark
"""
from astropy import units as u
from astropy.io import fits
import warnings
from astropy.utils.exceptions import AstropyWarning
from ccdproc import CCDData, Combiner
from drslib.config import CONFIG
from drslib import db
import numpy as np
import os, shutil
class GBDarks():