LSST Applications g0f08755f38+9c285cab97,g1635faa6d4+13f3999e92,g1653933729+a8ce1bb630,g1a0ca8cf93+bf6eb00ceb,g28da252d5a+0829b12dee,g29321ee8c0+5700dc9eac,g2bbee38e9b+9634bc57db,g2bc492864f+9634bc57db,g2cdde0e794+c2c89b37c4,g3156d2b45e+41e33cbcdc,g347aa1857d+9634bc57db,g35bb328faa+a8ce1bb630,g3a166c0a6a+9634bc57db,g3e281a1b8c+9f2c4e2fc3,g414038480c+077ccc18e7,g41af890bb2+fde0dd39b6,g5fbc88fb19+17cd334064,g781aacb6e4+a8ce1bb630,g80478fca09+55a9465950,g82479be7b0+d730eedb7d,g858d7b2824+9c285cab97,g9125e01d80+a8ce1bb630,g9726552aa6+10f999ec6a,ga5288a1d22+2a84bb7594,gacf8899fa4+c69c5206e8,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+9634bc57db,gcf0d15dbbd+4b7d09cae4,gda3e153d99+9c285cab97,gda6a2b7d83+4b7d09cae4,gdaeeff99f8+1711a396fd,ge2409df99d+5e831397f4,ge79ae78c31+9634bc57db,gf0baf85859+147a0692ba,gf3967379c6+41c94011de,gf3fb38a9a8+8f07a9901b,gfb92a5be7c+9c285cab97,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
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.
 
std::shared_ptr< ast::FrameDictreadLsstSkyWcs (daf::base::PropertySet &metadata, bool strip=true)
 Read an LSST celestial WCS FrameDict from a FITS header.
 
void stripWcsMetadata (daf::base::PropertySet &metadata)
 Strip all WCS metadata from a header.
 
std::shared_ptr< daf::base::PropertyListgetPropertyListFromFitsChan (ast::FitsChan &fitsChan)
 Copy values from an AST FitsChan into a PropertyList.
 
ast::FitsChan getFitsChanFromPropertyList (daf::base::PropertySet &metadata, std::set< std::string > const &excludeNames={}, std::string options="")
 Construct AST FitsChan from PropertyList.
 
template<class Transform >
std::shared_ptr< TransformreadStream (std::istream &is)
 Deserialize a Transform from an input stream.
 
template<class Transform >
void writeStream (Transform const &transform, std::ostream &os)
 Serialize a Transform to an output stream.
 
void wrapFrameSetUtils (lsst::cpputils::python::WrapperCollection &)
 

Variables

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

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 361 of file frameSetUtils.cc.

