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
Functions | Variables
lsst::afw::geom::detail Namespace Reference

Functions

std::shared_ptr< ast::FrameSetreadFitsWcs (daf::base::PropertySet &metadata, bool strip=true)
 Read a FITS convention WCS FrameSet from FITS metadata. More...
 
std::shared_ptr< ast::FrameDictreadLsstSkyWcs (daf::base::PropertySet &metadata, bool strip=true)
 Read an LSST celestial WCS FrameDict from a FITS header. More...
 
std::shared_ptr< daf::base::PropertyListgetPropertyListFromFitsChan (ast::FitsChan &fitsChan)
 Copy values from an AST FitsChan into a PropertyList. More...
 
ast::FitsChan getFitsChanFromPropertyList (daf::base::PropertySet &metadata, std::set< std::string > const &excludeNames={}, std::string options="")
 Construct AST FitsChan from PropertyList. More...
 
template<class Transform >
std::shared_ptr< TransformreadStream (std::istream &is)
 Deserialize a Transform from an input stream. More...
 
template<class Transform >
void writeStream (Transform const &transform, std::ostream &os)
 Serialize a Transform to an output stream. More...
 
void wrapFrameSetUtils (lsst::utils::python::WrapperCollection &)
 

Variables

constexpr int serializationVersion = 1
 version of serialization used when writing (older versions may also be supported when reading) More...
 

Function Documentation

◆ getFitsChanFromPropertyList()

ast::FitsChan lsst::afw::geom::detail::getFitsChanFromPropertyList ( daf::base::PropertySet metadata,
std::set< std::string > const &  excludeNames = {},
std::string  options = "" 
)

Construct AST FitsChan from PropertyList.

Parameters
[in]metadataMetadata to transfer; if this is a PropertyList then the order of items is preserved.
[in]excludeNamesNames of entries to exclude from the returned header string.
[in]optionsOptions string to pass to ast::FitsChan constructor.
Returns
an ast::FitsChan representing this PropertyList

Definition at line 316 of file frameSetUtils.cc.

318  {
319  // Create FitsChan to receive each of the parameters
320  auto stream = ast::StringStream("");
321  auto fc = ast::FitsChan(stream, options);
322 
323  // Get the parameter names (in order if necessary)
324  daf::base::PropertyList const *pl = dynamic_cast<daf::base::PropertyList const *>(&metadata);
325  std::vector<std::string> allParamNames;
326  if (pl) {
327  allParamNames = pl->getOrderedNames();
328  } else {
329  allParamNames = metadata.paramNames(false);
330  }
331 
332  // Loop over the names and add them to the FitsChan if not excluded
333  for (auto const &fullName : allParamNames) {
334  if (excludeNames.count(fullName) == 0) {
335  std::size_t lastPeriod = fullName.rfind(char('.'));
336  auto name = (lastPeriod == std::string::npos) ? fullName : fullName.substr(lastPeriod + 1);
337  std::type_info const &type = metadata.typeOf(name);
338 
339  if (name.size() > 8) {
340  continue; // The name is too long for a FITS keyword; skip this item
341  }
342 
343  if (type == typeid(bool)) {
344  fc.setFitsL(name, metadata.get<bool>(name));
345  } else if (type == typeid(std::uint8_t)) {
346  fc.setFitsI(name, static_cast<int>(metadata.get<std::uint8_t>(name)));
347  } else if (type == typeid(int)) {
348  fc.setFitsI(name, metadata.get<int>(name));
349  } else if (type == typeid(double) || type == typeid(float)) {
350  double value;
351  if (type == typeid(double)) {
352  value = metadata.get<double>(name);
353  } else {
354  value = static_cast<double>(metadata.get<float>(name));
355  }
356  // NaN is not allowed in a FitsChan (or in FITS)
357  if (!std::isnan(value)) {
358  fc.setFitsF(name, value);
359  } else {
360  // Treat it like an undefined value but warn about it
361  LOGLS_WARN("lsst.afw.geom.frameSetUtils",
362  boost::format("Found NaN in metadata item '%s'") % name);
363  }
364  } else if (type == typeid(std::string)) {
365  std::string str = metadata.get<std::string>(name);
366  // No support for long strings yet so skip those
367  if (str.size() <= 68) {
368  fc.setFitsS(name, metadata.get<std::string>(name));
369  }
370  }
371  }
372  }
373  // Rewind the channel
374  fc.setCard(0);
375  return fc;
376 }
table::Key< std::string > name
Definition: Amplifier.cc:116
table::Key< int > type
Definition: Detector.cc:163
#define LOGLS_WARN(logger, message)
Log a warn-level message using an iostream-based interface.
Definition: Log.h:659
A specialized form of Channel which reads and writes FITS header cards.
Definition: FitsChan.h:202
String-based source and sink for channels.
Definition: Stream.h:180
T count(T... args)
T isnan(T... args)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
T size(T... args)

