Region Spectral Profiles
------------------------
.. uml::
skinparam style strictuml
hide footbox
title Region spectral profile workflow
actor User
box "Client-side" #EDEDED
participant Frontend
end box
box "Server-side" #lightblue
participant Backend
end box
User -> Frontend: Open image
activate Frontend
Frontend -> Backend : 1. OPEN_FILE
activate Backend
Frontend <-- Backend : 2. OPEN_FILE_ACK
Frontend -> Backend : 3. ADD_REQUIRED_TILES
Frontend -> Backend : 4. SET_CURSOR
Frontend <-- Backend : 5. RASTER_TILE_DATA
Frontend <-- Backend : 5. SPATIAL_PROFILE_DATA
deactivate Backend
User <-- Frontend: Displays image
deactivate Frontend
User -> Frontend: Draw region
activate Frontend
Frontend -> Backend : 6. SET_REGION
activate Backend
Frontend <--[#red] Backend : 7. SET_REGION_ACK [Check 1]
deactivate Backend
User <-- Frontend: Displays region
deactivate Frontend
User -> Frontend: Request spectral profile
activate Frontend
Frontend -> Backend : 8. SET_SPECTRAL_REQUIREMENTS
activate Backend
Frontend <--[#red] Backend : 9. SPECTRAL_PROFILE_DATA [Check 2]
deactivate Backend
User <-- Frontend: Displays spectral profile
deactivate Frontend
REGION_SPECTRAL_PROFILE_RECTANGLE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See the `source code `__.
This test verifies that spectral profiles are computed correctly for rectangle regions, comparing results across CASA IMAGE and HDF5 formats.
**For each file format (M17_SWex.image and M17_SWex.hdf5):**
1. Frontend sends: **CLOSE_FILE** (``CloseFile``) and **OPEN_FILE** (``OpenFile``)
.. code-block:: protobuf
directory = "set_QA"
file = "M17_SWex.image" / "M17_SWex.hdf5"
hdu = ""
file_id = 0
render_mode = RASTER
2. Backend returns: **OPEN_FILE_ACK** (``OpenFileAck``) and **REGION_HISTOGRAM_DATA**
:red-text:`Check 1:` the OPEN_FILE_ACK should satisfy:
- OPEN_FILE_ACK.success = True
3. Frontend sends: **ADD_REQUIRED_TILES** and **SET_CURSOR**
.. code-block:: protobuf
file_id = 0
tiles = [0]
point = {x: 1.0, y: 1.0}
4. Frontend sends: **SET_REGION** (``SetRegion``) for 4 rectangle regions
Case 1 (no rotation):
.. code-block:: protobuf
file_id = 0
region_id = -1
region_type = RECTANGLE
control_points = [{x: 83, y: 489}, {x: 4, y: 6}]
rotation = 0.0
Case 2 (rotated 50 degrees):
.. code-block:: protobuf
file_id = 0
region_id = -1
region_type = RECTANGLE
control_points = [{x: 92, y: 522}, {x: 4, y: 6}]
rotation = 50.0
Case 3 (sub-pixel size):
.. code-block:: protobuf
file_id = 0
region_id = -1
region_type = RECTANGLE
control_points = [{x: 360, y: 490}, {x: 0.5, y: 0.5}]
rotation = 0.0
Case 4 (out-of-bounds, rotated):
.. code-block:: protobuf
file_id = 0
region_id = -1
region_type = RECTANGLE
control_points = [{x: 0, y: 522}, {x: 4, y: 6}]
rotation = 50.0
5. Backend returns: **SET_REGION_ACK** (``SetRegionAck``) for each region
:red-text:`Check 2:` the SET_REGION_ACK should satisfy:
- All SET_REGION_ACK.success = True
- region_id = 1, 2, 3, 4 respectively
6. Frontend sends: **SET_SPECTRAL_REQUIREMENTS** (``SetSpectralRequirements``) for each region
.. code-block:: protobuf
file_id = 0
region_id = <1-4>
spectral_profiles = [{
coordinate: "z",
stats_types: [NumPixels, Sum, FluxDensity, Mean, RMS, Sigma, SumSq, Min, Max, Extrema]
}]
7. Backend returns: **SPECTRAL_PROFILE_DATA** (``SpectralProfileData``) for each region
:red-text:`Check 3:` the SPECTRAL_PROFILE_DATA should satisfy:
- Should arrive within 5000 ms
- Cases 1-3: progress = 1, with valid rawValuesFp64 values at indices [0, 50, 100, 150, 199] matching expected byte arrays for each stats type
- Case 3 (sub-pixel region): profile length = 25, Sigma values = [0, 0, 0, 0, 0] (single pixel)
- Case 4 (out-of-bounds): all stats return NaN values
- Results should be consistent between CASA IMAGE and HDF5 formats (minor differences allowed for RMS and SumSq)
REGION_SPECTRAL_PROFILE_ELLIPSE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See the `source code `__.
This test verifies that spectral profiles are computed correctly for ellipse regions, comparing results across CASA IMAGE and HDF5 formats.
**For each file format (M17_SWex.image and M17_SWex.hdf5):**
1. Frontend sends: **CLOSE_FILE** (``CloseFile``) and **OPEN_FILE** (``OpenFile``)
.. code-block:: protobuf
directory = "set_QA"
file = "M17_SWex.image" / "M17_SWex.hdf5"
hdu = ""
file_id = 0
render_mode = RASTER
2. Backend returns: **OPEN_FILE_ACK** (``OpenFileAck``) and **REGION_HISTOGRAM_DATA**
:red-text:`Check 1:` the OPEN_FILE_ACK should satisfy:
- OPEN_FILE_ACK.success = True
3. Frontend sends: **ADD_REQUIRED_TILES** and **SET_CURSOR**
.. code-block:: protobuf
file_id = 0
tiles = [0]
point = {x: 1.0, y: 1.0}
4. Frontend sends: **SET_REGION** (``SetRegion``) for 2 ellipse regions
Case 1 (valid region, rotated 30 degrees):
.. code-block:: protobuf
file_id = 0
region_id = -1
region_type = ELLIPSE
control_points = [{x: 89, y: 516}, {x: 5, y: 3}]
rotation = 30.0
Case 2 (out-of-bounds, rotated 30 degrees):
.. code-block:: protobuf
file_id = 0
region_id = -1
region_type = ELLIPSE
control_points = [{x: 0, y: 516}, {x: 5, y: 3}]
rotation = 30.0
5. Backend returns: **SET_REGION_ACK** (``SetRegionAck``) for each region
:red-text:`Check 2:` the SET_REGION_ACK should satisfy:
- All SET_REGION_ACK.success = True
- region_id = 1, 2 respectively
6. Frontend sends: **SET_SPECTRAL_REQUIREMENTS** (``SetSpectralRequirements``) for each region
.. code-block:: protobuf
file_id = 0
region_id = <1-2>
spectral_profiles = [{
coordinate: "z",
stats_types: [NumPixels, Sum, FluxDensity, Mean, RMS, Sigma, SumSq, Min, Max, Extrema]
}]
7. Backend returns: **SPECTRAL_PROFILE_DATA** (``SpectralProfileData``) for each region
:red-text:`Check 3:` the SPECTRAL_PROFILE_DATA should satisfy:
- Should arrive within 5000 ms
- Case 1: progress = 1, profile length = 25, with valid rawValuesFp64 values at indices [0, 50, 100, 150, 199] matching expected byte arrays for each stats type
- Case 2 (out-of-bounds): all stats return NaN values
- Results should be consistent between CASA IMAGE and HDF5 formats (minor differences allowed for RMS and SumSq)
REGION_SPECTRAL_PROFILE_POLYGON
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See the `source code `__.
This test verifies that spectral profiles are computed correctly for polygon regions, comparing results across CASA IMAGE and HDF5 formats.
**For each file format (M17_SWex.image and M17_SWex.hdf5):**
1. Frontend sends: **CLOSE_FILE** (``CloseFile``) and **OPEN_FILE** (``OpenFile``)
.. code-block:: protobuf
directory = "set_QA"
file = "M17_SWex.image" / "M17_SWex.hdf5"
hdu = ""
file_id = 0
render_mode = RASTER
2. Backend returns: **OPEN_FILE_ACK** (``OpenFileAck``) and **REGION_HISTOGRAM_DATA**
:red-text:`Check 1:` the OPEN_FILE_ACK should satisfy:
- OPEN_FILE_ACK.success = True
3. Frontend sends: **ADD_REQUIRED_TILES** and **SET_CURSOR**
.. code-block:: protobuf
file_id = 0
tiles = [0]
point = {x: 1.0, y: 1.0}
4. Frontend sends: **SET_REGION** (``SetRegion``) for 2 polygon regions
Case 1 (valid region):
.. code-block:: protobuf
file_id = 0
region_id = -1
region_type = POLYGON
control_points = [{x: 547, y: 284}, {x: 543, y: 279}, {x: 551, y: 275}]
rotation = 0.0
Case 2 (out-of-bounds region):
.. code-block:: protobuf
file_id = 0
region_id = -1
region_type = POLYGON
control_points = [{x: 647, y: 272}, {x: 630, y: 262}, {x: 648, y: 253}]
rotation = 0.0
5. Backend returns: **SET_REGION_ACK** (``SetRegionAck``) for each region
:red-text:`Check 2:` the SET_REGION_ACK should satisfy:
- All SET_REGION_ACK.success = True
- region_id = 1, 2 respectively
6. Frontend sends: **SET_SPECTRAL_REQUIREMENTS** (``SetSpectralRequirements``) for each region
.. code-block:: protobuf
file_id = 0
region_id = <1-2>
spectral_profiles = [{
coordinate: "z",
stats_types: [NumPixels, Sum, FluxDensity, Mean, RMS, Sigma, SumSq, Min, Max, Extrema]
}]
7. Backend returns: **SPECTRAL_PROFILE_DATA** (``SpectralProfileData``) for each region
:red-text:`Check 3:` the SPECTRAL_PROFILE_DATA should satisfy:
- Should arrive within 5000 ms
- Case 1: progress = 1, profile length = 25, with valid rawValuesFp64 values at indices [0, 50, 100, 150, 199] matching expected byte arrays for each stats type
- Case 2 (out-of-bounds): all stats return NaN values
- Results should be consistent between CASA IMAGE and HDF5 formats (minor differences allowed for RMS and SumSq)
REGION_SPECTRAL_PROFILE_STOKES
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See the `source code `__.
This test verifies that spectral profiles are computed correctly for regions across different Stokes parameters, comparing results across FITS and HDF5 formats.
**For each file format (HH211_IQU.fits and HH211_IQU.hdf5):**
1. Frontend sends: **CLOSE_FILE** (``CloseFile``) and **OPEN_FILE** (``OpenFile``)
.. code-block:: protobuf
directory = "set_QA"
file = "HH211_IQU.fits" / "HH211_IQU.hdf5"
hdu = ""
file_id = 0
render_mode = RASTER
2. Backend returns: **OPEN_FILE_ACK** (``OpenFileAck``) and **REGION_HISTOGRAM_DATA**
:red-text:`Check 1:` the OPEN_FILE_ACK should satisfy:
- OPEN_FILE_ACK.success = True
3. Frontend sends: **ADD_REQUIRED_TILES** and **SET_CURSOR**
.. code-block:: protobuf
file_id = 0
tiles = [0]
point = {x: 1.0, y: 1.0}
4. Frontend sends: **SET_REGION** (``SetRegion``)
.. code-block:: protobuf
file_id = 0
region_id = -1
region_type = RECTANGLE
control_points = [{x: 522, y: 522}, {x: 10, y: 10}]
rotation = 0.0
5. Backend returns: **SET_REGION_ACK** (``SetRegionAck``)
:red-text:`Check 2:` the SET_REGION_ACK should satisfy:
- SET_REGION_ACK.success = True
- region_id = 1
**Case 1: Stokes I spectral profile (coordinate "z")**
6. Frontend sends: **SET_SPECTRAL_REQUIREMENTS** (``SetSpectralRequirements``)
.. code-block:: protobuf
file_id = 0
region_id = 1
spectral_profiles = [{coordinate: "z", stats_types: [Mean]}]
7. Backend returns: **SPECTRAL_PROFILE_DATA** (``SpectralProfileData``)
:red-text:`Check 3:` the SPECTRAL_PROFILE_DATA should satisfy:
- region_id = 1, progress = 1, profile length = 5
- rawValuesFp64 values at indices [0, 10, 20, 30, 39] should match expected byte arrays
**Case 2: Change to Stokes Q (stokes = 1)**
8. Frontend sends: **SET_IMAGE_CHANNELS** (``SetImageChannels``)
.. code-block:: protobuf
file_id = 0
channel = 0
stokes = 1
required_tiles = {file_id: 0, tiles: [0], compression_type: ZFP, compression_quality: 11}
9. Backend returns: **SPECTRAL_PROFILE_DATA** (auto-updated)
:red-text:`Check 4:` the SPECTRAL_PROFILE_DATA should satisfy:
- region_id = 1, progress = 1, profile length = 5
- rawValuesFp64 values at indices [0, 10, 20, 30, 39] should match expected byte arrays (different from Stokes I)
**Case 3: Stokes U spectral profile (coordinate "Uz")**
10. Frontend sends: **SET_SPECTRAL_REQUIREMENTS** (``SetSpectralRequirements``)
.. code-block:: protobuf
file_id = 0
region_id = 1
spectral_profiles = [{coordinate: "Uz", stats_types: [Mean]}]
11. Backend returns: **SPECTRAL_PROFILE_DATA** (``SpectralProfileData``)
:red-text:`Check 5:` the SPECTRAL_PROFILE_DATA should satisfy:
- region_id = 1, progress = 1, profile length = 5
- rawValuesFp64 values at indices [0, 10, 20, 30, 39] should match expected byte arrays
**Case 4: Invalid Stokes V spectral profile (coordinate "Vz")**
12. Frontend sends: **SET_SPECTRAL_REQUIREMENTS** (``SetSpectralRequirements``)
.. code-block:: protobuf
file_id = 0
region_id = 1
spectral_profiles = [{coordinate: "Vz", stats_types: [Mean]}]
13. Backend returns: **ERROR_DATA** (``ErrorData``)
:red-text:`Check 6:` the ERROR_DATA should satisfy:
.. code-block:: protobuf
message = "Spectral requirements not valid for region id 1"
severity = 3
tags = ["spectral"]