From: Michael S. <m-s...@us...> - 2005-09-09 09:22:52
|
[sorry, I forgot to send this to the list, here it comes:] On 09.09.05, Joerg Lehmann wrote: > Hi Michael! > > On 09.09.05, Michael Schindler wrote: > > I have hit a problem concerning the geometry things of the normpaths. > > Consider a Bezier curve that contains a point with infinite curvature. > > This is very easy to produce by setting e.g. the last two points to > > the same coordinates > > > > n = normcurve_pt(0,0, 1,1, 1,0, 1,0) > > > > The curveradius_pt returns "None" for parameter value 1. But the > > trafo/rotation does something quite unexpected. The tangent vector > > > > n.rotation([0.999999])[0].apply_pt(1, 0) > > > > seems to converge against (-1, 0) while adding more "9"s to the > > parameter. However, the tangent at the parameter value 1 is (1, 0). > > > > My question now is, how well do we want to really reproduce the true > > underlying geometry? We should return "None" for the rotation at such > > points also. > > I think, we should return the correct rotation instead of None. That is my problem. If you have infinite curvature, there is no geometrically defined rotation. Because the curvature is the change of the normal vector along the curve length, projected onto the tangent vector (or equally the other way round), you see that both vectors change infinitely fast. Thus, they do not exist in this point. > Geometrically, everything is well-defined, it's only that we commit some > numerical error because the length of (dx/dt, dy/dt) goes to zero. But > we should be able to treat this case better. What do you think of? We could look at the neighborhood and return a value that is expected to be the limiting rotation when we pass to the critial point. Michael. -- "A mathematician is a device for turning coffee into theorems" Paul Erdös. |
From: Andre W. <wo...@us...> - 2005-09-09 12:54:16
|
Hi, On 09.09.05, Michael Schindler wrote: > > Geometrically, everything is well-defined, it's only that we commit some > > numerical error because the length of (dx/dt, dy/dt) goes to zero. But > > we should be able to treat this case better. > > What do you think of? We could look at the neighborhood and return a > value that is expected to be the limiting rotation when we pass to > the critial point. But there are cases, where we really have an unsteady behaviour. At least for that cases, we should stop and raise a proper exception. I'm not sure whether it makes sense to distinguish between the two cases. It might not be worth the effort ... I'm not sure. Beside that, when raising an exception, it might be wise to introduce a special exception class here to enable the caller to handle this issue. André -- by _ _ _ Dr. André Wobst / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: Michael S. <m-s...@us...> - 2005-09-09 13:04:30
|
On 09.09.05, Andre Wobst wrote: > Hi, > > On 09.09.05, Michael Schindler wrote: > > > Geometrically, everything is well-defined, it's only that we commit some > > > numerical error because the length of (dx/dt, dy/dt) goes to zero. But > > > we should be able to treat this case better. > > > > What do you think of? We could look at the neighborhood and return a > > value that is expected to be the limiting rotation when we pass to > > the critial point. > > But there are cases, where we really have an unsteady behaviour. At > least for that cases, we should stop and raise a proper exception. I'm > not sure whether it makes sense to distinguish between the two cases. > It might not be worth the effort ... I'm not sure. Beside that, when > raising an exception, it might be wise to introduce a special > exception class here to enable the caller to handle this issue. This is a question to the Python coding masters: Is an exception the right thing to use here? I tend to dislike the try...except notation and am not quite sure how efficient this is. On the other had, with the different return types "float" or "None" one always has to ask for the proper return type. Michael. -- "A mathematician is a device for turning coffee into theorems" Paul Erdös. |
From: Andre W. <wo...@us...> - 2005-09-09 13:21:19
|
Hi, On 09.09.05, Michael Schindler wrote: > Is an exception the right thing to use here? I tend to dislike the > try...except notation and am not quite sure how efficient this is. > On the other had, with the different return types "float" or "None" > one always has to ask for the proper return type. Right. And in that sense such an specific exception is fine. And AFAIK (at least as long as exceptions do not occur very often), it is fine to use them. The overhead of the try-block is small (again AFAIK). Beside that one should keep in mind, that exceptions should better not be used to do flow control in a program. I.e. they should not be used as a regular feature when nothing special happens. But to properly work around certain instablilities, which are inherent, an exception seems to be the Right Thing (tm). André -- by _ _ _ Dr. André Wobst / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: Joerg L. <jo...@us...> - 2005-09-09 13:50:50
|
Hi! On 09.09.05, Andre Wobst wrote: > On 09.09.05, Michael Schindler wrote: > > Is an exception the right thing to use here? I tend to dislike the > > try...except notation and am not quite sure how efficient this is. > > On the other had, with the different return types "float" or "None" > > one always has to ask for the proper return type. > > Right. And in that sense such an specific exception is fine. And AFAIK > (at least as long as exceptions do not occur very often), it is fine > to use them. The overhead of the try-block is small (again AFAIK). Python's exception handling is very efficient. Furthermore, it's good practice to use exceptions instead of returning arbitrary marker values like None in cases where a result cannot be obtained due to some "exceptional" (ahem) condition - at least, as a rule of thumb, there are always exceptions, of course ;-) > Beside that one should keep in mind, that exceptions should better not > be used to do flow control in a program. I.e. they should not be used > as a regular feature when nothing special happens. [snip] Hey, there are even use cases for things like this, but I agree that this should not be done without real reason. Jörg |
From: Michael S. <m-s...@us...> - 2005-09-12 18:07:48
|
Hello, On 09.09.05, Joerg Lehmann wrote: > On 09.09.05, Andre Wobst wrote: > > On 09.09.05, Michael Schindler wrote: > > > Is an exception the right thing to use here? I tend to dislike the > > > try...except notation and am not quite sure how efficient this is. > > > On the other had, with the different return types "float" or "None" > > > one always has to ask for the proper return type. > > > > Right. And in that sense such an specific exception is fine. And AFAIK > > (at least as long as exceptions do not occur very often), it is fine > > to use them. The overhead of the try-block is small (again AFAIK). > > Python's exception handling is very efficient. Furthermore, it's good > practice to use exceptions instead of returning arbitrary marker values > like None in cases where a result cannot be obtained due to some > "exceptional" (ahem) condition - at least, as a rule of thumb, there are > always exceptions, of course ;-) There is something else that judges against raising an exception, in favour of the "arbitrary marker value": We calculate curvatures and rotations ... always for a list of parameter values. If one of them makes problems, you will never find out which one of them it was and you cannot do anything against it. The outcome would be that the user (or the module that uses this feature) has to ask for one parameter value after the other in a try...except block. Michael. -- "A mathematician is a device for turning coffee into theorems" Paul Erdös. |
From: Joerg L. <jo...@us...> - 2005-09-12 18:18:05
|
Hi Michael! On 12.09.05, Michael Schindler wrote: > There is something else that judges against raising an exception, in > favour of the "arbitrary marker value": We calculate curvatures and > rotations ... always for a list of parameter values. If one of them > makes problems, you will never find out which one of them it was and > you cannot do anything against it. The outcome would be that the user > (or the module that uses this feature) has to ask for one > parameter value after the other in a try...except block. I would say so. We could put this information in the exception instance and probably should do that anyway. Jörg |
From: Joerg L. <jo...@us...> - 2005-09-12 18:29:37
|
On 12.09.05, Joerg Lehmann wrote: > On 12.09.05, Michael Schindler wrote: > > There is something else that judges against raising an exception, in > > favour of the "arbitrary marker value": We calculate curvatures and > > rotations ... always for a list of parameter values. If one of them > > makes problems, you will never find out which one of them it was and > > you cannot do anything against it. The outcome would be that the user > > (or the module that uses this feature) has to ask for one > > parameter value after the other in a try...except block. > > I would say so. We could put this information in the exception instance > and probably should do that anyway. s/say/not say/ Jörg |
From: Andre W. <wo...@us...> - 2005-09-14 07:24:45
|
Hi, On 12.09.05, Joerg Lehmann wrote: > On 12.09.05, Joerg Lehmann wrote: > > On 12.09.05, Michael Schindler wrote: > > > There is something else that judges against raising an exception, in > > > favour of the "arbitrary marker value": We calculate curvatures and > > > rotations ... always for a list of parameter values. If one of them > > > makes problems, you will never find out which one of them it was and > > > you cannot do anything against it. The outcome would be that the user > > > (or the module that uses this feature) has to ask for one > > > parameter value after the other in a try...except block. > > > > I would say so. We could put this information in the exception instance > > and probably should do that anyway. > > s/say/not say/ Ok. I think we're in trouble here. An exception doesn't provide us with a proper recovery strategy. (It's a well known limitation of an exception system.) There are several ways out. - We could raise an execption and mark it with further information. Still, since we processed an list of values, the whole system is complicated and inappropriate. We can raise only an single exception and should provide all information we collected. In some sence, the exception is a return value containing some results, which we were able to get and some error information. It's a no win situation compared to using a marker in the result. - We could return a marker. This marker could be clever in that sence, that it raises an exception as soon as it is accessed. (However you could do a "x is _marker" check without an excpetion.) It would be kind of a late evaluation exception raising similar to what we did with the _invalidcurrentpoint in earlier versions of the path system (cf. http://cvs.sourceforge.net/viewcvs.py/pyx/pyx/pyx/path.py?rev=1.228&view=markup) - The third solution could be a callback function in case we step into an error. In other languages (list, smalltalk) a (more advanced) condition system is used in general in favour of excepts, but the question is, whether it's that easy to recover from an error by some callback/fallback/whatever. I think the second option is by far the most easiest one for our use-case of invalid curvatures/transformations etc. We could make it a general feature of the marker instance we're planing in favor of the existing helper.nodefault to raise an exception on access. That's by the way something such a marker is for ... André -- by _ _ _ Dr. André Wobst / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: Joerg L. <jo...@us...> - 2005-09-14 08:04:21
|
Hi, On 14.09.05, Andre Wobst wrote: > On 12.09.05, Joerg Lehmann wrote: > > On 12.09.05, Joerg Lehmann wrote: > > > On 12.09.05, Michael Schindler wrote: > > > > There is something else that judges against raising an exception, in > > > > favour of the "arbitrary marker value": We calculate curvatures and > > > > rotations ... always for a list of parameter values. If one of them > > > > makes problems, you will never find out which one of them it was and > > > > you cannot do anything against it. The outcome would be that the user > > > > (or the module that uses this feature) has to ask for one > > > > parameter value after the other in a try...except block. > > > > > > I would say so. We could put this information in the exception instance > > > and probably should do that anyway. > > > > s/say/not say/ > > Ok. I think we're in trouble here. An exception doesn't provide us > with a proper recovery strategy. (It's a well known limitation of an > exception system.) There are several ways out. > > - We could raise an execption and mark it with further information. > Still, since we processed an list of values, the whole system is > complicated and inappropriate. We can raise only an single exception > and should provide all information we collected. In some sence, the > exception is a return value containing some results, which we were > able to get and some error information. It's a no win situation > compared to using a marker in the result. In the framework of our present implementation it would be easy to put the parameter value leading to the problem in the exception. This has the drawback that when the caller has passed a list, he doesn't know the index in the list, which is suboptimal. On the other hand, we could capture the exception in the method decorator. There we still know the list index, which we could use to generate a new exception containing this information. Then the caller would get all the information he needs. > - We could return a marker. This marker could be clever in that sence, > that it raises an exception as soon as it is accessed. (However you > could do a "x is _marker" check without an excpetion.) It would be > kind of a late evaluation exception raising similar to what we did > with the _invalidcurrentpoint in earlier versions of the path system > (cf. > http://cvs.sourceforge.net/viewcvs.py/pyx/pyx/pyx/path.py?rev=1.228&view=markup) > I don't like this idea too much. The main thing which bothers me, that we somehow mask an error, which actually has occured. In this sense, this is totally different from the _invalidcurrentpoint example. There is one argument in favour of it, namely the existence of NaN in many floating point implementations. This would set a precedence for a similar solution in PyX. > - The third solution could be a callback function in case we step into > an error. In other languages (list, smalltalk) a (more advanced) > condition system is used in general in favour of excepts, but the > question is, whether it's that easy to recover from an error by some > callback/fallback/whatever. This gets a definite -1 from me, as it strikes me as being totally unpythonic. > I think the second option is by far the most easiest one for our > use-case of invalid curvatures/transformations etc. We could make it a > general feature of the marker instance we're planing in favor of the > existing helper.nodefault to raise an exception on access. That's by > the way something such a marker is for ... No. Internally, we should no how to deal with our markers. There is really no need to protect us from ourselves. All in all, I would still favour the first option, as long as there are not more arguments against it. Alternatively, you can try to convince me of the merits of the second solution :-) Jörg |
From: Michael S. <m-s...@us...> - 2005-09-14 08:40:08
|
Hello, On 14.09.05, Joerg Lehmann wrote: > On 14.09.05, Andre Wobst wrote: > > On 12.09.05, Joerg Lehmann wrote: > > > > On 12.09.05, Michael Schindler wrote: > > > > > There is something else that judges against raising an exception, in > > > > > favour of the "arbitrary marker value": We calculate curvatures and > > > > > rotations ... always for a list of parameter values. If one of them > > > > > makes problems, you will never find out which one of them it was and > > > > > you cannot do anything against it. The outcome would be that the user > > > > > (or the module that uses this feature) has to ask for one > > > > > parameter value after the other in a try...except block. > > Ok. I think we're in trouble here. An exception doesn't provide us > > with a proper recovery strategy. (It's a well known limitation of an > > exception system.) There are several ways out. > > > > - We could raise an execption and mark it with further information. > > Still, since we processed an list of values, the whole system is > > complicated and inappropriate. We can raise only an single exception > > and should provide all information we collected. In some sence, the > > exception is a return value containing some results, which we were > > able to get and some error information. It's a no win situation > > compared to using a marker in the result. > > In the framework of our present implementation it would be easy to put > the parameter value leading to the problem in the exception. This has > the drawback that when the caller has passed a list, he doesn't know the > index in the list, which is suboptimal. On the other hand, we could > capture the exception in the method decorator. There we still know the > list index, which we could use to generate a new exception containing > this information. Then the caller would get all the information he > needs. I do not really understand this suggestion. When doing parallel deformation, I have infinite curvatures (which is equivalent to a parameter "velocity" of zero) quite regularly. This is nothing the user should be bothered with, because the parallel deformer will know how to deal with it. My question is: How will this look in the code, when implementing that exception which tells me that there were errors processing a list? try: curvatures = np.curvature_pt(somelist) except GeometricError: list_of_invalid_curvatures = ??? How do I access the return string/value of that GeometricException here? > > - We could return a marker. This marker could be clever in that sence, > > that it raises an exception as soon as it is accessed. (However you > > could do a "x is _marker" check without an excpetion.) It would be > > kind of a late evaluation exception raising similar to what we did > > with the _invalidcurrentpoint in earlier versions of the path system > > (cf. > > http://cvs.sourceforge.net/viewcvs.py/pyx/pyx/pyx/path.py?rev=1.228&view=markup) > > > I don't like this idea too much. The main thing which bothers me, that > we somehow mask an error, which actually has occured. In this sense, > this is totally different from the _invalidcurrentpoint example. There > is one argument in favour of it, namely the existence of NaN in many > floating point implementations. This would set a precedence for a > similar solution in PyX. I prefer this option -- not so much for the curvatures, because they are simply numbers (and we could use +"inf" or -"inf" which are easily produced by saying float("inf") -- this is much better than Nan, because we can divide by it). When thinking of invalid transformations, this gets really reasonable. Why not introduce a trafo.invalid class in the trafo module? This could be returned without any problems, and it raises an error, as André suggests. The next thing is that there was this invalid scaling in a recent PyX-user thread: trafo.scale(0, 0) looks like a perfect candidate for trafo.invalid. The only question here is -- as always -- the question of thresholds. Meybe there is a possibility to check this at least for normpaths, when writing them. > > - The third solution could be a callback function in case we step into > > an error. In other languages (list, smalltalk) a (more advanced) > > condition system is used in general in favour of excepts, but the > > question is, whether it's that easy to recover from an error by some > > callback/fallback/whatever. > > This gets a definite -1 from me, as it strikes me as being totally > unpythonic. This sounds very complicated, again. Michael. -- "A mathematician is a device for turning coffee into theorems" Paul Erdös. |
From: Joerg L. <jo...@us...> - 2005-09-14 09:21:11
|
Hello, On 14.09.05, Michael Schindler wrote: > On 14.09.05, Joerg Lehmann wrote: > > On 14.09.05, Andre Wobst wrote: > > > On 12.09.05, Joerg Lehmann wrote: > > > > > On 12.09.05, Michael Schindler wrote: > > > > > > There is something else that judges against raising an exception, in > > > > > > favour of the "arbitrary marker value": We calculate curvatures and > > > > > > rotations ... always for a list of parameter values. If one of them > > > > > > makes problems, you will never find out which one of them it was and > > > > > > you cannot do anything against it. The outcome would be that the user > > > > > > (or the module that uses this feature) has to ask for one > > > > > > parameter value after the other in a try...except block. > > > > Ok. I think we're in trouble here. An exception doesn't provide us > > > with a proper recovery strategy. (It's a well known limitation of an > > > exception system.) There are several ways out. > > > > > > - We could raise an execption and mark it with further information. > > > Still, since we processed an list of values, the whole system is > > > complicated and inappropriate. We can raise only an single exception > > > and should provide all information we collected. In some sence, the > > > exception is a return value containing some results, which we were > > > able to get and some error information. It's a no win situation > > > compared to using a marker in the result. > > > > In the framework of our present implementation it would be easy to put > > the parameter value leading to the problem in the exception. This has > > the drawback that when the caller has passed a list, he doesn't know the > > index in the list, which is suboptimal. On the other hand, we could > > capture the exception in the method decorator. There we still know the > > list index, which we could use to generate a new exception containing > > this information. Then the caller would get all the information he > > needs. > > I do not really understand this suggestion. > When doing parallel deformation, I have infinite curvatures (which is > equivalent to a parameter "velocity" of zero) quite regularly. This is > nothing the user should be bothered with, because the parallel > deformer will know how to deal with it. My question is: How will this > look in the code, when implementing that exception which tells me that > there were errors processing a list? You would access it like this try: curvatures = np.curvature_pt(somelist) except GeometricError, e: list_of_invalid_curvatures = e.invalid_indices Or alternatively, we could generate a new list exception containing the separate exceptions: try: curvatures = np.curvature_pt(somelist) except PathExceptionList, ies: for index, e in ies: # index is the index of the exception # e is the corresponding PathException > > > - We could return a marker. This marker could be clever in that sence, > > > that it raises an exception as soon as it is accessed. (However you > > > could do a "x is _marker" check without an excpetion.) It would be > > > kind of a late evaluation exception raising similar to what we did > > > with the _invalidcurrentpoint in earlier versions of the path system > > > (cf. > > > http://cvs.sourceforge.net/viewcvs.py/pyx/pyx/pyx/path.py?rev=1.228&view=markup) > > > > > > I don't like this idea too much. The main thing which bothers me, that > > we somehow mask an error, which actually has occured. In this sense, > > this is totally different from the _invalidcurrentpoint example. There > > is one argument in favour of it, namely the existence of NaN in many > > floating point implementations. This would set a precedence for a > > similar solution in PyX. > > I prefer this option -- not so much for the curvatures, because they > are simply numbers (and we could use +"inf" or -"inf" which are easily > produced by saying float("inf") That's impossible since it is only existent on certain platforms. Python doesn't guarantee the existence of NaN, inf, etc. See the standard quoute on this topic by Tim Peters: http://mail.python.org/pipermail/python-dev/2004-February/042421.html Note that this shows that in this case, even the Python documentation/standard doesn't define whether to return something like a marker (NaN) or to raise an exception (ValueError). Note also, that the OP in the referenced thread expected Python to raise an exception when math.sqrt(-1) is being called - an expectation which Tim Peters didn't explicitely object to. Note finally that this means that the present PyX code may already raise exceptions on other platforms when it doesn't do so on Linux. > -- this is much better than Nan, > because we can divide by it). Btw, I just picked NaN because this is the thing which is most resembling the marker thing. Inf would be less since from a mathematical point of view, you could think of a compactified version of the real numbers (in which -Inf doesn't fit, though), so Inf would be just a number. > When thinking of invalid transformations, this gets really reasonable. > Why not introduce a > trafo.invalid > class in the trafo module? Hmm. And what would you return for the curvatures? > This could be returned without any > problems, and it raises an error, as André suggests. Would trafo.scale(0, 0).inverse() return trafo.invalid? > The next thing is that there was this invalid scaling in a recent > PyX-user thread: trafo.scale(0, 0) looks like a perfect candidate for > trafo.invalid. André would argument against this, I suppose. And me as well, for the reason given by yourself: > The only question here is -- as always -- the question > of thresholds. Meybe there is a possibility to check this at least for > normpaths, when writing them. Coming back to the original question, you probably have in mind the simplicity of the deformer implementation. If I understand you correctly, you say that an exception-based system makes the code more involved. This is certainly a point to take into account. Initially, I mainly objected to using None as a marker. Against some more specialized marker, I would only mildly object, though. And certainly, your deformer code represents a rather comprehensive use case for the path system. So, we could introduce something like trafo.invalid but we would also need a marker for the infinite curvature case. Alternatively, we could just live with a single notdefined marker. Jörg |
From: Andre W. <wo...@us...> - 2005-09-14 10:16:09
|
Hi, On 14.09.05, Joerg Lehmann wrote: > You would access it like this > > try: > curvatures = np.curvature_pt(somelist) > except GeometricError, e: > list_of_invalid_curvatures = e.invalid_indices > > Or alternatively, we could generate a new list exception containing > the separate exceptions: > > try: > curvatures = np.curvature_pt(somelist) > except PathExceptionList, ies: > for index, e in ies: > # index is the index of the exception > # e is the corresponding PathException Ah ... you want to return a full set of invalid indices. That's at least better in terms of redoing calculations (especially when the fallback does something completely different, which might be likely in certain use-cases). I was thinking to return a single index for the first problematic point only ... > http://mail.python.org/pipermail/python-dev/2004-February/042421.html I've seen the different behaviour of sqrt of negative values myself already (switching between Mac and Linux). You just have to get used to it. > Btw, I just picked NaN because this is the thing which is most > resembling the marker thing. Inf would be less since from a mathematical > point of view, you could think of a compactified version of the real > numbers (in which -Inf doesn't fit, though), so Inf would be just a > number. > > > When thinking of invalid transformations, this gets really reasonable. > > Why not introduce a > > trafo.invalid > > class in the trafo module? > > Hmm. And what would you return for the curvatures? I think we should have a generic invalid marker. > > This could be returned without any > > problems, and it raises an error, as André suggests. > > Would trafo.scale(0, 0).inverse() return trafo.invalid? Hmmm. Maybe. Yes, I think so. I think its best to return invalid here too. Just fetch a ArithmeticError and that's it. Still, a plattform might not raise the ArithmeticError (ZeroDivisionError). Than we can't do much in this case ... > > The next thing is that there was this invalid scaling in a recent > > PyX-user thread: trafo.scale(0, 0) looks like a perfect candidate for > > trafo.invalid. > > André would argument against this, I suppose. And me as well, for the > reason given by yourself: Right. I'm against it. There are trafos which can't be inverted. But they are perfect affine trafos. > > The only question here is -- as always -- the question > > of thresholds. Meybe there is a possibility to check this at least for > > normpaths, when writing them. > > Coming back to the original question, you probably have in mind the > simplicity of the deformer implementation. If I understand you > correctly, you say that an exception-based system makes the code more > involved. This is certainly a point to take into account. Right. We do want to handle the invalid case at the point we're accessing it. We should not have the burden to always have to prehandle that case. That's why an exception is not very useful. > Initially, I > mainly objected to using None as a marker. Against some more specialized > marker, I would only mildly object, though. And certainly, your deformer > code represents a rather comprehensive use case for the path system. > > So, we could introduce something like trafo.invalid but we would also > need a marker for the infinite curvature case. Alternatively, we could > just live with a single notdefined marker. I'm at least +0 for a generic notdefined marker. Which -- for the sake of easy to use -- should raise exceptions on access like the old invalidcurrentpoint did. It's just handy. And I would also like to have a André -- by _ _ _ Dr. André Wobst / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: Andre W. <wo...@us...> - 2005-09-14 10:37:29
|
On 14.09.05, Andre Wobst wrote: > > So, we could introduce something like trafo.invalid but we would also > > need a marker for the infinite curvature case. Alternatively, we could > > just live with a single notdefined marker. > > I'm at least +0 for a generic notdefined marker. Which -- for the sake > of easy to use -- should raise exceptions on access like the old > invalidcurrentpoint did. It's just handy. And I would also like to > have a Sorry. I wanted to say, that I still think, that we could use this notdefined in keyword arguments as well. The point is, that we should never use this marker but only check by "... is notdefined". Then we're back at the naming issue. For the use case in this thread "notdefined" seems appropriate. For the keyword arg "_marker" is more common. We might just create two instances for that. Fine. The last question I would than ask, whether we want it underscored or not (in the helper module). I would not underscore it, although this is would be different from "_marker". BTW did we reach a final decision whether to have a single _marker in helper or whether we should create such a class/instance/whatever in every module. I would like to have a single instance ... André -- by _ _ _ Dr. André Wobst / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: Joerg L. <jo...@us...> - 2005-09-14 10:57:28
|
Hi André, [ sorry, forgot to CC the list, here we go ] On 14.09.05, Andre Wobst wrote: > On 14.09.05, Andre Wobst wrote: > > > So, we could introduce something like trafo.invalid but we would also > > > need a marker for the infinite curvature case. Alternatively, we could > > > just live with a single notdefined marker. > > > > I'm at least +0 for a generic notdefined marker. Which -- for the sake > > of easy to use -- should raise exceptions on access like the old > > invalidcurrentpoint did. It's just handy. And I would also like to > > have a > > Sorry. I wanted to say, that I still think, that we could use this > notdefined in keyword arguments as well. The point is, that we should > never use this marker but only check by "... is notdefined". What means notdefined in the context of keyword arguments. Sounds strange. > Then > we're back at the naming issue. For the use case in this thread > "notdefined" seems appropriate. For the keyword arg "_marker" is more > common. We might just create two instances for that. Fine. The last > question I would than ask, whether we want it underscored or not (in > the helper module). I would not underscore it, although this is would > be different from "_marker". BTW did we reach a final decision whether > to have a single _marker in helper or whether we should create such a > class/instance/whatever in every module. I would like to have a single > instance ... Why? What's the advantage of from helper import _marker as opposed to class _marker: pass Not speaking of having to import an underscored name from a module. A not-underscored version is out, because it would indicate that this is an external interface, which it explicitely should not be. In other words, no caller should be allowed to pass it as argument, simply because he was never allowed to access it. So, I see only one way (and that's anyway the standard way): we use one _marker per module. Jörg |
From: Andre W. <wo...@us...> - 2005-09-14 11:36:59
|
Hi, On 14.09.05, Joerg Lehmann wrote: > So, I see only one way (and that's anyway the standard way): we > use one _marker per module. Ok, the arguments are overwhelming ... ;-) André -- by _ _ _ Dr. André Wobst / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: Michael S. <m-s...@us...> - 2005-09-14 12:42:06
|
Hello Jörg, On 14.09.05, Joerg Lehmann wrote: > On 14.09.05, Andre Wobst wrote: > > On 14.09.05, Andre Wobst wrote: > > > > So, we could introduce something like trafo.invalid but we would also > > > > need a marker for the infinite curvature case. Alternatively, we could > > > > just live with a single notdefined marker. > > > > > > I'm at least +0 for a generic notdefined marker. Which -- for the sake > > > of easy to use -- should raise exceptions on access like the old > > > invalidcurrentpoint did. It's just handy. And I would also like to > > > have a > > > > Sorry. I wanted to say, that I still think, that we could use this > > notdefined in keyword arguments as well. The point is, that we should > > never use this marker but only check by "... is notdefined". > > What means notdefined in the context of keyword arguments. Sounds > strange. > > > Then > > we're back at the naming issue. For the use case in this thread > > "notdefined" seems appropriate. For the keyword arg "_marker" is more > > common. We might just create two instances for that. Fine. The last > > question I would than ask, whether we want it underscored or not (in > > the helper module). I would not underscore it, although this is would > > be different from "_marker". BTW did we reach a final decision whether > > to have a single _marker in helper or whether we should create such a > > class/instance/whatever in every module. I would like to have a single > > instance ... > > Why? What's the advantage of > > from helper import _marker > > as opposed to > > class _marker: pass > > Not speaking of having to import an underscored name from a module. > > A not-underscored version is out, because it would indicate that this is > an external interface, which it explicitely should not be. In other > words, no caller should be allowed to pass it as argument, simply > because he was never allowed to access it. > > So, I see only one way (and that's anyway the standard way): we > use one _marker per module. This means I have to compare with the _marker from the corresponding module: normpath._marker in this case: [code in deformer.py] curvatures = anormpath.curvature_pt(alist) for curvature in curvatures: if curvature is normpath._marker: do fallback else: do real things I cannot see the difference to saying helper._marker here. Michael. -- "A mathematician is a device for turning coffee into theorems" Paul Erdös. |
From: Joerg L. <jo...@us...> - 2005-09-14 12:49:16
|
Hello Michael, On 14.09.05, Michael Schindler wrote: > On 14.09.05, Joerg Lehmann wrote: > > On 14.09.05, Andre Wobst wrote: > > > On 14.09.05, Andre Wobst wrote: > > > > > So, we could introduce something like trafo.invalid but we would also > > > > > need a marker for the infinite curvature case. Alternatively, we could > > > > > just live with a single notdefined marker. > > > > > > > > I'm at least +0 for a generic notdefined marker. Which -- for the sake > > > > of easy to use -- should raise exceptions on access like the old > > > > invalidcurrentpoint did. It's just handy. And I would also like to > > > > have a > > > > > > Sorry. I wanted to say, that I still think, that we could use this > > > notdefined in keyword arguments as well. The point is, that we should > > > never use this marker but only check by "... is notdefined". > > > > What means notdefined in the context of keyword arguments. Sounds > > strange. > > > > > Then > > > we're back at the naming issue. For the use case in this thread > > > "notdefined" seems appropriate. For the keyword arg "_marker" is more > > > common. We might just create two instances for that. Fine. The last > > > question I would than ask, whether we want it underscored or not (in > > > the helper module). I would not underscore it, although this is would > > > be different from "_marker". BTW did we reach a final decision whether > > > to have a single _marker in helper or whether we should create such a > > > class/instance/whatever in every module. I would like to have a single > > > instance ... > > > > Why? What's the advantage of > > > > from helper import _marker > > > > as opposed to > > > > class _marker: pass > > > > Not speaking of having to import an underscored name from a module. > > > > A not-underscored version is out, because it would indicate that this is > > an external interface, which it explicitely should not be. In other > > words, no caller should be allowed to pass it as argument, simply > > because he was never allowed to access it. > > > > So, I see only one way (and that's anyway the standard way): we > > use one _marker per module. > > This means I have to compare with the _marker from the corresponding > module: normpath._marker in this case: No, sorry, you misunderstood that. _marker is only used for determining whether someone passed a keyword argument or not. That's completely unrelated to the discussion on the undefined results. There, of course, we have to export the undefined instance. But again, it should not be contained in the helper module, but in the corresponding module (i.e. normpath) itself. Btw, as you said yourself, <module>._marker would be bad anyway. But we already convinced André, so no need to discuss this again. Jörg |
From: Andre W. <wo...@us...> - 2005-09-14 13:13:10
|
Hi, On 14.09.05, Joerg Lehmann wrote: > > This means I have to compare with the _marker from the corresponding > > module: normpath._marker in this case: > > No, sorry, you misunderstood that. _marker is only used for determining > whether someone passed a keyword argument or not. That's completely > unrelated to the discussion on the undefined results. There, of course, > we have to export the undefined instance. But again, it should not be > contained in the helper module, but in the corresponding module (i.e. > normpath) itself. > > Btw, as you said yourself, <module>._marker would be bad anyway. Right, those markers should be local only. I was trying to use a single _marker all over the place for some other reason, which I'm now convinced was a bad idea after the latest discussion on that list. > But we > already convinced André, so no need to discuss this again. *smile* I bag you pardon for mixing up the different issues. Orgininally I thought it would be worth to thing about, but it's rejected. To summarize it again: We should have local _markers and an global helper._invalid. The later should (for the moment) be used as return value in result lists of various normpath methods, which are able to handle a handle/process/evaluate a list of points to mark errors. There's no need for an trafo.invalid, since a trafo is either valid or it raises an exception ... André -- by _ _ _ Dr. André Wobst / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: Michael S. <m-s...@us...> - 2005-09-14 11:12:34
|
On 14.09.05, Andre Wobst wrote: > Hi, > > On 14.09.05, Joerg Lehmann wrote: > > You would access it like this > > > > try: > > curvatures = np.curvature_pt(somelist) > > except GeometricError, e: > > list_of_invalid_curvatures = e.invalid_indices > > > > Or alternatively, we could generate a new list exception containing > > the separate exceptions: > > > > try: > > curvatures = np.curvature_pt(somelist) > > except PathExceptionList, ies: > > for index, e in ies: > > # index is the index of the exception > > # e is the corresponding PathException > > Ah ... you want to return a full set of invalid indices. That's at > least better in terms of redoing calculations (especially when the > fallback does something completely different, which might be likely in > certain use-cases). I was thinking to return a single index for the > first problematic point only ... > > > http://mail.python.org/pipermail/python-dev/2004-February/042421.html > > I've seen the different behaviour of sqrt of negative values myself > already (switching between Mac and Linux). You just have to get used > to it. > > > Btw, I just picked NaN because this is the thing which is most > > resembling the marker thing. Inf would be less since from a mathematical > > point of view, you could think of a compactified version of the real > > numbers (in which -Inf doesn't fit, though), so Inf would be just a > > number. > > > > > When thinking of invalid transformations, this gets really reasonable. > > > Why not introduce a > > > trafo.invalid > > > class in the trafo module? > > > > Hmm. And what would you return for the curvatures? > > I think we should have a generic invalid marker. > > > > This could be returned without any > > > problems, and it raises an error, as André suggests. > > > > Would trafo.scale(0, 0).inverse() return trafo.invalid? > > Hmmm. Maybe. Yes, I think so. I think its best to return invalid here > too. Just fetch a ArithmeticError and that's it. Still, a plattform > might not raise the ArithmeticError (ZeroDivisionError). Than we can't > do much in this case ... > > > > The next thing is that there was this invalid scaling in a recent > > > PyX-user thread: trafo.scale(0, 0) looks like a perfect candidate for > > > trafo.invalid. > > > > André would argument against this, I suppose. And me as well, for the > > reason given by yourself: > > Right. I'm against it. There are trafos which can't be inverted. But > they are perfect affine trafos. This is right, but inverting a trafo is still an open problem. In trafo.py at the moment an exception is raised: raise UndefinedResultError, "transformation matrix must not be singular" The comment "# shouldn't be zero, but" indicated that something is not completely finished here. > > > The only question here is -- as always -- the question > > > of thresholds. Meybe there is a possibility to check this at least for > > > normpaths, when writing them. > > Coming back to the original question, you probably have in mind the > > simplicity of the deformer implementation. If I understand you > > correctly, you say that an exception-based system makes the code more > > involved. This is certainly a point to take into account. Yes. > Right. We do want to handle the invalid case at the point we're > accessing it. We should not have the burden to always have to > prehandle that case. That's why an exception is not very useful. Yes. > > Initially, I > > mainly objected to using None as a marker. Against some more specialized > > marker, I would only mildly object, though. And certainly, your deformer > > code represents a rather comprehensive use case for the path system. > > > > So, we could introduce something like trafo.invalid but we would also > > need a marker for the infinite curvature case. Alternatively, we could > > just live with a single notdefined marker. +0.5 for both: trafo.invalid (as a more specialized marker) and _marker (or notdefined or helper.notdefined ...) for the curvature/radius case. > I'm at least +0 for a generic notdefined marker. Which -- for the sake > of easy to use -- should raise exceptions on access like the old > invalidcurrentpoint did. It's just handy. And I would also like to > have a > > Sorry. I wanted to say, that I still think, that we could use this > notdefined in keyword arguments as well. The point is, that we should > never use this marker but only check by "... is notdefined". Then > we're back at the naming issue. For the use case in this thread > "notdefined" seems appropriate. For the keyword arg "_marker" is more > common. We might just create two instances for that. Fine. The last > question I would than ask, whether we want it underscored or not (in > the helper module). I would not underscore it, although this is would > be different from "_marker". BTW did we reach a final decision whether > to have a single _marker in helper or whether we should create such a > class/instance/whatever in every module. I would like to have a single > instance ... An underscore would rather prevent users from using it. They should not. Michael. -- "A mathematician is a device for turning coffee into theorems" Paul Erdös. |
From: Andre W. <wo...@us...> - 2005-09-14 09:03:09
|
Hi, On 14.09.05, Joerg Lehmann wrote: > > - We could raise an execption and mark it with further information. > > Still, since we processed an list of values, the whole system is > > complicated and inappropriate. We can raise only an single exception > > and should provide all information we collected. In some sence, the > > exception is a return value containing some results, which we were > > able to get and some error information. It's a no win situation > > compared to using a marker in the result. > > In the framework of our present implementation it would be easy to put > the parameter value leading to the problem in the exception. This has > the drawback that when the caller has passed a list, he doesn't know the > index in the list, which is suboptimal. On the other hand, we could > capture the exception in the method decorator. There we still know the > list index, which we could use to generate a new exception containing > this information. Then the caller would get all the information he > needs. Right, but that's not the point. Whenever we pass parts of the list to normsubpathitems etc., we just also need to catch the exception and correct the list index where the error occur. This would be a clean and easy solution. There are just to small issues here: The first is, that the we throw away solutions we just calculated. This is highly contra-productive, since we wanted the lists to be used to improve the performance. The second is, that it would be difficult for the caller to use. Whenever a problem occurs it must resolve the (local) issue before doing the (global) calculation. I expect that it'll be most easy to for the caller to use a single item list all the time. For that case we do not even need the index, but we would get it in the exception. The index will always be 0. Ok, let's analyse the use-cases. We'll step into the problem for the curveradius, the rotation, the trafo and the tangent (and the curvature, once we'll introduce it) only. Usually the exception might not be catched at all, so it doesn't really matter. The only interesting point is, when we want to recover from such an situation. Any case outside of the parallel deformer, where we expect that to happen? Maybe we should just live with it. I'm not sure. > > - We could return a marker. This marker could be clever in that sence, > > that it raises an exception as soon as it is accessed. (However you > > could do a "x is _marker" check without an excpetion.) It would be > > kind of a late evaluation exception raising similar to what we did > > with the _invalidcurrentpoint in earlier versions of the path system > > (cf. > > http://cvs.sourceforge.net/viewcvs.py/pyx/pyx/pyx/path.py?rev=1.228&view=markup) > > > > I don't like this idea too much. The main thing which bothers me, that > we somehow mask an error, which actually has occured. In this sense, > this is totally different from the _invalidcurrentpoint example. There > is one argument in favour of it, namely the existence of NaN in many > floating point implementations. This would set a precedence for a > similar solution in PyX. I didn't even thought about this point, but this more or less supports the idea instead of being against it. So why not? > > - The third solution could be a callback function in case we step into > > an error. In other languages (list, smalltalk) a (more advanced) > > condition system is used in general in favour of excepts, but the > > question is, whether it's that easy to recover from an error by some > > callback/fallback/whatever. > > This gets a definite -1 from me, as it strikes me as being totally > unpythonic. Sure. It was not under serious consideration by me either. > > I think the second option is by far the most easiest one for our > > use-case of invalid curvatures/transformations etc. We could make it a > > general feature of the marker instance we're planing in favor of the > > existing helper.nodefault to raise an exception on access. That's by > > the way something such a marker is for ... > > No. Internally, we should no how to deal with our markers. There is > really no need to protect us from ourselves. Question is, whether _marker and _invalid is the same. > All in all, I would still favour the first option, as long as there are > not more arguments against it. Alternatively, you can try to convince me > of the merits of the second solution :-) My major concern is, that for cases where we want to recover from such an situation, the exception solution will lead to a typical useage scenario with a single item list. That would at least be strange. And that's also what Michael started the discussion with ... André -- by _ _ _ Dr. André Wobst / \ \ / ) wo...@us..., http://www.wobsta.de/ / _ \ \/\/ / PyX - High quality PostScript and PDF figures (_/ \_)_/\_/ with Python & TeX: visit http://pyx.sourceforge.net/ |
From: Joerg L. <jo...@us...> - 2005-09-14 09:29:17
|
Hi André, parallelism... On 14.09.05, Andre Wobst wrote: > Hi, > > On 14.09.05, Joerg Lehmann wrote: > > > - We could raise an execption and mark it with further information. > > > Still, since we processed an list of values, the whole system is > > > complicated and inappropriate. We can raise only an single exception > > > and should provide all information we collected. In some sence, the > > > exception is a return value containing some results, which we were > > > able to get and some error information. It's a no win situation > > > compared to using a marker in the result. > > > > In the framework of our present implementation it would be easy to put > > the parameter value leading to the problem in the exception. This has > > the drawback that when the caller has passed a list, he doesn't know the > > index in the list, which is suboptimal. On the other hand, we could > > capture the exception in the method decorator. There we still know the > > list index, which we could use to generate a new exception containing > > this information. Then the caller would get all the information he > > needs. > > Right, but that's not the point. Whenever we pass parts of the list to > normsubpathitems etc., we just also need to catch the exception and > correct the list index where the error occur. This would be a clean > and easy solution. > > There are just to small issues here: The first is, that the we throw > away solutions we just calculated. This is highly contra-productive, > since we wanted the lists to be used to improve the performance. The > second is, that it would be difficult for the caller to use. Whenever > a problem occurs it must resolve the (local) issue before doing the > (global) calculation. Yep, that's a point against this. > I expect that it'll be most easy to for the caller to use a single > item list all the time. For that case we do not even need the index, > but we would get it in the exception. The index will always be 0. Yep. > Ok, let's analyse the use-cases. We'll step into the problem for the > curveradius, the rotation, the trafo and the tangent (and the > curvature, once we'll introduce it) only. Usually the exception might > not be catched at all, so it doesn't really matter. The only > interesting point is, when we want to recover from such an situation. > Any case outside of the parallel deformer, where we expect that to > happen? Maybe we should just live with it. I'm not sure. As I wrote in my previous mail, the defomer is a very comprehensive use case, which we should take into account. > > > - We could return a marker. This marker could be clever in that sence, > > > that it raises an exception as soon as it is accessed. (However you > > > could do a "x is _marker" check without an excpetion.) It would be > > > kind of a late evaluation exception raising similar to what we did > > > with the _invalidcurrentpoint in earlier versions of the path system > > > (cf. > > > http://cvs.sourceforge.net/viewcvs.py/pyx/pyx/pyx/path.py?rev=1.228&view=markup) > > > > > > > I don't like this idea too much. The main thing which bothers me, that > > we somehow mask an error, which actually has occured. In this sense, > > this is totally different from the _invalidcurrentpoint example. There > > is one argument in favour of it, namely the existence of NaN in many > > floating point implementations. This would set a precedence for a > > similar solution in PyX. > > I didn't even thought about this point, but this more or less supports > the idea instead of being against it. So why not? Yes, it supports the marker idea (hey, I tried to find arguments for all options). > > > I think the second option is by far the most easiest one for our > > > use-case of invalid curvatures/transformations etc. We could make it a > > > general feature of the marker instance we're planing in favor of the > > > existing helper.nodefault to raise an exception on access. That's by > > > the way something such a marker is for ... > > > > No. Internally, we should no how to deal with our markers. There is > > really no need to protect us from ourselves. > > Question is, whether _marker and _invalid is the same. See my other mail. This has to be discussed. > > All in all, I would still favour the first option, as long as there are > > not more arguments against it. Alternatively, you can try to convince me > > of the merits of the second solution :-) > > My major concern is, that for cases where we want to recover from such > an situation, the exception solution will lead to a typical useage > scenario with a single item list. That would at least be strange. And > that's also what Michael started the discussion with ... Yep, Michael put forward some good arguments, so I would accept the second option with marker != None. Jörg |