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

Enable unit support on all functional models #6183

Merged
merged 15 commits into from
Jun 14, 2017

Conversation

astrofrog
Copy link
Member

@astrofrog astrofrog commented Jun 12, 2017

The goal of this PR is to add tests for all functional models with units and fix any issues that come up. This is now ready for review. The only thing is that the absorption gaussian can't be made unit-aware because of the 1 - term - there is no way to attach a unit to 1 (I personally find this model strange since really one should do Const1D - Gaussian1D). Maybe we should replace 1 by a model parameter, but I suggest deferring that to a separate PR (I'm trying to keep my modeling PRs from getting out of control...)

@astrofrog astrofrog added this to the v2.0.0 milestone Jun 12, 2017
@pllim pllim added Affects-dev PRs and issues that do not impact an existing Astropy release modeling Work in progress units labels Jun 12, 2017
@taldcroft taldcroft requested a review from nden June 12, 2017 14:20
@bsipocz
Copy link
Member

bsipocz commented Jun 13, 2017

@astrofrog - I have manually cancelled the last travis, sadly the skipping is not working as expected in PRs, but I'm on it.

@pllim
Copy link
Member

pllim commented Jun 13, 2017

@nden asked if you plan to address non-functional models, like projections, mapping, etc.

@astrofrog astrofrog force-pushed the enable-units-all-models branch 4 times, most recently from edeffbc to df8ef51 Compare June 13, 2017 17:32
@astrofrog
Copy link
Member Author

astrofrog commented Jun 13, 2017

@pllim - I think projections are currently tested already thanks to @Cadair, but haven't looked into mappings yet. I do plan to take a look at this though, but not in this PR.

@astrofrog astrofrog changed the title WIP: Enable unit support on all functional models Enable unit support on all functional models Jun 13, 2017
@astrofrog astrofrog requested a review from pllim June 13, 2017 17:38
@astrofrog
Copy link
Member Author

@nden @pllim - can you review this when you get a chance? Thanks!

Copy link
Member

@pllim pllim left a comment

Choose a reason for hiding this comment

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

I do have plans to fully test this functionality over at my synphot work but that won't happen before v2.0 release.

CHANGES.rst Outdated
model evaluation and fitting, added support for units on Gaussian1D
and added a new Blackbody1D model. [#4855]
model evaluation and fitting, added support for units on most
functional models and added a new Blackbody1D model. [#4855, #6183]
Copy link
Member

Choose a reason for hiding this comment

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

BlackBody1D (both B's are capitalized in the code).

@@ -1475,22 +1475,17 @@ def prepare_inputs(self, *inputs, **kwargs):
for i in range(len(inputs)):

input_name = self.inputs[i]
input_unit = self.input_units.get(input_name, None)
Copy link
Member

Choose a reason for hiding this comment

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

This change assumes self.input_units is now always a dictionary. The deleted code allowed for None type and a dictionary. Is this intentional?

Copy link
Contributor

Choose a reason for hiding this comment

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

At this point it's always a dict. The check for None is done earlier.


return amplitude * np.sin(2 * np.pi * frequency * x + 2 * np.pi * phase)
argument = TWOPI * (frequency * x + phase)
if isinstance(argument, Quantity):
Copy link
Member

Choose a reason for hiding this comment

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

If it is not Quantity and you want to attach radian unit to it, I get it. But here, you are multiplying radian unit to it but only if it is a Quantity, which I do not get. What are you trying to do here?

Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder about this too. The code works but I'm not sure I understand why it's done this way.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah yes - I admit it's a little confusing - the reason for this is because if frequency and x are quantities, argument will end up being dimensionless because TWOPI doesn't have a unit (even though it should be radians). But then np.sin(dimensionless) crashes.

Another option would be to do argument = argument.value which would work too. I might do that instead since that will work too, and will put a comment.

except ImportError:
HAS_SCIPY = False

# TODO: GaussianAbsorption1D doesn't work with units because the 1- part doesn't
Copy link
Member

Choose a reason for hiding this comment

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

Good question. GaussianAbsorption1D as it is now is only useful as a multiplicative factor to a continuum to create an absorption line. Otherwise, you can create absorption line without it by using continuum_model - Gaussian1D. (This model might had been written a long time ago before the math operators worked properly?) I wonder if GaussianAbsorption1D is used by anyone at all. Maybe deprecate it for future removal? That way, we can just say "this model is deprecated and does not support units".

Related reading: http://synphot.readthedocs.io/en/latest/synphot/spectrum.html#gaussian-absorption

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe we could first ask if anyone is using it on astropy-dev - another option is to make the continuum level a parameter.

Copy link
Member Author

Choose a reason for hiding this comment

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

I opened an issue to discuss this: #6195

z = np.exp(-x.value**2 - y.value**2) * model['evaluation'][0][2].unit
args = [x, y, z]
fitter = LevMarLSQFitter()
m_new = fitter(m, *args)
Copy link
Member

Choose a reason for hiding this comment

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

This simply tests that fitter does not crash but does not test whether the fitted values are actually correct (both values and units).

Copy link
Member Author

Choose a reason for hiding this comment

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

That is correct - I should at least make sure that the resulting models have units - however I think checking the fitted parameter values is beyond the scopes of these tests

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I've now expanded that to make sure the resulting model has units and that they are compatible with the starting units.



@pytest.mark.parametrize('model', MODELS)
def test_models_bounding_box(model):
Copy link
Member

Choose a reason for hiding this comment

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

Why is there a need to test this as part of this PR? Bounding box seems unrelated here. If your goal is to test whether bounding box has the correct unit, that does not seem to be tested.

Copy link
Member Author

Choose a reason for hiding this comment

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

Because for some models, bounding_box crashed if units were present, so I had to fix those and wanted a regression test. I agree we could check the actual values, but the purpose here is first and foremost to check that it does anything at all.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've updated this to now check for the actual accuracy of the bounding box values too

@nden
Copy link
Contributor

nden commented Jun 13, 2017

@astrofrog This looks good to me.
I got one error in GWCS due to a rotation model initialized with a SkyCoord object.
If no one is working on rotations I can try to add units there.

@astrofrog
Copy link
Member Author

@nden - if you'd like to work on rotations that would be great! Just ping me if you run into any issues.

@astrofrog
Copy link
Member Author

@nden @pllim - thanks for the reviews! I think I've addressed all your concerns/comments. If the CI passes, i think this is good to go, but I'll let one of you merge if you are happy with it (let's wait for Travis etc to run first though).

@astrofrog
Copy link
Member Author

astrofrog commented Jun 14, 2017

@nden - just for info I plan to look into power laws and polynomials (in a separate PR), but I'll leave rotations for you to take a look at. This is ready for a final review/merge.

Copy link
Member

@pllim pllim left a comment

Choose a reason for hiding this comment

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

Just nitpicks on the tests. Also, maybe a squash? (I am notorious for asking people to squash, so if you disagree on that, you don't have to.)

# values one by one.
for i in range(len(model['bounding_box'])):
bbox = m.bounding_box
print(bbox)
Copy link
Member

Choose a reason for hiding this comment

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

print function does not seem necessary. Is this leftover from debugging phase?

SCIPY_MODELS = set([Sersic1D, Sersic2D, AiryDisk2D])

@pytest.mark.parametrize('model', MODELS)
def test_models_evaluatate_without_units(model):
Copy link
Member

Choose a reason for hiding this comment

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

evaluatate -> evaluate (multiple occurrences)

@astrofrog
Copy link
Member Author

@pllim - I've implemented the fixes. In general I think we should only ask people to squash if they spend say 10 commits making trivial changes, or if they accidentally add then remove a large file, but for 600+ line changes, I don't think it's unreasonable to have a dozen commits.

Copy link
Member

@pllim pllim left a comment

Choose a reason for hiding this comment

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

LGTM. I'll add a "merge when CI pass" tag. @nden has until then to disagree. 😉

@pllim pllim added the 💤 merge-when-ci-passes Do not use: We have auto-merge option now. label Jun 14, 2017
@astrofrog astrofrog merged commit d561702 into astropy:master Jun 14, 2017
@MSeifert04 MSeifert04 removed the 💤 merge-when-ci-passes Do not use: We have auto-merge option now. label Oct 17, 2017
@astrofrog astrofrog deleted the enable-units-all-models branch November 14, 2018 15:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Affects-dev PRs and issues that do not impact an existing Astropy release modeling Ready-for-final-review units
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants