Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-9792: Mapping::getInverse not exception-safe #3

Merged
merged 4 commits into from Mar 16, 2017
Merged

Conversation

r-owen
Copy link
Contributor

@r-owen r-owen commented Mar 15, 2017

No description provided.

If the call to `assertOK` in Mapping.getInverse threw an exception
then the AST object `rawCopy` would never be deallocated.
Copy link
Member

@kfindeisen kfindeisen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some comments/corrections to the documentation, otherwise looks good.

doc/mainpage.dox Outdated
@@ -45,7 +45,7 @@ that support time, spectra and tables have yet been wrapped. The python wrapping
- After calling AST code the wrapper checks AST's error state and if invalid,
the wrapper resets the AST status code and throws `std::runtime_error`.
At present the exception contain an error number, rather than useful text,
and useful text is printed to stderr. I hope to fix that at some point.
and useful text is printed to stderr. Work in in progress to fix this.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Work is in progress

- Methods that output floating point data have `AST__BAD` replaced with `nan`.

### Smaller differences (not a complete list):

- Methods such as @ref Object.set do not support printf formatting and extra arguments.
- Methods such as @ref Object.set and the attributes argument of constructors do not support
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general we don't need @ref anymore, only for all-lowercase unqualified names.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know. But cleaning up all the usage in this package would be quite a chore. I'm inclined to leave it as explicit.

Get @ref Mapping_TranForward "TranForward": is the forward transform defined?
Is the forward transform available?

Note: this gets the @ref Mapping_TranForward "TranForward" attribute,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer the @note tag to plain text. Same for hasTranInverse.

Copy link
Contributor Author

@r-owen r-owen Mar 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. I'll change it though I personally dislike the resulting HTML formatting produced by Doxygen.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we could ask @jonathansick to make it less prominent in the breathe output. I think the styling is still TBD.

Note that the inverse mapping contains exactly the same model coefficients as the original,
but they are used by @tranInverse instead of @tranForward. Thus for example if a @ref ZoomMap
has a zoom factor of 4.0 then its inverse also reports a zoom factor of 4.0 (despite behaving
like an uninverted @ref ZoomMap with zoom factor of 0.24).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good grief. This is definitely unintuitive, 👍 for documenting it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the final coefficient be 0.25?

Copy link
Contributor Author

@r-owen r-owen Mar 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our existing XYTransform works almost the same way, but inversion is handled by a class that contains another transform, which is arguably a simpler model. In both cases the model coefficients are left unchanged. That is easier than trying to work out new model coefficients, especially for complex mappings such as PolyMap that may not even have an analytic inverse.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @kfindeisen is saying that 0.24 should be 0.25.

And yes, there's nothing to gain from the shim layer trying to recalculate the coefficients itself when AST is already doing that internally.

@@ -134,7 +136,7 @@ friend class Object;
return std::static_pointer_cast<PolyMap>(_copyPolymorphic());
}

/// Get @ref PolyMap_IterInverse "IterInverse": provide an iterative inverse transformation?
/// Get @ref PolyMap_IterInverse "IterInverse": does this provide an iterative inverse transformation?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I prefer the style you adopted for Mapping::hasTranForward, i.e., make the brief description plain English and mention the equivalent property in the detailed description.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume these getters can't be noexcept because getB might throw over a completely unrelated error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have used the style above for all getters and setters throughout astshim with a few well-motivated minor exceptions. Changing it would be a bigger job than I want to tackle right now.

Correct that they cannot be noexcept.

@@ -289,7 +291,7 @@ friend class Object;
ncoeff_i, coeff_i.getData(), options.c_str());
}

/// Make a raw AstPolyMap with only a forward transform.
/// Make a raw AstPolyMap with a specified forward transform and a numeric approximation inverse.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The grammar seems a bit weird. Maybe "a numerically approximated inverse"?

xn = 1.2 * xi * xi - 0.5 * yi * xi
yn = yi
self.assertAlmostEqual(xn, xo)
self.assertAlmostEqual(yn, yo)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is kind of hard to read. Maybe if you renamed pin and pout (I think they're data, not coefficients, right)? Maybe also xn -> xExpect?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was bothering me, too. I cleaned it up quite a bit and simplified it by using numpy.test.assert_allclose.

[-0.5, 1, 1, 1],
[1.0, 2, 0, 1],
])
pm = astshim.PolyMap(coeff_f, 2, "IterInverse=0")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume the stringly typed code is an AST-ism. Are there any plans to replace this with some kind of preferences object (e.g., a map)?

Copy link
Member

@timj timj Mar 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean the IterInverse=0 string? That's part of the AST API but it can also accept printf-style formatting. AST won't care if astshim builds the options internally (the Perl and pyast interfaces both support alternate ways of specifying the key/value options). Sometimes the string is clearer though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not like specifying values as an option string, but as @timj says, it is part of the AST API and not a part I felt could reasonably be hidden by astshim.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does astshim support the printf-options?

Copy link
Contributor Author

@r-owen r-owen Mar 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. C++ string formatting is simple enough without it and Python string formatting is nearly trivial. Is there a use case I am missing for printf style formatting? It's not type safe and I would much rather avoid it if possible.

self.assertTrue(pminv.isInverted())

pout2 = pminv.tranInverse(pin)
# pout and pout2 should be numerically identical because inverting
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"numerically identical" -> "exactly equal"?

- Explain Mapping.getInverse in detail.
- Provide links to useful attributes in PolyMap's
  constructor that only specifies the forward transform.
- Tweak mainpage.dox.
- Test a PolyMap with no inverse transform (this test turned
  up a bug in AST which is fixed in AST 8.5.0).
- Test the default iterative inverse.
- Test setting attributes at construction.
and similarly for getTranInverse
@r-owen r-owen merged commit a38aba5 into master Mar 16, 2017
@ktlim ktlim deleted the tickets/DM-9792 branch August 25, 2018 04:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants