""" `TweakReg` - A replacement for IRAF-based `tweakshifts`
:Authors: Warren Hack, Mihai Cara
:License: :doc:`LICENSE`
"""
from __future__ import absolute_import, division, print_function
import os
import sys
import numpy as np
from copy import copy
from six import string_types
from stsci.tools import parseinput, teal
from stsci.tools import logutil, textutil
from stsci.tools.cfgpars import DuplicateKeyError
from stwcs import updatewcs
from . import util
# __version__ and __version_date__ are defined here, prior to the importing
# of the modules below, so that those modules can use the values
# from these variable definitions, allowing the values to be designated
# in one location only.
#
# This is specifically NOT intended to match the package-wide version information.
__version__ = '1.4.7'
__version_date__ = '18-April-2018'
from . import tweakutils
from . import imgclasses
from . import catalogs
from . import imagefindpars
from . import refimagefindpars
__taskname__ = 'tweakreg' # unless someone comes up with anything better
PSET_SECTION = '_SOURCE FINDING PARS_'
PSET_SECTION_REFIMG = '_REF IMAGE SOURCE FINDING PARS_'
# !! Use pre and post underscores to hide this added section in TEAL, so that
# TEAL allows its data to stay alongside the expected data during a call to
# TweakReg(). All of this needs to be revisited.
log = logutil.create_logger(__name__)
def _managePsets(configobj, section_name, task_name, iparsobj=None, input_dict=None):
""" Read in parameter values from PSET-like configobj tasks defined for
source-finding algorithms, and any other PSET-like tasks under this task,
and merge those values into the input configobj dictionary.
"""
# Merge all configobj instances into a single object
configobj[section_name] = {}
# Load the default full set of configuration parameters for the PSET:
iparsobj_cfg = teal.load(task_name)
# Identify optional parameters in input_dicts that are from this
# PSET and add it to iparsobj:
if input_dict is not None:
for key in list(input_dict.keys()):
if key in iparsobj_cfg:
if iparsobj is not None and key in iparsobj:
raise DuplicateKeyError("Duplicate parameter '{:s}' "
"provided for task {:s}".format(key, task_name))
iparsobj_cfg[key] = input_dict[key]
del input_dict[key]
if iparsobj is not None:
iparsobj_cfg.update(iparsobj)
del iparsobj_cfg['_task_name_']
# merge these parameters into full set
configobj[section_name].merge(iparsobj_cfg)
# clean up configobj a little to make it easier for later...
# if '_RULES_' in configobj:
# del configobj['_RULES_']
def edit_imagefindpars():
""" Allows the user to edit the imagefindpars configObj in a TEAL GUI
"""
teal.teal(imagefindpars.__taskname__, returnAs=None,
autoClose=True, loadOnly=False, canExecute=False)
def edit_refimagefindpars():
""" Allows the user to edit the refimagefindpars configObj in a TEAL GUI
"""
teal.teal(refimagefindpars.__taskname__, returnAs=None,
autoClose=True, loadOnly=False, canExecute=False)
@util.with_logging
def run(configobj):
""" Primary Python interface for image registration code
This task replaces 'tweakshifts'
"""
print('TweakReg Version %s(%s) started at: %s \n'%(
__version__,__version_date__,util._ptime()[0]))
util.print_pkg_versions()
# make sure 'updatewcs' is set to False when running from GUI or if missing
# from configObj:
if 'updatewcs' not in configobj:
configobj['updatewcs'] = False
# Check to see whether or not the imagefindpars parameters have
# already been loaded, as done through the python interface.
# Repeat for refimagefindpars
if PSET_SECTION not in configobj:
# Manage PSETs for source finding algorithms
_managePsets(configobj, PSET_SECTION, imagefindpars.__taskname__)
#print configobj[PSET_SECTION]
if PSET_SECTION_REFIMG not in configobj:
# Manage PSETs for source finding algorithms in reference image
_managePsets(configobj, PSET_SECTION_REFIMG,
refimagefindpars.__taskname__)
# print out user set input parameter values for running this task
log.info("USER INPUT PARAMETERS common to all Processing Steps:")
util.printParams(configobj, log=log)
# start interpretation of input parameters
input_files = configobj['input']
# Start by interpreting the inputs
use_catfile = True
expand_refcat = configobj['expand_refcat']
enforce_user_order = configobj['enforce_user_order']
filenames, catnames = tweakutils.parse_input(
input_files, sort_wildcards=not enforce_user_order
)
catdict = {}
for indx,f in enumerate(filenames):
if catnames is not None and len(catnames) > 0:
catdict[f] = catnames[indx]
else:
catdict[f] = None
if not filenames:
print('No filenames matching input %r were found.' % input_files)
raise IOError
# Verify that files are writable (based on file permissions) so that
# they can be updated if either 'updatewcs' or 'updatehdr' have
# been turned on (2 cases which require updating the input files)
if configobj['updatewcs'] or configobj['UPDATE HEADER']['updatehdr']:
filenames = util.verifyFilePermissions(filenames)
if filenames is None or len(filenames) == 0:
raise IOError
if configobj['UPDATE HEADER']['updatehdr']:
wname = configobj['UPDATE HEADER']['wcsname']
# verify that a unique WCSNAME has been specified by the user
if not configobj['UPDATE HEADER']['reusename']:
for fname in filenames:
uniq = util.verifyUniqueWcsname(fname,wname)
if not uniq:
errstr = 'WCSNAME "%s" already present in "%s". '%(wname,fname)+\
'A unique value for the "wcsname" parameter needs to be ' + \
'specified. \n\nQuitting!'
print(textutil.textbox(errstr,width=60))
raise IOError
if configobj['updatewcs']:
print('\nRestoring WCS solutions to original state using updatewcs...\n')
updatewcs.updatewcs(filenames)
if catnames in [None,'',' ','INDEF'] or len(catnames) == 0:
catfile_par = configobj['COORDINATE FILE DESCRIPTION']['catfile']
# check to see whether the user specified input catalogs through other parameters
if catfile_par not in [None,'',' ','INDEF']:
# read in catalog file list provided by user
catnames,catdict = tweakutils.parse_atfile_cat('@'+catfile_par)
else:
use_catfile = False
if 'exclusions' in configobj and \
configobj['exclusions'] not in [None,'',' ','INDEF']:
if os.path.exists(configobj['exclusions']):
excl_files, excl_dict = tweakutils.parse_atfile_cat(
'@'+configobj['exclusions'])
# make sure the dictionary is well formed and that keys are base
# file names and that exclusion files have been expanded:
exclusion_files = []
exclusion_dict = {}
rootpath = os.path.abspath(
os.path.split(configobj['exclusions'])[0]
)
for f in excl_dict.keys():
print(f)
bf = os.path.basename(f)
exclusion_files.append(bf)
reglist = excl_dict[f]
if reglist is None:
exclusion_dict[bf] = None
continue
new_reglist = []
for regfile in reglist:
if regfile in [ None, 'None', '', ' ', 'INDEF' ]:
new_reglist.append(None)
else:
abs_regfile = os.path.normpath(
os.path.join(rootpath, regfile)
)
new_reglist.append(abs_regfile)
exclusion_dict[bf] = new_reglist
else:
raise IOError('Could not find specified exclusions file "{:s}"'
.format(configobj['exclusions']))
else:
exclusion_files = [None]*len(filenames)
exclusion_dict = {}
for f in filenames:
exclusion_dict[os.path.basename(f)] = None
# Verify that we have the same number of catalog files as input images
if catnames is not None and (len(catnames) > 0):
missed_files = []
for f in filenames:
if f not in catdict:
missed_files.append(f)
if len(missed_files) > 0:
print('The input catalogs does not contain entries for the following images:')
print(missed_files)
raise IOError
else:
# setup array of None values as input to catalog parameter for Image class
catnames = [None]*len(filenames)
use_catfile = False
# convert input images and any provided catalog file names into Image objects
input_images = []
# copy out only those parameters needed for Image class
catfile_kwargs = tweakutils.get_configobj_root(configobj)
# define default value for 'xyunits' assuming sources to be derived from image directly
catfile_kwargs['xyunits'] = 'pixels' # initialized here, required by Image class
del catfile_kwargs['exclusions']
if use_catfile:
# reset parameters based on parameter settings in this section
catfile_kwargs.update(configobj['COORDINATE FILE DESCRIPTION'])
for sort_par in imgclasses.sortKeys:
catfile_kwargs['sort_'+sort_par] = catfile_kwargs[sort_par]
# Update parameter set with 'SOURCE FINDING PARS' now
catfile_kwargs.update(configobj[PSET_SECTION])
uphdr_par = configobj['UPDATE HEADER']
hdrlet_par = configobj['HEADERLET CREATION']
objmatch_par = configobj['OBJECT MATCHING PARAMETERS']
catfit_pars = configobj['CATALOG FITTING PARAMETERS']
catfit_pars['minobj'] = objmatch_par['minobj']
objmatch_par['residplot'] = catfit_pars['residplot']
hdrlet_par.update(uphdr_par) # default hdrlet name
catfile_kwargs['updatehdr'] = uphdr_par['updatehdr']
shiftpars = configobj['OPTIONAL SHIFTFILE OUTPUT']
# verify a valid hdrname was provided, if headerlet was set to True
imgclasses.verify_hdrname(**hdrlet_par)
print('\nFinding shifts for: ')
for f in filenames:
print(' {}'.format(f))
log.info("USER INPUT PARAMETERS for finding sources for each input image:")
util.printParams(catfile_kwargs, log=log)
try:
minsources = max(1, catfit_pars['minobj'])
omitted_images = []
all_input_images = []
for imgnum in range(len(filenames)):
# Create Image instances for all input images
try:
regexcl = exclusion_dict[os.path.basename(filenames[imgnum])]
except KeyError:
regexcl = None
pass
img = imgclasses.Image(filenames[imgnum],
input_catalogs=catdict[filenames[imgnum]],
exclusions=regexcl,
**catfile_kwargs)
all_input_images.append(img)
if img.num_sources < minsources:
warn_str = "Image '{}' will not be aligned " \
"since it contains fewer than {} sources." \
.format(img.name, minsources)
print('\nWARNING: {}\n'.format(warn_str))
log.warning(warn_str)
omitted_images.append(img)
continue
input_images.append(img)
except KeyboardInterrupt:
for img in input_images:
img.close()
print('Quitting as a result of user request (Ctrl-C)...')
return
# create set of parameters to pass to RefImage class
kwargs = tweakutils.get_configobj_root(configobj)
# Determine a reference image or catalog and
# return the full list of RA/Dec positions
# Determine what WCS needs to be used for reference tangent plane
refcat_par = configobj['REFERENCE CATALOG DESCRIPTION']
if refcat_par['refcat'] not in [None,'',' ','INDEF']: # User specified a catalog to use
# Update kwargs with reference catalog parameters
kwargs.update(refcat_par)
# input_images list can be modified below.
# So, make a copy of the original:
input_images_orig_copy = copy(input_images)
do_match_refimg = False
# otherwise, extract the catalog from the first input image source list
if configobj['refimage'] not in [None, '',' ','INDEF']: # User specified an image to use
# A hack to allow different source finding parameters for
# the reference image:
ref_sourcefind_pars = \
tweakutils.get_configobj_root(configobj[PSET_SECTION_REFIMG])
ref_catfile_kwargs = catfile_kwargs.copy()
ref_catfile_kwargs.update(ref_sourcefind_pars)
ref_catfile_kwargs['updatehdr'] = False
log.info("USER INPUT PARAMETERS for finding sources for "
"the reference image:")
util.printParams(ref_catfile_kwargs, log=log)
#refimg = imgclasses.Image(configobj['refimage'],**catfile_kwargs)
# Check to see whether the user specified a separate catalog
# of reference source positions and replace default source list with it
if refcat_par['refcat'] not in [None,'',' ','INDEF']: # User specified a catalog to use
ref_source = refcat_par['refcat']
cat_src = ref_source
xycat = None
cat_src_type = 'catalog'
else:
try:
regexcl = exclusion_dict[configobj['refimage']]
except KeyError:
regexcl = None
pass
refimg = imgclasses.Image(configobj['refimage'],
exclusions=regexcl,
**ref_catfile_kwargs)
ref_source = refimg.all_radec
cat_src = None
xycat = refimg.xy_catalog
cat_src_type = 'image'
try:
if 'use_sharp_round' in ref_catfile_kwargs:
kwargs['use_sharp_round'] = ref_catfile_kwargs['use_sharp_round']
refimage = imgclasses.RefImage(configobj['refimage'],
ref_source, xycatalog=xycat,
cat_origin=cat_src, **kwargs)
refwcs_fname = refimage.wcs.filename
if cat_src is not None:
refimage.name = cat_src
except KeyboardInterrupt:
refimage.close()
for img in input_images:
img.close()
print('Quitting as a result of user request (Ctrl-C)...')
return
if len(input_images) < 1:
warn_str = "Fewer than two images are available for alignment. " \
"Quitting..."
print('\nWARNING: {}\n'.format(warn_str))
log.warning(warn_str)
for img in input_images:
img.close()
return
image = _max_overlap_image(refimage, input_images, expand_refcat,
enforce_user_order)
elif refcat_par['refcat'] not in [None,'',' ','INDEF']:
# a reference catalog is provided but not the reference image/wcs
if len(input_images) < 1:
warn_str = "No images available for alignment. Quitting..."
print('\nWARNING: {}\n'.format(warn_str))
log.warning(warn_str)
for img in input_images:
img.close()
return
if len(input_images) == 1:
image = input_images.pop(0)
else:
image, image2 = _max_overlap_pair(input_images, expand_refcat,
enforce_user_order)
input_images.insert(0, image2)
# Workaround the defect described in ticket:
# http://redink.stsci.edu/trac/ssb/stsci_python/ticket/1151
refwcs = []
for i in all_input_images:
refwcs.extend(i.get_wcs())
kwargs['ref_wcs_name'] = image.get_wcs()[0].filename
# A hack to allow different source finding parameters for
# the reference image:
ref_sourcefind_pars = \
tweakutils.get_configobj_root(configobj[PSET_SECTION_REFIMG])
ref_catfile_kwargs = catfile_kwargs.copy()
ref_catfile_kwargs.update(ref_sourcefind_pars)
ref_catfile_kwargs['updatehdr'] = False
log.info("USER INPUT PARAMETERS for finding sources for "
"the reference image (not used):")
util.printParams(ref_catfile_kwargs, log=log)
ref_source = refcat_par['refcat']
cat_src = ref_source
xycat = None
try:
if 'use_sharp_round' in ref_catfile_kwargs:
kwargs['use_sharp_round'] = ref_catfile_kwargs['use_sharp_round']
kwargs['find_bounding_polygon'] = True
refimage = imgclasses.RefImage(refwcs,
ref_source, xycatalog=xycat,
cat_origin=cat_src, **kwargs)
refwcs_fname = refimage.wcs.filename
refimage.name = cat_src
cat_src_type = 'catalog'
except KeyboardInterrupt:
refimage.close()
for img in input_images:
img.close()
print('Quitting as a result of user request (Ctrl-C)...')
return
else:
if len(input_images) < 2:
warn_str = "Fewer than two images available for alignment. " \
"Quitting..."
print('\nWARNING: {}\n'.format(warn_str))
log.warning(warn_str)
for img in input_images:
img.close()
return
kwargs['use_sharp_round'] = catfile_kwargs['use_sharp_round']
cat_src = None
refimg, image = _max_overlap_pair(input_images, expand_refcat,
enforce_user_order)
refwcs = []
#refwcs.extend(refimg.get_wcs())
#refwcs.extend(image.get_wcs())
#for i in input_images:
#refwcs.extend(i.get_wcs())
# Workaround the defect described in ticket:
# http://redink.stsci.edu/trac/ssb/stsci_python/ticket/1151
for i in all_input_images:
refwcs.extend(i.get_wcs())
kwargs['ref_wcs_name'] = refimg.get_wcs()[0].filename
try:
ref_source = refimg.all_radec
refimage = imgclasses.RefImage(refwcs, ref_source,
xycatalog=refimg.xy_catalog, **kwargs)
refwcs_fname = refimg.name
cat_src_type = 'image'
except KeyboardInterrupt:
refimage.close()
for img in input_images:
img.close()
print('Quitting as a result of user request (Ctrl-C)...')
return
omitted_images.insert(0, refimg) # refimage *must* be first
do_match_refimg = True
print("\n{0}\nPerforming alignment in the projection plane defined by the "
"WCS\nderived from '{1}'\n{0}\n".format('='*63, refwcs_fname))
if refimage.outxy is not None:
if cat_src is None:
cat_src = refimage.name
try:
log.info("USER INPUT PARAMETERS for matching sources:")
util.printParams(objmatch_par, log=log)
log.info("USER INPUT PARAMETERS for fitting source lists:")
util.printParams(configobj['CATALOG FITTING PARAMETERS'], log=log)
if hdrlet_par['headerlet']:
log.info("USER INPUT PARAMETERS for creating headerlets:")
util.printParams(hdrlet_par, log=log)
if shiftpars['shiftfile']:
log.info("USER INPUT PARAMETERS for creating a shiftfile:")
util.printParams(shiftpars, log=log)
# Now, apply reference WCS to each image's sky positions as well as the
# reference catalog sky positions,
# then perform the fit between the reference catalog positions and
# each image's positions
quit_immediately = False
xycat_lines = ''
xycat_filename = None
for img in input_images_orig_copy:
if xycat_filename is None:
xycat_filename = img.rootname+'_xy_catfile.list'
# Keep a record of all the generated input_xy catalogs
xycat_lines += img.get_xy_catnames()
retry_flags = len(input_images)*[0]
objmatch_par['cat_src_type'] = cat_src_type
while image is not None:
print ('\n'+'='*20)
print ('Performing fit for: {}\n'.format(image.name))
image.match(refimage, quiet_identity=False, **objmatch_par)
assert(len(retry_flags) == len(input_images))
if not image.goodmatch:
# we will try to match it again once reference catalog
# has expanded with new sources:
#if expand_refcat:
input_images.append(image)
retry_flags.append(1)
if len(retry_flags) > 0 and retry_flags[0] == 0:
retry_flags.pop(0)
image = input_images.pop(0)
# try to match next image in the list
continue
else:
# no new sources have been added to the reference
# catalog and we have already tried to match
# images to the existing reference catalog
#input_images.append(image) # <- add it back for later reporting
#retry_flags.append(1)
break
image.performFit(**catfit_pars)
if image.quit_immediately:
quit_immediately = True
image.close()
break
# add unmatched sources to the reference catalog
# (to expand it):
if expand_refcat:
refimage.append_not_matched_sources(image)
image.updateHeader(wcsname=uphdr_par['wcsname'],
reusename=uphdr_par['reusename'])
if hdrlet_par['headerlet']:
image.writeHeaderlet(**hdrlet_par)
if configobj['clean']:
image.clean()
image.close()
if refimage.dirty and len(input_images) > 0:
# The reference catalog has been updated with new sources.
# Clear retry flags and get next image:
image = _max_overlap_image(
refimage, input_images, expand_refcat,
enforce_user_order
)
retry_flags = len(input_images)*[0]
refimage.clear_dirty_flag()
elif len(input_images) > 0 and retry_flags[0] == 0:
retry_flags.pop(0)
image = input_images.pop(0)
else:
break
assert(len(retry_flags) == len(input_images))
if not quit_immediately:
# process images that have not been matched in order to
# update their headers:
si = 0
if do_match_refimg:
image = omitted_images[0]
image.match(refimage, quiet_identity=True, **objmatch_par)
si = 1
# process omitted (from start) images separately:
for image in omitted_images[si:]:
image.match(refimage, quiet_identity=False, **objmatch_par)
# add to the list of omitted images, images that could not
# be matched:
omitted_images.extend(input_images)
if len(input_images) > 0:
print("\nUnable to match the following images:")
print("-------------------------------------")
for image in input_images:
print(image.name)
print("")
# update headers:
for image in omitted_images:
image.performFit(**catfit_pars)
if image.quit_immediately:
quit_immediately = True
image.close()
break
image.updateHeader(wcsname=uphdr_par['wcsname'],
reusename=uphdr_par['reusename'])
if hdrlet_par['headerlet']:
image.writeHeaderlet(**hdrlet_par)
if configobj['clean']:
image.clean()
image.close()
if configobj['writecat'] and not configobj['clean']:
# Write out catalog file recording input XY catalogs used
# This file will be suitable for use as input to 'tweakreg'
# as the 'catfile' parameter
if os.path.exists(xycat_filename):
os.remove(xycat_filename)
f = open(xycat_filename, mode='w')
f.writelines(xycat_lines)
f.close()
if expand_refcat:
base_reg_name = os.path.splitext(
os.path.basename(cat_src))[0]
refimage.write_skycatalog(
'cumulative_sky_refcat_{:s}.coo' \
.format(base_reg_name),
show_flux=True, show_id=True
)
# write out shiftfile (if specified)
if shiftpars['shiftfile']:
tweakutils.write_shiftfile(input_images_orig_copy,
shiftpars['outshifts'],
outwcs=shiftpars['outwcs'])
except KeyboardInterrupt:
refimage.close()
for img in input_images_orig_copy:
img.close()
del img
print ('Quitting as a result of user request (Ctrl-C)...')
return
else:
print ('No valid sources in reference frame. Quitting...')
return
def _overlap_matrix(images):
nimg = len(images)
m = np.zeros((nimg,nimg), dtype=np.float)
for i in range(nimg):
for j in range(i+1,nimg):
p = images[i].skyline.intersection(images[j].skyline)
area = np.fabs(p.area())
m[j,i] = area
m[i,j] = area
return m
def _max_overlap_pair(images, expand_refcat, enforce_user_order):
assert(len(images) > 1)
if len(images) == 2 or not expand_refcat or enforce_user_order:
# for the special case when only two images are provided
# return (refimage, image) in the same order as provided in 'images'.
# Also, when ref. catalog is static - revert to old tweakreg behavior
im1 = images.pop(0) # reference image
im2 = images.pop(0)
return (im1, im2)
m = _overlap_matrix(images)
imgs = [f.name for f in images]
n = m.shape[0]
index = m.argmax()
i = index // n
j = index % n
si = np.sum(m[i])
sj = np.sum(m[:,j])
if si < sj:
c = j
j = i
i = c
if i < j:
j -= 1
im1 = images.pop(i) # reference image
im2 = images.pop(j)
# Sort the remaining of the input list of images by overlap area
# with the reference image (in decreasing order):
row = m[i]
row = np.delete(row, i)
row = np.delete(row, j)
sorting_indices = np.argsort(row)[::-1]
images_arr = np.asarray(images)[sorting_indices]
while len(images) > 0:
del images[0]
for k in range(images_arr.shape[0]):
images.append(images_arr[k])
return (im1, im2)
def _max_overlap_image(refimage, images, expand_refcat, enforce_user_order):
nimg = len(images)
assert(nimg > 0)
if not expand_refcat or enforce_user_order:
# revert to old tweakreg behavior
return images.pop(0)
area = np.zeros(nimg, dtype=np.float)
for i in range(nimg):
area[i] = np.fabs(
refimage.skyline.intersection(images[i].skyline).area()
)
# Sort the remaining of the input list of images by overlap area
# with the reference image (in decreasing order):
sorting_indices = np.argsort(area)[::-1]
images_arr = np.asarray(images)[sorting_indices]
while len(images) > 0:
del images[0]
for k in range(images_arr.shape[0]):
images.append(images_arr[k])
return images.pop(0)
#
# Primary interface for running this task from Python
#
[docs]def TweakReg(files=None, editpars=False, configobj=None, imagefindcfg=None,
refimagefindcfg=None, **input_dict):
"""
"""
# support input of filenames from command-line without a parameter name
# then copy this into input_dict for merging with TEAL ConfigObj parameters
# Get default or user-specified configobj for primary task
if isinstance(configobj, string_types):
if configobj == 'defaults':
# load "TEAL"-defaults (from ~/.teal/):
configobj = teal.load(__taskname__)
else:
if not os.path.exists(configobj):
raise RuntimeError('Cannot find .cfg file: '+configobj)
configobj = teal.load(configobj, strict=False)
elif configobj is None:
# load 'astrodrizzle' parameter defaults as described in the docs:
configobj = teal.load(__taskname__, defaults=True)
if files and not util.is_blank(files):
input_dict['input'] = files
elif configobj is None:
raise TypeError("TweakReg() needs either 'files' or "
"'configobj' arguments")
if 'updatewcs' in input_dict: # user trying to explicitly turn on updatewcs
configobj['updatewcs'] = input_dict['updatewcs']
del input_dict['updatewcs']
# Merge PSET configobj with full task configobj
_managePsets(configobj, PSET_SECTION, imagefindpars.__taskname__,
iparsobj=imagefindcfg, input_dict=input_dict)
_managePsets(configobj, PSET_SECTION_REFIMG,
refimagefindpars.__taskname__, iparsobj=refimagefindcfg)
# !! NOTE - the above line needs to be done so that getDefaultConfigObj()
# can merge in input_dict, however the TEAL GUI is not going to understand
# the extra section, (or use it), so work needs to be done here - some
# more thinking about how to accomplish what we want to with PSETS.
# !! For now, warn them that imagefindpars args will be ignored in GUI.
if editpars and input_dict:
idkeys = input_dict.keys()
for i in idkeys:
if i in configobj[PSET_SECTION]:
print('WARNING: ignoring imagefindpars setting "'+i+
'='+str(input_dict[i])+'", for now please enter directly into TEAL.')
input_dict.pop(i)
del configobj[PSET_SECTION] # force run() to pull it again after GUI use
del configobj[PSET_SECTION_REFIMG] # force run() to pull it again after GUI use
# If called from interactive user-interface, configObj will not be
# defined yet, so get defaults using EPAR/TEAL.
#
# Also insure that the input_dict (user-specified values) are folded in
# with a fully populated configObj instance.
try:
configObj = util.getDefaultConfigObj(__taskname__, configobj,
input_dict,
loadOnly=(not editpars))
except ValueError:
print("Problem with input parameters. Quitting...")
return
if configObj is None:
return
# If 'editpars' was set to True, util.getDefaultConfigObj() will have
# already called 'run()'.
if not editpars:
# Pass full set of parameters on to the task
run(configObj)
[docs]def help(file=None):
"""
Print out syntax help for running astrodrizzle
Parameters
----------
file : str (Default = None)
If given, write out help to the filename specified by this parameter
Any previously existing file with this name will be deleted before
writing out the help.
"""
helpstr = getHelpAsString(docstring=True, show_ver = True)
if file is None:
print(helpstr)
else:
if os.path.exists(file): os.remove(file)
f = open(file, mode = 'w')
f.write(helpstr)
f.close()
def getHelpAsString(docstring = False, show_ver = True):
"""
return useful help from a file in the script directory called
__taskname__.help
"""
install_dir = os.path.dirname(__file__)
taskname = util.base_taskname(__taskname__, '')
htmlfile = os.path.join(install_dir, 'htmlhelp', taskname + '.html')
helpfile = os.path.join(install_dir, taskname + '.help')
if docstring or (not docstring and not os.path.exists(htmlfile)):
if show_ver:
helpString = os.linesep + \
' '.join([__taskname__, 'Version', __version__,
' updated on ', __version_date__]) + 2*os.linesep
else:
helpString = ''
if os.path.exists(helpfile):
helpString += teal.getHelpFileAsString(taskname, __file__)
else:
if __doc__ is not None:
helpString += __doc__ + os.linesep
else:
helpString = 'file://' + htmlfile
return helpString
TweakReg.__doc__ = getHelpAsString(docstring = True, show_ver = False)