◆ getPropertyListFromFitsChan()

std::shared_ptr< daf::base::PropertyList > lsst::afw::geom::detail::getPropertyListFromFitsChan ( ast::FitsChan fitsChan)

Copy values from an AST FitsChan into a PropertyList.

Warning
COMMENT and HISTORY cards are treated as string values
Exceptions
lsst::pex::exceptions::TypeErrorif fitsChan contains cards whose type is not supported by PropertyList: complex numbers, or cards with no value

Definition at line 251 of file frameSetUtils.cc.

251  {
252  int const numCards = fitsChan.getNCard();
253  auto metadata = std::make_shared<daf::base::PropertyList>();
254  for (int cardNum = 1; cardNum <= numCards; ++cardNum) {
255  fitsChan.setCard(cardNum);
256  auto const cardType = fitsChan.getCardType();
257  auto const cardName = fitsChan.getCardName();
258  auto const cardComment = fitsChan.getCardComm();
259  switch (cardType) {
260  case ast::CardType::FLOAT: {
261  auto foundValue = fitsChan.getFitsF();
262  setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
263  break;
264  }
265  case ast::CardType::INT: {
266  auto foundValue = fitsChan.getFitsI();
267  setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
268  break;
269  }
270  case ast::CardType::STRING: {
271  auto foundValue = fitsChan.getFitsS();
272  setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
273  break;
274  }
275  case ast::CardType::LOGICAL: {
276  auto foundValue = fitsChan.getFitsL();
277  setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
278  break;
279  }
280  case ast::CardType::UNDEF: {
281  if (cardComment.empty()) {
282  metadata->set(cardName, nullptr);
283  } else {
284  metadata->set(cardName, nullptr, cardComment);
285  }
286  break;
287  }
289  auto foundValue = fitsChan.getFitsCN();
290  setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
291  break;
292  }
294  // Drop HISTORY and COMMENT cards
295  break;
298  // PropertyList supports neither complex numbers nor cards with no value
300  os << "Card " << cardNum << " with name \"" << cardName << "\" has type "
301  << static_cast<int>(cardType) << ", which is not supported by PropertyList";
303  }
304  case ast::CardType::NOTYPE: {
305  // This should only occur if cardNum is invalid, and that should be impossible
307  os << "Bug! Card " << cardNum << " with name \"" << cardName
308  << "\" has type NOTYPE, which should not be possible";
310  }
311  }
312  }
313  return metadata;
314 }
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
std::ostream * os
Definition: Schema.cc:557
std::string getCardComm() const
Get CardComm: the comment of the current card.
Definition: FitsChan.h:491
FoundValue< std::string > getFitsS(std::string const &name="", std::string defval="") const
Get the value of a string card.
Definition: FitsChan.cc:98
void setCard(int ind)
Set Card: the index of the current card, where 1 is the first card.
Definition: FitsChan.h:1036
FoundValue< bool > getFitsL(std::string const &name="", bool defval=false) const
Get the value of a bool card.
Definition: FitsChan.cc:91
std::string getCardName() const
Get CardName: the keyword name of the current card.
Definition: FitsChan.h:496
FoundValue< int > getFitsI(std::string const &name="", int defval=0) const
Get the value of a int card.
Definition: FitsChan.cc:84
CardType getCardType() const
Get CardType: data type of the current FITS card.
Definition: FitsChan.h:501
int getNCard() const
Get NCard: the number of cards.
Definition: FitsChan.h:555
FoundValue< double > getFitsF(std::string const &name="", double defval=0) const
Get the value of a double card.
Definition: FitsChan.cc:77
FoundValue< std::string > getFitsCN(std::string const &name="", std::string defval="") const
Get the value of a CONTINUE card.
Definition: FitsChan.cc:69
Reports errors from accepting an object of an unexpected or inappropriate type.
Definition: Runtime.h:167
@ NOTYPE
card does not exist (card number invalid)
@ CONTINUE
CONTINUE card.
@ LOGICAL
boolean
@ COMPLEXI
complex integer
@ INT
integer
@ COMPLEXF
complex floating point
@ STRING
string
@ UNDEF
card has no value
@ COMMENT
card is a comment-style card with no "=" (COMMENT, HISTORY, ...)

