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
"""