1111#include " EncodeMtg2.h"
1212
1313#include < iostream>
14- #include < type_traits>
1514
15+ #include " eckit/config/LocalConfiguration.h"
1616#include " eckit/exception/Exceptions.h"
1717
1818#include " multio/action/encode-mtg2/AtlasGeoSetter.h"
1919#include " multio/action/encode-mtg2/EncodeMtg2Exception.h"
2020#include " multio/datamod/MarsMiscGeo.h"
21+ #include " multio/datamod/core/EntryDumper.h"
2122#include " multio/datamod/core/EntryParser.h"
2223#include " multio/datamod/core/Record.h"
23- #include " multio/mars2grib/api/RawAPI.h"
2424#include " multio/mars2mars/Rules.h"
2525#include " multio/message/Parametrization.h"
2626#include " multio/util/PrecisionTag.h"
2727
28- namespace multio ::action {
28+ namespace multio ::action::encode_mtg2 {
2929
3030namespace dm = multio::datamod;
3131
3232using message::Message;
3333using message::Peer;
3434
35- mars2grib::RawOptions mapOpts (EncodeMtg2Options opts) {
36- mars2grib::RawOptions ret;
37- ret.cached = opts.cached ;
38- return ret;
39- };
40-
4135
4236EncodeMtg2::EncodeMtg2 (const ComponentConfiguration& compConf) :
43- ChainedAction{compConf}, opts_{cf::parseActionConfig<EncodeMtg2Options>(compConf)}, mars2grib_{mapOpts (opts_)} {}
37+ ChainedAction{compConf}, opts_{cf::parseActionConfig<EncodeMtg2Options>(compConf)}, encoder_{} {
38+ if (opts_.cached ) {
39+ throw eckit::NotImplemented{" Encoder cache is currently not implemented!" , Here ()};
40+ }
41+ }
4442
4543
4644void EncodeMtg2::executeImpl (Message msg) {
@@ -49,94 +47,76 @@ void EncodeMtg2::executeImpl(Message msg) {
4947 return ;
5048 }
5149
50+ if (msg.payload ().size () == 0 ) {
51+ throw EncodeMtg2Exception (" Message has empty payload - no values to encode" , Here ());
52+ }
53+
5254 auto & md = msg.metadata ();
5355
54- {
55- // Read and set unscoped mars keys
56- auto marsRec = dm::readRecord<dm::FullMarsRecord>(md);
57-
58- // Read scoped misc keys
59- auto scopedMiscRec = dm::scopeRecord (dm::MiscRecord{});
60- dm::readRecord (scopedMiscRec, md);
61- // Write unscoped misc keys
62- auto miscRec = dm::unscopeRecord (std::move (scopedMiscRec));
63-
64- auto scopedGeo = dm::getGeometryRecord (marsRec);
65-
66- // If grid.. check if atlas is given.
67- if (marsRec.grid .isSet ()) {
68- std::string scope{std::visit ([](const auto & k) { return dm::getRecordScope (k); }, scopedGeo)};
69- const auto & global = message::Parametrization::instance ().get ();
70- // Fetch atlas and store in global parametrization (by scoping keys...)
71- // Scoping here may be refactored
72- if (opts_.geoFromAtlas && (global.find (scope) == global.end ())) {
73- extract::AtlasGeoSetter::handleGrid (scope, marsRec.grid .get ());
74- }
56+ // Read and set unscoped mars keys
57+ auto marsRec = dm::readRecord<dm::FullMarsRecord>(md);
58+
59+ // Read scoped misc keys
60+ auto scopedMiscRec = dm::scopeRecord (dm::MiscRecord{});
61+ dm::readRecord (scopedMiscRec, md);
62+ // Write unscoped misc keys
63+ auto miscRec = dm::unscopeRecord (std::move (scopedMiscRec));
64+
65+ auto scopedGeom = dm::getGeometryRecord (marsRec);
66+
67+ // If grid.. check if atlas is given.
68+ if (marsRec.grid .isSet ()) {
69+ std::string scope{std::visit ([](const auto & k) { return dm::getRecordScope (k); }, scopedGeom)};
70+ const auto & global = message::Parametrization::instance ().get ();
71+ // Fetch atlas and store in global parametrization (by scoping keys...)
72+ // Scoping here may be refactored
73+ if (opts_.geoFromAtlas && (global.find (scope) == global.end ())) {
74+ extract::AtlasGeoSetter::handleGrid (scope, marsRec.grid .get ());
7575 }
76+ }
7677
77- // Read & unscope geo keys from metadata
78- auto geo = std::visit (
79- [&](auto && geoRec) -> dm::Geometry {
80- dm::readRecord (geoRec, md);
81- return unscopeRecord (std::move (geoRec));
82- },
83- std::move (scopedGeo));
84-
85-
86- // Apply mappings
87- auto mappingResult = mars2mars::applyMappings (mars2mars::allRules (), marsRec, miscRec);
88-
78+ // Read & unscope geo keys from metadata
79+ auto geomRec = std::visit (
80+ [&](auto && scopedGeom) -> dm::Geometry {
81+ dm::readRecord (scopedGeom, md);
82+ return unscopeRecord (std::move (scopedGeom));
83+ },
84+ std::move (scopedGeom));
85+
86+ // Apply mappings
87+ auto mappingResult = mars2mars::applyMappings (mars2mars::allRules (), marsRec, miscRec);
88+
89+ const auto mars = dm::dumpRecord<eckit::LocalConfiguration>(marsRec);
90+ const auto misc = dm::dumpRecord<eckit::LocalConfiguration>(miscRec);
91+ const auto geom
92+ = std::visit ([](const auto & geomRec) { return dm::dumpRecord<eckit::LocalConfiguration>(geomRec); }, geomRec);
93+
94+ executeNext (dispatchPrecisionTag (msg.precision (), [&](auto pt) {
95+ using Precision = typename decltype (pt)::type;
96+ auto values = static_cast <Precision*>(msg.payload ().modifyData ());
97+ size_t size = msg.payload ().size () / sizeof (Precision);
98+
99+ // Check if values need scaling
100+ if (mappingResult && mappingResult->valuesScaleFactor ) {
101+ msg.payload ().acquire ();
102+ ASSERT (values);
103+
104+ const auto scaleFactor = *(mappingResult->valuesScaleFactor );
105+ std::transform (values, values + size, values,
106+ [&](const Precision& value) -> Precision { return value * scaleFactor; });
107+ }
89108
90- std::unique_ptr<metkit::codes::CodesHandle> sample = mars2grib_.getHandle (marsRec, miscRec, geo);
109+ // Call the GRIB2 encoder in metkit
110+ const auto sample = encoder_.encode (mars, misc, geom, values, size);
91111
92- if (msg.payload ().size () == 0 ) {
93- throw EncodeMtg2Exception (" Message has empty payload - no values to encode" , Here ());
94- }
112+ eckit::Buffer buf{sample->messageSize ()};
113+ sample->copyInto (reinterpret_cast <uint8_t *>(buf.data ()), buf.size ());
95114
96- // ecCodes does not support setting float values (yet)
97- auto setValuesAsDouble = [&] (const auto * data, size_t size) {
98- using Precision = std::decay_t <decltype (*data)>;
99- if constexpr (std::is_same_v<Precision, double >) {
100- sample->set (" values" , metkit::codes::Span<const Precision>(data, size));
101- }
102- else {
103- sample->set (" values" , std::vector<double >{data, data+size});
104- }
105- };
106-
107- executeNext (dispatchPrecisionTag (msg.precision (), [&](auto pt) {
108- using Precision = typename decltype (pt)::type;
109- size_t size = msg.payload ().size () / sizeof (Precision);
110-
111- // Check if values need scaling
112- if (mappingResult && mappingResult->valuesScaleFactor ) {
113- msg.payload ().acquire ();
114- auto values = static_cast <Precision*>(msg.payload ().modifyData ());
115- ASSERT (values);
116-
117- const auto scaleFactor = *(mappingResult->valuesScaleFactor );
118- std::transform (values, values + size, values,
119- [&](const Precision& value) -> Precision { return value * scaleFactor; });
120-
121- setValuesAsDouble (values, size);
122- }
123- else {
124- // No scaling
125- auto values = static_cast <const Precision*>(msg.payload ().data ());
126- setValuesAsDouble (values, size);
127- }
128-
129- // The +32 is related to bug
130- // TODO(pgeier) Track bug ECC-2130: https://jira.ecmwf.int/browse/ECC-2130
131- eckit::Buffer buf{sample->messageSize ()};
132- sample->copyInto (reinterpret_cast <uint8_t *>(buf.data ()), buf.size ());
133-
134- // TODO(pgeier) write mapped metadata
135- return Message{Message::Header{Message::Tag::Field, Peer{msg.source ()}, Peer{msg.destination ()},
136- dm::dumpRecord<message::Metadata>(marsRec)},
137- std::move (buf)};
138- }));
139- }
115+ // TODO(pgeier) write mapped metadata
116+ return Message{Message::Header{Message::Tag::Field, Peer{msg.source ()}, Peer{msg.destination ()},
117+ dm::dumpRecord<message::Metadata>(marsRec)},
118+ std::move (buf)};
119+ }));
140120}
141121
142122void EncodeMtg2::print (std::ostream& os) const {
@@ -146,4 +126,4 @@ void EncodeMtg2::print(std::ostream& os) const {
146126
147127static ActionBuilder<EncodeMtg2> EncodeMtg2Builder (" encode-mtg2" );
148128
149- } // namespace multio::action
129+ } // namespace multio::action::encode_mtg2
0 commit comments