LSST Applications 27.0.0,g0265f82a02+469cd937ee,g02d81e74bb+21ad69e7e1,g1470d8bcf6+cbe83ee85a,g2079a07aa2+e67c6346a6,g212a7c68fe+04a9158687,g2305ad1205+94392ce272,g295015adf3+81dd352a9d,g2bbee38e9b+469cd937ee,g337abbeb29+469cd937ee,g3939d97d7f+72a9f7b576,g487adcacf7+71499e7cba,g50ff169b8f+5929b3527e,g52b1c1532d+a6fc98d2e7,g591dd9f2cf+df404f777f,g5a732f18d5+be83d3ecdb,g64a986408d+21ad69e7e1,g858d7b2824+21ad69e7e1,g8a8a8dda67+a6fc98d2e7,g99cad8db69+f62e5b0af5,g9ddcbc5298+d4bad12328,ga1e77700b3+9c366c4306,ga8c6da7877+71e4819109,gb0e22166c9+25ba2f69a1,gb6a65358fc+469cd937ee,gbb8dafda3b+69d3c0e320,gc07e1c2157+a98bf949bb,gc120e1dc64+615ec43309,gc28159a63d+469cd937ee,gcf0d15dbbd+72a9f7b576,gdaeeff99f8+a38ce5ea23,ge6526c86ff+3a7c1ac5f1,ge79ae78c31+469cd937ee,gee10cc3b42+a6fc98d2e7,gf1cff7945b+21ad69e7e1,gfbcc870c63+9a11dc8c8f
LSST Data Management Base Package
Loading...
Searching...
No Matches
SchemaMapper.cc
Go to the documentation of this file.
1#include "boost/preprocessor/seq/for_each.hpp"
2#include "boost/preprocessor/tuple/to_seq.hpp"
3
6
7namespace lsst {
8namespace afw {
9namespace table {
10
11namespace {
12
13// Variant visitation functor used in SchemaMapper::invert()
14struct SwapKeyPair {
15 void operator()(detail::SchemaMapperImpl::KeyPairVariant &v) const {
16 std::visit([](auto & pair) { std::swap(pair.first, pair.second); }, v);
17 }
18};
19
20// Variant visitation functor that returns true if the input key in a KeyPairVariant matches a
21// the Key the functor was initialized with.
22template <typename T>
23struct KeyPairCompareEqual {
24
25 bool operator()(detail::SchemaMapperImpl::KeyPairVariant const &v) const {
26 return std::visit([this](auto const & pair) -> bool { return this->_target == pair.first; }, v);
27 }
28
29 explicit KeyPairCompareEqual(Key<T> const &target) : _target(target) {}
30
31private:
32 Key<T> const &_target;
33};
34
35// Functor used to iterate through a minimal schema and map all fields present in the
36// input schema and add those that are not.
37struct MapMinimalSchema {
38 template <typename U>
39 void operator()(SchemaItem<U> const &item) const {
40 Key<U> outputKey;
41 if (_doMap) {
42 try {
43 SchemaItem<U> inputItem = _mapper->getInputSchema().find(item.key);
44 outputKey = _mapper->addMapping(item.key);
45 } catch (pex::exceptions::NotFoundError &) {
46 outputKey = _mapper->addOutputField(item.field);
47 }
48 } else {
49 outputKey = _mapper->addOutputField(item.field);
50 }
51 assert(outputKey == item.key);
52 }
53
54 explicit MapMinimalSchema(SchemaMapper *mapper, bool doMap) : _mapper(mapper), _doMap(doMap) {}
55
56private:
57 SchemaMapper *_mapper;
58 bool _doMap;
59};
60
61// Schema::forEach functor that copies all fields from an schema to a schema mapper and maps them.
62struct AddMapped {
63 template <typename T>
64 void operator()(SchemaItem<T> const &item) const {
65 Field<T> field(prefix + item.field.getName(), item.field.getDoc(), item.field.getUnits(), item.field);
66 mapper->addMapping(item.key, field);
67 }
68
69 explicit AddMapped(SchemaMapper *mapper_) : mapper(mapper_) {}
70
71 SchemaMapper *mapper;
73};
74
75// Schema::forEach functor that copies all fields from an schema to a schema mapper without mapping them.
76struct AddUnmapped {
77 template <typename T>
78 void operator()(SchemaItem<T> const &item) const {
79 Field<T> field(prefix + item.field.getName(), item.field.getDoc(), item.field.getUnits(), item.field);
80 mapper->addOutputField(field);
81 }
82
83 explicit AddUnmapped(SchemaMapper *mapper_) : mapper(mapper_) {}
84
85 SchemaMapper *mapper;
87};
88
89struct RemoveMinimalSchema {
90 template <typename T>
91 void operator()(SchemaItem<T> const &item) const {
92 if (!minimal.contains(item)) {
93 mapper->addMapping(item.key);
94 }
95 }
96
97 RemoveMinimalSchema(SchemaMapper *mapper_, Schema const &minimal_) : mapper(mapper_), minimal(minimal_) {}
98
99 SchemaMapper *mapper;
100 Schema minimal;
101};
102
103} // namespace
104
106
107SchemaMapper::SchemaMapper(SchemaMapper const &other) : _impl(new Impl(*other._impl)) {}
108// Delegate to copy constructor for backwards compatibility
110
111SchemaMapper::SchemaMapper(Schema const &input, Schema const &output) : _impl(new Impl(input, output)) {}
112
113SchemaMapper::SchemaMapper(Schema const &input, bool shareAliasMap) : _impl(new Impl(input, Schema())) {
114 if (shareAliasMap) {
116 }
117}
118
120 std::unique_ptr<Impl> tmp(new Impl(*other._impl));
121 _impl.swap(tmp);
122 return *this;
123}
124// Delegate to copy assignment for backwards compatibility
125SchemaMapper &SchemaMapper::operator=(SchemaMapper &&other) { return *this = other; }
126
128
129template <typename T>
131 typename Impl::KeyPairMap::iterator i =
132 std::find_if(_impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual<T>(inputKey));
133 Field<T> inputField = _impl->_input.find(inputKey).field;
134 if (i != _impl->_map.end()) {
135 Key<T> const &outputKey = std::get<std::pair<Key<T>, Key<T>>>(*i).second;
136 _impl->_output.replaceField(outputKey, inputField);
137 return outputKey;
138 } else {
139 Key<T> outputKey = _impl->_output.addField(inputField, doReplace);
140 _impl->_map.insert(i, std::make_pair(inputKey, outputKey));
141 return outputKey;
142 }
143}
144
145template <typename T>
146Key<T> SchemaMapper::addMapping(Key<T> const &inputKey, Field<T> const &field, bool doReplace) {
147 typename Impl::KeyPairMap::iterator i =
148 std::find_if(_impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual<T>(inputKey));
149 if (i != _impl->_map.end()) {
150 Key<T> const &outputKey = std::get<std::pair<Key<T>, Key<T>>>(*i).second;
151 _impl->_output.replaceField(outputKey, field);
152 return outputKey;
153 } else {
154 Key<T> outputKey = _impl->_output.addField(field, doReplace);
155 _impl->_map.insert(i, std::make_pair(inputKey, outputKey));
156 return outputKey;
157 }
158}
159
160template <typename T>
162 typename Impl::KeyPairMap::iterator i =
163 std::find_if(_impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual<T>(inputKey));
164 if (i != _impl->_map.end()) {
165 Key<T> const &outputKey = std::get<std::pair<Key<T>, Key<T>>>(*i).second;
166 Field<T> field = _impl->_output.find(outputKey).field;
167 field = field.copyRenamed(outputName);
168 _impl->_output.replaceField(outputKey, field);
169 return outputKey;
170 } else {
171 Field<T> inputField = _impl->_input.find(inputKey).field;
173 Key<T> outputKey = _impl->_output.addField(outputField, doReplace);
174 _impl->_map.insert(i, std::make_pair(inputKey, outputKey));
175 return outputKey;
176 }
177}
178
180 if (getOutputSchema().getFieldCount() > 0) {
182 "Must add minimal schema to mapper before adding any other fields");
183 }
184 MapMinimalSchema f(this, doMap);
185 minimal.forEach(f);
186}
187
189 SchemaMapper mapper(input);
190 RemoveMinimalSchema f(&mapper, minimal);
191 input.forEach(f);
192 return mapper;
193}
194
196 std::swap(_impl->_input, _impl->_output);
197 std::for_each(_impl->_map.begin(), _impl->_map.end(), SwapKeyPair());
198}
199
200template <typename T>
202 return std::count_if(_impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual<T>(inputKey));
203}
204
205template <typename T>
207 typename Impl::KeyPairMap::iterator i =
208 std::find_if(_impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual<T>(inputKey));
209 if (i == _impl->_map.end()) {
210 throw LSST_EXCEPT(lsst::pex::exceptions::NotFoundError, "Input Key is not mapped.");
211 }
212 return std::get<std::pair<Key<T>, Key<T>>>(*i).second;
213}
214
217 std::size_t const size = inputs.size();
218 if (!prefixes.empty() && prefixes.size() != inputs.size()) {
219 throw LSST_EXCEPT(
221 (boost::format("prefix vector size (%d) must be the same as input vector size (%d)") %
222 prefixes.size() % inputs.size())
223 .str());
224 }
226 for (std::size_t i = 0; i < size; ++i) {
227 result.emplace_back(inputs[i]);
228 }
229 for (std::size_t i = 0; i < size; ++i) {
230 for (std::size_t j = 0; j < size; ++j) {
231 if (i == j) {
232 AddMapped functor(&result[j]);
233 if (!prefixes.empty()) functor.prefix = prefixes[i];
234 inputs[i].forEach(functor);
235 } else {
236 AddUnmapped functor(&result[j]);
237 if (!prefixes.empty()) functor.prefix = prefixes[i];
238 inputs[i].forEach(functor);
239 }
240 }
241 }
242 return result;
243}
244
245//----- Explicit instantiation ------------------------------------------------------------------------------
246
247#define INSTANTIATE_LAYOUTMAPPER(r, data, elem) \
248 template Key<elem> SchemaMapper::addOutputField(Field<elem> const &, bool); \
249 template Key<elem> SchemaMapper::addMapping(Key<elem> const &, bool); \
250 template Key<elem> SchemaMapper::addMapping(Key<elem> const &, Field<elem> const &, bool); \
251 template Key<elem> SchemaMapper::addMapping(Key<elem> const &, std::string const &, bool); \
252 template bool SchemaMapper::isMapped(Key<elem> const &) const; \
253 template Key<elem> SchemaMapper::getMapping(Key<elem> const &) const;
254
257} // namespace table
258} // namespace afw
259} // namespace lsst
py::object result
Definition _schema.cc:429
table::Key< int > field
Definition ApCorrMap.cc:77
Key< Flag > const & target
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
std::string prefix
SchemaMapper * mapper
#define INSTANTIATE_LAYOUTMAPPER(r, data, elem)
Schema minimal
T begin(T... args)
Tag types used to declare specialized field types.
Definition misc.h:31
Defines the fields and offsets for a table.
Definition Schema.h:51
void forEach(F &func) const
Apply a functor to each SchemaItem in the Schema.
Definition Schema.h:214
void setAliasMap(std::shared_ptr< AliasMap > aliases)
Set the alias map.
Definition Schema.cc:533
std::shared_ptr< AliasMap > getAliasMap() const
Return the map of aliases.
Definition Schema.h:279
Key< T > addField(Field< T > const &field, bool doReplace=false)
Add a new field to the Schema, and return the associated Key.
Definition Schema.cc:479
void replaceField(Key< T > const &key, Field< T > const &field)
Replace the Field (name/description) for an existing Key.
Definition Schema.cc:485
SchemaItem< T > find(std::string const &name) const
Find a SchemaItem in the Schema by name.
Definition Schema.cc:467
A mapping between the keys of two Schemas, used to copy data between them.
Schema const getOutputSchema() const
Return the output schema (copy-on-write).
SchemaMapper()
Construct an empty mapper; useless unless you assign a fully-constructed one to it.
SchemaMapper & operator=(SchemaMapper const &other)
Assignment (copy-on-write).
Key< T > addMapping(Key< T > const &inputKey, bool doReplace=false)
Add a new field to the output Schema that is a copy of a field in the input Schema.
static SchemaMapper removeMinimalSchema(Schema const &input, Schema const &minimal)
Create a mapper by removing fields from the front of a schema.
static std::vector< SchemaMapper > join(std::vector< Schema > const &inputs, std::vector< std::string > const &prefixes=std::vector< std::string >())
Combine a sequence of schemas into one, creating a SchemaMapper for each.
Schema & editOutputSchema()
Return a reference to the output schema that allows it to be modified in place.
Key< T > getMapping(Key< T > const &inputKey) const
Return the output Key corresponding to the given input Key, or raise NotFoundError.
bool isMapped(Key< T > const &inputKey) const
Return true if the given input Key is mapped to an output Key.
void addMinimalSchema(Schema const &minimal, bool doMap=true)
Add the given minimal schema to the output schema.
void invert()
Swap the input and output schemas in-place.
A private implementation class to hide the messy details of SchemaMapper.
decltype(makeKeyPairVariantType(FieldTypes{})) KeyPairVariant
A Variant type that can hold any one of the allowed pairx types.
Reports attempts to exceed implementation-defined length limits for some classes.
Definition Runtime.h:76
Reports errors in the logical structure of the program.
Definition Runtime.h:46
Reports attempts to access elements using an invalid key.
Definition Runtime.h:151
T count_if(T... args)
T emplace_back(T... args)
T end(T... args)
T find_if(T... args)
T for_each(T... args)
T insert(T... args)
T make_pair(T... args)
BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_COLUMNVIEW_SCALAR, _, BOOST_PP_TUPLE_TO_SEQ(AFW_TABLE_SCALAR_FIELD_TYPE_N, AFW_TABLE_SCALAR_FIELD_TYPE_TUPLE)) BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_COLUMNVIEW_ARRAY
T swap(T... args)
SchemaMapper _mapper
Definition Exposure.cc:220
#define AFW_TABLE_FIELD_TYPE_N
Definition types.h:38
#define AFW_TABLE_FIELD_TYPE_TUPLE
Definition types.h:43