Skip to content

Commit 0430742

Browse files
committed
Add HIRS formats, add copyright headers and replace size fieldname with dim_size
1 parent 958daf3 commit 0430742

24 files changed

+389
-36
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
# Copyright (c) 2025 EUMETSAT
2+
# License: MIT
3+
14
include("AMSU_A_records.jl")
25
include("AMSU_A_dimensions.jl")

src/Instruments/ATOVS/AMSU_A/AMSU_A_dimensions.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright (c) 2024 EUMETSAT
2+
# License: MIT
3+
14
function get_dimensions(T::Type{<:AMSA_XXX_1B})
25
return Dict(
36
"lat_lon" => 2,

src/Instruments/ATOVS/AMSU_A/AMSU_A_records.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright (c) 2024 EUMETSAT
2+
# License: MIT
3+
14
const AMSA_XXX_1B_V10_format = @path joinpath(@__DIR__, "csv_formats/AMSA_XXX_1B_V10.csv")
25

36
abstract type AMSA_XXX_1B <: ATOVS_1B end

src/Instruments/ATOVS/ATOVS.jl

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,27 @@
1+
# Copyright (c) 2025 EUMETSAT
2+
# License: MIT
3+
14
abstract type ATOVS_1B <: DataRecord end
25

6+
const DATA_CAL_NAME = :data_calibration
37
const DATA_CAL_NEDT_NAME = :data_calibration_nedt
48
const DATA_CAL_QUALITY_NAME = :data_calibration_quality
5-
const DATA_CAL_NAME = :data_calibration
9+
10+
const ELEMENT_RAD_NAME = :digital_a_data_element_rad
11+
const ELEMENT_RAD_DATA_NAME = :digital_a_rad
12+
const ELEMENT_RAD_HEADER_NAME = :digital_a_rad_header
13+
14+
const ELEMENT_FLAG_NAME = :digital_a_data_element_flag
15+
const ELEMENT_FLAG_DATA_NAME = :digital_a_flag
16+
const ELEMENT_FLAG_HEADER_NAME = :digital_a_flag_header
17+
18+
const EXTRACTED_VARS = (DATA_CAL_NEDT_NAME, DATA_CAL_QUALITY_NAME, ELEMENT_RAD_DATA_NAME,
19+
ELEMENT_RAD_HEADER_NAME, ELEMENT_FLAG_DATA_NAME, ELEMENT_FLAG_HEADER_NAME)
620

721
const DATA_CAL_NEDT_DESCRIPTION = "Noise-Equivalent Delta Temperature"
822
const DATA_CAL_QUALITY_DESCRIPTION = "Channel Quality Flags"
923

1024
include("MHS/MHS.jl")
1125
include("AMSU_A/AMSU_A.jl")
26+
include("HIRS/HIRS.jl")
1227
include("VariableExtra.jl")
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Copyright (c) 2024 EUMETSAT
2+
# License: MIT
3+
4+
# DataElementMetopDiskArray is used to handle the compound types in the HIRS L1B format.
5+
struct DataElementMetopDiskArray{T, N} <: AbstractMetopDiskArray{T, N}
6+
file_pointer::IOStream
7+
field_name::Symbol
8+
is_header::Bool
9+
10+
# computed
11+
data_element_type::Type
12+
field_type::Type
13+
offsets_in_file::Vector{Int64}
14+
record_type::Type{<:DataRecord}
15+
dim_size::NTuple{N, Int64}
16+
end
17+
18+
function DataElementMetopDiskArray(file_pointer::IOStream,
19+
record_layouts::Vector{<:RecordLayout},
20+
field_name::Symbol, data_element_field_name::Symbol; auto_convert = true)
21+
data_element_type, record_count, offsets_in_file, record_type = layout_info_for_disk_array(
22+
record_layouts, data_element_field_name)
23+
24+
is_header = field_name in (ELEMENT_RAD_HEADER_NAME, ELEMENT_FLAG_HEADER_NAME)
25+
26+
field_type = if is_header
27+
Vector{fieldtypes(eltype(data_element_type))[1]}
28+
else
29+
Matrix{eltype(fieldtypes(eltype(data_element_type))[2])}
30+
end
31+
32+
T, N = _get_T_and_N(field_type, auto_convert)
33+
34+
data_element_field_array_size = _get_field_array_size(
35+
record_layouts, record_type, data_element_field_name)
36+
dim_size = if is_header
37+
dim_size = (data_element_field_array_size..., record_count)
38+
else
39+
dim_size = (20, data_element_field_array_size..., record_count)
40+
end
41+
42+
return DataElementMetopDiskArray{T, N}(
43+
file_pointer,
44+
field_name,
45+
is_header,
46+
47+
# computed
48+
data_element_type,
49+
field_type,
50+
offsets_in_file,
51+
record_type,
52+
dim_size)
53+
end
54+
55+
function _native_read_data_element_header(io::IO, T::Type, byte_to_skip)
56+
val = native_read(io, T)
57+
skip(io, byte_to_skip)
58+
return val
59+
end
60+
61+
function _native_read_data_element_data(io::IO, T::Type)
62+
skip(io, 4)
63+
return native_read_array(io, T, (20,))
64+
end
65+
66+
# Extend get index functions
67+
function DiskArrays.readblock!(disk_array::DataElementMetopDiskArray{T, N},
68+
aout,
69+
i::Vararg{OrdinalRange, N}) where {T, N}
70+
71+
# separate record range.
72+
i_record = i[end]
73+
i_array = i[1:(end - 1)]
74+
75+
is_header = disk_array.is_header
76+
header_field_type = fieldtypes(eltype(disk_array.data_element_type))[1]
77+
data_field_type = fieldtypes(eltype(disk_array.data_element_type))[2]
78+
79+
byte_to_skip = is_header ? native_sizeof(data_field_type) :
80+
native_sizeof(header_field_type)
81+
data_element_per_record = is_header ? disk_array.dim_size[1] : disk_array.dim_size[2]
82+
83+
field_element_type = eltype(disk_array.field_type)
84+
85+
for k in eachindex(i_record)
86+
record_index = i_record[k]
87+
field_start_position = disk_array.offsets_in_file[record_index]
88+
seek(disk_array.file_pointer, field_start_position)
89+
90+
full_field = if is_header
91+
[_native_read_data_element_header(
92+
disk_array.file_pointer, field_element_type, byte_to_skip)
93+
for i in 1:data_element_per_record]
94+
else
95+
reduce(hcat,
96+
_native_read_data_element_data(
97+
disk_array.file_pointer, Vector{field_element_type})
98+
for i in 1:data_element_per_record)
99+
end
100+
101+
aout_rec = selectdim(aout, N, k)
102+
aout_rec .= _auto_convert.(T, full_field[i_array...])
103+
end
104+
return nothing
105+
end

src/Instruments/ATOVS/HIRS/HIRS.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright (c) 2025 EUMETSAT
2+
# License: MIT
3+
4+
include("HIRS_records.jl")
5+
include("HIRS_dimensions.jl")
6+
include("DiskArrayExtra.jl")
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copyright (c) 2025 EUMETSAT
2+
# License: MIT
3+
4+
function get_dimensions(T::Type{<:HIRS_XXX_1B})
5+
return Dict(
6+
"lat_lon" => 2,
7+
"channels" => 20,
8+
"xtrack" => 56,
9+
"transmitter_telemetry" => 9,
10+
"roll_pitch_yaw" => 3,
11+
"solar_angles" => 4,
12+
"flags" => 8,
13+
"analog_data" => 16
14+
)
15+
end
16+
17+
function get_field_dimensions(T::Type{<:HIRS_XXX_1B},
18+
field_name::Symbol)::Vector{<:AbstractString}
19+
if field_name in (DATA_CAL_QUALITY_NAME, DATA_CAL_NEDT_NAME)
20+
return ["channels"]
21+
elseif field_name == ELEMENT_RAD_DATA_NAME
22+
return ["channels", "xtrack"]
23+
elseif field_name == ELEMENT_RAD_HEADER_NAME
24+
return ["xtrack"]
25+
elseif field_name == ELEMENT_FLAG_DATA_NAME
26+
return ["channels", "flags"]
27+
elseif field_name == ELEMENT_FLAG_HEADER_NAME
28+
return ["flags"]
29+
end
30+
31+
if !(fieldtype(T, field_name) <: Array)
32+
return String[]
33+
end
34+
35+
array_size = _get_array_size(T, field_name)
36+
37+
if array_size == (20,)
38+
return ["channels"]
39+
elseif array_size == (56,)
40+
return ["xtrack"]
41+
elseif array_size == (2, 56)
42+
return ["lat_lon", "xtrack"]
43+
else
44+
if field_name == :analog_data
45+
return ["analog_data"]
46+
elseif field_name == :euler_angle
47+
return ["roll_pitch_yaw"]
48+
elseif field_name == :angular_relation
49+
return ["solar_angles", "xtrack"]
50+
end
51+
error("Dimensions not set for $field_type")
52+
end
53+
end
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright (c) 2025 EUMETSAT
2+
# License: MIT
3+
4+
const HIRS_XXX_1B_V10_format = @path joinpath(@__DIR__, "csv_formats/HIRS_XXX_1B_V10.csv")
5+
6+
abstract type HIRS_XXX_1B <: ATOVS_1B end
7+
# create data structure, add description and scale factors
8+
eval(record_struct_expression(HIRS_XXX_1B_V10_format, HIRS_XXX_1B))
9+
10+
function data_record_type(header::MainProductHeader, product_type::Val{:HIRS_xxx_1B})::Type
11+
if header.format_major_version == 10
12+
return HIRS_XXX_1B_V10
13+
else
14+
error("No format found for format major version :$(header.format_major_version)")
15+
end
16+
end
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
FIELD,DESCRIPTION,SF,UNITS,DIM1,DIM2,DIM3,TYPE,TYPE SIZE,FIELD SIZE,OFFSET
2+
RECORD_HEADER,Generic Record Header,0,,1,1,1,REC_HEAD,20,20,0
3+
,GENERIC QUALITY INDICATORS,,,,,,,,,20
4+
DEGRADED_INST_MDR,Quality of MDR has been degraded from nominal due to an instrument degradation,0,NA,1,1,1,boolean,1,1,20
5+
DEGRADED_PROC_MDR,Quality of MDR has been degraded from nominal due to a processing degradation,0,NA,1,1,1,boolean,1,1,21
6+
Scan Line Information,,,,,,,,,,22
7+
LINE_COUNTER,Line counter since last auto-calibration sequence. If calibration enabled then it runs from 0 to 39 else from 0 to 8191 followed by 0 to 8191 and so on,0,NA,1,1,1,u-integer2,2,2,22
8+
SCAN_TYPE_CODE,"Scan type code (0 = Earth view, 1 = space view, 2 = cold BB view, 3 = warm BB view, 4 = else.",0,NA,1,1,1,u-integer2,2,2,24
9+
QUALITY_INDICATOR,Quality Indicator Bit Field,0,N/A,1,1,1,bitst(32),4,4,26
10+
SCAN_LINE_QUALITY,Scan Line Quality Flags,0,N/A,1,1,1,bitst(32),4,4,30
11+
DATA_CALIBRATION,Noise-Equivalent Delta N and Channel Quality Flags,0,N/A,20,1,1,DATA_CALQUAL,2,40,34
12+
MEASUREMENT DATA ,,,,,,,,,,74
13+
DIGITAL_A_DATA_ELEMENT_RAD,Radiances for 56 pixel values of a scan line in the 20 channels. Earth scan pixel values are calibrated to radiances (channel 1 - 19) and reflectance factors (channel 20),4,NA,56,1,1,DATA_ELEM_RAD,84,4704,74
14+
DIGITAL_A_DATA_ELEMENT_FLAG,Information on the instrument status.,0,NA,8,1,1,DATA_ELEM_FLAG,44,352,4778
15+
Digital B telemetry,,,,,,,,,,5130
16+
INSTRUMENT_INVALID_DIGITAL_WORD_FLAG,Invalid Word Bit Flags,0,N/A,1,1,1,bitst(16),2,2,5130
17+
DIGITAL_B_DATA,Digital B Data,0,N/A,1,1,1,bitst(16),2,2,5132
18+
Analog telemetry,,,,,,,,,,5134
19+
INSTRUMENT_INVALID_ANALOG_WORD_FLAG,Invalid Word Bit Flags,0,N/A,1,1,1,bitst(32),4,4,5134
20+
ANALOG_DATA,Analog Data,0,N/A,16,1,1,u-byte,1,16,5138
21+
NAVIGATION DATA AT SCAN LINE,,,,,,,,,,5154
22+
TIME_ATTITUDE,Time Associated with Attitude Angles,0,s,1,1,1,u-integer4,4,4,5154
23+
EULER_ANGLE,"Euler Angles: Roll, Pitch, Yaw",3,deg,3,1,1,integer2,2,6,5158
24+
NAVIGATION_STATUS,Navigation Status Bit Field,0,N/A,1,1,1,bitst(32),4,4,5164
25+
SPACECRAFT_ALTITUDE,Spacecraft Altitude Above Reference Geoid (MSL) ,1,km,1,1,1,u-integer4,4,4,5168
26+
ANGULAR_RELATION,"Angular relationships: solar zenith angle, satellite zenith angle, solar azimuth angle, satellite azimuth angle (FOV 1 to 56) Note: azimuth angle range is -180 to +180, where minus is west and plus is east.",2,deg,4,56,1,integer2,2,448,5172
27+
EARTH_LOCATION,"Earth Location: latitude, longitude (FOV 1 to 56)",4,deg,2,56,1,integer4,4,448,5620
28+
SURFACE_PROPERTY,"Surface property (0 = water, 1 = mixed/coast, 2 = land) ",,,56,1,1,integer2,2,112,6068
29+
TERRAIN_ELEVATION,Average terrain elevation (FOV 1 to 56),,m,56,1,1,integer2,2,112,6180
30+
Calibration Coefficient (see Section 3.5.1.12),,,,,,,,,,6292
31+
PRIMARY_CALIBRATION_SECOND_TERM,Primary Calibration Second Order Term a2 (ch. 1-20) ,12,�mW/m2/sr/cm-1/cnt2 or % alb/cnt2 (ch 20),20,1,1,integer4,4,80,6292
32+
PRIMARY_CALIBRATION_FIRST_TERM,Primary Calibration First Order Term a1 (ch. 1-20) ,9,�mW/m2/sr/cm-1/cnt or % alb/cnt (ch 20),20,1,1,integer4,4,80,6372
33+
PRIMARY_CALIBRATION_ZEROTH_TERM,Primary Calibration Zeroth Order Term a0 (ch. 1-20) ,6,�mW/m2/sr/cm-1 or % alb (ch 20) ,20,1,1,integer4,4,80,6452
34+
SPARE_CALIBRATION_SECOND_TERM,Spare Calibration Second Order Term (ch. 1-20) ,12,�mW/m2/sr/cm-1/cnt2 or % alb/cnt2 (ch 20),20,1,1,integer4,4,80,6532
35+
SPARE_CALIBRATION_FIRST_TERM,Spare Calibration First Order Term (ch. 1-20) ,9,�mW/m2/sr/cm-1/cnt or % alb/cnt (ch 20),20,1,1,integer4,4,80,6612
36+
SPARE_CALIBRATION_ZEROTH_TERM,Spare Calibration Zeroth Order Term(ch. 1-20) ,6,�mW/m2/sr/cm-1 or % alb (ch 20),20,1,1,integer4,4,80,6692
37+
CLOUD COVERAGE INFORMATION,,,,,,,,,,6772
38+
PERCENTAGE_CLEAR_SKY,Percentage of sky that is clear of clouds,2,%,56,1,1,u-integer2,2,112,6772
39+
SIZE OF THE MDR,,,,,,,,,,6884

src/Instruments/ATOVS/MHS/MHS.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
# Copyright (c) 2025 EUMETSAT
2+
# License: MIT
3+
14
include("MHS_records.jl")
25
include("MHS_dimensions.jl")

0 commit comments

Comments
 (0)