aboutsummaryrefslogtreecommitdiffstats
path: root/acispy/header.py
blob: 6aa0eadb14d966f797ac3c73ab26fa285ec43f02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# Copyright (c) 2017 Weitian LI <liweitianux@live.com>
# MIT license

"""
Manipulate the FITS header keywords using CIAO tools
``dmkeypar`` and ``dmhedit``, as well as ``astropy.io.fits``.
"""

import subprocess

from astropy.io import fits


def read_keyword(infile, keyword):
    """
    Read the specified header keyword using CIAO tool ``dmkeypar``,
    and return a dictionary with its value, unit, data type, and comment.

    NOTE
    ----
    The ``dmkeypar`` tool cannot read some raw/reserved keywords in FITS
    header, e.g., ``BUNIT``.  These raw header keywords can be obtained
    using ``dmlist <infile> opt=header,raw``, or using the following
    ``read_keyword2()``.
    """
    DATATYPES = {
        "real": float,
        "integer": int,
        "boolean": bool,
        "string": str
    }
    subprocess.check_call(["punlearn", "dmkeypar"])
    subprocess.check_call([
        "dmkeypar", "infile=%s" % infile, "keyword=%s" % keyword
    ])
    datatype = subprocess.check_output([
        "pget", "dmkeypar", "datatype"
    ]).decode("utf-8").strip()
    value = subprocess.check_output([
        "pget", "dmkeypar", "value"
    ]).decode("utf-8").strip()
    value = DATATYPES[datatype](value)
    unit = subprocess.check_output([
        "pget", "dmkeypar", "unit"
    ]).decode("utf-8").strip()
    comment = subprocess.check_output([
        "pget", "dmkeypar", "comment"
    ]).decode("utf-8").strip()
    return {"value": value, "datatype": datatype,
            "unit": unit, "comment": comment}


def read_keyword2(infile, keyword):
    """
    Read the specified header keyword using ``astropy.io.fits``
    and return a tuple of ``(value, comment)``.

    NOTE
    ----
    Header of all extensions (a.k.a. blocks) are combined to locate
    the keyword.
    """
    with fits.open(infile) as f:
        h = fits.header.Header()
        for hdu in f:
            h.extend(hdu.header)
        value = h[keyword]
        comment = h.comments[keyword]
    return (value, comment)


def write_keyword(infile, keyword, value, datatype=None,
                  unit=None, comment=None):
    """
    Write the specified keyword to the file header.
    """
    DATATYPES = {
        "real": "double",
        "integer": "long",
        "boolean": "boolean",
        "string": "string"
    }
    subprocess.check_call(["punlearn", "dmhedit"])
    cmd = [
        "dmhedit", "infile=%s" % infile, "filelist=none",
        "operation=add", "key=%s" % keyword, "value=%s" % value
    ]
    if datatype:
        cmd += ["datatype=%s" % DATATYPES[datatype]]
    if unit:
        cmd += ["unit=%s" % unit]
    if comment:
        cmd += ["comment=%s" % comment]
    subprocess.check_call(cmd)


def copy_keyword(infile1, infile2, keyword):
    """
    Copy the specified keyword(s) from infile1 to infile2.
    """
    if not isinstance(keyword, list):
        keyword = [keyword]
    for kw in keyword:
        data = read_keyword(infile1, kw)
        write_keyword(infile2, kw, **data)