Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

parameter-based GSObject classes #195

Closed
TallJimbo opened this Issue · 34 comments

4 participants

@TallJimbo
Collaborator

In the comments for #148, Barney suggested moving one aspect of a proposal I made there into a new issue, so here it is.

The idea is to change the GSObject class (and subclasses) from something that constructs its SBProfile immediately, and then holds it as an attribute, to something that holds all the parameters needed to define a particular SBProfile, and then constructs it (and possible caches it) when it is first requested.

I think there are two and a half motivations for this:

  • It makes it much easier for GSObjects to have user-accessible parameters (like radii and ellipticity); doing this in the current model is problematic because the SBProfile object may be an SBDistort or SBConvolve that does not have accessors.

  • It makes it possible to unify the definitions of the parameters of different kinds of objects in the GSObject hierarchy, so that we wouldn't have to duplicate that information when defining the config file schema, because it makes the GSObject classes more introspectable. That will require additional work on #148, but I think it makes sense to complete this issue first before pressing forward on that.

Another advantage is that I think it also hides the implementation details of SBProfile from the user a little. For instance, ellipticity will feel more natural as a part of a GSObject's definition; the fact that this is implemented by an SBDistort adapter around the original profile class becomes completely invisible. In fact, while I think I could make this change in a way that doesn't change the current GSObject API, I'd like to also remove the "public" .SBProfile attribute and replace it with something that starts with an underscore (in either case, this would become a property that is computed on-the-fly, of course, though it may be cached).

This touches a lot of code, but I think it'd be very straightforward to do, and even I could get it done pretty quickly. I'm going to start converting a few classes on the branch immediately to serve as examples for discussion.

@TallJimbo TallJimbo was assigned
@rmjarvis
Owner

I think reason 1 is obviated by the changes I made in #142. When it's a Distortion, python knows and gives a TypeError if someone tries to use the getters. I think this is exactly the functionality we want for this. (After all, what should getSigma return if you really have a sheared and/or dilated Gaussian?) In any case, you should probably start your branch from the current #142 branch (which will shortly be merged) since it included quite a few changes around this part of the code.

I'm not sure about your second reason. Probably because I don't really know what you have in mind for #148. I would have thought all the information you need is already in the definition of the constructor for each sub-type of GSObject.

I do agree that the SBProfile should be made "private". I don't think that should be part of the public interface.

@TallJimbo
Collaborator

Raising a descriptive TypeError is better than some other failure, but I still don't think it's nearly as nice as being able to return the value the user was asking for. And while there are many radii one can define for an elliptical object, people certainly do talk about the radii of elliptical things, and we just need to document what we're returning. And there are things like flux that aren't at all ambiguous are are very useful to be able to get from an object, even if you've transformed it some way.

On the second point, the information we need for the configuration interface is essentially:

  • what parameters define an object
  • what the data types are
  • what their defaults should be
  • whether None is an allowed value (i.e. whether the default can be computed)
  • which parameters are redundant and shouldn't be specified together
  • (optional) what range of values is allowed for each parameter

If we don't use *args and **kwds in our constructors, we could extract some of that from the __init__ method signature with the inspect module, but that's clunky, and it doesn't give us all the information. And I think we do want to use **kwds (as we have been doing).

Alternatively, if we can find a way to make the configs work by just using the constructor, then we don't need to extract that information - but that's not what we've done so far, and I don't think we'd be happy with the config interface we get if we go that route.

Anyhow, I will definitely start from the #142 branch. I'll also take another look to see if I can get #148 a little further so as to provide a little more motivation by example; there's a bit of a chicken-and-egg problem between the two issues.

@rmjarvis
Owner

And there are things like flux that aren't at all ambiguous are are very useful to be able to get from an object

getFlux is available for all GSObjects.

And I think we do want to use **kwds (as we have been doing).

The only one is Convolve. If that's the sticking point, it wouldn't be hard to switch that to explicit keywords in the init rather than parsing several options. The only reason I did it that way is for the syntactic sugar of allowing both Convolve([psf,gal]) and Convolve(psf,gal). We can easily remove that latter functionality, which would let us use a normal init definition.

@TallJimbo
Collaborator

Thanks for the clarification, and sorry I maligned the current state of the code!

@barnabytprowe

