Ticket #64 (closed enhancement: fixed)
Improve Header interface; fold CardList functionality into it
|Reported by:||stsci_embray||Owned by:||stsci_embray|
Description (last modified by stsci_embray) (diff)
Phil pointed out that the attribute Header.ascard is not a terribly useful name (I only use it because it's what was already there). There are at least two problems with it:
- Who knows what a "card" is anymore? Although it's a useful abstraction at times, a user looking for a way to view a header as a list of keyword,value,comment triplets would not necessarily know to go looking for "cards".
- It's just not very gramatically accurate: It should at least be Header.ascards or Header.ascardlist since a header is composed of multiple cards.
Phil proposed renaming it Header.aslist or something of the like. I'd go a bit further and say that the Header interface needs to be reworked.
For one, the existing CardList interface should be an entirely internal detail, and should probably be folded into the Header class. The two classes already share quite a bit of functionality (for example, they both act a little bit like a sequence and a little bit like a mapping, though CardList is more directly sequence-like since it currently subclasses list).
A FITS header is essentially an ordered mapping and thus should have an interface similar to Python's built in OrderedDict, though with some special functionality required by FITS headers:
- It must support insertion of new key/value pairs at arbitrary positions in the ordering.
- Similarly, it should support other sequence-like operations such as concatenation/extend().
- It must support duplicate keywords. Although duplicate keywords (other than commentary keywords) are a bad idea, they are theoretically supported by the FITS standard. They are also required for record-valued keyword card support.
- It must also be able to support an arbitrary number of COMMENT and HISTORY items as well as blank items in the sequence.
- It must allow position-based indexing as well as keyword-based indexing.
When position-based indexing is used, the position refers to an actual 'card' in the sequence of 80-byte blocks. This can include blank and commentary cards. This interface would allow direct manipulation of the header.For now, position-based indexing will just return the value of the n-th card, like with keyword-based. Keeping the interface more consistent I think would be less confusing in the long term.
- When keyword-based indexing is used the value of that keyword is returned. There are some additional requirements here:
- If there are duplicate cards with the same keyword, the value of the first card with that keyword is returned and a warning is issued explaining that there are duplicate keywords and one should be removed.
- It should also allow a [keyword,n] style of indexing where n refers to the n-th card with the same keyword. This allows the values of duplicate keywords to be accessed. Though this is a rare case, it should be easy enough to support.
- In the case of the 'COMMENT' and 'HISTORY' keywords it should return lists of all the COMMENT and HISTORY values in the order that they appear in the header. ['COMMENT',n] and ['HISTORY',n] indexing would still return the n-th COMMENT or HISTORY values respectively.
- Currently, indexing a Header object returns the value of the Card associated with that index. To access the Card object itself, which contains the keyword, value, and comment values, one must go through Header.ascard to access the underlying CardList object. Since I want to make CardList an internal detail, there still should be a way to access things like the comment.
I would propose having Header return proxies for the values that have the .keyword, .value, and .comment attributes associated with the card that the value came from. By using proxies, the returned values can still be used as ints, floats, strings, etc., but will have these additional attributes attached to them.After further consideration, I think that the proxy idea is to frought with perils. I think that for most cases it would work, but it's not worth the effort for the corner cases where it gets complicated. Also, only one of the three attached attributes are useful: .key isn't that useful, since in most cases values are looked up by keyword, so you already know the key. .value would only be a reference to the actual value being proxied, and so that leaves .comment as the only attribute that adds new information. A simpler approach would be to have a Header.comments attribute that can return card comments given either an integer index or keyword.
- CONTINUE cards must be completely abstracted away from the user (as they are currently). A card composed of multiple CONTINUE cards must be represented to the user as a single item in the card sequence.
- Howard pointed out a while back that Headers should support intelligent extend/concatenate functionality. For example, to support adding keywords from a primary header to an extension header or vice-versa. Duplicate and standard keywords should be stripped from the header on the RHS of the operation.