◆ readFitsWcs()

std::shared_ptr< ast::FrameSet > lsst::afw::geom::detail::readFitsWcs ( daf::base::PropertySet metadata,
bool  strip = true 
)

Read a FITS convention WCS FrameSet from FITS metadata.

The resulting FrameSet may be any kind of WCS supported by FITS; if it is a celestial WCS then 1,1 will be the lower left corner of the image (the FITS convention, not the LSST convention).

This routine replaces RADECSYS with RADESYS if the former is present and the latter is not, since that is a common misspelling in FITS headers.

The returned FrameSet will have an IWC (intermediate world coordinate system) frame.

Parameters
[in,out]metadataFITS header cards
[in]stripIf true: strip items from metadata used to create the WCS, such as RADESYS, EQUINOX, CTYPE12, CRPIX12, CRVAL12, etc. Always keep keywords that might be wanted for other purpposes, including NAXIS12 and date-related keywords such as "DATE-OBS" and "TIMESYS" (but not "EQUINOX").
Exceptions
pex::exceptions::TypeErrorif the metadata does not contain a FITS-WCS

Definition at line 82 of file frameSetUtils.cc.

82  {
83  // Exclude WCS A keywords because LSST uses them to store XY0
84  auto wcsANames = createTrivialWcsMetadata("A", lsst::geom::Point2I(0, 0))->names();
85  std::set<std::string> excludeNames(wcsANames.begin(), wcsANames.end());
86  // Ignore NAXIS1, NAXIS2 because if they are zero then AST will fail to read a WCS
87  // Ignore LTV1/2 because LSST adds it and this code should ignore it and not strip it
88  // Exclude comments and history to reduce clutter
89  std::set<std::string> moreNames{"NAXIS1", "NAXIS2", "LTV1", "LTV2", "COMMENT", "HISTORY"};
90  excludeNames.insert(moreNames.begin(), moreNames.end());
91 
92  // Replace RADECSYS with RADESYS if only the former is present
93  if (metadata.exists("RADECSYS") && !metadata.exists("RADESYS")) {
94  metadata.set("RADESYS", metadata.getAsString("RADECSYS"));
95  metadata.remove("RADECSYS");
96  }
97 
98  auto channel = getFitsChanFromPropertyList(metadata, excludeNames,
99  "Encoding=FITS-WCS, IWC=1, SipReplace=0, ReportLevel=3");
100  auto const initialNames = strip ? setFromVector(channel.getAllCardNames()) : std::set<std::string>();
102  try {
103  obj = channel.read();
104  } catch (std::runtime_error const&) {
105  throw LSST_EXCEPT(pex::exceptions::TypeError, "The metadata does not describe an AST object");
106  }
107 
108  auto frameSet = std::dynamic_pointer_cast<ast::FrameSet>(obj);
109  if (!frameSet) {
110  throw LSST_EXCEPT(pex::exceptions::TypeError,
111  "metadata describes a " + obj->getClassName() + ", not a FrameSet");
112  }
113  if (strip) {
114  auto const finalNames = setFromVector(channel.getAllCardNames());
115 
116  // FITS keywords that FitsChan stripped
117  std::set<std::string> namesChannelStripped;
118  std::set_difference(initialNames.begin(), initialNames.end(), finalNames.begin(), finalNames.end(),
119  std::inserter(namesChannelStripped, namesChannelStripped.begin()));
120 
121  // FITS keywords that FitsChan may strip that we want to keep in `metadata`
122  std::set<std::string> const namesToKeep = {"DATE-OBS", "MJD-OBS"};
123 
124  std::set<std::string> namesToStrip; // names to strip from metadata
125  std::set_difference(namesChannelStripped.begin(), namesChannelStripped.end(), namesToKeep.begin(),
126  namesToKeep.end(), std::inserter(namesToStrip, namesToStrip.begin()));
127  for (auto const& name : namesToStrip) {
128  metadata.remove(name);
129  }
130  }
131  return frameSet;
132 }
table::Key< table::Array< std::uint8_t > > frameSet
T begin(T... args)
T end(T... args)
daf::base::PropertySet * set
Definition: fits.cc:912
bool strip
Definition: fits.cc:911
T insert(T... args)
T inserter(T... args)
ast::FitsChan getFitsChanFromPropertyList(daf::base::PropertySet &metadata, std::set< std::string > const &excludeNames={}, std::string options="")
Construct AST FitsChan from PropertyList.
std::shared_ptr< daf::base::PropertyList > createTrivialWcsMetadata(std::string const &wcsName, lsst::geom::Point2I const &xy0)
Definition: wcsUtils.cc:48
STL namespace.
T set_difference(T... args)

