Skip to content

Use numpy broadcasting for altaz and constraints - #286

Merged
bmorris3 merged 45 commits into
astropy:masterfrom
StuartLittlefair:use_broadcasting
Jun 8, 2017
Merged

bmorris3 merged 45 commits into
astropy:masterfrom
StuartLittlefair:use_broadcasting

Conversation

@StuartLittlefair

@StuartLittlefair StuartLittlefair commented Feb 4, 2017 •

Copy link
Copy Markdown
Contributor

As discussed in #285 I think there is an advantage to relying on the broadcasting of times and targets in astropy, now that those objects are shape aware. This PR is basically to show how that would work, so the code maintainers can discuss if it's a good idea or not.

This PR passes all tests locally (some of which have been tweaked to accommodate changed behaviour - see below). To do this I have included changes in #281, #279, #273 as well.

The three potential gains are cleaner code, faster performance and greater flexibility. The downsides are that it requires astropy v1.3, and that it's a change which will probably break user code - see discussion below.

Cleaner Code

The philosophy is to always convert target arguments to SkyCoord objects. As a result, we no longer have to have two paths through the code for vector and non-vector targets. We can also get rid of constructions like:

target_coos = [target.coord if hasattr(target, 'coord') else target
                         for target in targets]
target_altazs = [observer.altaz(times, coo) for coo in target_coos]
solar_separation = Angle([sunaltaz.separation(taa) for taa in target_altazs])

which becomes

solar_separation = targets.separation(sunaltaz)
Faster performance

Performance is similar for single targets and single or a few times. However, when calculating the altaz or evaluating constraints over many targets and times it is much faster. For example evaluating the built-in constraints for 100 times and 2 targets has improved from 15s to 1.5s. Scheduling currently does every combination of target/time one-by-one so doesn't see any speed-up but the code could be adapted in a future PR.

Greater flexibility

This is also where the code-breaking behaviour arises. Previously, evaluating a constraint or calculating altaz for N targets and M times would always return an NxM array. This is no longer true. If N and M are equal, for example, the result will be a 1D array of size M.

I'd argue this is an improvement - one doesn't always want to calculate every target at every time. To minimise the transition pain, both altaz and the constraint call function have a grid argument, which restores the previous behaviour.

@StuartLittlefair

StuartLittlefair commented Feb 4, 2017 •

Copy link
Copy Markdown
Contributor Author

OK, I was going to ping people when this was passing tests, but I can't understand some of the failures - in particular I'm not sure what to do about the sphinx failures.

The older version of numpy also seem to fail because Time has no len attribute. Not sure what to do about that.

So, for discussion, @eteq, @bmorris3, @bsipocz you might want to take a look at this PR sometime.

@StuartLittlefair

StuartLittlefair commented Feb 24, 2017 •

Copy link
Copy Markdown
Contributor Author

I have now rebased this so it is easier to see what has changed. I've also profiled the changes here against the current master which also uses SkyCoords internally. I evaluated each constraint for 100 times and 3 targets, and also for each combination of scalar time, vector target and vice versa.

This PR is faster, but not dramatically so (with the exception of the MoonSeparationConstraint.

The results (in s) are shown below:

Constraint Master This PR
Altitude 0.35 0.27
Airmass 0.06 0.09
AtNight 0.19 0.21
SunSeparation 1.07 0.53
MoonSeparation 29.46 1.09
MoonIllumination 0.76 0.59
LocalTime 0.02 0.09
Time 0.01 0.11

@bmorris3

Copy link
Copy Markdown
Contributor

@StuartLittlefair It looks like this PR is good to go! I just want to check before I click the green button that this one is ready to merge?

@StuartLittlefair

Copy link
Copy Markdown
Contributor Author

I'm happy with it.

I'd be happier if @eteq took a look at it because it's a big change. Also, does it need a change log entry?

@bmorris3

Copy link
Copy Markdown
Contributor

Ok, then I'm going to do an intermediate release first, so that we can get v0.2.1 on pypi ASAP.

@StuartLittlefair

Copy link
Copy Markdown
Contributor Author

Good plan!

@StuartLittlefair

StuartLittlefair commented May 9, 2017 •

Copy link
Copy Markdown
Contributor Author

Hi @bmorris3.

I'm thinking of finishing up this PR, but I can't make my mind up about the default behaviour. In the past astroplan has always done calculations for a grid of times and targets and as you know, this PR changes this default. It doesn't have to; we could make gridding the default again, and allow non gridding as an option.

Edit: my own opinion is that the intuitive behaviour is the one in this PR; if I supply three times and three targets to altaz (for example), I kind of expect three altaz results...

I'm going to finish up editing the docs and adding a changelog over the next week, but before I do that I wanted to check that you are happy with this decision?

EDIT: this PR is now ready to go as far as I'm concerned. It just really needs package maintainers to agree on the API breaking change.

@StuartLittlefair

Copy link
Copy Markdown
Contributor Author

p.s, this PR fixes #296

@StuartLittlefair

Copy link
Copy Markdown
Contributor Author

@bmorris3, @eteq - can I nudge you for a code review of this PR? I'm already starting to use it in our own telescope control/scheduling package due to the speedups involved in not gridding targets and times where not needed.

@bmorris3

bmorris3 commented Jun 7, 2017

Copy link
Copy Markdown
Contributor

@StuartLittlefair sorry for the long delay there! I just finished my candidacy exam and can take a look now. Reviewing!

Comment thread docs/tutorials/constraints.rst Outdated
To see the (target x time) array for the non-boolean score::
By default, calling a constraint will try to broadcast the time and target arrays
against each other, and raise a `ValueError` if this is not possible. To see the
(target x time) array for the constraint, there is an optional "grid_times_targets"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Small correction – would you please make "grid_times_targets" -> `grid_times_targets`? That way it will be rendered nicely in the docs.

Comment thread CHANGES.rst Outdated
@@ -3,6 +3,13 @@

- No changes yet

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We can remove this line with your addition below.

@StuartLittlefair

Copy link
Copy Markdown
Contributor Author

@bmorris3 congratulations!

I've made the minor changes requested

@StuartLittlefair

Copy link
Copy Markdown
Contributor Author

Closed and re-opened to start tests, which failed due to random lookup failure for APO site.

@bmorris3

bmorris3 commented Jun 8, 2017

Copy link
Copy Markdown
Contributor

Thanks for all of your hard work @StuartLittlefair!

@bmorris3
bmorris3 merged commit 42e3607 into astropy:master Jun 8, 2017
@StuartLittlefair
StuartLittlefair deleted the use_broadcasting branch August 18, 2023 10:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants