LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
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 
7 namespace lsst {
8 namespace afw {
9 namespace table {
10 
11 namespace {
12 
13 // Variant visitation functor used in SchemaMapper::invert()
14 struct 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.
22 template <typename T>
23 struct 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 
31 private:
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.
37 struct 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 
56 private:
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.
62 struct 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.
76 struct 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 
89 struct 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 
107 SchemaMapper::SchemaMapper(SchemaMapper const &other) : _impl(new Impl(*other._impl)) {}
108 // Delegate to copy constructor for backwards compatibility
110 
111 SchemaMapper::SchemaMapper(Schema const &input, Schema const &output) : _impl(new Impl(input, output)) {}
112 
113 SchemaMapper::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
125 SchemaMapper &SchemaMapper::operator=(SchemaMapper &&other) { return *this = other; }
126 
127 SchemaMapper::~SchemaMapper() = default;
128 
129 template <typename T>
130 Key<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 
145 template <typename T>
146 Key<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 
160 template <typename T>
161 Key<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 
200 template <typename T>
201 bool SchemaMapper::isMapped(Key<T> const &inputKey) const {
202  return std::count_if(_impl->_map.begin(), _impl->_map.end(), KeyPairCompareEqual<T>(inputKey));
203 }
204 
205 template <typename T>
206 Key<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 
256  BOOST_PP_TUPLE_TO_SEQ(AFW_TABLE_FIELD_TYPE_N, AFW_TABLE_FIELD_TYPE_TUPLE))
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
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
std::shared_ptr< AliasMap > getAliasMap() const
Return the map of aliases.
Definition: Schema.h:279
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).
Schema & editOutputSchema()
Return a reference to the output schema that allows it to be modified in place.
Definition: SchemaMapper.h:30
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.
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
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
A base class for image defects.
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