◆ readLsstSkyWcs()

std::shared_ptr< ast::FrameDict > lsst::afw::geom::detail::readLsstSkyWcs ( daf::base::PropertySet metadata,
bool  strip = true 
)

Read an LSST celestial WCS FrameDict from a FITS header.

Calls getImageXY0FromMetadata to determine image XY0.

Saves CRVAL by setting the output SkyFrame's SkyRef to CRVAL and SkyRefIs="Ignore" (so SkyRef is not treated as an offset).

Warning
Does not compensate for the offset between a subimage and its parent image; callers must do that manually, e.g. by calling SkyWcs::copyAtShiftedPosition.
the general SkyWcs generated by LSST software cannot be exactly represented using standard WCS FITS cards, and so this function cannot read those. This function is intended for two purposes:
  • Read the standard FITS WCS found in raw data and other images from non-LSST observatories and convert it to the LSST pixel convention.
  • Read the approximate FITS WCS that LSST writes to FITS images (for use by non-LSST code).

The frames of the returned WCS will be as follows:

  • "PIXELS" (base frame): pixel frame with 0,0 the lower left corner of the image (LSST convention)
  • "IWC": FITS WCS intermediate world coordinate system
  • "SKY" (current frame): an ast::SkyFrame with domain "SKY": ICRS RA, Dec

All frames are instances of ast::Frame except the SKY frame. All have 2 axes.

Parameters
[in,out]metadataFITS header cards
[in]stripIf true: strip items from metadata used to create the WCS, such as RADESYS, EQUINOX, CTYPE12, CRPIX12, CRVAL12, etc. Always keep keywords that might be wanted for other purpposes, including NAXIS12 and date-related keywords such as "DATE-OBS" and "TIMESYS" (but not "EQUINOX").
Exceptions
lsst::pex::exceptions::TypeErrorif the metadata does not describe a celestial WCS.

Definition at line 134 of file frameSetUtils.cc.

