Skip to content

Commit 44c33b4

Browse files
committed
MUL-290: Use datamod for scale action configuration
1 parent 8d005bc commit 44c33b4

File tree

2 files changed

+119
-65
lines changed

2 files changed

+119
-65
lines changed

src/multio/action/scale/Scale.cc

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include "multio/action/scale/Scale.h"
1212

1313
#include "eckit/config/LocalConfiguration.h"
14-
#include "eckit/exception/Exceptions.h"
1514

1615
#include "multio/LibMultio.h"
1716
#include "multio/datamod/ContainerInterop.h"
@@ -21,63 +20,58 @@
2120

2221
namespace multio::action::scale {
2322

24-
const Mappings getMappings(const std::string& preset) {
25-
if (preset != "local-to-wmo" && preset != "wmo-to-local") {
26-
throw eckit::UserError("Preset " + preset + " does not exist!", Here());
27-
}
23+
ScaleConfig parseConfig(const ComponentConfiguration& compConf) {
24+
dm::ParseOptions opts;
25+
opts.allowAdditionalKeys = false;
26+
27+
// TODO(pgeier) Fix after refactoring action - need to remove keys "type" and "next"
28+
auto conf = compConf.parsedConfig();
29+
conf.remove("type");
30+
conf.remove("next");
2831

32+
return dm::readRecordByValue<ScaleConfig>(conf, opts);
33+
}
34+
35+
const std::vector<ScaleMappingConfig> getPresetMappings(const Preset& preset) {
2936
// Load the mapping file
3037
eckit::LocalConfiguration mappingConf{eckit::YAMLConfiguration{eckit::PathName{
3138
multio::LibMultio::instance().libraryHome() + "/share/multio/mappings/local-to-wmo.yaml"
3239
}}};
3340

34-
// Read the mappings and put them into the map
35-
// We use the same mapping file for local-to-wmo and wmo-to-local, the
36-
// second is just the reverse mapping of the first!
37-
Mappings mappings;
38-
for (auto& mapping : mappingConf.getSubConfigurations()) {
39-
const auto paramIn = mapping.getInt64("param-in");
40-
const auto paramOut = mapping.getInt64("param-out");
41-
const auto scaling = mapping.getDouble("scaling");
42-
if (preset == "local-to-wmo") {
43-
mappings[paramIn] = {paramOut, scaling};
44-
}
45-
else {
46-
mappings[paramOut] = {paramIn, 1.0 / scaling};
41+
auto mappings = datamod::RecordMapper<std::vector<ScaleMappingConfig>>::parse(mappingConf.getSubConfigurations());
42+
43+
if (preset == Preset::WmoToLocal) {
44+
for (auto& mapping : mappings) {
45+
std::swap(mapping.paramIn, mapping.paramOut);
46+
mapping.scaling.set(1.0 / mapping.scaling.get());
4747
}
4848
}
49+
4950
return mappings;
5051
}
5152

52-
Mappings getMappings(const eckit::LocalConfiguration& config) {
53+
Mappings getMappings(const ScaleConfig& config) {
5354
Mappings mappings;
5455

5556
// Read the preset mapping from a mappings file
56-
if (config.has("preset-mappings")) {
57-
ASSERT(config.isString("preset-mappings"));
58-
mappings = getMappings(config.getString("preset-mappings"));
57+
if (config.presetMappings.isSet()) {
58+
for (auto& mapping : getPresetMappings(config.presetMappings.get())) {
59+
mappings[mapping.paramIn.get()] = {mapping.paramOut.get(), mapping.scaling.get()};
60+
}
5961
}
6062

6163
// Read any user defined mappings from the action configuration
62-
if (config.has("custom-mappings")) {
63-
ASSERT(config.isSubConfigurationList("custom-mappings"));
64-
for (auto& mapping : config.getSubConfigurations("custom-mappings")) {
65-
const auto paramIn = mapping.getInt64("param-in");
66-
const auto paramOut = mapping.getInt64("param-out");
67-
const auto scaling = mapping.getDouble("scaling");
68-
ASSERT(mappings.find(paramIn) == mappings.end());
69-
mappings[paramIn] = {paramOut, scaling};
64+
if (config.customMappings.isSet()) {
65+
for (auto& mapping : config.customMappings.get()) {
66+
mappings[mapping.paramIn.get()] = {mapping.paramOut.get(), mapping.scaling.get()};
7067
}
7168
}
7269

73-
if (mappings.empty()) {
74-
throw eckit::UserError("No scale mapping was found, set 'preset' or 'mappings' in action configuration!", Here());
75-
}
7670
return mappings;
7771
}
7872

7973
Scale::Scale(const ComponentConfiguration& compConf) :
80-
ChainedAction(compConf), mappings_{getMappings(compConf.parsedConfig())} {}
74+
ChainedAction(compConf), mappings_{getMappings(parseConfig(compConf))} {}
8175

8276
void Scale::executeImpl(message::Message msg) {
8377
// Skip non-field messages
@@ -133,3 +127,21 @@ void Scale::print(std::ostream& os) const {
133127
static ActionBuilder<Scale> ScaleBuilder("scale");
134128

135129
} // namespace multio::action::scale
130+
131+
132+
namespace multio::datamod {
133+
134+
action::scale::Preset ParseType<action::scale::Preset>::parse(const std::string& val) {
135+
if (val == "local-to-wmo") {
136+
return action::scale::Preset::LocalToWmo;
137+
}
138+
if (val == "wmo-to-local") {
139+
return action::scale::Preset::WmoToLocal;
140+
}
141+
throw DataModellingException(
142+
std::string("ParseType<PresetMappings>::parse Unknown value for PresetMappings: ") + val,
143+
Here()
144+
);
145+
}
146+
147+
} // namespace multio::datamod

src/multio/action/scale/Scale.h

Lines changed: 73 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
#pragma once
22

3+
#include "eckit/exception/Exceptions.h"
4+
35
#include "multio/action/ChainedAction.h"
46
#include "multio/datamod/core/EntryDef.h"
7+
#include "multio/datamod/core/NestedRecord.h"
58
#include "multio/datamod/MarsKeys.h"
69
#include "multio/datamod/GribKeys.h"
710

@@ -23,37 +26,51 @@ struct ScaleMetadataKeys {
2326
};
2427

2528
//------------------------ Action Configuration Keys ------------------------//
26-
//
27-
// TODO: Support (lists of) sub-records in datamod
28-
//
29-
// struct ScaleMappingKeys {
30-
// dm::Entry<std::int64_t> paramIn;
31-
// dm::Entry<std::int64_t> paramOut;
32-
// dm::Entry<double> scaling;
33-
//
34-
// static constexpr std::string_view record_name_ = "scale-mapping-keys";
35-
//
36-
// using SMK = ScaleMappingKeys;
37-
// static constexpr auto record_entries_ = std::make_tuple(
38-
// dm::entryDef("param-in", &SMK::paramIn),
39-
// dm::entryDef("param-out", &SMK::paramOut),
40-
// dm::entryDef("scaling", &SMK::scaling)
41-
// );
42-
// };
43-
//
44-
// struct ScaleConfigurationKeys {
45-
// dm::Entry<std::string> presetMappings;
46-
// dm::Entry<std::List<ScaleMappingKeys>> customMappings;
47-
//
48-
// static constexpr std::string_view record_name_ = "scale-action-configuration";
49-
//
50-
// using SCK = ScaleConfigurationKeys;
51-
// static constexpr auto record_entries_ = std::make_tuple(
52-
// dm::entryDef("preset-mappings", &SCK::presetMappings).tagOptional(),
53-
// dm::entryDef("custom-mappings", &SCK::customMappings).tagOptional()
54-
// );
55-
// };
56-
//
29+
30+
enum class Preset : std::size_t
31+
{
32+
LocalToWmo, // "local-to-wmo"
33+
WmoToLocal // "wmo-to-local"
34+
};
35+
36+
struct ScaleMappingConfig {
37+
dm::Entry<std::int64_t> paramIn;
38+
dm::Entry<std::int64_t> paramOut;
39+
dm::Entry<double> scaling;
40+
41+
static constexpr std::string_view record_name_ = "scale-mapping-config";
42+
43+
static constexpr auto record_entries_ = std::make_tuple(
44+
dm::entryDef("param-in", &ScaleMappingConfig::paramIn),
45+
dm::entryDef("param-out", &ScaleMappingConfig::paramOut),
46+
dm::entryDef("scaling", &ScaleMappingConfig::scaling)
47+
);
48+
};
49+
50+
struct ScaleConfig {
51+
dm::Entry<Preset> presetMappings;
52+
dm::NestedEntry_t<std::vector<ScaleMappingConfig>> customMappings;
53+
54+
static constexpr std::string_view record_name_ = "scale-action-config";
55+
56+
static constexpr auto record_entries_ = std::make_tuple(
57+
dm::entryDef("preset-mappings", &ScaleConfig::presetMappings).tagOptional(),
58+
59+
// Custom mappings are user defined mappings that will be applied on top of a preset, if a mapping from a
60+
// param already exists, it will be overwritten by the custom mapping.
61+
dm::entryDef("custom-mappings", &ScaleConfig::customMappings).tagOptional()
62+
);
63+
64+
static void validate(const ScaleConfig& k) {
65+
if (!k.presetMappings.isSet() && (!k.customMappings.isSet() || k.customMappings.get().empty())) {
66+
throw eckit::UserError(
67+
"Either 'preset-mappings' or 'custom-mappings' must be set in scale action configuration!",
68+
Here()
69+
);
70+
}
71+
}
72+
};
73+
5774
//---------------------------------------------------------------------------//
5875

5976
using Param = std::int64_t;
@@ -78,3 +95,28 @@ class Scale final : public ChainedAction {
7895
};
7996

8097
} // namespace multio::action::scale
98+
99+
100+
namespace multio::util {
101+
102+
template <>
103+
struct TypeToString<action::scale::ScaleMappingConfig> {
104+
std::string operator()() const { return std::string("ScaleMappingConfig"); };
105+
};
106+
107+
template <>
108+
struct TypeToString<action::scale::Preset> {
109+
std::string operator()() const { return std::string("PresetMappings"); };
110+
};
111+
112+
} // namespace multio::util
113+
114+
115+
namespace multio::datamod {
116+
117+
template <>
118+
struct ParseType<action::scale::Preset> {
119+
static action::scale::Preset parse(const std::string& s);
120+
};
121+
122+
} // namespace multio::datamod

0 commit comments

Comments
 (0)