I think that some of the information that the inspect module doesn't give us, and which we want to be available to the config module at least, are the types of parameters - currently we have required, size and optional, all of which may vary in length. Parameter based GSObject classes would allow this information to be accessible to the config parser by introspection as Jim says, without needing the special functions of Mike's original config implementation, or the imperfect object_param_dict currently being used.

I would see this as the primary benefit of this work - allowing a GSObject to know exactly what it stores and thus what it needs to be constructed from heterogeneous user input.

As a secondary point, I do also think it would be nice to continue to return sizes and ellipticities from even distorted objects. Obviously, all bets are off once you get to Adds and Convolves, but if an object is merely sheared and/or dilated we can simply adopt a convention (I always think that r^2 -> a*b for semi major and minor axes a & b makes sense) and stick to it... The actual implementation would be fairly easy, and it would be undeniably nice...

@rmjarvis
Owner

(I always think that r^2 -> a*b for semi major and minor axes a & b makes sense)

And I prefer r^2 = (a^2 + b^2)/2.

Which gets immediately to the problem. If we have some kind of getSize() that everything implements in some way or another, users will assume it means something in particular, and many of them will assume wrong. I think we should let each class implement the things that actually do make sense for it and not try to shoehorn in things that are imprecise at best and sometimes even nonsensical.

@rmjarvis
Owner

On the first point, I'll take your and Jim's word for it that this will be useful. So I'm remaining agnostic until I see how this affects the implementation of the config stuff. I don't have any particular aversion to it. I just don't yet see how it will be helpful.

@barnabytprowe

Taking on this task in light of the discussion and design review telecon held for #148. Will update with changes ASAP, I fully expect to get this wrong the first one (or two) tries!

@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe hmmmm, code totally formative but think I have enough to ask Jim some…
… more directed questions. Think so. Will email to set up a chat.

(#195)
5b5e85e
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe made the SBProfile a property that re-inits itself as needed, passed …
…__doc__ to GSObject param descriptors

(#195)
ef7a880
@barnabytprowe

Hi all,

Have spent a bit of time working on this revision of the GSObject internals, and have put a trial implementation of only the Gaussian class into a new (temporary) file called galsim/sandbox.py.

Would really like to get some people's opinions on this (anyone welcome, but I'm picking out @rmjarvis , @joezuntz , @pmelchior , @rearmstr , @joergdietrich for special pinging!).

I found the stuff on Python descriptors very impenetrable at first, but Jim has been extremely helpful and today we had a breakthrough! Nonetheless, it's something of a big change so we would welcome your thoughts on this trial, 'sandbox' implementation.

Main points:

  1. We wanted to make the GSObject derived classes (e.g. Gaussian or Exponential) know what parameters they need to initialize themselves, so that user input in config files or catalogues can be parsed. Moving this info into the classes themselves is desirable so that there is no longer any need to keep a separate record (e.g. the object_param_dict in base.py, which is our old workaround).

  2. One way to do this is to make these parameters attributes of the Class, with values that get set when an instance is initialized. Then the config routines can cycle through these attributes and find which ones it needs from the user config files.

  3. However, we want these attributes to have some customized behaviour, and so Jim suggested we make them descriptor instances. A new Gaussian1 reimplementation of the Gaussian can be seen in sandbox.py. This also requires two descriptor classes SimpleParam and GetSetParam, and some minor mods to the way the GSObject stores its SBProfile.

So much for the motivation, and broad sweep of what's been tried here. Some of the new features of this implementation for the Gaussian1 :

a) The sigma, half_light_radius, fwhm and flux are all now attributes of a Gaussian1 instance. These keep themselves updated, for example...

In [6]: g = galsim.sandbox.Gaussian1(half_light_radius=1., flux=2.)

In [7]: g.sigma
Out[7]: 1.1774100225154747

In [8]: g.sigma=3

In [9]: g.half_light_radius
Out[9]: 2.547965400864057

(N.B. In the current example implementation I have removed the getSigma, setSigma etc. methods for clarity, but I will re-instate these for checking purposes if completing this revamp. These do the same calculations by different paths.)

b) Not only this, but the C++ SBProfile instance for which the GSObject classes are a glorified container is also updated for any change in the parameter attributes. This is achieved via the freedom to customize the way the descriptors behave: g.sigma = 3 above not only changes the underlying size for the Gaussian1, but it also sets the stored SBProfile to None. When this SBProfile is eventually needed, it is re-initialized using the most up-to-date set of attributes.

