diff --git a/changes/1592.associations.rst b/changes/1592.associations.rst new file mode 100644 index 000000000..a1918363f --- /dev/null +++ b/changes/1592.associations.rst @@ -0,0 +1 @@ +Fix bug where skycell_wcs_info was double json encoded diff --git a/romancal/associations/lib/asn_schema_jw_level3.json b/romancal/associations/lib/asn_schema_jw_level3.json index ac7495675..b275acb5b 100644 --- a/romancal/associations/lib/asn_schema_jw_level3.json +++ b/romancal/associations/lib/asn_schema_jw_level3.json @@ -22,37 +22,55 @@ "type": "string" }, "skycell_wcs_info": { - "description": "WCS information for the projection cell", - "type": "string", - "properties":{ - "pixel_scale": { - "type": "number" - }, - "ra_cent": { - "type": "number" - }, - "dec_cent": { - "type": "number" - }, - "shiftx": { - "type": "integer" - }, - "shifty": { - "type": "integer" - }, - "nx": { - "type": "integer" - }, - "ny": { - "type": "integer" - }, - "orient": { - "type": "number" - }, - "orientat_projection_center": { - "type": "number" - } - } + "oneOf": [ + { + "type": "string", + "enum": ["none"] + }, + { + "description": "WCS information for the projection cell", + "type": "object", + "properties":{ + "name": { + "type": "string" + }, + "pixel_scale": { + "type": "number" + }, + "ra_projection_center": { + "type": "number" + }, + "dec_projection_center": { + "type": "number" + }, + "x0_projection": { + "type": "number" + }, + "y0_projection": { + "type": "number" + }, + "ra_center": { + "type": "number" + }, + "dec_center": { + "type": "number" + }, + "nx": { + "type": "number" + }, + "ny": { + "type": "number" + }, + "orientat": { + "type": "number" + }, + "orientat_projection_center": { + "type": "number" + } + }, + "required": ["name", "pixel_scale", "ra_projection_center", "dec_projection_center", "x0_projection", "y0_projection", "ra_center", "dec_center", "nx", "ny", "orientat", "orientat_projection_center"] + } + ] }, "target": { "description": "Canonical name of the astronomical object being observed.", diff --git a/romancal/associations/skycell_asn.py b/romancal/associations/skycell_asn.py index 671af18f2..c080a2a5e 100644 --- a/romancal/associations/skycell_asn.py +++ b/romancal/associations/skycell_asn.py @@ -1,7 +1,6 @@ """Create an association based on skycells""" import argparse -import json import logging import sys @@ -121,15 +120,17 @@ def skycell_asn(filelist, output_file_root, product_type, release_product): + filter_id ) + prompt_product_asn = asn_from_list.asn_from_list( + member_list, product_name=asn_file_name + ) + prompt_product_asn["asn_type"] = "image" + prompt_product_asn["program"] = program_id + prompt_product_asn["target"] = patch_name + prompt_product_asn["skycell_wcs_info"] = projcell_info + + _, serialized = prompt_product_asn.dump(format="json") + with open(asn_file_name + "_asn.json", "w") as outfile: - prompt_product_asn = asn_from_list.asn_from_list( - member_list, product_name=asn_file_name - ) - prompt_product_asn["asn_type"] = "image" - prompt_product_asn["program"] = program_id - prompt_product_asn["target"] = patch_name - prompt_product_asn["skycell_wcs_info"] = json.dumps(projcell_info) - _, serialized = prompt_product_asn.dump(format="json") outfile.write(serialized) diff --git a/romancal/pipeline/mosaic_pipeline.py b/romancal/pipeline/mosaic_pipeline.py index fb5f2315f..149d5ddcb 100644 --- a/romancal/pipeline/mosaic_pipeline.py +++ b/romancal/pipeline/mosaic_pipeline.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from __future__ import annotations -import json import logging import re from os.path import basename, isfile @@ -96,9 +95,12 @@ def process(self, input): if re.match(r"r\d{3}\w{2}\d{2}x\d{2}y\d{2}", skycell_name): # check to see if the skycell coords are in the asn header if # so read the string and convert to a dictionary to match the patch table - try: - skycell_record = json.loads(input.asn["skycell_wcs_info"]) - except (KeyError, json.JSONDecodeError): + if ( + "skycell_wcs_info" in input.asn + and input.asn["skycell_wcs_info"] != "none" + ): + skycell_record = input.asn["skycell_wcs_info"] + else: if patch_match.PATCH_TABLE is None: patch_match.load_patch_table() skycell_record = patch_match.PATCH_TABLE[ diff --git a/romancal/regtest/test_skycell_generation.py b/romancal/regtest/test_skycell_generation.py index f032c25ae..65d00c890 100644 --- a/romancal/regtest/test_skycell_generation.py +++ b/romancal/regtest/test_skycell_generation.py @@ -1,15 +1,30 @@ """Roman tests for generating associatinos based on skycells""" +import json import os import pytest +import roman_datamodels.datamodels as rdm from romancal.associations import skycell_asn +from romancal.pipeline.mosaic_pipeline import MosaicPipeline +# mark all tests in this module +pytestmark = [pytest.mark.bigdata] -@pytest.mark.bigdata -def test_skycell_asn_generation(rtdata): - """Test for the generation of associations based on skycells""" +EXPECTED_FILENAMES = [ + "r512_p_v01001001001_r274dp63x31y80_f158_asn.json", + "r512_p_v01001001001_r274dp63x31y81_f158_asn.json", + "r512_p_v01001001001_r274dp63x32y82_f158_asn.json", + "r512_p_v01001001001_r274dp63x32y80_f158_asn.json", + "r512_p_v01001001001_r274dp63x32y81_f158_asn.json", + "r512_p_v01001001001_r274dp63x32y82_f158_asn.json", +] + + +@pytest.fixture(scope="module") +def run_skycell_asn(rtdata_module): + rtdata = rtdata_module # This test should generate seven json files args = [ @@ -22,17 +37,43 @@ def test_skycell_asn_generation(rtdata): rtdata.get_data("WFI/image/r0000101001001001001_0002_wfi10_cal.asdf") skycell_asn._cli(args) + return rtdata + - # skycell associations that should be generated - output_files = [ - "r512_p_v01001001001_r274dp63x31y80_f158_asn.json", - "r512_p_v01001001001_r274dp63x31y81_f158_asn.json", - "r512_p_v01001001001_r274dp63x32y82_f158_asn.json", - "r512_p_v01001001001_r274dp63x32y80_f158_asn.json", - "r512_p_v01001001001_r274dp63x32y81_f158_asn.json", - "r512_p_v01001001001_r274dp63x32y82_f158_asn.json", +@pytest.fixture(scope="module") +def mosaic_pipeline_on_skycell_asn(run_skycell_asn): + rtdata = run_skycell_asn + rtdata.input = EXPECTED_FILENAMES[0] + rtdata.output = f"{rtdata.input.rsplit('_', maxsplit=1)[0]}_coadd.asdf" + + # just run the first association (not all) + args = [ + "roman_mos", + rtdata.input, ] - # Test that the json files exist - for file in output_files: - skycell_asn.logger.info(f"Check that the json file exists{file}") - assert os.path.isfile(file) + + # we don't setup or fetch a truth file here as the aim of this + # test is to check the output is resampled onto a skycell + MosaicPipeline.from_cmdline(args) + return rtdata + + +@pytest.mark.parametrize("expected_filename", EXPECTED_FILENAMES) +def test_file_exists(run_skycell_asn, expected_filename): + """Test that the expected json files were generated""" + assert os.path.isfile(expected_filename) + + +@pytest.mark.parametrize("expected_filename", EXPECTED_FILENAMES) +def test_files_contain_wcsinfo(run_skycell_asn, expected_filename): + with open(expected_filename) as f: + asn = json.load(f) + assert "skycell_wcs_info" in asn + + +def test_mosaic_output_is_skycell(mosaic_pipeline_on_skycell_asn): + """Check that the mos output for the generated association is on a skycell""" + rtdata = mosaic_pipeline_on_skycell_asn + filename = rtdata.output + with rdm.open(filename) as model: + assert model.meta.basic.location_name == "r274dp63x31y80"