Source code for satpy.readers.seviri_l1b_native_hdr
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2014-2019 Satpy developers
#
# This file is part of satpy.
#
# satpy is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# satpy is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# satpy. If not, see <http://www.gnu.org/licenses/>.
"""Header and trailer records of SEVIRI native format."""
import numpy as np
from satpy.readers.eum_base import time_cds, time_cds_expanded, time_cds_short
from satpy.readers.seviri_base import HRV_NUM_COLUMNS, HRV_NUM_LINES, VISIR_NUM_COLUMNS, VISIR_NUM_LINES
[docs]
class GSDTRecords(object):
"""MSG Ground Segment Data Type records.
Reference Document (EUM/MSG/SPE/055):
MSG Ground Segment Design Specification (GSDS)
"""
gp_fac_env = np.uint8
gp_fac_id = np.uint8
gp_sc_id = np.uint16
gp_su_id = np.uint32
gp_svce_type = np.uint8
# 4 bytes
gp_cpu_address = [
("Qualifier_1", np.uint8),
("Qualifier_2", np.uint8),
("Qualifier_3", np.uint8),
("Qualifier_4", np.uint8)
]
# 22 bytes
gp_pk_header = [
("HeaderVersionNo", np.uint8),
("PacketType", np.uint8),
("SubHeaderType", np.uint8),
("SourceFacilityId", gp_fac_id),
("SourceEnvId", gp_fac_env),
("SourceInstanceId", np.uint8),
("SourceSUId", gp_su_id),
("SourceCPUId", gp_cpu_address),
("DestFacilityId", gp_fac_id),
("DestEnvId", gp_fac_env),
("SequenceCount", np.uint16),
("PacketLength", np.int32)
]
# 16 bytes
gp_pk_sh1 = [
("SubHeaderVersionNo", np.uint8),
("ChecksumFlag", bool),
("Acknowledgement", (np.uint8, 4)),
("ServiceType", gp_svce_type),
("ServiceSubtype", np.uint8),
("PacketTime", time_cds_short),
("SpacecraftId", gp_sc_id)
]
[docs]
class Msg15NativeHeaderRecord(object):
"""SEVIRI Level 1.5 header for native-format."""
[docs]
def get(self, with_archive_header):
"""Get the header type."""
# 450400 bytes including archive header
# 445286 bytes excluding archive header
record = []
if with_archive_header:
record += [
("15_MAIN_PRODUCT_HEADER", L15MainProductHeaderRecord().get()),
("15_SECONDARY_PRODUCT_HEADER",
L15SecondaryProductHeaderRecord().get()),
]
record += [
("GP_PK_HEADER", GSDTRecords.gp_pk_header),
("GP_PK_SH1", GSDTRecords.gp_pk_sh1),
("15_DATA_HEADER", L15DataHeaderRecord().get())
]
return np.dtype(record).newbyteorder(">")
[docs]
class L15PhData(object):
"""L15 Ph handler."""
# 80 bytes
l15_ph_data = [
("Name", "S30"),
("Value", "S50")
]
[docs]
class L15MainProductHeaderRecord(object):
"""L15 Main Product header handler.
Reference Document:
MSG Level 1.5 Native Format File Definition
"""
[docs]
def get(self):
"""Get header data."""
l15_ph_data = L15PhData.l15_ph_data
l15_ph_data_identification = [
("Name", "S30"),
("Size", "S16"),
("Address", "S16")
]
# 3674 bytes
record = [
("FormatName", l15_ph_data),
("FormatDocumentName", l15_ph_data),
("FormatDocumentMajorVersion", l15_ph_data),
("FormatDocumentMinorVersion", l15_ph_data),
("CreationDateTime", l15_ph_data),
("CreatingCentre", l15_ph_data),
("DataSetIdentification", (l15_ph_data_identification, 27)),
("TotalFileSize", l15_ph_data),
("GORT", l15_ph_data),
("ASTI", l15_ph_data),
("LLOS", l15_ph_data),
("SNIT", l15_ph_data),
("AIID", l15_ph_data),
("SSBT", l15_ph_data),
("SSST", l15_ph_data),
("RRCC", l15_ph_data),
("RRBT", l15_ph_data),
("RRST", l15_ph_data),
("PPRC", l15_ph_data),
("PPDT", l15_ph_data),
("GPLV", l15_ph_data),
("APNM", l15_ph_data),
("AARF", l15_ph_data),
("UUDT", l15_ph_data),
("QQOV", l15_ph_data),
("UDSP", l15_ph_data)
]
return record
[docs]
class L15SecondaryProductHeaderRecord(object):
"""L15 Secondary Product header handler.
Reference Document:
MSG Level 1.5 Native Format File Definition
"""
[docs]
def get(self):
"""Get header data."""
l15_ph_data = L15PhData.l15_ph_data
# 1440 bytes
record = [
("ABID", l15_ph_data),
("SMOD", l15_ph_data),
("APXS", l15_ph_data),
("AVPA", l15_ph_data),
("LSCD", l15_ph_data),
("LMAP", l15_ph_data),
("QDLC", l15_ph_data),
("QDLP", l15_ph_data),
("QQAI", l15_ph_data),
("SelectedBandIDs", l15_ph_data),
("SouthLineSelectedRectangle", l15_ph_data),
("NorthLineSelectedRectangle", l15_ph_data),
("EastColumnSelectedRectangle", l15_ph_data),
("WestColumnSelectedRectangle", l15_ph_data),
("NumberLinesVISIR", l15_ph_data),
("NumberColumnsVISIR", l15_ph_data),
("NumberLinesHRV", l15_ph_data),
("NumberColumnsHRV", l15_ph_data)
]
return record
[docs]
class L15DataHeaderRecord(object):
"""L15 Data Header handler.
Reference Document (EUM/MSG/ICD/105):
MSG Level 1.5 Image Data Format Description
"""
[docs]
def get(self):
"""Get header record data."""
# 445248 bytes
record = [
("15HeaderVersion", np.uint8),
("SatelliteStatus", self.satellite_status),
("ImageAcquisition", self.image_acquisition),
("CelestialEvents", self.celestial_events),
("ImageDescription", self.image_description),
("RadiometricProcessing", self.radiometric_processing),
("GeometricProcessing", self.geometric_processing),
("IMPFConfiguration", self.impf_configuration)]
return record
@property
def satellite_status(self):
"""Get satellite status data."""
# 7 bytes
satellite_definition = [
("SatelliteId", np.uint16),
("NominalLongitude", np.float32),
("SatelliteStatus", np.uint8)]
# 28 bytes
satellite_operations = [
("LastManoeuvreFlag", bool),
("LastManoeuvreStartTime", time_cds_short),
("LastManoeuvreEndTime", time_cds_short),
("LastManoeuvreType", np.uint8),
("NextManoeuvreFlag", bool),
("NextManoeuvreStartTime", time_cds_short),
("NextManoeuvreEndTime", time_cds_short),
("NextManoeuvreType", np.uint8)]
# 396 bytes
orbit_coeff = [
("StartTime", time_cds_short),
("EndTime", time_cds_short),
("X", (np.float64, 8)),
("Y", (np.float64, 8)),
("Z", (np.float64, 8)),
("VX", (np.float64, 8)),
("VY", (np.float64, 8)),
("VZ", (np.float64, 8))]
# 39612 bytes
orbit = [
("PeriodStartTime", time_cds_short),
("PeriodEndTime", time_cds_short),
("OrbitPolynomial", (orbit_coeff, 100))]
# 204 bytes
attitude_coeff = [
("StartTime", time_cds_short),
("EndTime", time_cds_short),
("XofSpinAxis", (np.float64, 8)),
("YofSpinAxis", (np.float64, 8)),
("ZofSpinAxis", (np.float64, 8))]
# 20420 bytes
attitude = [
("PeriodStartTime", time_cds_short),
("PeriodEndTime", time_cds_short),
("PrincipleAxisOffsetAngle", np.float64),
("AttitudePolynomial", (attitude_coeff, 100))]
# 59 bytes
utc_correlation = [
("PeriodStartTime", time_cds_short),
("PeriodEndTime", time_cds_short),
("OnBoardTimeStart", (np.uint8, 7)),
("VarOnBoardTimeStart", np.float64),
("A1", np.float64),
("VarA1", np.float64),
("A2", np.float64),
("VarA2", np.float64)]
# 60134 bytes
record = [
("SatelliteDefinition", satellite_definition),
("SatelliteOperations", satellite_operations),
("Orbit", orbit),
("Attitude", attitude),
("SpinRetreatRCStart", np.float64),
("UTCCorrelation", utc_correlation)]
return record
@property
def image_acquisition(self):
"""Get image acquisition data."""
planned_acquisition_time = [
("TrueRepeatCycleStart", time_cds_expanded),
("PlanForwardScanEnd", time_cds_expanded),
("PlannedRepeatCycleEnd", time_cds_expanded)]
radiometer_status = [
("ChannelStatus", (np.uint8, 12)),
("DetectorStatus", (np.uint8, 42))]
hrv_frame_offsets = [
("MDUNomHRVDelay1", np.uint16),
("MDUNomHRVDelay2", np.uint16),
("Spare", np.uint16),
("MDUNomHRVBreakLine", np.uint16)]
operation_parameters = [
("L0_LineCounter", np.uint16),
("K1_RetraceLines", np.uint16),
("K2_PauseDeciseconds", np.uint16),
("K3_RetraceLines", np.uint16),
("K4_PauseDeciseconds", np.uint16),
("K5_RetraceLines", np.uint16),
("XDeepSpaceWindowPosition", np.uint8)]
radiometer_settings = [
("MDUSamplingDelays", (np.uint16, 42)),
("HRVFrameOffsets", hrv_frame_offsets),
("DHSSSynchSelection", np.uint8),
("MDUOutGain", (np.uint16, 42)),
("MDUCoarseGain", (np.uint8, 42)),
("MDUFineGain", (np.uint16, 42)),
("MDUNumericalOffset", (np.uint16, 42)),
("PUGain", (np.uint16, 42)),
("PUOffset", (np.uint16, 27)),
("PUBias", (np.uint16, 15)),
("OperationParameters", operation_parameters),
("RefocusingLines", np.uint16),
("RefocusingDirection", np.uint8),
("RefocusingPosition", np.uint16),
("ScanRefPosFlag", bool),
("ScanRefPosNumber", np.uint16),
("ScanRefPosVal", np.float32),
("ScanFirstLine", np.uint16),
("ScanLastLine", np.uint16),
("RetraceStartLine", np.uint16)]
decontamination = [
("DecontaminationNow", bool),
("DecontaminationStart", time_cds_short),
("DecontaminationEnd", time_cds_short)]
radiometer_operations = [
("LastGainChangeFlag", bool),
("LastGainChangeTime", time_cds_short),
("Decontamination", decontamination),
("BBCalScheduled", bool),
("BBCalibrationType", np.uint8),
("BBFirstLine", np.uint16),
("BBLastLine", np.uint16),
("ColdFocalPlaneOpTemp", np.uint16),
("WarmFocalPlaneOpTemp", np.uint16)]
record = [
("PlannedAcquisitionTime", planned_acquisition_time),
("RadiometerStatus", radiometer_status),
("RadiometerSettings", radiometer_settings),
("RadiometerOperations", radiometer_operations)]
return record
@property
def celestial_events(self):
"""Get celestial events data."""
earth_moon_sun_coeff = [
("StartTime", time_cds_short),
("EndTime", time_cds_short),
("AlphaCoef", (np.float64, 8)),
("BetaCoef", (np.float64, 8))]
star_coeff = [
("StarId", np.uint16),
("StartTime", time_cds_short),
("EndTime", time_cds_short),
("AlphaCoef", (np.float64, 8)),
("BetaCoef", (np.float64, 8))]
ephemeris = [
("PeriodTimeStart", time_cds_short),
("PeriodTimeEnd", time_cds_short),
("RelatedOrbitFileTime", "S15"),
("RelatedAttitudeFileTime", "S15"),
("EarthEphemeris", (earth_moon_sun_coeff, 100)),
("MoonEphemeris", (earth_moon_sun_coeff, 100)),
("SunEphemeris", (earth_moon_sun_coeff, 100)),
("StarEphemeris", (star_coeff, (20, 100)))]
relation_to_image = [
("TypeOfEclipse", np.uint8),
("EclipseStartTime", time_cds_short),
("EclipseEndTime", time_cds_short),
("VisibleBodiesInImage", np.uint8),
("BodiesCloseToFOV", np.uint8),
("ImpactOnImageQuality", np.uint8)]
record = [
("CelestialBodiesPosition", ephemeris),
("RelationToImage", relation_to_image)]
return record
@property
def image_description(self):
"""Get image description data."""
projection_description = [
("TypeOfProjection", np.uint8),
("LongitudeOfSSP", np.float32)]
reference_grid = [
("NumberOfLines", np.int32),
("NumberOfColumns", np.int32),
("LineDirGridStep", np.float32),
("ColumnDirGridStep", np.float32),
("GridOrigin", np.uint8)]
planned_coverage_vis_ir = [
("SouthernLinePlanned", np.int32),
("NorthernLinePlanned", np.int32),
("EasternColumnPlanned", np.int32),
("WesternColumnPlanned", np.int32)]
planned_coverage_hrv = [
("LowerSouthLinePlanned", np.int32),
("LowerNorthLinePlanned", np.int32),
("LowerEastColumnPlanned", np.int32),
("LowerWestColumnPlanned", np.int32),
("UpperSouthLinePlanned", np.int32),
("UpperNorthLinePlanned", np.int32),
("UpperEastColumnPlanned", np.int32),
("UpperWestColumnPlanned", np.int32)]
level_15_image_production = [
("ImageProcDirection", np.uint8),
("PixelGenDirection", np.uint8),
("PlannedChanProcessing", (np.uint8, 12))]
record = [
("ProjectionDescription", projection_description),
("ReferenceGridVIS_IR", reference_grid),
("ReferenceGridHRV", reference_grid),
("PlannedCoverageVIS_IR", planned_coverage_vis_ir),
("PlannedCoverageHRV", planned_coverage_hrv),
("Level15ImageProduction", level_15_image_production)]
return record
@property
def radiometric_processing(self):
"""Get radiometric processing data."""
rp_summary = [
("RadianceLinearization", (bool, 12)),
("DetectorEqualization", (bool, 12)),
("OnboardCalibrationResult", (bool, 12)),
("MPEFCalFeedback", (bool, 12)),
("MTFAdaptation", (bool, 12)),
("StrayLightCorrection", (bool, 12))]
level_15_image_calibration = [
("CalSlope", np.float64),
("CalOffset", np.float64)]
time_cuc_size = [
("CT1", np.uint8),
("CT2", np.uint8),
("CT3", np.uint8),
("CT4", np.uint8),
("FT1", np.uint8),
("FT2", np.uint8),
("FT3", np.uint8)]
cold_fp_temperature = [
("FCUNominalColdFocalPlaneTemp", np.uint16),
("FCURedundantColdFocalPlaneTemp", np.uint16)]
warm_fp_temperature = [
("FCUNominalWarmFocalPlaneVHROTemp", np.uint16),
("FCURedundantWarmFocalPlaneVHROTemp", np.uint16)]
scan_mirror_temperature = [
("FCUNominalScanMirrorSensor1Temp", np.uint16),
("FCURedundantScanMirrorSensor1Temp", np.uint16),
("FCUNominalScanMirrorSensor2Temp", np.uint16),
("FCURedundantScanMirrorSensor2Temp", np.uint16)]
m1m2m3_temperature = [
("FCUNominalM1MirrorSensor1Temp", np.uint16),
("FCURedundantM1MirrorSensor1Temp", np.uint16),
("FCUNominalM1MirrorSensor2Temp", np.uint16),
("FCURedundantM1MirrorSensor2Temp", np.uint16),
("FCUNominalM23AssemblySensor1Temp", np.uint8),
("FCURedundantM23AssemblySensor1Temp", np.uint8),
("FCUNominalM23AssemblySensor2Temp", np.uint8),
("FCURedundantM23AssemblySensor2Temp", np.uint8)]
baffle_temperature = [
("FCUNominalM1BaffleTemp", np.uint16),
("FCURedundantM1BaffleTemp", np.uint16)]
blackbody_temperature = [
("FCUNominalBlackBodySensorTemp", np.uint16),
("FCURedundantBlackBodySensorTemp", np.uint16)]
fcu_mode = [
("FCUNominalSMMStatus", "S2"),
("FCURedundantSMMStatus", "S2")]
extracted_bb_data = [
("NumberOfPixelsUsed", np.uint32),
("MeanCount", np.float32),
("RMS", np.float32),
("MaxCount", np.uint16),
("MinCount", np.uint16),
("BB_Processing_Slope", np.float64),
("BB_Processing_Offset", np.float64)]
bb_related_data = [
("OnBoardBBTime", time_cuc_size),
("MDUOutGain", (np.uint16, 42)),
("MDUCoarseGain", (np.uint8, 42)),
("MDUFineGain", (np.uint16, 42)),
("MDUNumericalOffset", (np.uint16, 42)),
("PUGain", (np.uint16, 42)),
("PUOffset", (np.uint16, 27)),
("PUBias", (np.uint16, 15)),
("DCRValues", (np.uint8, 63)),
("X_DeepSpaceWindowPosition", np.int8),
("ColdFPTemperature", cold_fp_temperature),
("WarmFPTemperature", warm_fp_temperature),
("ScanMirrorTemperature", scan_mirror_temperature),
("M1M2M3Temperature", m1m2m3_temperature),
("BaffleTemperature", baffle_temperature),
("BlackBodyTemperature", blackbody_temperature),
("FCUMode", fcu_mode),
("ExtractedBBData", (extracted_bb_data, 12))]
black_body_data_used = [
("BBObservationUTC", time_cds_expanded),
("BBRelatedData", bb_related_data)]
impf_cal_data = [
("ImageQualityFlag", np.uint8),
("ReferenceDataFlag", np.uint8),
("AbsCalMethod", np.uint8),
("Pad1", "S1"),
("AbsCalWeightVic", np.float32),
("AbsCalWeightXsat", np.float32),
("AbsCalCoeff", np.float32),
("AbsCalError", np.float32),
("GSICSCalCoeff", np.float32),
("GSICSCalError", np.float32),
("GSICSOffsetCount", np.float32)]
rad_proc_mtf_adaptation = [
("VIS_IRMTFCorrectionE_W", (np.float32, (33, 16))),
("VIS_IRMTFCorrectionN_S", (np.float32, (33, 16))),
("HRVMTFCorrectionE_W", (np.float32, (9, 16))),
("HRVMTFCorrectionN_S", (np.float32, (9, 16))),
("StraylightCorrection", (np.float32, (12, 8, 8)))]
record = [
("RPSummary", rp_summary),
("Level15ImageCalibration", (level_15_image_calibration, 12)),
("BlackBodyDataUsed", black_body_data_used),
("MPEFCalFeedback", (impf_cal_data, 12)),
("RadTransform", (np.float32, (42, 64))),
("RadProcMTFAdaptation", rad_proc_mtf_adaptation)]
return record
@property
def geometric_processing(self):
"""Get geometric processing data."""
opt_axis_distances = [
("E-WFocalPlane", (np.float32, 42)),
("N_SFocalPlane", (np.float32, 42))]
earth_model = [
("TypeOfEarthModel", np.uint8),
("EquatorialRadius", np.float64),
("NorthPolarRadius", np.float64),
("SouthPolarRadius", np.float64)]
record = [
("OptAxisDistances", opt_axis_distances),
("EarthModel", earth_model),
("AtmosphericModel", (np.float32, (12, 360))),
("ResamplingFunctions", (np.uint8, 12))]
return record
@property
def impf_configuration(self):
"""Get impf configuration information."""
overall_configuration = [
("Issue", np.uint16),
("Revision", np.uint16)
]
sw_version = overall_configuration
info_base_versions = sw_version
su_configuration = [
("SWVersion", sw_version),
("InfoBaseVersions", (info_base_versions, 10))
]
su_details = [
("SUId", GSDTRecords.gp_su_id),
("SUIdInstance", np.int8),
("SUMode", np.uint8),
("SUState", np.uint8),
("SUConfiguration", su_configuration)
]
equalisation_params = [
("ConstCoeff", np.float32),
("LinearCoeff", np.float32),
("QuadraticCoeff", np.float32)
]
black_body_data_for_warm_start = [
("GTotalForMethod1", (np.float64, 12)),
("GTotalForMethod2", (np.float64, 12)),
("GTotalForMethod3", (np.float64, 12)),
("GBackForMethod1", (np.float64, 12)),
("GBackForMethod2", (np.float64, 12)),
("GBackForMethod3", (np.float64, 12)),
("RatioGTotalToGBack", (np.float64, 12)),
("GainInFrontOpticsCont", (np.float64, 12)),
("CalibrationConstants", (np.float32, 12)),
("maxIncidentRadiance", (np.float64, 12)),
("TimeOfColdObsSeconds", np.float64),
("TimeOfColdObsNanoSecs", np.float64),
("IncidenceRadiance", (np.float64, 12)),
("TempCal", np.float64),
("TempM1", np.float64),
("TempScan", np.float64),
("TempM1Baf", np.float64),
("TempCalSurround", np.float64)
]
mirror_parameters = [
("MaxFeedbackVoltage", np.float64),
("MinFeedbackVoltage", np.float64),
("MirrorSlipEstimate", np.float64)
]
hktm_parameters = [
("TimeS0Packet", time_cds_short),
("TimeS1Packet", time_cds_short),
("TimeS2Packet", time_cds_short),
("TimeS3Packet", time_cds_short),
("TimeS4Packet", time_cds_short),
("TimeS5Packet", time_cds_short),
("TimeS6Packet", time_cds_short),
("TimeS7Packet", time_cds_short),
("TimeS8Packet", time_cds_short),
("TimeS9Packet", time_cds_short),
("TimeSYPacket", time_cds_short),
("TimePSPacket", time_cds_short)
]
warm_start_params = [
("ScanningLaw", (np.float64, 1527)),
("RadFramesAlignment", (np.float64, 3)),
("ScanningLawVariation", (np.float32, 2)),
("EqualisationParams", (equalisation_params, 42)),
("BlackBodyDataForWarmStart", black_body_data_for_warm_start),
("MirrorParameters", mirror_parameters),
("LastSpinPeriod", np.float64),
("HKTMParameters", hktm_parameters),
("WSPReserved", (np.uint8, 3312))
]
record = [
("OverallConfiguration", overall_configuration),
("SUDetails", (su_details, 50)),
("WarmStartParams", warm_start_params)
]
return record
[docs]
class Msg15NativeTrailerRecord(object):
"""SEVIRI Level 1.5 trailer for native-format.
Reference Document (EUM/MSG/ICD/105):
MSG Level 1.5 Image Data Format Description
"""
[docs]
def get(self):
"""Get header record data."""
# 380363 bytes
record = [
("GP_PK_HEADER", GSDTRecords.gp_pk_header),
("GP_PK_SH1", GSDTRecords.gp_pk_sh1),
("15TRAILER", self.seviri_l15_trailer)
]
return np.dtype(record).newbyteorder(">")
@property
def seviri_l15_trailer(self):
"""Get file trailer data."""
record = [
("15TrailerVersion", np.uint8),
("ImageProductionStats", self.image_production_stats),
("NavigationExtractionResults", self.navigation_extraction_results),
("RadiometricQuality", self.radiometric_quality),
("GeometricQuality", self.geometric_quality),
("TimelinessAndCompleteness", self.timeliness_and_completeness)
]
return record
@property
def image_production_stats(self):
"""Get image production statistics."""
gp_sc_id = GSDTRecords.gp_sc_id
actual_scanning_summary = [
("NominalImageScanning", np.uint8),
("ReducedScan", np.uint8),
("ForwardScanStart", time_cds_short),
("ForwardScanEnd", time_cds_short)
]
radiometric_behaviour = [
("NominalBehaviour", np.uint8),
("RadScanIrregularity", np.uint8),
("RadStoppage", np.uint8),
("RepeatCycleNotCompleted", np.uint8),
("GainChangeTookPlace", np.uint8),
("DecontaminationTookPlace", np.uint8),
("NoBBCalibrationAchieved", np.uint8),
("IncorrectTemperature", np.uint8),
("InvalidBBData", np.uint8),
("InvalidAuxOrHKTMData", np.uint8),
("RefocusingMechanismActuated", np.uint8),
("MirrorBackToReferencePos", np.uint8)
]
reception_summary_stats = [
("PlannedNumberOfL10Lines", (np.uint32, 12)),
("NumberOfMissingL10Lines", (np.uint32, 12)),
("NumberOfCorruptedL10Lines", (np.uint32, 12)),
("NumberOfReplacedL10Lines", (np.uint32, 12))
]
l15_image_validity = [
("NominalImage", np.uint8),
("NonNominalBecauseIncomplete", np.uint8),
("NonNominalRadiometricQuality", np.uint8),
("NonNominalGeometricQuality", np.uint8),
("NonNominalTimeliness", np.uint8),
("IncompleteL15", np.uint8),
]
actual_l15_coverage_vis_ir = [
("SouthernLineActual", np.int32),
("NorthernLineActual", np.int32),
("EasternColumnActual", np.int32),
("WesternColumnActual", np.int32)
]
actual_l15_coverage_hrv = [
("LowerSouthLineActual", np.int32),
("LowerNorthLineActual", np.int32),
("LowerEastColumnActual", np.int32),
("LowerWestColumnActual", np.int32),
("UpperSouthLineActual", np.int32),
("UpperNorthLineActual", np.int32),
("UpperEastColumnActual", np.int32),
("UpperWestColumnActual", np.int32),
]
record = [
("SatelliteId", gp_sc_id),
("ActualScanningSummary", actual_scanning_summary),
("RadiometricBehaviour", radiometric_behaviour),
("ReceptionSummaryStats", reception_summary_stats),
("L15ImageValidity", (l15_image_validity, 12)),
("ActualL15CoverageVIS_IR", actual_l15_coverage_vis_ir),
("ActualL15CoverageHRV", actual_l15_coverage_hrv)
]
return record
@property
def navigation_extraction_results(self):
"""Get navigation extraction data."""
horizon_observation = [
("HorizonId", np.uint8),
("Alpha", np.float64),
("AlphaConfidence", np.float64),
("Beta", np.float64),
("BetaConfidence", np.float64),
("ObservationTime", time_cds),
("SpinRate", np.float64),
("AlphaDeviation", np.float64),
("BetaDeviation", np.float64)
]
star_observation = [
("StarId", np.uint16),
("Alpha", np.float64),
("AlphaConfidence", np.float64),
("Beta", np.float64),
("BetaConfidence", np.float64),
("ObservationTime", time_cds),
("SpinRate", np.float64),
("AlphaDeviation", np.float64),
("BetaDeviation", np.float64)
]
landmark_observation = [
("LandmarkId", np.uint16),
("LandmarkLongitude", np.float64),
("LandmarkLatitude", np.float64),
("Alpha", np.float64),
("AlphaConfidence", np.float64),
("Beta", np.float64),
("BetaConfidence", np.float64),
("ObservationTime", time_cds),
("SpinRate", np.float64),
("AlphaDeviation", np.float64),
("BetaDeviation", np.float64)
]
record = [
("ExtractedHorizons", (horizon_observation, 4)),
("ExtractedStars", (star_observation, 20)),
("ExtractedLandmarks", (landmark_observation, 50))
]
return record
@property
def radiometric_quality(self):
"""Get radiometric quality record data."""
l10_rad_quality = [
("FullImageMinimumCount", np.uint16),
("FullImageMaximumCount", np.uint16),
("EarthDiskMinimumCount", np.uint16),
("EarthDiskMaximumCount", np.uint16),
("MoonMinimumCount", np.uint16),
("MoonMaximumCount", np.uint16),
("FullImageMeanCount", np.float32),
("FullImageStandardDeviation", np.float32),
("EarthDiskMeanCount", np.float32),
("EarthDiskStandardDeviation", np.float32),
("MoonMeanCount", np.float32),
("MoonStandardDeviation", np.float32),
("SpaceMeanCount", np.float32),
("SpaceStandardDeviation", np.float32),
("SESpaceCornerMeanCount", np.float32),
("SESpaceCornerStandardDeviation", np.float32),
("SWSpaceCornerMeanCount", np.float32),
("SWSpaceCornerStandardDeviation", np.float32),
("NESpaceCornerMeanCount", np.float32),
("NESpaceCornerStandardDeviation", np.float32),
("NWSpaceCornerMeanCount", np.float32),
("NWSpaceCornerStandardDeviation", np.float32),
("4SpaceCornersMeanCount", np.float32),
("4SpaceCornersStandardDeviation", np.float32),
("FullImageHistogram", (np.uint32, 256)),
("EarthDiskHistogram", (np.uint32, 256)),
("ImageCentreSquareHistogram", (np.uint32, 256)),
("SESpaceCornerHistogram", (np.uint32, 128)),
("SWSpaceCornerHistogram", (np.uint32, 128)),
("NESpaceCornerHistogram", (np.uint32, 128)),
("NWSpaceCornerHistogram", (np.uint32, 128)),
("FullImageEntropy", (np.float32, 3)),
("EarthDiskEntropy", (np.float32, 3)),
("ImageCentreSquareEntropy", (np.float32, 3)),
("SESpaceCornerEntropy", (np.float32, 3)),
("SWSpaceCornerEntropy", (np.float32, 3)),
("NESpaceCornerEntropy", (np.float32, 3)),
("NWSpaceCornerEntropy", (np.float32, 3)),
("4SpaceCornersEntropy", (np.float32, 3)),
("ImageCentreSquarePSD_EW", (np.float32, 128)),
("FullImagePSD_EW", (np.float32, 128)),
("ImageCentreSquarePSD_NS", (np.float32, 128)),
("FullImagePSD_NS", (np.float32, 128))
]
l15_rad_quality = [
("FullImageMinimumCount", np.uint16),
("FullImageMaximumCount", np.uint16),
("EarthDiskMinimumCount", np.uint16),
("EarthDiskMaximumCount", np.uint16),
("FullImageMeanCount", np.float32),
("FullImageStandardDeviation", np.float32),
("EarthDiskMeanCount", np.float32),
("EarthDiskStandardDeviation", np.float32),
("SpaceMeanCount", np.float32),
("SpaceStandardDeviation", np.float32),
("FullImageHistogram", (np.uint32, 256)),
("EarthDiskHistogram", (np.uint32, 256)),
("ImageCentreSquareHistogram", (np.uint32, 256)),
("FullImageEntropy", (np.float32, 3)),
("EarthDiskEntropy", (np.float32, 3)),
("ImageCentreSquareEntropy", (np.float32, 3)),
("ImageCentreSquarePSD_EW", (np.float32, 128)),
("FullImagePSD_EW", (np.float32, 128)),
("ImageCentreSquarePSD_NS", (np.float32, 128)),
("FullImagePSD_NS", (np.float32, 128)),
("SESpaceCornerL15_RMS", np.float32),
("SESpaceCornerL15_Mean", np.float32),
("SWSpaceCornerL15_RMS", np.float32),
("SWSpaceCornerL15_Mean", np.float32),
("NESpaceCornerL15_RMS", np.float32),
("NESpaceCornerL15_Mean", np.float32),
("NWSpaceCornerL15_RMS", np.float32),
("NWSpaceCornerL15_Mean", np.float32)
]
record = [
("L10RadQuality", (l10_rad_quality, 42)),
("L15RadQuality", (l15_rad_quality, 12))
]
return record
@property
def geometric_quality(self):
"""Get geometric quality record data."""
absolute_accuracy = [
("QualityInfoValidity", np.uint8),
("EastWestAccuracyRMS", np.float32),
("NorthSouthAccuracyRMS", np.float32),
("MagnitudeRMS", np.float32),
("EastWestUncertaintyRMS", np.float32),
("NorthSouthUncertaintyRMS", np.float32),
("MagnitudeUncertaintyRMS", np.float32),
("EastWestMaxDeviation", np.float32),
("NorthSouthMaxDeviation", np.float32),
("MagnitudeMaxDeviation", np.float32),
("EastWestUncertaintyMax", np.float32),
("NorthSouthUncertaintyMax", np.float32),
("MagnitudeUncertaintyMax", np.float32)
]
relative_accuracy = absolute_accuracy
pixels_500_relative_accuracy = absolute_accuracy
pixels_16_relative_accuracy = absolute_accuracy
misregistration_residuals = [
("QualityInfoValidity", np.uint8),
("EastWestResidual", np.float32),
("NorthSouthResidual", np.float32),
("EastWestUncertainty", np.float32),
("NorthSouthUncertainty", np.float32),
("EastWestRMS", np.float32),
("NorthSouthRMS", np.float32),
("EastWestMagnitude", np.float32),
("NorthSouthMagnitude", np.float32),
("EastWestMagnitudeUncertainty", np.float32),
("NorthSouthMagnitudeUncertainty", np.float32)
]
geometric_quality_status = [
("QualityNominal", np.uint8),
("NominalAbsolute", np.uint8),
("NominalRelativeToPreviousImage", np.uint8),
("NominalForREL500", np.uint8),
("NominalForREL16", np.uint8),
("NominalForResMisreg", np.uint8)
]
record = [
("AbsoluteAccuracy", (absolute_accuracy, 12)),
("RelativeAccuracy", (relative_accuracy, 12)),
("500PixelsRelativeAccuracy", (pixels_500_relative_accuracy, 12)),
("16PixelsRelativeAccuracy", (pixels_16_relative_accuracy, 12)),
("MisregistrationResiduals", (misregistration_residuals, 12)),
("GeometricQualityStatus", (geometric_quality_status, 12))
]
return record
@property
def timeliness_and_completeness(self):
"""Get time and completeness record data."""
timeliness = [
("MaxDelay", np.float32),
("MinDelay", np.float32),
("MeanDelay", np.float32)
]
completeness = [
("PlannedL15ImageLines", np.uint16),
("GeneratedL15ImageLines", np.uint16),
("ValidL15ImageLines", np.uint16),
("DummyL15ImageLines", np.uint16),
("CorruptedL15ImageLines", np.uint16)
]
record = [
("Timeliness", timeliness),
("Completeness", (completeness, 12))
]
return record
[docs]
class HritPrologue(L15DataHeaderRecord):
"""HRIT Prologue handler."""
[docs]
def get(self):
"""Get record data array."""
# X bytes
record = [
("SatelliteStatus", self.satellite_status),
("ImageAcquisition", self.image_acquisition),
("CelestialEvents", self.celestial_events),
("ImageDescription", self.image_description),
("RadiometricProcessing", self.radiometric_processing),
("GeometricProcessing", self.geometric_processing)
]
return np.dtype(record).newbyteorder(">")
[docs]
def get_native_header(with_archive_header=True):
"""Get Native format header type.
There are two variants, one including an ASCII archive header and one
without that header. The header is prepended if the data are ordered
through the EUMETSAT data center.
"""
return Msg15NativeHeaderRecord().get(with_archive_header)
DEFAULT_15_SECONDARY_PRODUCT_HEADER = {
"NorthLineSelectedRectangle": {"Value": VISIR_NUM_LINES},
"SouthLineSelectedRectangle": {"Value": 1},
"EastColumnSelectedRectangle": {"Value": 1},
"WestColumnSelectedRectangle": {"Value": VISIR_NUM_COLUMNS},
"NumberColumnsVISIR": {"Value": VISIR_NUM_COLUMNS},
"NumberLinesVISIR": {"Value": VISIR_NUM_LINES},
"NumberColumnsHRV": {"Value": HRV_NUM_COLUMNS},
"NumberLinesHRV": {"Value": HRV_NUM_LINES},
"SelectedBandIDs": {"Value": "XXXXXXXXXXXX"}
}
"""Default secondary product header for files containing all channels."""
hrit_epilogue = np.dtype(
Msg15NativeTrailerRecord().seviri_l15_trailer).newbyteorder(">")
hrit_prologue = HritPrologue().get()
impf_configuration = np.dtype(
L15DataHeaderRecord().impf_configuration).newbyteorder(">")
native_trailer = Msg15NativeTrailerRecord().get()