This is not completed by a long way, and there are some things that will need to be streamlined/added for handling the whole set of GSObjects: many of them have things in common like being defined by a radial profile, and so a shared intermediate base class would avoid much duplication. We would also probably exampled the descriptors SimpleParam, GetSetParam to store more info of use to users and the config routines, and move these to a separate file descriptors.py.

However, the basic pattern is outlined here.

Questions:

Does this scheme seem comprehensible? (It took me a while to grasp it)

If it seems a little more complex, do we think this is worth it to be able to have all the GSObjects store all the information needed to build themselves in one place?

Is this going to be an overly high bar to future expansion by possible third parties?

My personal feeling is that it is worth it, but smoothing it all out will be a bit of work. Yet, I would love it if the GSObject classes and class instances carried around all the info they need...

@rmjarvis
Owner

This is a little bit unwieldy, especially since many classes are going to have almost identical code for their set of multiple size types (that takes up most of the code in Gaussian1), so it would be nice if there was an intermediate class that did all this work for the types that had multiple sizes. Or maybe a function that can set this up automatically? For example, I think it would be possible in python to have the Gaussian1 class look something like the following:

class Gaussian1(GSObject):
    half_light_radius = SimpleParam(
        "half_light_radius", default=None,
        doc="Half light radius, kept consistent with the other size attributes.")

    flux = SimpleParam("flux", default=1., doc="flux of this object")

    def _SBInitialize(self):
        GSObject.__init__(self, galsim.SBGaussian(half_light_radius=self.half_light_radius,
                                                  flux=self.flux))

    def __init__(self, half_light_radius=None, sigma=None, fwhm=None, flux=1.):
        checkSizes(half_light_radius, sigma, fwhm)
        self.flux = flux
        self._SBInitialize()

AddAlternateSize(Gaussian1, 'fwhm', 2.)  # fwhm = 2 * half_light_radius
AddAlternateSize(Gaussian1, 'sigma', 1.1774100225154747)   # sigma = sqrt[2ln(2)] * half_light_radius

Then checkSizes would do the checks that exactly one size is set. And AddAlternateSize would add the setters and getters, etc. to the class specified for the extra size name. This would make the upkeep requirements simpler (the code to do all this stuff only exists once), and it lowers the bar for adding new profile classes.

The only other comment I have is that we might not want flux to be a SimpleParam. We don't need to recreate the SBProfile if the user changes the flux. We can just setFlux on the one that is already there, which wraps the existing profile with a flux scaling. Most of the SBProfiles have fairly trivial constructors, so it's probably not too inefficient to recreate them most of the time. But a few of them aren't. (For example, SBMoffat currently calculates its fourier transform on construction. We might want to move this to an Info class like Sersic and Airy do, but that's not how it works right now.) I'm not sure whether the additional complication of making the flux work like this is worth it. For now you should probably leave it as a SimpleParam and have the update to something more sophisticated be a future issue.

@rmandelb
Owner

Just to be clear, that formalism you have above works for all the simple parametric profiles. We'll have to do something different for AtmosphericPSF, OpticalPSF, RealGalaxy, Add, Convolve. I know that we discussed these briefly (or at least, we discussed the ones that contain an SBInterpolatedImage, maybe not Add or Convolve). Can you give a summary here for how those would work, in case it's useful for everyone in deciding how they like the new proposed structure for our base classes?

@TallJimbo
Collaborator

Mike has brought up some issues on the #220 that suggest we should hold off on making descriptors for some of the geometric parameters of objects. We'll need to come up with some other way of declaring all the possible geometric transforms and their parameters, in a way that also allows us to specify the order of operations.

We may want to start by looking at all our potential parameters, and categorizing them all as "apply only" (e.g. shears), "get/set only" (e.g. Sersic index), or "apply + get/set" (e.g. flux). And see if there's anything that doesn't fit into one of those categories.

@rmandelb
Owner