363 {
364 // Create FitsChan to receive each of the parameters
365 auto stream = ast::StringStream("");
366 auto fc = ast::FitsChan(stream, options);
367
368 // Get the parameter names (in order if necessary)
369 daf::base::PropertyList const *pl = dynamic_cast<daf::base::PropertyList const *>(&metadata);
370 std::vector<std::string> allParamNames;
371 if (pl) {
372 allParamNames = pl->getOrderedNames();
373 } else {
374 allParamNames = metadata.paramNames(false);
375 }
376
377 // Loop over the names and add them to the FitsChan if not excluded
378 for (auto const &fullName : allParamNames) {
379 if (excludeNames.count(fullName) == 0) {
380 std::size_t lastPeriod = fullName.rfind(char('.'));
381 auto name = (lastPeriod == std::string::npos) ? fullName : fullName.substr(lastPeriod + 1);
382 std::type_info const &type = metadata.typeOf(name);
383
384 if (name.size() > 8) {
385 continue; // The name is too long for a FITS keyword; skip this item
386 }
387
388 if (type == typeid(bool)) {
389 fc.setFitsL(name, metadata.get<bool>(name));
390 } else if (type == typeid(std::uint8_t)) {
391 fc.setFitsI(name, static_cast<int>(metadata.get<std::uint8_t>(name)));
392 } else if (type == typeid(int)) {
393 fc.setFitsI(name, metadata.get<int>(name));
394 } else if (type == typeid(double) || type == typeid(float)) {
395 double value;
396 if (type == typeid(double)) {
397 value = metadata.get<double>(name);
398 } else {
399 value = static_cast<double>(metadata.get<float>(name));
400 }
401 // NaN is not allowed in a FitsChan (or in FITS)
402 if (!std::isnan(value)) {
403 fc.setFitsF(name, value);
404 } else {
405 // Treat it like an undefined value but warn about it
406 LOGLS_WARN("lsst.afw.geom.frameSetUtils",
407 boost::format("Found NaN in metadata item '%s'") % name);
408 }
409 } else if (type == typeid(std::string)) {
410 std::string str = metadata.get<std::string>(name);
411 // No support for long strings yet so skip those
412 if (str.size() <= 68) {
413 fc.setFitsS(name, metadata.get<std::string>(name));
414 }
415 }
416 }
417 }
418 // Rewind the channel
419 fc.setCard(0);
420 return fc;
421}
table::Key< std::string > name
Definition Amplifier.cc:116
#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
Class for storing ordered metadata with comments.
std::vector< std::string > getOrderedNames() const
Get the list of property names, in the order they were added.
std::type_info const & typeOf(std::string const &name) const
Get the type of values for a property name (possibly hierarchical).
T get(std::string const &name) const
Get the last value for a property name (possibly hierarchical).
std::vector< std::string > paramNames(bool topLevelOnly=true) const
A variant of names that excludes the names of subproperties.
T count(T... args)
T isnan(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 296 of file frameSetUtils.cc.

296 {
297 int const numCards = fitsChan.getNCard();
298 auto metadata = std::make_shared<daf::base::PropertyList>();
299 for (int cardNum = 1; cardNum <= numCards; ++cardNum) {
300 fitsChan.setCard(cardNum);
301 auto const cardType = fitsChan.getCardType();
302 auto const cardName = fitsChan.getCardName();
303 auto const cardComment = fitsChan.getCardComm();
304 switch (cardType) {
306 auto foundValue = fitsChan.getFitsF();
307 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
308 break;
309 }
310 case ast::CardType::INT: {
311 auto foundValue = fitsChan.getFitsI();
312 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
313 break;
314 }
316 auto foundValue = fitsChan.getFitsS();
317 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
318 break;
319 }
321 auto foundValue = fitsChan.getFitsL();
322 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
323 break;
324 }
326 if (cardComment.empty()) {
327 metadata->set(cardName, nullptr);
328 } else {
329 metadata->set(cardName, nullptr, cardComment);
330 }
331 break;
332 }
334 auto foundValue = fitsChan.getFitsCN();
335 setMetadataFromFoundValue(*metadata, cardName, foundValue, cardComment);
336 break;
337 }
339 // Drop HISTORY and COMMENT cards
340 break;
343 // PropertyList supports neither complex numbers nor cards with no value
345 os << "Card " << cardNum << " with name \"" << cardName << "\" has type "
346 << static_cast<int>(cardType) << ", which is not supported by PropertyList";
348 }
350 // This should only occur if cardNum is invalid, and that should be impossible
352 os << "Bug! Card " << cardNum << " with name \"" << cardName
353 << "\" has type NOTYPE, which should not be possible";
355 }
356 }
357 }
358 return metadata;
359}
#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)
std::string getAsString(std::string const &name) const
Get the last value for a string property name (possibly hierarchical).
virtual void remove(std::string const &name)
Remove all values for a property name (possibly hierarchical).
bool exists(std::string const &name) const
Determine if a name (possibly hierarchical) exists.
void set(std::string const &name, T const &value)
Replace all values for a property name (possibly hierarchical) with a new scalar value.
T end(T... args)
bool strip
Definition fits.cc:930
T insert(T... args)
T inserter(T... args)
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 179 of file frameSetUtils.cc.

