LSST Applications g070148d5b3+33e5256705,g0d53e28543+25c8b88941,g0da5cf3356+2dd1178308,g1081da9e2a+62d12e78cb,g17e5ecfddb+7e422d6136,g1c76d35bf8+ede3a706f7,g295839609d+225697d880,g2e2c1a68ba+cc1f6f037e,g2ffcdf413f+853cd4dcde,g38293774b4+62d12e78cb,g3b44f30a73+d953f1ac34,g48ccf36440+885b902d19,g4b2f1765b6+7dedbde6d2,g5320a0a9f6+0c5d6105b6,g56b687f8c9+ede3a706f7,g5c4744a4d9+ef6ac23297,g5ffd174ac0+0c5d6105b6,g6075d09f38+66af417445,g667d525e37+2ced63db88,g670421136f+2ced63db88,g71f27ac40c+2ced63db88,g774830318a+463cbe8d1f,g7876bc68e5+1d137996f1,g7985c39107+62d12e78cb,g7fdac2220c+0fd8241c05,g96f01af41f+368e6903a7,g9ca82378b8+2ced63db88,g9d27549199+ef6ac23297,gabe93b2c52+e3573e3735,gb065e2a02a+3dfbe639da,gbc3249ced9+0c5d6105b6,gbec6a3398f+0c5d6105b6,gc9534b9d65+35b9f25267,gd01420fc67+0c5d6105b6,geee7ff78d7+a14128c129,gf63283c776+ede3a706f7,gfed783d017+0c5d6105b6,w.2022.47
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>
130Key<T> SchemaMapper::addMapping(Key<T> const &inputKey, bool doReplace) {
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>
161Key<T> SchemaMapper::addMapping(Key<T> const &inputKey, std::string const &outputName, bool doReplace) {
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;
172 Field<T> outputField = inputField.copyRenamed(outputName);
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>
201bool SchemaMapper::isMapped(Key<T> const &inputKey) const {
202 return std::count_if(_impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual<T>(inputKey));
203}
204
205template <typename T>
206Key<T> SchemaMapper::getMapping(Key<T> const &inputKey) const {
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
216 std::vector<std::string> const &prefixes) {
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
Definition: SchemaMapper.cc:72
SchemaMapper * mapper
Definition: SchemaMapper.cc:71
#define INSTANTIATE_LAYOUTMAPPER(r, data, elem)
Schema minimal
T begin(T... args)
A class used as a handle to a particular field in a table.
Definition: Key.h:53
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.
Definition: SchemaMapper.h:21
Schema const getOutputSchema() const
Return the output schema (copy-on-write).
Definition: SchemaMapper.h:27
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.
Definition: SchemaMapper.h:30
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 empty(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 size(T... args)
A description of a field in a table.
Definition: Field.h:24
Field< T > copyRenamed(std::string const &newName) const
Return a new Field with a new name and other properties the same as this.
Definition: Field.h:89
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