Skip to content

Commit

Permalink
joinup now generates ds9 region files
Browse files Browse the repository at this point in the history
option if an aperture files is given
  • Loading branch information
Tom Marsh committed May 29, 2021
1 parent 6c83d64 commit 467d42f
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 45 deletions.
116 changes: 84 additions & 32 deletions hipercam/scripts/hpackage.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import sys
import os
import tempfile
import signal
import re
import shutil

import numpy as np
from astropy.time import Time
Expand Down Expand Up @@ -29,11 +31,11 @@ def hpackage(args=None):
``hpackage`` looks for standard data products run#.hcm, run#.ape,
run#.red, run#.log, (where # is an integer identifier), spits out
joined up images of the CCDs in run#.hcm, converts the log to fits,
and writes out a "region" file representing the apertures readable by
ds9. It then tars the whole lot up. For simplicity, it deliberately runs
with a minimal set or arguments: the run name. It won't overwrite any
file.
joined up images of the CCDs in run#.hcm, converts the log to
fits, and writes out a "region" file representing the apertures
readable by ds9. It then tars the whole lot up. For simplicity, it
deliberately runs with a minimal set or arguments: the run
name. It must be run in the directory with all the files.
"""

Expand All @@ -45,28 +47,50 @@ def hpackage(args=None):
# register parameters
cl.register("run", Cline.LOCAL, Cline.PROMPT)
run = cl.get_value("run", "run name", cline.Fname("run005", hcam.HCAM))
mccd = hcam.MCCD.read(run)
if os.path.dirname(run) != '':
raise hcam.HipercamError(
'hpackage only runs on files in the working directory'
)

# check for existence of various files
if not os.path.exists(run + HCAM.APE):
raise hcam.HipercamError(f'Could not find file = {run + hcam.APE}')
# strip extension
root = os.path.splitext(run)[0]

nre = re.compile('(\d\d\d\d)[-_](\d\d)[-_](\d\d)')
cwd = os.getcwd()
m = nre.search(cwd)
if m is None:
raise hcam.HipercamError(
'hpackage must be run in a sub-directory'
' of a night directory [YYYY[-_]MM[-_]DD]'
)

# Finally, read the hcm file
mccd = hcam.MCCD.read(run)

# check for existence of various files
if not os.path.exists(run + HCAM.LOG):
raise hcam.HipercamError(f'Could not find file = {run + hcam.LOG}')
night_run = f'{m.group(1)}-{m.group(2)}-{m.group(3)}-{root}'

with tempfile.TemporaryDirectory() as tmpdir:
# create temporary directory where everything
# gets written
print('Will write files to {tmpdir}')
# Make name of temporary directory
tdir = utils.temp_dir()
tmpdir = os.path.join(tdir, night_run)

# First make individual CCDs from .hcm file
with CleanUp(tmpdir) as cleanup:

for nc, cnam in enumerate(ccds):
ccd = mccd[cnam]
# create directory
os.makedirs(tmpdir, exist_ok=True)
print(f'Will write files to {tmpdir}')

# We need to generate a single data array for all data. First
# check that it is even possible
# copy standard files over
for ext in (hcam.APER,hcam.LOG,hcam.RED):
source = utils.add_extension(root,ext)
target = os.path.join(tmpdir,source)
shutil.copyfile(source, target)
print(f'copied {source} to {target}')

for cnam, ccd in mccd.items():

# We need to generate a single data array for all
# data. First check that it is even possible

for n, wind in enumerate(ccd.values()):
if n == 0:
Expand All @@ -83,9 +107,16 @@ def hpackage(args=None):
urxmax = max(urxmax, wind.urx)
urymax = max(urymax, wind.ury)
if xbin != wind.xbin or ybin != wind.ybin:
raise hcam.HipercamError('Found windows with clashing binning factors')
if (wind.llx - llx) % xbin != 0 or (wind.lly - lly) % ybin != 0:
raise hcam.HipercamError('Found windows which are out of sync with each other')
raise hcam.HipercamError(
'Found windows with clashing binning factors'
)

if (wind.llx - llx) % xbin != 0 or \
(wind.lly - lly) % ybin != 0:
raise hcam.HipercamError(
'Found windows which are out '
'of sync with each other'
)

# create huge array of nothing
ny = (urymax-llymin+1) // ybin
Expand All @@ -104,9 +135,14 @@ def hpackage(args=None):

# Add some extra stuff
phead["CCDLABEL"] = (cnam, "CCD label")
phead["NFRAME"] = (nf, "Frame number")
phead["LLX"] = (llxmin, "X of lower-left unbinned pixel (starts at 1)")
phead["LLY"] = (llymin, "Y of lower-left unbinned pixel (starts at 1)")
phead["LLX"] = (
llxmin,
"X of lower-left unbinned pixel (starts at 1)"
)
phead["LLY"] = (
llymin,
"Y of lower-left unbinned pixel (starts at 1)"
)
phead["NXTOT"] = (ccd.nxtot, "Total unbinned X dimension")
phead["NYTOT"] = (ccd.nytot, "Total unbinned Y dimension")
phead.add_comment('Written by HiPERCAM script "hpackage"')
Expand Down Expand Up @@ -145,9 +181,9 @@ def hpackage(args=None):
w.wcs.ctype = ['RA---TAN','DEC--TAN']
w.wcs.cunit = ["deg", "deg"]
header.update(w.to_header())
print(f' CCD {cnam}: added WCS')
print(f'CCD {cnam}: added WCS')
else:
print(f' CCD {cnam}: missing positional data; no WCS added')
print(f'CCD {cnam}: missing positional data; no WCS added')

# make the first & only HDU
hdul = fits.HDUList()
Expand All @@ -157,9 +193,25 @@ def hpackage(args=None):
)
hdul.append(compressed_hdu)

root = os.path.basename(os.path.splitext(run])[0])
oname = os.path.join(tmpdir, f'{root}_ccd{cnam}.fits')

hdul.writeto(oname, overwrite=overwrite)
print(f' CCD {cnam}: written to {oname}')
hdul.writeto(oname)
print(f'CCD {cnam}: written to {oname}')

class CleanUp:
"""
Context manager to handle temporary files
"""
def __init__(self, tmpdir):
self.tmpdir = tmpdir

def _sigint_handler(self, signal_received, frame):
print("\nhpackage aborted")
sys.exit(1)

def __enter__(self):
signal.signal(signal.SIGINT, self._sigint_handler)

def __exit__(self, type, value, traceback):
print(f'removing temporary directory {self.tmpdir}')
# shutil.rmtree(self.tmpdir)
87 changes: 79 additions & 8 deletions hipercam/scripts/joinup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

def joinup(args=None):
"""``joinup [source] (run first [twait tmax] | flist) trim ([ncol
nrow]) (ccd) bias dark flat fmap (fpair nhalf rmin rmax) msub
nrow]) (ccd) (aper) bias dark flat fmap (fpair nhalf rmin rmax) msub
dtype dmax nmax [overwrite] compress``
Converts a run or a list of hcm images into as near as possible
Expand Down Expand Up @@ -80,7 +80,7 @@ def joinup(args=None):
seconds.
flist : str [if source ends 'f']
name of file list
name of file list or just a single hcm file
trim : bool [if source starts with 'u']
True to trim columns and/or rows off the edges of windows nearest
Expand All @@ -96,6 +96,12 @@ def joinup(args=None):
ccd : string
CCD(s) to plot, '0' for all, '1 3' to plot '1' and '3' only, etc.
aper : str [if source ends 's' or 'l' or just a single file]
A photometric aperture file associated with the run or images.
This will be translated into a file of "regions" (extension .reg)
for each CCD they are defined for. The file can be loaded into
ds9 showing the apertures over the image.
bias : str
Name of bias frame to subtract, 'none' to ignore.
Expand Down Expand Up @@ -221,6 +227,7 @@ def joinup(args=None):
cl.register("tmax", Cline.LOCAL, Cline.HIDE)
cl.register("flist", Cline.LOCAL, Cline.PROMPT)
cl.register("ccd", Cline.LOCAL, Cline.PROMPT)
cl.register("aper", Cline.GLOBAL, Cline.PROMPT)
cl.register("bias", Cline.LOCAL, Cline.PROMPT)
cl.register("dark", Cline.LOCAL, Cline.PROMPT)
cl.register("flat", Cline.LOCAL, Cline.PROMPT)
Expand Down Expand Up @@ -249,6 +256,7 @@ def joinup(args=None):

