LSSTApplications  1.1.2+25,10.0+13,10.0+132,10.0+133,10.0+224,10.0+41,10.0+8,10.0-1-g0f53050+14,10.0-1-g4b7b172+19,10.0-1-g61a5bae+98,10.0-1-g7408a83+3,10.0-1-gc1e0f5a+19,10.0-1-gdb4482e+14,10.0-11-g3947115+2,10.0-12-g8719d8b+2,10.0-15-ga3f480f+1,10.0-2-g4f67435,10.0-2-gcb4bc6c+26,10.0-28-gf7f57a9+1,10.0-3-g1bbe32c+14,10.0-3-g5b46d21,10.0-4-g027f45f+5,10.0-4-g86f66b5+2,10.0-4-gc4fccf3+24,10.0-40-g4349866+2,10.0-5-g766159b,10.0-5-gca2295e+25,10.0-6-g462a451+1
LSSTDataManagementBasePackage
csvUtils.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2012 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
31 #include "lsst/ap/utils/csvUtils.h"
32 
33 #include "boost/ref.hpp"
34 #include "boost/type_traits/is_integral.hpp"
35 #include "boost/type_traits/is_same.hpp"
36 
37 #include "lsst/afw/geom/Angle.h"
38 #include "lsst/afw/coord.h"
40 #include "lsst/ap/utils/Csv.h"
41 
43 
46 
52 using lsst::afw::table::Flag;
58 
59 
60 namespace lsst { namespace ap { namespace utils {
61 
62 namespace {
63 
64  typedef std::vector<std::string>::const_iterator StringIter;
65 
66  uint8_t const SKIP_FIELD = 0x1;
67  uint8_t const NULLABLE_INT = 0x2;
68  uint8_t const RAD2 = 0x4;
69  uint8_t const RAD4 = 0x8;
70 
71  // computed to 30 digit precision with Maple
72  double const ARCSEC2_PER_RAD2 = 4.25451702961521995803707621197e10;
73  double const ARCSEC4_PER_RAD4 = 1.81009151552859144174773079111e21;
74 
75  int nFlagInts(int count) {
76  return (count + 62) / 63;
77  }
78 
79  // Helper class for CsvConverter initialization
80  class CsvConverterInit {
81  public:
82  CsvConverterInit(CsvConversionControl const & control, uint8_t * fieldFlags) :
83  _control(control), _fieldFlags(fieldFlags), _curField(0) { }
84 
85  ~CsvConverterInit() { }
86 
87  template <typename T>
88  void operator()(SchemaItem<T> const & item) const {
89  std::string const name = item.field.getName();
90  StringIter i = _control.ignoreFields.begin();
91  StringIter e = _control.ignoreFields.end();
92  uint8_t c = 0;
93  if (std::find(i, e, name) != e) {
94  c |= SKIP_FIELD;
95  } else if (boost::is_integral<T>::value) {
96  i = _control.nullableIntegers.begin();
97  e = _control.nullableIntegers.end();
98  if (std::find(i, e, name) != e) {
99  c |= NULLABLE_INT;
100  }
101  } else if (item.field.getUnits() == "rad^2" &&
102  (boost::is_same<T, Covariance<Point<float> > >::value ||
103  boost::is_same<T, Covariance<Point<float> > >::value ||
104  boost::is_same<T, Moments<float> >::value ||
105  boost::is_same<T, Moments<double> >::value)) {
106  // Flag point covariance matrixes and moments with units of
107  // rad^2 for unit conversion to arcsec^2.
108  c |= RAD2;
109  } else if (item.field.getUnits() == "rad^4" &&
110  (boost::is_same<T, Covariance<Moments<float> > >::value ||
111  boost::is_same<T, Covariance<Moments<double> > >::value)) {
112  // Flag moment covariance matrixes with units of rad^4 for
113  // unit conversion to arcsec^4.
114  c |= RAD4;
115  }
116  _fieldFlags[_curField++] = c;
117  }
118 
119  private:
120  CsvConversionControl const & _control;
121  uint8_t mutable * _fieldFlags;
122  int mutable _curField;
123  };
124 
125  // CSV conversion functor invoked for every item in a catalog's schema,
126  // one catalog record at a time.
127  class CsvConverter {
128  public:
129  CsvConverter(CsvWriter & writer,
130  Schema const & schema,
131  CsvConversionControl const & control) :
132  _writer(&writer),
133  _record(),
134  _flagsAsBits(control.flagsAsBits),
135  _nFlagInts(nFlagInts(schema.getFlagFieldCount())),
136  _curField(0),
137  _curFlag(0),
138  _flagInts(new int64_t[_nFlagInts]),
139  _fieldFlags(new uint8_t[schema.getFieldCount()]),
141  {
142  std::memset(_fieldFlags.get(), 0,
143  schema.getFieldCount() * sizeof(uint8_t));
144  CsvConverterInit init(control, _fieldFlags.get());
145  schema.forEach(boost::ref(init));
146  for (StringIter i = control.canonicalFlags.begin(),
147  e = control.canonicalFlags.end(); i != e; ++i) {
148  _canonicalFlags.push_back(schema.find<Flag>(*i).key);
149  }
150  }
151 
152  ~CsvConverter() { }
153 
154  // Set the record to extract data from
155  void startRecord(boost::shared_ptr<BaseRecord const> const &record) {
156  _record = record;
157  // zero out flag words
158  if (!_flagsAsBits) {
159  std::memset(_flagInts.get(), 0, _nFlagInts * sizeof(int64_t));
160  _curFlag = 0;
161  }
162  _curField = 0;
163  }
164 
165  // Finish conversion process for a record
166  void endRecord() {
167  typedef std::vector<Key<Flag > >::const_iterator FlagIter;
168  if (!_flagsAsBits) {
169  // write our flag integers
170  for (int i = 0; i < _nFlagInts; ++i) {
171  _writer->appendField(_flagInts[i]);
172  }
173  // write out canonical flag integers
174  int64_t f = 0;
175  int b = 0;
176  for (FlagIter i = _canonicalFlags.begin(), e = _canonicalFlags.end();
177  i != e; ++i) {
178  if (_record->get(*i)) {
179  f |= static_cast<int64_t>(1) << b;
180  }
181  ++b;
182  if (b == 63) {
183  _writer->appendField(f);
184  f = 0;
185  b = 0;
186  }
187  }
188  if (b > 0) {
189  _writer->appendField(f);
190  }
191  }
192  _writer->endRecord();
193  _record.reset();
194  }
195 
196  // -- Field conversion --------
197 
198  // basic types
199  template <typename T>
200  void operator()(SchemaItem<T> const & item) const {
201  uint8_t const c = _fieldFlags[_curField++];
202  if ((c & SKIP_FIELD) != 0) {
203  return;
204  }
205  T val = _record->get(item.key);
206  if (boost::is_integral<T>::value && (c & NULLABLE_INT) != 0 &&
207  val == static_cast<T>(0)) {
208  // T is integral, val is 0, and item is a nullable integer field
209  _writer->appendNull();
210  } else {
211  _writer->appendField(val);
212  }
213  }
214 
215  // angles and coordinates
216  void operator()(SchemaItem<Angle> const & item) const {
217  if ((_fieldFlags[_curField++] & SKIP_FIELD) != 0) {
218  return;
219  }
220  _writer->appendField(_record->get(item.key).asDegrees());
221  }
222 
223  void operator()(SchemaItem<Coord> const & item) const {
224  if ((_fieldFlags[_curField++] & SKIP_FIELD) != 0) {
225  return;
226  }
227  Field<Coord>::Value c = _record->get(item.key);
228  _writer->appendField(c.getLongitude().asDegrees());
229  _writer->appendField(c.getLatitude().asDegrees());
230  }
231 
232  // arrays
233  template <typename T>
234  void operator()(SchemaItem<Array<T> > const & item) const {
235  if ((_fieldFlags[_curField++] & SKIP_FIELD) != 0) {
236  return;
237  }
238  typename Field<Array<T> >::Value a = _record->get(item.key);
239  for (int i = 0, e = item.field.getSize(); i != e; ++i) {
240  _writer->appendField(a[i]);
241  }
242  }
243 
244  // points
245  template <typename T>
246  void operator()(SchemaItem<Point<T> > const & item) const {
247  if ((_fieldFlags[_curField++] & SKIP_FIELD) != 0) {
248  return;
249  }
250  typename Field<Point<T> >::Value p = _record->get(item.key);
251  _writer->appendField(p.getX());
252  _writer->appendField(p.getY());
253  }
254 
255  // moments
256  template <typename T>
257  void operator()(SchemaItem<Moments<T> > const & item) const {
258  uint8_t const c = _fieldFlags[_curField++];
259  if ((c & SKIP_FIELD) != 0) {
260  return;
261  }
262  typename Field<Moments<T> >::Value p = _record->get(item.key);
263  double const scale = ((c & RAD2) == 0 ? 1.0 : ARCSEC2_PER_RAD2);
264  _writer->appendField(scale * p.getIxx());
265  _writer->appendField(scale * p.getIyy());
266  _writer->appendField(scale * p.getIxy());
267  }
268 
269  // covariances
270  template <typename T>
271  void operator()(SchemaItem<Covariance<T> > const & item) const {
272  uint8_t const c = _fieldFlags[_curField++];
273  if ((c & SKIP_FIELD) != 0) {
274  return;
275  }
276  typename Field<Covariance<T> >::Value cov = _record->get(item.key);
277  int const sz = item.field.getSize();
278  double scale = 1.0;
279  if ((c & RAD2) != 0) {
280  scale = ARCSEC2_PER_RAD2;
281  } else if ((c & RAD4) != 0) {
282  scale = ARCSEC4_PER_RAD4;
283  }
284  for (int i = 0; i < sz; ++i) {
285  for (int j = i; j < sz; ++j) {
286  _writer->appendField(scale * cov(i, j));
287  }
288  }
289  }
290 
291  // flags
292  void operator()(SchemaItem<Flag> const & item) const {
293  if ((_fieldFlags[_curField++] & SKIP_FIELD) != 0) {
294  return;
295  }
296  if (_flagsAsBits) {
297  _writer->appendField(_record->get(item.key));
298  } else {
299  if (_record->get(item.key)) {
300  _flagInts[_curFlag / 63] |= static_cast<int64_t>(1) << (_curFlag % 63);
301  }
302  ++_curFlag;
303  }
304  }
305 
306  private:
307  // disable copy construction/assignment
308  CsvConverter(CsvConverter const &);
309  CsvConverter& operator=(CsvConverter const &);
310 
311  CsvWriter mutable * _writer;
312  boost::shared_ptr<BaseRecord const> _record;
315  int mutable _curField;
316  int mutable _curFlag;
317  boost::scoped_array<int64_t> mutable _flagInts;
318  boost::scoped_array<uint8_t> _fieldFlags;
319  std::vector<Key<Flag> > _canonicalFlags;
320  };
321 
322 } // namespace <anonymous>
323 
324 
326  flagsAsBits(true),
327  ignoreFields(),
328  nullableIntegers(),
329  canonicalFlags()
330 { }
331 
333 
334 
335 void writeCsv(BaseCatalog const & catalog,
336  CsvConversionControl const & cnvControl,
337  CsvControl const & csvControl,
338  std::string const & csvFile,
339  bool truncate,
340  bool append)
341 {
342  CsvWriter writer(csvFile, csvControl, truncate, append);
343  Schema schema = catalog.getSchema();
344  CsvConverter cnv(writer, schema, cnvControl);
345  boost::reference_wrapper<CsvConverter> cnvRef = boost::ref(cnv);
346  for (BaseCatalog::const_iterator i = catalog.begin(), e = catalog.end(); i != e; ++i) {
347  cnv.startRecord(i);
348  schema.forEach(cnvRef);
349  cnv.endRecord();
350  }
351  writer.flush();
352 }
353 
354 }}} // namespace lsst:ap::utils
Extent< int, N > truncate(Extent< double, N > const &input)
Defines the fields and offsets for a table.
Definition: Schema.h:46
bool _flagsAsBits
Definition: csvUtils.cc:313
lsst::afw::coord::Coord Coord
Definition: misc.h:39
CsvConversionControl const & _control
Definition: csvUtils.cc:120
Parameters that define a Character-Separated-Value dialect.
Definition: CsvControl.h:48
CatalogT< BaseRecord > BaseCatalog
Definition: fwd.h:61
An include file to include the header files for lsst::afw::coord.
CSV utilities.
boost::scoped_array< int64_t > _flagInts
Definition: csvUtils.cc:317
CsvWriter _writer
lsst::afw::coord::IcrsCoord IcrsCoord
Definition: misc.h:41
int _nFlagInts
Definition: csvUtils.cc:314
Catalog to CSV conversion parameters.
Definition: csvUtils.h:43
int _curField
Definition: csvUtils.cc:122
tbl::Schema schema
Definition: CoaddPsf.cc:324
std::vector< Key< Flag > > _canonicalFlags
Definition: csvUtils.cc:319
A description of a field in a table.
Definition: Field.h:22
SchemaItem< T > find(std::string const &name) const
Find a SchemaItem in the Schema by name.
int _curFlag
Definition: csvUtils.cc:316
Base class for all records.
Definition: BaseRecord.h:27
A class used as a handle to a particular field in a table.
Definition: fwd.h:44
lsst::afw::geom::Angle Angle
Definition: misc.h:42
void writeCsv(BaseCatalog const &catalog, CsvConversionControl const &cnvControl, CsvControl const &csvControl, std::string const &csvFile, bool truncate, bool append)
Definition: csvUtils.cc:335
afw::table::Key< double > b
uint8_t * _fieldFlags
Definition: csvUtils.cc:121
int getFieldCount() const
The total number of fields.
Definition: Schema.h:135
int getFlagFieldCount() const
The number of Flag fields.
Definition: Schema.h:138
Classes for CSV I/O.
Tag types used to declare specialized field types.
Definition: misc.h:35
ImageT val
Definition: CR.cc:154
dictionary Point
Definition: __init__.py:38
void forEach(F func) const
Apply a functor to each SchemaItem in the Schema.
Definition: Schema.h:204
std::string _record
A simple pair-like struct for mapping a Field (name and description) with a Key (used for actual data...
Definition: SchemaImpl.h:27