Commit f2e7f6de authored by yuedong0607's avatar yuedong0607
Browse files

add "formatted_output" field to the readout_modes

parent a69300e3
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@
# ok to pass either way or both, as long as they are consistent
# work_dir: "/public/home/fangyuedong/project/workplace/"
work_dir: "/home/yuedong/Work/CSST_sim/output/"
run_name: "test_ghost"
run_name: "legacy_v1"
data_set: "csst-msc-c11-1000sqdeg-wide-v1"

# Project cycle and run counter are used to name the outputs
@@ -21,7 +21,7 @@ run_counter: 1

# Versioned detector definitions used by Chip and the readout simulation steps
instrument_data:
  release: next-v1
  release: legacy-v1
  release_directory: null
  detector_overrides: {}

@@ -113,8 +113,8 @@ psf_setting:
  # path to PSF data
  # NOTE: only valid for "Interp" PSF
  # PSF models for photometry survey simulation
  # psf_pho_dir: "/home/yuedong/Work/CSST_sim/input_data/PSFCube/set1_dynamic/"
  psf_pho_dir: "/home/yuedong/Work/CSST_sim/input_data/psfCube202607/"
  psf_pho_dir: "/home/yuedong/Work/CSST_sim/input_data/PSFCube/set1_dynamic/"
  # psf_pho_dir: "/home/yuedong/Work/CSST_sim/input_data/psfCube202607/"
  # PSF models for slitless spectrum survey simulation
  psf_sls_dir: "/home/yuedong/Work/CSST_sim/input_data/PSFCube/SLS_PSF_PCA_fp/"

@@ -136,7 +136,7 @@ shear_setting:
# Output options
###############################################
output_setting:
  # format_output:  NO # Whether to export as 16 channels (subimages) with pre- and over-scan ("image"/"channels")
  # format_output:  YES # Whether to export as 16 channels (subimages) with pre- and over-scan ("image"/"channels")
  shutter_output: NO # Whether to export shutter effect 16-bit image
  prnu_output:    NO # Whether to export the PRNU (pixel-to-pixel flat-fielding) files

+2 −2
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ obs_id: "00000001" # this setting will only be used if pointing list file is not
# Define list of chips
# run_chips: [6,7,8,9,11,12,13,14,15,16,17,18,19,20,22,23,24,25] # Photometric chips
#run_chips: [1,2,3,4,5,10,21,26,27,28,29,30] # Spectroscopic chips
run_chips: [7]
run_chips: [8]

# Define observation sequence
call_sequence:
@@ -89,5 +89,5 @@ call_sequence:
    gain_16channel: YES
  # Output the final image
  quantization_and_output:
    format_output: NO
    format_output: YES