# set some flags
server_or_local = source.endswith("s") or source.endswith("l")
ask_aper = server_or_local

if server_or_local:
resource = cl.get_value("run", "run name", "run005")
Expand All @@ -270,9 +278,23 @@ def joinup(args=None):
)

else:
# file or file list
resource = cl.get_value(
"flist", "file list", cline.Fname("files.lis", hcam.LIST)
"flist", "file name or file list",
"run005.hcm"
)
root,ext = os.path.splitext(resource)
if (ext == hcam.HCAM and os.path.exists(resource)) or \
(ext != hcam.LIST and \
os.path.exists(utils.add_extension(resource,hcam.HCAM))):
# single file
resource = [resource]
ask_aper = True

elif ext != hcam.LIST or not os.path.exists(resource):
raise hcam.HipercamError(
f'Cannot interpret {resource} as either a single file or a list'
)
first = 1

trim = cl.get_value(
Expand Down Expand Up @@ -304,6 +326,20 @@ def joinup(args=None):
else:
ccds = list(ccdinf.keys())

if ask_aper:
# aperture file (if any)
aper = cl.get_value(
"aper",
"aperture file to generate regions for ds9 ['none' to ignore]",
cline.Fname("run005", hcam.APER),
ignore="none",
)
if aper is not None:
# read the aperture file
aper = hcam.aperture.MccdAper.read(aper)
else:
aper = None

# bias frame (if any)
bias = cl.get_value(
"bias",
Expand Down Expand Up @@ -457,7 +493,7 @@ def joinup(args=None):
fmap = fmap.crop(mccd)
fpair = fpair.crop(mccd, nhalf)

# OK here goes
# Now the images
for nc, cnam in enumerate(ccds):
ccd = mccd[cnam]

Expand Down Expand Up @@ -511,9 +547,13 @@ def joinup(args=None):
urxmax = max(urxmax, wind.urx)
urymax = max(urymax, wind.ury)
if xbin != wind.xbin or ybin != wind.ybin:
raise hcam.HipercamError('Found windows with clashing binning factors')
raise hcam.HipercamError(
'Found windows with clashing binning factors'
)
if (wind.llx - llx) % xbin != 0 or (wind.lly - lly) % ybin != 0:
raise hcam.HipercamError('Found windows which are out of sync with each other')
raise hcam.HipercamError(
'Found windows which are out of sync with each other'
)

# create huge array of nothing
ny = (urymax-llymin+1) // ybin
Expand All @@ -528,7 +568,8 @@ def joinup(args=None):

if dtype == 'uint16' and (data.min() < 0 or data.max() > 65535):
raise hcam.HipercamError(
f'CCD {cnam}, frame {nf}, data range {data.min()} to {data.max()}, is incompatible with uint16'
f'CCD {cnam}, frame {nf}, data range '
f'{data.min()} to {data.max()}, is incompatible with uint16'
)

# Header
Expand Down Expand Up @@ -621,7 +662,30 @@ def joinup(args=None):
oname = f'{root}_ccd{cnam}.fits'
oname = os.path.join(odir, oname)
hdul.writeto(oname, overwrite=overwrite)
print(f' CCD {cnam}: written to {oname}')
print(f' CCD {cnam}: written {oname}')

if nframe == first and aper is not None and cnam in aper:
# ds9 region files

if server_or_local:
abase = os.path.basename(resource)
else:
abase = os.path.basename(resource[0])
abase = os.path.join(odir, abase)
oname = f'{abase}_ccd{cnam}.reg'

caper = aper[cnam]

with open(oname,'w') as fp:
fp.write(DS9_REG_HEADER)
for apnam, ap in caper.items():
x = (ap.x - llxmin + 1) / xbin
y = (ap.y - llymin + 1) / ybin
rad = ap.rsky2/xbin
fp.write(f'circle({x},{y},{rad})\n')
fp.write(f'# text({x-rad},{y-rad}) text={{{apnam}}}\n')

print(f' CCD {cnam}: written {oname}')
nfile += 1

else:
Expand All @@ -633,3 +697,10 @@ def joinup(args=None):
break

print(f'Written {nfile} FITS files to disk.')

DS9_REG_HEADER = """
# Region file format: DS9 version 4.1
global color=green dashlist=8 3 width=1 font="helvetica 10 normal roman" select=1 highlite=1 dash=0 fixed=0 edit=1 move=1 delete=1 include=1 source=1
image
"""

11 changes: 6 additions & 5 deletions hipercam/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -650,11 +650,12 @@ def dec2sexg(value, sign, dp, sep=':'):
return f'{v1:02d}{sep}{v2:02d}{sep}{v3:0{3+dp}.{dp}f}'

def temp_dir():
"""
Generates the name of the hipercam temp directory which will be used to store
temporary files. Creates the directory if it does not exist. The temp directory
is called "tmp" and is created as a subdirectory of the directory containing
the command default files (".hipercam" by default)
"""Generates the name of the hipercam temp directory which will be
used to store temporary files. Creates the directory if it does
not exist. The temp directory is called "tmp" and is created as a
subdirectory of the directory containing the command default files
(".hipercam" by default)
"""

# Generate temp directory name
Expand Down

0 comments on commit 467d42f

Please sign in to comment.