I wonder if there is value to another discussion now that we have an explicit code example to talk about? (Jim, I realize you won't be available next week.) There's been a lot of GitHub activity that might be more easily addressed by talking.

@TallJimbo
Collaborator

A discussion might be valuable for a discussion to evaluate the complexity/maintainability of what Barney has started with (and I wouldn't need to be there for that, I think).

But I think we need to come up with some example code for how to handle the apply-based parameters in configs before it's worthwhile to discuss those live.

@barnabytprowe

Hi all,

Apologies for the radio silence, got home yesterday from Pittsburgh and the internet at home is not functioning. So I'll be quick, and I'll work offline on expanding the examples taking into account the suggestions you've made (e.g. doing some other classes as per Rachel, giving the flux a special status since it doesn't necessitate rebuilding the whole SBProfile as per Mike).

However, the purpose here, since only on Thursday did I actually get this working at all, was to illustrate the new approach on our simplest class and generate informed discussion: this seems to have worked.

A quick direct response:

This is a little bit unwieldy, especially since many classes are going to have almost identical code for their set of multiple size types (that takes up most of the code in Gaussian1), so it would be nice if there was an intermediate class that did all this work for the types that had multiple sizes.

This is not completed by a long way, and there are some things that will need to be streamlined/added for handling the whole set of GSObjects: many of them have things in common like being defined by a radial profile, and so a shared intermediate base class would avoid much duplication.

I think I prefer the intermediate base class to the function idea, as it would perhaps help us to group the classes into their more conceptually distinct types... But I'll try both. At any rate, there will be some cases (e.g. HLR for a truncated Moffat) where a simple multiplication-by-a-constant is not sufficient, so there will need to be some mechanism to allow each GSObject to define a function if it's not super simple.

Finally, I also think I like the suggestion on #220 to make shears "apply/get". We can shear all objects, so the config machinery really doesn't need to know that it has to set these shear parameters: it can assume that it is asked to shear things then it can. That's my 2p anyhow, I'll either be back in touch tomorrow (if our internet is fixed/I go into Caltech) or on Monday with an update. After that, we can think about another chat on the phone...

@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe added dox 671a031
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe acknowledged fact that OpticalPSF and AtmosphericPSF are RadialProfil…
…e objects by my own definition, also added un-setness testing for size params in _parse_sizes

(#195)
24ffb95
@barnabytprowe

Hi all,

Sorry this took rather longer than I wanted, but I think the results are quite encouraging.

  1. I have made a new file on this branch called descriptors.py which contains the descriptors (funnily enough).

  2. GetSetParam has now been renamed GetSetFuncParam and a new GetSetScaleParam descriptor has been added to the descriptors.py module to allow quick definition of attributes via another and a scaling factor, as per Mike's suggestion.

  3. I've added a group attribute to each descriptor to allow later config machinery to help work out what params are required and which are optional, which currently groups things in a similar way to the current config object_param_dict. This is up for debate, of course!

  4. I've made an intermediate base class RadialProfile in sandbox.py which defines the two parameters all such classes have in common (flux and half light radius) in its scope. It also defines a _parse_sizes() method which takes a bunch of input sizes and ensures one, but only one, are set. This function will be available to all RadialProfiles, helping to avoid repetitive klunkiness.

  5. To illustrate how this paradigm works for another RadialProfile, I implemented Sersic in sandbox.py too.

  6. To illustrate how this paradigm works for a non-RadialProfile, I've implemented the RealGalaxy class too, also in sandbox.py. This is reasonable so far, but not yet perfect. Actually, some of the params I've described as optional are a bit like the size params in the RadialProfile: at least one but not more of a number of optional params needs to be set. This is not fully reflected, so I'd like to tinker with that to get it right. But you can see the idea overall.

  7. I've tried to give pretty good, beefed up docstrings and documentation.

  8. Flux now has its own Param descriptor, which does the right thing and calls setFlux.

  9. Finally, as all of our objects can have Shear, Magnification etc. applied to them, since these are done via the GSObject methods, any config plan we come up with will not need more information about what to expect regarding these on a class-by-class basis as for the other params. I think that for these 'apply' qualities a system for simply recording transformations that have been applied will be enough. And I think that this does not necessarily need to be done via the descriptor formalism we're using for the 'get/set' params. At any rate, the config stuff does not depend on it, so I would propose to postpone this part of the issue until we have reached consensus about (and I've rolled out) changes to the get/set GSObject params.

Thoughts, comments much encouraged and welcomed! Also, if people think a phone call would be useful, let me know and I'll organize a time.

@rmandelb
Owner

Sorry if I'm being clueless, but the dox for RadialProfile say that AtmosphericPSF and OpticalPSF are RadialProfiles, and I hadn't expected that since they contains SBInterpolatedImages rather than a parametric SBProfile. I guess nominally they do fit the description (i.e., they are defined by some size parameter and a bunch of additional parameters, though the Kolmogorov that goes into AtmosphericPSF doesn't have a half_light_radius that I know of)...

I'm still trying to grok some of this, but I see how what you've done can address some of our complaints, e.g., the need to maintain a separate object_param_dict vs. using descriptors right in the class definition. I found descriptors.py to be tough going, but the class definitions in sandbox.py seemed clear enough given those examples that I can see how the rest of them would go, how to add new keywords to existing classes...

@barnabytprowe

Hmmm you are totally right about there not being half light radii defined for the AtmosphericPSF and OpticalPSF. I changed the dox lae last night to include them, goes to show I should try to work when my brain is more switched on! However, they do otherwise fit the description, so I think we have a choice:
1. Strike them both from the RadialProfile roster.
2. Remove the half_light_radius from the RadialProfile and let each derived class add it or not depending on whether they have it.

I think 1. might be cleaner, so will do that for now, but have no strong feelings.

I'm still trying to grok some of this, but I see how what you've done can address some of our complaints, e.g., the need to maintain a separate object_param_dict vs. using descriptors right in the class definition. I found descriptors.py to be tough going, but the class definitions in sandbox.py seemed clear enough given those examples that I can see how the rest of them would go, how to add new keywords to existing classes...

Yes, I think it's not perhaps yet quite perfect but it does solve the object_param_dict problem without introducing too many more. It's actually quite fun playing with the attributes in interactive mode python, watching them update each other and the SBProfile too. There this really works intuitively, and instead of a = object.getSigma() and object.setSigma(b) we have the rather nice a = object.sigma and object.sigma = b, together with the full updating of other params and an update to the SBProfile only when it's needed.

I agree descriptors.py is a lot harder to parse, but I hope that we will soon be able to reach a point where only the truly dedicated (or interested) developers need to delve into that module...

@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe fixed tab d3103c1
@rmandelb
Owner
@barnabytprowe

Would welcome any comments from the usual suspects (e.g. @TallJimbo , @rmjarvis ) + others before pressing ahead. Otherwise, I'll move forward any transfer all the GSObjects first thing next week.

@rmjarvis
Owner

My suggestion is to do Moffat next, since it doesn't have a simple scaling relation between its sizes. So you might need to think about how that should work in this context.

AtmosphericPSF will also require some thought, since its half-light-radius is NotImplemented. So that might need to work differently as well, even though it is naturally a RadialProfile. (Unlike OpticalPSF or RealGalaxy which aren't radial.)

@barnabytprowe

Just wanted to respond on that: great suggestion Mike, am working on it. I spent some good time on that this afternoon and there was indeed a little experimentation needed to get the Moffat working. It ended up taking more time than I'd hoped but I've ended up relatively happy with the results. The thing that makes it all possible is the fact you can just define a half light radius parameter in the Moffat class scope and it simply overrides the definition inherited from the RadialProfile base class.

I'll push it all tomorrow, along with the AtmosphericPSF (thinking about that too, currently left it as not implemented) once I've added docs!

@barnabytprowe

OK, sorry for the delay, an implementation of the Moffat and the AtmosphericPSF are now pushed, in sandbox.py.

The Moffat required a little thought: I think the solution I came up with (storing a little switch specifying whether the last size set was a half light radius) is reasonably efficient in most cases, but not 100% all...

The AtmosphericPSF was easier, I think

@rmandelb
Owner
@barnabytprowe

Glad it's not too daunting. It is, all round, a step up in complexity from what we had before. But the Moffat was a somewhat tricky case among the RadialProfile objects, I think.

The small inefficiency that remains is in the use case where people are switching between radius definitions (fwhm/scale_radius to half_light_radius and back) without using other functions of the SBProfile. Currently I use the SBProfile-internal functions to provide the calculations in some (not all) cases, specifically those cases where the user wants the HLR for a scale_radius or fwhm-initialized object, and vice versa. The initialization of the SBProfile requires setting up the FT of the profile at the C++ layer. It's not a big overhead, but it's an unnecessary one if the user is not then planning to use any of the other SBProfile methods that require the FT. Probably a corner case, but I wanted to flag it.

I think your plan sounds good. Rolling out the rest will not now be a long process, and I'd like to have it done before the weekend if people agree - I fly back to London on Monday!

@rmjarvis
Owner

If this corner case is a concern, it would not be hard at all to make the Moffat class only compute the FT if and when it needs it. It's maybe three lines of code to change. If you want I can just go ahead do make the change on this branch and lay the concern to rest.

@barnabytprowe
@rmandelb
Owner
@rmjarvis
Owner

I don't have a good sense of what you actually think about this change overall?

So far I'm still going on faith that these changes will facilitate a more user-friendly config system than what we currently have. I guess we'll see how that turns out. I'll have a better opinion on the matter when I can see a new version of the MultiObjectDemo script 2 that uses all this stuff.

The other reason for these changes was to make things more maintainable. I'm not terribly convinced about that point, especially considering how complex some of the required machinery has turned out to be. But what matters more to me is the syntax for the config files that the end user will use. If that ends up being more user friendly than the current system, then I'll be in favor. If not, I might push back against it.

@rmandelb
Owner
@barnabytprowe
@rmjarvis
Owner

As you wish Mike! That would be neat, but I certainly don't think it's urgent. I won't be making many changes to the *.cpp while I roll out the other GSObjects, so please hack away if you have a chance!

Let me know when the branch is passing tests, and I'll add my changes then. It seems to be currently in an unfinished state, so I don't really want to go mucking around it in just yet.

@barnabytprowe
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe added Airy e96563b
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe updated base.py Gaussian, and added SBProfile innards with RadialProf…
…ile (needed for testing the DoubleGaussian in sandbox.py)

(#195)
e96b5e5
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe added pixel 31f5970
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe migrated new GSObjects from sandbox, updated comments a little, updat…
…ed object_param_dict for futile good measure

(#195)
a359b4c
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe fixed new bug 3417227
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe fixed bug 01ea2db
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe noticed that getMu and mu property are inconsistent and misleading wh…
…en the init call is expecting dilation. Will open issue to raise this...

(#195)
7614478
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe fixed update_on_set=False bug for Add, Convolve and DoubleGaussian fl…
…ux params, also updated use of flux parameter in GSObject / and * operators

(#195)
f59e8c4
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe improved descriptors and GSObjects so that all transformations (shear…
…, dilation, shift, rotation) are recorded, and that following such a transformation all parameters except flux become unavailable to get/set

(#195)
d46ea5d
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe reinstated AttributeError raising tests post transformation in test_S…
…BProfile.py (although have removed post-flux raising test as this is now fine)

(#195)
aa25146
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe realised appropriate to make some RealGalaxy aux data available for a…
…ccess/reset even after transformation, so set ok_if_transformed=True in descriptor constructor

(#195)
b615ae4
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe updated all setFlux calls to also now update the change in the class …
…of the SBProfile attribute. This would naturally raise an AttributeError now, but to provide a slightly less opaque error return in the case of Mike's corner case have defined some new AttributeErrors for the moffat>

(#195)
3dd442e
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe updated base.py to remove atmoic SBInitialize calls in __init__, but …
…this is causing tests to fail... Want to see why

(#195)
9526991
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe fixed error where _data store was held in the class, and so multiple …
…objects overwrote each other. Now initialized in each instance using the _setup_data_store() method inherited from GSObject

(#195)
49a5604
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe made hard_edge not a parameter of the Convovle, and fixed some missin…
…g group= that I noticed and really should not have got wrong... :S

(#195)
343f6cf
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe moved initialization of self._SBProfile = None and self.transformatio…
…ns to within _setup_data_store where they can be done as instance variables. Also corrected an error in copy which needs to catch extra such variables in special cases too.

(#195)
9f872f0
@barnabytprowe barnabytprowe referenced this issue from a commit
@barnabytprowe barnabytprowe made Add and Convolve initialize the GSObject as None, and test this …
…in _get_sbprofile raising an informative Exception.

(#195)
152b502
@barnabytprowe

This is now being closed in light of other config work on #234, #148 and #241.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.