...
+58 −16
Original line number Diff line number Diff line
@@ -47,48 +47,69 @@ readout_modes:
        raw_mosaic_bbox: {x0: 8750, y0: 0, width: 1250, height: 4700}
      - id: CH09
        detector_bbox: {x0: 0, y0: 4616, width: 1152, height: 4616}
        detector_to_raw: rotate_180
        detector_to_raw: flip_y
        scan: *science_scan
        raw_mosaic_bbox: {x0: 0, y0: 4700, width: 1250, height: 4700}
      - id: CH10
        detector_bbox: {x0: 1152, y0: 4616, width: 1152, height: 4616}
        detector_to_raw: rotate_180
        detector_to_raw: flip_y
        scan: *science_scan
        raw_mosaic_bbox: {x0: 1250, y0: 4700, width: 1250, height: 4700}
      - id: CH11
        detector_bbox: {x0: 2304, y0: 4616, width: 1152, height: 4616}
        detector_to_raw: rotate_180
        detector_to_raw: flip_y
        scan: *science_scan
        raw_mosaic_bbox: {x0: 2500, y0: 4700, width: 1250, height: 4700}
      - id: CH12
        detector_bbox: {x0: 3456, y0: 4616, width: 1152, height: 4616}
        detector_to_raw: rotate_180
        detector_to_raw: flip_y
        scan: *science_scan
        raw_mosaic_bbox: {x0: 3750, y0: 4700, width: 1250, height: 4700}
      - id: CH13
        detector_bbox: {x0: 4608, y0: 4616, width: 1152, height: 4616}
        detector_to_raw: flip_y
        detector_to_raw: rotate_180
        scan: *science_scan
        raw_mosaic_bbox: {x0: 5000, y0: 4700, width: 1250, height: 4700}
      - id: CH14
        detector_bbox: {x0: 5760, y0: 4616, width: 1152, height: 4616}
        detector_to_raw: flip_y
        detector_to_raw: rotate_180
        scan: *science_scan
        raw_mosaic_bbox: {x0: 6250, y0: 4700, width: 1250, height: 4700}
      - id: CH15
        detector_bbox: {x0: 6912, y0: 4616, width: 1152, height: 4616}
        detector_to_raw: flip_y
        detector_to_raw: rotate_180
        scan: *science_scan
        raw_mosaic_bbox: {x0: 7500, y0: 4700, width: 1250, height: 4700}
      - id: CH16
        detector_bbox: {x0: 8064, y0: 4616, width: 1152, height: 4616}
        detector_to_raw: flip_y
        detector_to_raw: rotate_180
        scan: *science_scan
        raw_mosaic_bbox: {x0: 8750, y0: 4700, width: 1250, height: 4700}
    raw_output:
      layout: single_mosaic
      mosaic_shape: {columns: 10000, rows: 9400}
      channel_order: [CH01, CH02, CH03, CH04, CH05, CH06, CH07, CH08, CH16, CH15, CH14, CH13, CH12, CH11, CH10, CH09]
    formatted_output:
      layout: single_mosaic
      mosaic_shape: {columns: 20000, rows: 4700}
      channel_order: [CH01, CH02, CH03, CH04, CH05, CH06, CH07, CH08, CH16, CH15, CH14, CH13, CH12, CH11, CH10, CH09]
      channel_placements:
        CH01: {x0: 0, y0: 0, width: 1250, height: 4700}
        CH02: {x0: 1250, y0: 0, width: 1250, height: 4700}
        CH03: {x0: 2500, y0: 0, width: 1250, height: 4700}
        CH04: {x0: 3750, y0: 0, width: 1250, height: 4700}
        CH05: {x0: 5000, y0: 0, width: 1250, height: 4700}
        CH06: {x0: 6250, y0: 0, width: 1250, height: 4700}
        CH07: {x0: 7500, y0: 0, width: 1250, height: 4700}
        CH08: {x0: 8750, y0: 0, width: 1250, height: 4700}
        CH16: {x0: 10000, y0: 0, width: 1250, height: 4700}
        CH15: {x0: 11250, y0: 0, width: 1250, height: 4700}
        CH14: {x0: 12500, y0: 0, width: 1250, height: 4700}
        CH13: {x0: 13750, y0: 0, width: 1250, height: 4700}
        CH12: {x0: 15000, y0: 0, width: 1250, height: 4700}
        CH11: {x0: 16250, y0: 0, width: 1250, height: 4700}
        CH10: {x0: 17500, y0: 0, width: 1250, height: 4700}
        CH09: {x0: 18750, y0: 0, width: 1250, height: 4700}

  fgs_16ch_legacy:
    detector_family: fgs_cmos