179 {
180 // Record CRPIX in GRID coordinates
181 // so we can compute CRVAL after standardizing the SkyFrame to ICRS
182 // (that standardization is why we don't simply save CRVAL now)
183 std::vector<double> crpixGrid(2);
184 try {
185 crpixGrid[0] = metadata.getAsDouble("CRPIX1");
186 crpixGrid[1] = metadata.getAsDouble("CRPIX2");
188 // std::string used because e.what() returns a C string and two C strings cannot be added
190 e.what() + std::string("; cannot read metadata as a SkyWcs"));
191 }
192
193 auto rawFrameSet = readFitsWcs(metadata, strip);
194 auto const initialBaseIndex = rawFrameSet->getBase();
195
196 // Find the GRID frame
197 auto gridIndex = ast::FrameSet::NOFRAME;
198 if (rawFrameSet->findFrame(ast::Frame(2, "Domain=GRID"))) {
199 gridIndex = rawFrameSet->getCurrent();
200 } else {
201 // No appropriate GRID frame found; if the original base frame is of type Frame
202 // with 2 axes and a blank domain then use that, else give up
203 auto const baseFrame = rawFrameSet->getFrame(initialBaseIndex, false);
204 auto const baseClassName = rawFrameSet->getClassName();
205 if (baseFrame->getClassName() != "Frame") {
207 "The base frame is of type " + baseFrame->getClassName() +
208 "instead of Frame; cannot read metadata as a SkyWcs");
209 }
210 if (baseFrame->getNAxes() != 2) {
211 throw LSST_EXCEPT(pex::exceptions::TypeError,
212 "The base frame has " + std::to_string(baseFrame->getNAxes()) +
213 " axes instead of 2; cannot read metadata as a SkyWcs");
214 }
215 if (baseFrame->getDomain() != "") {
216 throw LSST_EXCEPT(pex::exceptions::TypeError,
217 "The base frame has domain \"" + baseFrame->getDomain() +
218 "\" instead of blank or GRID; cannot read metadata as a SkyWcs");
219 }
220 // Original base frame has a blank Domain, is of type Frame, and has 2 axes, so
221 // Set its domain to GRID, and set some other potentially useful attributes.
222 gridIndex = initialBaseIndex;
223 }
224
225 // Find the IWC frame
226 if (!rawFrameSet->findFrame(ast::Frame(2, "Domain=IWC"))) {
227 throw LSST_EXCEPT(pex::exceptions::TypeError, "No IWC frame found; cannot read metadata as a SkyWcs");
228 }
229 auto const iwcIndex = rawFrameSet->getCurrent();
230 auto const iwcFrame = rawFrameSet->getFrame(iwcIndex);
231
232 // Create a standard sky frame: ICRS with axis order RA, Dec
233
234 // Create the a template for the standard sky frame
235 auto const stdSkyFrameTemplate = ast::SkyFrame("System=ICRS");
236
237 // Locate a Frame in the target FrameSet that looks like the template
238 // and hence can be used as the original sky frame.
239 // We ignore the frame set returned by findFrame because that goes from pixels to sky,
240 // and using it would add an unwanted extra branch to our WCS; instead, later on,
241 // we compute a mapping from the old sky frame to the new sky frame and add that.
242 if (!rawFrameSet->findFrame(stdSkyFrameTemplate)) {
243 throw LSST_EXCEPT(pex::exceptions::TypeError,
244 "Could not find a SkyFrame; cannot read metadata as a SkyWcs");
245 }
246 auto initialSkyIndex = rawFrameSet->getCurrent();
247
248 // Compute a frame set that maps from the original sky frame to our desired sky frame template;
249 // this contains the mapping and sky frame we will insert into the frame set.
250 // (Temporarily set the base frame to the sky frame, because findFrame
251 // produces a mapping from base to the found frame).
252 rawFrameSet->setBase(initialSkyIndex);
253 auto stdSkyFrameSet = rawFrameSet->findFrame(stdSkyFrameTemplate);
254 if (!stdSkyFrameSet) {
255 throw LSST_EXCEPT(pex::exceptions::LogicError,
256 "Bug: found a SkyFrame the first time, but not the second time");
257 }
258
259 // Add the new mapping into rawFrameSet, connecting it to the original SkyFrame.
260 // Note: we use stdSkyFrameSet as the new frame (meaning stdSkyFrameSet's current frame),
261 // because, unlike stdSkyFrameTemplate, stdSkyFrameSet's current frame has inherited some
262 // potentially useful attributes from the old sky frame, such as epoch.
263 rawFrameSet->addFrame(initialSkyIndex, *stdSkyFrameSet->getMapping()->simplified(),
264 *stdSkyFrameSet->getFrame(ast::FrameSet::CURRENT));
265 auto const stdSkyIndex = rawFrameSet->getCurrent();
266 auto const stdSkyFrame = rawFrameSet->getFrame(stdSkyIndex, false);
267
268 // Compute a mapping from PIXELS (0-based in parent coordinates)
269 // to GRID (1-based in local coordinates)
270 auto xy0 = getImageXY0FromMetadata(metadata, image::detail::wcsNameForXY0, strip);
271 std::vector<double> pixelToGridArray = {1.0 - xy0[0], 1.0 - xy0[1]}; // 1.0 for FITS vs LSST convention
272 auto pixelToGrid = ast::ShiftMap(pixelToGridArray);
273
274 // Now construct the returned FrameDict
275 auto const gridToIwc = rawFrameSet->getMapping(gridIndex, iwcIndex)->simplified();
276 auto const pixelToIwc = pixelToGrid.then(*gridToIwc).simplified();
277 auto const iwcToStdSky = rawFrameSet->getMapping(iwcIndex, stdSkyIndex);
278
279 auto frameDict = std::make_shared<ast::FrameDict>(ast::Frame(2, "Domain=PIXELS"), *pixelToIwc, *iwcFrame);
280 frameDict->addFrame("IWC", *iwcToStdSky, *stdSkyFrame);
281
282 // Record CRVAL as SkyRef in the SkyFrame so it can easily be obtained later;
283 // set SkyRefIs = "Ignored" (the default) so SkyRef value is ignored instead of used as an offset
284 auto crpixPixels = pixelToGrid.applyInverse(crpixGrid);
285 auto crvalRad = frameDict->applyForward(crpixPixels);
286 auto skyFrame = std::dynamic_pointer_cast<ast::SkyFrame>(frameDict->getFrame("SKY", false));
287 if (!skyFrame) {
288 throw LSST_EXCEPT(pex::exceptions::LogicError, "SKY frame is not a SkyFrame");
289 }
290 skyFrame->setSkyRefIs("Ignored");
291 skyFrame->setSkyRef(crvalRad);
292
293 return frameDict;
294}
Frame is used to represent a coordinate system.
Definition Frame.h:157
static int constexpr CURRENT
index of current frame
Definition FrameSet.h:105
static int constexpr 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
double getAsDouble(std::string const &name) const
Get the last value for any arithmetic property name (possibly hierarchical).
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
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) {
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();
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";
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
Reports invalid arguments.
Definition Runtime.h:66

◆ stripWcsMetadata()

void lsst::afw::geom::detail::stripWcsMetadata ( daf::base::PropertySet & metadata)

Strip all WCS metadata from a header.

Parameters
[in,out]metadataFITS header cards

Definition at line 134 of file frameSetUtils.cc.

134 {
135 // Exclude WCS A keywords because LSST uses them to store XY0
136 auto wcsANames = createTrivialWcsMetadata("A", lsst::geom::Point2I(0, 0))->names();
137 std::set<std::string> excludeNames(wcsANames.begin(), wcsANames.end());
138 // Ignore NAXIS1, NAXIS2 because if they are zero then AST will fail to read a WCS
139 // Ignore LTV1/2 because LSST adds it and this code should ignore it and not strip it
140 // Exclude comments and history to reduce clutter
141 std::set<std::string> moreNames{"NAXIS1", "NAXIS2", "LTV1", "LTV2", "COMMENT", "HISTORY"};
142 excludeNames.insert(moreNames.begin(), moreNames.end());
143
144 // Replace RADECSYS with RADESYS if only the former is present
145 if (metadata.exists("RADECSYS") && !metadata.exists("RADESYS")) {
146 metadata.set("RADESYS", metadata.getAsString("RADECSYS"));
147 metadata.remove("RADECSYS");
148 }
149
150 auto channel = getFitsChanFromPropertyList(metadata, excludeNames,
151 "Encoding=FITS-WCS, IWC=1, SipReplace=0, ReportLevel=3");
152 auto const initialNames = setFromVector(channel.getAllCardNames());
153
155 try {
156 obj = channel.read();
157 } catch (std::runtime_error const&) {
158 return;
159 }
160
161 auto const finalNames = setFromVector(channel.getAllCardNames());
162
163 // FITS keywords that FitsChan stripped
164 std::set<std::string> namesChannelStripped;
165 std::set_difference(initialNames.begin(), initialNames.end(), finalNames.begin(), finalNames.end(),
166 std::inserter(namesChannelStripped, namesChannelStripped.begin()));
167
168 // FITS keywords that FitsChan may strip that we want to keep in `metadata`
169 std::set<std::string> const namesToKeep = {"DATE-OBS", "MJD-OBS"};
170
171 std::set<std::string> namesToStrip; // names to strip from metadata
172 std::set_difference(namesChannelStripped.begin(), namesChannelStripped.end(), namesToKeep.begin(),
173 namesToKeep.end(), std::inserter(namesToStrip, namesToStrip.begin()));
174 for (auto const& name : namesToStrip) {
175 metadata.remove(name);
176 }
177}

◆ wrapFrameSetUtils()

void lsst::afw::geom::detail::wrapFrameSetUtils ( lsst::cpputils::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}
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.