134  {
135  // Record CRPIX in GRID coordinates
136  // so we can compute CRVAL after standardizing the SkyFrame to ICRS
137  // (that standardization is why we don't simply save CRVAL now)
138  std::vector<double> crpixGrid(2);
139  try {
140  crpixGrid[0] = metadata.getAsDouble("CRPIX1");
141  crpixGrid[1] = metadata.getAsDouble("CRPIX2");
143  // std::string used because e.what() returns a C string and two C strings cannot be added
145  e.what() + std::string("; cannot read metadata as a SkyWcs"));
146  }
147 
148  auto rawFrameSet = readFitsWcs(metadata, strip);
149  auto const initialBaseIndex = rawFrameSet->getBase();
150 
151  // Find the GRID frame
152  auto gridIndex = ast::FrameSet::NOFRAME;
153  if (rawFrameSet->findFrame(ast::Frame(2, "Domain=GRID"))) {
154  gridIndex = rawFrameSet->getCurrent();
155  } else {
156  // No appropriate GRID frame found; if the original base frame is of type Frame
157  // with 2 axes and a blank domain then use that, else give up
158  auto const baseFrame = rawFrameSet->getFrame(initialBaseIndex, false);
159  auto const baseClassName = rawFrameSet->getClassName();
160  if (baseFrame->getClassName() != "Frame") {
161  throw LSST_EXCEPT(pex::exceptions::TypeError,
162  "The base frame is of type " + baseFrame->getClassName() +
163  "instead of Frame; cannot read metadata as a SkyWcs");
164  }
165  if (baseFrame->getNAxes() != 2) {
166  throw LSST_EXCEPT(pex::exceptions::TypeError,
167  "The base frame has " + std::to_string(baseFrame->getNAxes()) +
168  " axes instead of 2; cannot read metadata as a SkyWcs");
169  }
170  if (baseFrame->getDomain() != "") {
171  throw LSST_EXCEPT(pex::exceptions::TypeError,
172  "The base frame has domain \"" + baseFrame->getDomain() +
173  "\" instead of blank or GRID; cannot read metadata as a SkyWcs");
174  }
175  // Original base frame has a blank Domain, is of type Frame, and has 2 axes, so
176  // Set its domain to GRID, and set some other potentially useful attributes.
177  gridIndex = initialBaseIndex;
178  }
179 
180  // Find the IWC frame
181  if (!rawFrameSet->findFrame(ast::Frame(2, "Domain=IWC"))) {
182  throw LSST_EXCEPT(pex::exceptions::TypeError, "No IWC frame found; cannot read metadata as a SkyWcs");
183  }
184  auto const iwcIndex = rawFrameSet->getCurrent();
185  auto const iwcFrame = rawFrameSet->getFrame(iwcIndex);
186 
187  // Create a standard sky frame: ICRS with axis order RA, Dec
188 
189  // Create the a template for the standard sky frame
190  auto const stdSkyFrameTemplate = ast::SkyFrame("System=ICRS");
191 
192  // Locate a Frame in the target FrameSet that looks like the template
193  // and hence can be used as the original sky frame.
194  // We ignore the frame set returned by findFrame because that goes from pixels to sky,
195  // and using it would add an unwanted extra branch to our WCS; instead, later on,
196  // we compute a mapping from the old sky frame to the new sky frame and add that.
197  if (!rawFrameSet->findFrame(stdSkyFrameTemplate)) {
198  throw LSST_EXCEPT(pex::exceptions::TypeError,
199  "Could not find a SkyFrame; cannot read metadata as a SkyWcs");
200  }
201  auto initialSkyIndex = rawFrameSet->getCurrent();
202 
203  // Compute a frame set that maps from the original sky frame to our desired sky frame template;
204  // this contains the mapping and sky frame we will insert into the frame set.
205  // (Temporarily set the base frame to the sky frame, because findFrame
206  // produces a mapping from base to the found frame).
207  rawFrameSet->setBase(initialSkyIndex);
208  auto stdSkyFrameSet = rawFrameSet->findFrame(stdSkyFrameTemplate);
209  if (!stdSkyFrameSet) {
210  throw LSST_EXCEPT(pex::exceptions::LogicError,
211  "Bug: found a SkyFrame the first time, but not the second time");
212  }
213 
214  // Add the new mapping into rawFrameSet, connecting it to the original SkyFrame.
215  // Note: we use stdSkyFrameSet as the new frame (meaning stdSkyFrameSet's current frame),
216  // because, unlike stdSkyFrameTemplate, stdSkyFrameSet's current frame has inherited some
217  // potentially useful attributes from the old sky frame, such as epoch.
218  rawFrameSet->addFrame(initialSkyIndex, *stdSkyFrameSet->getMapping()->simplified(),
219  *stdSkyFrameSet->getFrame(ast::FrameSet::CURRENT));
220  auto const stdSkyIndex = rawFrameSet->getCurrent();
221  auto const stdSkyFrame = rawFrameSet->getFrame(stdSkyIndex, false);
222 
223  // Compute a mapping from PIXELS (0-based in parent coordinates)
224  // to GRID (1-based in local coordinates)
226  std::vector<double> pixelToGridArray = {1.0 - xy0[0], 1.0 - xy0[1]}; // 1.0 for FITS vs LSST convention
227  auto pixelToGrid = ast::ShiftMap(pixelToGridArray);
228 
229  // Now construct the returned FrameDict
230  auto const gridToIwc = rawFrameSet->getMapping(gridIndex, iwcIndex)->simplified();
231  auto const pixelToIwc = pixelToGrid.then(*gridToIwc).simplified();
232  auto const iwcToStdSky = rawFrameSet->getMapping(iwcIndex, stdSkyIndex);
233 
234  auto frameDict = std::make_shared<ast::FrameDict>(ast::Frame(2, "Domain=PIXELS"), *pixelToIwc, *iwcFrame);
235  frameDict->addFrame("IWC", *iwcToStdSky, *stdSkyFrame);
236 
237  // Record CRVAL as SkyRef in the SkyFrame so it can easily be obtained later;
238  // set SkyRefIs = "Ignored" (the default) so SkyRef value is ignored instead of used as an offset
239  auto crpixPixels = pixelToGrid.applyInverse(crpixGrid);
240  auto crvalRad = frameDict->applyForward(crpixPixels);
241  auto skyFrame = std::dynamic_pointer_cast<ast::SkyFrame>(frameDict->getFrame("SKY", false));
242  if (!skyFrame) {
243  throw LSST_EXCEPT(pex::exceptions::LogicError, "SKY frame is not a SkyFrame");
244  }
245  skyFrame->setSkyRefIs("Ignored");
246  skyFrame->setSkyRef(crvalRad);
247 
248  return frameDict;
249 }
Frame is used to represent a coordinate system.
Definition: Frame.h:157
static constexpr int CURRENT
index of current frame
Definition: FrameSet.h:105
static constexpr int NOFRAME
an invalid frame index
Definition: FrameSet.h:106
ShiftMap is a linear Mapping which shifts each axis by a specified constant value.
Definition: ShiftMap.h:40
SkyFrame is a specialised form of Frame which describes celestial longitude/latitude coordinate syste...
Definition: SkyFrame.h:66
virtual char const * what(void) const noexcept
Return a character string summarizing this exception.
Definition: Exception.cc:99
Reports attempts to access elements using an invalid key.
Definition: Runtime.h:151
std::shared_ptr< ast::FrameSet > readFitsWcs(daf::base::PropertySet &metadata, bool strip=true)
Read a FITS convention WCS FrameSet from FITS metadata.
lsst::geom::Point2I getImageXY0FromMetadata(daf::base::PropertySet &metadata, std::string const &wcsName, bool strip=false)
Definition: wcsUtils.cc:95
std::string const wcsNameForXY0
Definition: ImageBase.h:70
T to_string(T... args)

