Coverage for tests/test_fits_date_header.py: 100%

37 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-16 15:24 -0700

1# This file is part of lsst-images. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (https://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# Use of this source code is governed by a 3-clause BSD-style 

10# license that can be found in the LICENSE file. 

11 

12from __future__ import annotations 

13 

14from pathlib import Path 

15 

16import astropy.io.fits 

17import astropy.time 

18 

19from lsst.images import Image 

20from lsst.images.fits import ExtensionKey, FitsInputArchive 

21 

22 

23def _simple_image() -> Image: 

24 return Image(0.0, shape=(4, 4), dtype="float32") 

25 

26 

27def test_every_hdu_has_a_fits_compliant_date(tmp_path: Path) -> None: 

28 """Test that each HDU carries a DATE card recording approximately when 

29 the file was written. 

30 """ 

31 before = astropy.time.Time.now() 

32 path = tmp_path / "x.fits" 

33 _simple_image().write(path) 

34 after = astropy.time.Time.now() 

35 with astropy.io.fits.open(path) as hdul: 

36 assert len(hdul) > 1 

37 for index, hdu in enumerate(hdul): 

38 extname = hdu.header.get("EXTNAME", "PRIMARY") 

39 assert "DATE" in hdu.header, f"hdu={index} ({extname}): no DATE header" 

40 # The value must parse in the FITS time format. 

41 date = astropy.time.Time(hdu.header["DATE"], format="fits") 

42 # And it must reflect this write, not a stale value. 

43 assert date.jd >= before.jd, f"hdu={index} ({extname}): DATE before write started" 

44 assert date.jd <= after.jd, f"hdu={index} ({extname}): DATE after write finished" 

45 

46 

47def test_update_header_cannot_set_a_stale_primary_date(tmp_path: Path) -> None: 

48 """Test that an ``update_header`` callback cannot leave a stale DATE in 

49 the primary header. 

50 """ 

51 before = astropy.time.Time.now() 

52 path = tmp_path / "x.fits" 

53 _simple_image().write(path, update_header=lambda h: h.set("DATE", "1999-01-01T00:00:00")) 

54 after = astropy.time.Time.now() 

55 with astropy.io.fits.open(path) as hdul: 

56 date = astropy.time.Time(hdul[0].header["DATE"], format="fits") 

57 assert date.jd >= before.jd 

58 assert date.jd <= after.jd 

59 

60 

61def test_date_is_not_captured_as_opaque_metadata(tmp_path: Path) -> None: 

62 """Test that DATE is not stored in opaque metadata. 

63 

64 DATE is regenerated on every write, so the value read back must not 

65 be carried in opaque metadata (which would propagate a stale date to 

66 the next write). 

67 """ 

68 path = tmp_path / "x.fits" 

69 _simple_image().write(path) 

70 with FitsInputArchive.open(path) as archive: 

71 opaque = archive.get_opaque_metadata() 

72 primary_header = opaque.headers[ExtensionKey()] 

73 assert "DATE" not in primary_header