@@ -136,45 +157,66 @@ readout_modes:
        raw_mosaic_bbox: {x0: 10542, y0: 0, width: 1506, height: 3924}
      - id: CH09
        detector_bbox: {x0: 0, y0: 3840, width: 1408, height: 3840}
        detector_to_raw: rotate_180
        detector_to_raw: flip_y
        scan: *fgs_scan
        raw_mosaic_bbox: {x0: 0, y0: 3924, width: 1506, height: 3924}
      - id: CH10
        detector_bbox: {x0: 1408, y0: 3840, width: 1408, height: 3840}
        detector_to_raw: rotate_180
        detector_to_raw: flip_y
        scan: *fgs_scan
        raw_mosaic_bbox: {x0: 1506, y0: 3924, width: 1506, height: 3924}
      - id: CH11
        detector_bbox: {x0: 2816, y0: 3840, width: 1408, height: 3840}
        detector_to_raw: rotate_180
        detector_to_raw: flip_y
        scan: *fgs_scan
        raw_mosaic_bbox: {x0: 3012, y0: 3924, width: 1506, height: 3924}
      - id: CH12
        detector_bbox: {x0: 4224, y0: 3840, width: 1408, height: 3840}
        detector_to_raw: rotate_180
        detector_to_raw: flip_y
        scan: *fgs_scan
        raw_mosaic_bbox: {x0: 4518, y0: 3924, width: 1506, height: 3924}
      - id: CH13
        detector_bbox: {x0: 5632, y0: 3840, width: 1408, height: 3840}
        detector_to_raw: flip_y
        detector_to_raw: rotate_180
        scan: *fgs_scan
        raw_mosaic_bbox: {x0: 6024, y0: 3924, width: 1506, height: 3924}
      - id: CH14
        detector_bbox: {x0: 7040, y0: 3840, width: 1408, height: 3840}
        detector_to_raw: flip_y
        detector_to_raw: rotate_180
        scan: *fgs_scan
        raw_mosaic_bbox: {x0: 7530, y0: 3924, width: 1506, height: 3924}
      - id: CH15
        detector_bbox: {x0: 8448, y0: 3840, width: 1408, height: 3840}
        detector_to_raw: flip_y
        detector_to_raw: rotate_180
        scan: *fgs_scan
        raw_mosaic_bbox: {x0: 9036, y0: 3924, width: 1506, height: 3924}
      - id: CH16
        detector_bbox: {x0: 9856, y0: 3840, width: 1408, height: 3840}
        detector_to_raw: flip_y
        detector_to_raw: rotate_180
        scan: *fgs_scan
        raw_mosaic_bbox: {x0: 10542, y0: 3924, width: 1506, height: 3924}
    raw_output:
      layout: single_mosaic
      mosaic_shape: {columns: 12048, rows: 7848}
      channel_order: [CH01, CH02, CH03, CH04, CH05, CH06, CH07, CH08, CH16, CH15, CH14, CH13, CH12, CH11, CH10, CH09]
    formatted_output:
      layout: single_mosaic
      mosaic_shape: {columns: 24096, rows: 3924}
      channel_order: [CH01, CH02, CH03, CH04, CH05, CH06, CH07, CH08, CH16, CH15, CH14, CH13, CH12, CH11, CH10, CH09]
      channel_placements:
        CH01: {x0: 0, y0: 0, width: 1506, height: 3924}
        CH02: {x0: 1506, y0: 0, width: 1506, height: 3924}
        CH03: {x0: 3012, y0: 0, width: 1506, height: 3924}
        CH04: {x0: 4518, y0: 0, width: 1506, height: 3924}
        CH05: {x0: 6024, y0: 0, width: 1506, height: 3924}
        CH06: {x0: 7530, y0: 0, width: 1506, height: 3924}
        CH07: {x0: 9036, y0: 0, width: 1506, height: 3924}
        CH08: {x0: 10542, y0: 0, width: 1506, height: 3924}
        CH16: {x0: 12048, y0: 0, width: 1506, height: 3924}
        CH15: {x0: 13554, y0: 0, width: 1506, height: 3924}
        CH14: {x0: 15060, y0: 0, width: 1506, height: 3924}
        CH13: {x0: 16566, y0: 0, width: 1506, height: 3924}
        CH12: {x0: 18072, y0: 0, width: 1506, height: 3924}
        CH11: {x0: 19578, y0: 0, width: 1506, height: 3924}
        CH10: {x0: 21084, y0: 0, width: 1506, height: 3924}
        CH09: {x0: 22590, y0: 0, width: 1506, height: 3924}
+29 −0
Original line number Diff line number Diff line
@@ -173,12 +173,27 @@ class RawOutput(StrictModel):
        return tuple(value)