◆ readStream()

template<class Transform >
std::shared_ptr< Transform > lsst::afw::geom::detail::readStream ( std::istream is)

Deserialize a Transform from an input stream.

Template Parameters
Transformthe Transform class; can be Transform<FromEndpoint, ToEndpoint>, SkyWcs, or any other compatible class, i.e. it must support the following (see Transform.h for details):
  • a constructor that takes an ast::FrameSet
  • static method getShortClassName
  • method getMapping
Parameters
[in]isinput stream from which to deserialize this Transform

Definition at line 79 of file transformUtils.h.

79  {
80  int version;
81  is >> version;
82  if (version != 1) {
83  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError,
84  "Unsupported version " + std::to_string(version));
85  }
86  std::string shortClassName;
87  is >> shortClassName;
88  if (shortClassName != Transform::getShortClassName()) {
90  os << "Class name in stream " << shortClassName << " != " << Transform::getShortClassName();
91  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, os.str());
92  }
93  auto astStream = ast::Stream(&is, nullptr);
94  auto astObjectPtr = ast::Channel(astStream).read();
95  auto mapping = std::dynamic_pointer_cast<ast::Mapping>(astObjectPtr);
96  if (!mapping) {
98  os << "The AST serialization was read as a " << astObjectPtr->getClassName()
99  << " instead of a Mapping";
100  throw LSST_EXCEPT(pex::exceptions::InvalidParameterError, os.str());
101  }
102 
103  return std::make_shared<Transform>(*mapping);
104 }
Channel provides input/output of AST objects.
Definition: Channel.h:60
std::shared_ptr< Object > read()
Read an object from a channel.
Definition: Channel.cc:52
A stream for ast::Channel.
Definition: Stream.h:41

◆ wrapFrameSetUtils()

void lsst::afw::geom::detail::wrapFrameSetUtils ( lsst::utils::python::WrapperCollection &  )

◆ writeStream()

template<class Transform >
void lsst::afw::geom::detail::writeStream ( Transform const &  transform,
std::ostream os 
)

Serialize a Transform to an output stream.

Version 1 format is as follows:

  • The version number (an integer)
  • A space
  • The short class name, as obtained from getShortClassName
  • A space
  • The contained ast::FrameSet written using FrameSet.show(os, false)
Parameters
[out]osoutput stream to which to serialize this Transform
[in]transformTransform to serialize

Definition at line 107 of file transformUtils.h.

107  {
108  os << serializationVersion << " " << Transform::getShortClassName();
109  transform.getMapping()->show(os, false); // false = do not write comments
110 }
table::Key< int > transform
constexpr int serializationVersion
version of serialization used when writing (older versions may also be supported when reading)

Variable Documentation

◆ serializationVersion

constexpr int lsst::afw::geom::detail::serializationVersion = 1
constexpr

version of serialization used when writing (older versions may also be supported when reading)

Definition at line 42 of file transformUtils.h.