"""Tests for the composite renderer. The blending in ``merger_FITS`` is the product's visual identity -- years of tuning that no test can meaningfully assert the *correctness* of. What these tests protect is that it does not change: it was lifted out of a worker loop so the bench could render reconstructed frames, and the only thing that makes such a refactor safe is proof the pixels came out the same. """ import numpy as np import pytest import merger_FITS as M from conftest import solar_disc @pytest.fixture def six_bands(): """Six distinct 1280x1280 bands, bright enough to exercise every blend stage.""" return [ solar_disc(peak=peak, radius=386, active_region=True) for peak in (0.06, 0.12, 1.2, 1.6, 1.2, 3.0) ] def test_renders_a_composite_of_the_expected_shape(six_bands): img = M.composite_from_arrays(six_bands, 1715212800) # 1280 trimmed by 2*64 in x and 2*100 in y, then padded by a third either side. assert img.size == (1920, 1080) assert img.mode == "RGB" def test_rendering_is_deterministic(six_bands): first = M.composite_from_arrays(six_bands, 1715212800).tobytes() second = M.composite_from_arrays(six_bands, 1715212800).tobytes() assert first == second def test_the_timestamp_is_drawn_on_the_image(six_bands): """Two timestamps must differ only where the caption is.""" a = np.asarray(M.composite_from_arrays(six_bands, 1715212800)) b = np.asarray(M.composite_from_arrays(six_bands, 1715299200)) assert not np.array_equal(a, b) # The caption sits in the top strip; everything below it is identical. assert np.array_equal(a[60:], b[60:]) def test_every_band_contributes(six_bands): """Changing any one band must change the output. Guards against an indexing slip in the extracted function silently dropping a band -- the composite would still render, and still look plausible. """ reference = np.asarray(M.composite_from_arrays(six_bands, 1715212800)) for index in range(6): altered = list(six_bands) altered[index] = altered[index] * 1.5 assert not np.array_equal( np.asarray(M.composite_from_arrays(altered, 1715212800)), reference ), f"band {index} made no difference to the composite" def test_band_order_matters(six_bands): """The six arrays are positional; a caller passing them shuffled must not match.""" shuffled = [six_bands[i] for i in (5, 4, 3, 2, 1, 0)] assert not np.array_equal( np.asarray(M.composite_from_arrays(shuffled, 1715212800)), np.asarray(M.composite_from_arrays(six_bands, 1715212800)), ) def test_render_assets_are_built_once(): """The first four colormaps are mutated in place, so building twice would re-apply the mutation to already-mutated objects.""" first = M._render_assets() second = M._render_assets() assert first is second assert first["cmaps"][0] is second["cmaps"][0] def test_tolerates_a_filled_frame_containing_no_signal(six_bands): """Reconstructed frames can be blank; rendering must not raise on them.""" blanked = list(six_bands) blanked[2] = np.zeros_like(blanked[2]) img = M.composite_from_arrays(blanked, 1715212800) assert img.size == (1920, 1080) def test_mapping_constants_line_up_with_the_bands(): assert len(M.VMINS) == len(M.VMAXS) == len(M.GAMMAS) == len(M.image_names) == 6