class FormattedOutput(StrictModel):
    """Placement of processed raw channel frames in a delivered mosaic."""

    layout: Literal["single_mosaic"]
    mosaic_shape: PixelShape
    channel_order: tuple[str, ...]
    channel_placements: dict[str, BBox]

    @field_validator("channel_order", mode="before")
    @classmethod
    def freeze_channel_order(cls, value):
        return tuple(value)


class ReadoutMode(StrictModel):
    detector_family: str
    detector_types: tuple[str, ...] = ()
    require_full_active_coverage: bool = True
    channels: tuple[ChannelGeometry, ...]
    raw_output: RawOutput
    formatted_output: FormattedOutput | None = None

    @field_validator("detector_types", mode="before")
    @classmethod
@@ -206,6 +221,20 @@ class ReadoutMode(StrictModel):
            raise ValueError(
                "raw_output.channel_order must list every channel exactly once"
            )
        formatted = self.formatted_output
        if formatted is not None:
            formatted_order = formatted.channel_order
            if len(formatted_order) != len(set(formatted_order)):
                raise ValueError("formatted_output.channel_order contains duplicates")
            if set(ids) != set(formatted_order):
                raise ValueError(
                    "formatted_output.channel_order must list every channel exactly once"
                )
            if set(ids) != set(formatted.channel_placements):
                raise ValueError(
                    "formatted_output.channel_placements must place every channel "
                    "exactly once"
                )
        return self

    def channel(self, channel_id: str) -> ChannelGeometry:
+54 −0
Original line number Diff line number Diff line
@@ -231,6 +231,36 @@ class ResolvedDetector:
            mosaic[channel.raw_mosaic_slices] = raw
        return mosaic

    def format_raw_output(self, raw_mosaic: np.ndarray) -> np.ndarray:
        """Place processed raw channel frames in the delivered output mosaic."""

        raw_output = self.readout_mode.raw_output
        if raw_output.layout != "single_mosaic" or raw_output.mosaic_shape is None:
            raise ValueError(
                f"readout mode {self.readout_mode_id!r} does not define a raw mosaic"
            )
        expected = (raw_output.mosaic_shape.rows, raw_output.mosaic_shape.columns)
        if raw_mosaic.shape != expected:
            raise ValueError(
                f"raw mosaic shape is {raw_mosaic.shape}, expected {expected}"
            )

        output = self.readout_mode.formatted_output
        if output is None:
            raise ValueError(
                f"readout mode {self.readout_mode_id!r} does not define a "
                "formatted output"
            )
        formatted = np.zeros(
            (output.mosaic_shape.rows, output.mosaic_shape.columns),
            dtype=raw_mosaic.dtype,
        )
        for channel_id in output.channel_order:
            channel = self.channel(channel_id)
            destination = output.channel_placements[channel_id]
            formatted[destination.slices] = raw_mosaic[channel.raw_mosaic_slices]
        return formatted

    @property
    def legacy_attributes(self) -> dict[str, object]:
        """Compatibility values for code not yet converted to the wrapper API."""
@@ -1206,6 +1236,30 @@ class InstrumentRepository:
        elif output.mosaic_shape is not None:
            raise ValueError("channel_hdus output must not define mosaic_shape")

        formatted = mode.formatted_output
        if formatted is not None:
            formatted_boxes = []
            for channel_id in formatted.channel_order:
                channel = mode.channel(channel_id)
                box = formatted.channel_placements[channel_id]
                raw = channel.raw_shape
                if box.width != raw.columns or box.height != raw.rows:
                    raise ValueError(
                        f"channel {channel_id!r} formatted placement does not match "
                        "raw_shape"
                    )
                if (
                    box.x1 > formatted.mosaic_shape.columns
                    or box.y1 > formatted.mosaic_shape.rows
                ):
                    raise ValueError(
                        f"channel {channel_id!r} lies outside the formatted mosaic"
                    )
                formatted_boxes.append(box)
            InstrumentRepository._validate_no_overlap(
                formatted_boxes, mode_id, "formatted mosaic"
            )

    @staticmethod
    def _validate_no_overlap(boxes: list[BBox], mode_id: str, space: str) -> None:
        for index, box in enumerate(boxes):
Loading