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

Basic horizon constraint features #368

Merged
merged 35 commits into from
Jan 19, 2018

Conversation

wtgee
Copy link
Member

@wtgee wtgee commented Jan 16, 2018

This is an attempt to get basic support for a custom horizon into the codebase. This is neither feature complete nor robust but hopefully is enough of a stepping stone such that others could work on the code.

Basic fixes and suggestions are welcome here but I'd prefer to get this merged soon. To that end, there is an umbrella issue #367 and any additional features, tests, etc. should get their own issue added to that umbrella issue. Hopefully those smaller issues can then be doled out to individuals to work on.

See the notebook first for an example of what is going on.

Would appreciate basic comments and suggestions for features/testing from @joshwalawender @AnthonyHorton @lspitler @jamessynge. Mostly just on the overall idea. Please go ahead and create any related issues.

brendan-o and others added 24 commits November 25, 2016 13:38
…a images) into the pocs examples notebooks folder.
* Build horizon line
* Added example notebook
the new `Horizon` class
* Updating some log output to be cleaner
* Updating notebook
* Removing sample from config file
@wtgee wtgee requested review from a team January 16, 2018 12:48
@@ -146,11 +107,11 @@ def get_score(self, time, observer, observation, **kwargs):
except KeyError:
self.logger.error("Moon must be set")

moon_sep = moon.separation(observation.field.coord).value
moon_sep = observation.field.coord.separation(moon).value
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'm not sure why this changed, I'll check it out.

@wtgee wtgee mentioned this pull request Jan 16, 2018
8 tasks
# Simple constraint for now
constraints = [MoonAvoidance(), Duration(30 * u.deg)]
constraints = [
Altitude(horizon=horizon),
Copy link
Member Author

Choose a reason for hiding this comment

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

For now this will just create a flat line at the base horizon level so shouldn't affect current scheduler.

@wtgee wtgee mentioned this pull request Jan 16, 2018
Copy link
Contributor

@jamessynge jamessynge left a comment

Choose a reason for hiding this comment

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

Looks good to me, but I'm not sure I fully understand how the scoring is performed.


# This would potentially be within image
if moon_sep < 15:
self.logger.debug("Moon separation: {}".format(moon_sep))
self.logger.debug("\t\tMoon separation: {:.02f}".format(moon_sep))
Copy link
Contributor

Choose a reason for hiding this comment

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

\t\t seems unnecessary.

Copy link
Member Author

@wtgee wtgee Jan 17, 2018

Choose a reason for hiding this comment

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

It helps with the output in this case and makes it consistent with the other scheduler items. If we don't want here we should remove everywhere in scheduler.

Copy link
Contributor

@jamessynge jamessynge Jan 17, 2018

Choose a reason for hiding this comment

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

Remove everywhere, IMHO. ;-)

I've been guilty of using this approach in the past, and they stay long after they are useful. Perhaps it would be better to use a custom log colorizer.

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed about the tabs but I do think they are useful here. Long ago I had them all over the logs and it became a nightmare. Then I started thinking about how to write some logger wrapper that would auto-figure out the indent. Luckily I wisely abandoned the whole idea and removed all indents...except for here in the scheduler call.

I know @AnthonyHorton has used some in the SBIG and FLI code and I've been meaning to mention removing them. ;)

I'm going to leave in here unless very serious concerns (see notebook for how output looks) and again the additions here were to make the whole scheduler output consistent as it otherwise looked pretty bad.

Agree that we should try to avoid them elsewhere (i.e I get to be the exception but no one else. 😁).

Copy link
Contributor

Choose a reason for hiding this comment

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

I think you see the slippery slope all to well!

@@ -159,3 +120,40 @@ def get_score(self, time, observer, observation, **kwargs):

def __str__(self):
return "Moon Avoidance"


class Altitude(BaseConstraint):
Copy link
Contributor

Choose a reason for hiding this comment

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

The move down the file seems unnecessary, FWIW.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

No, I mean the order of the classes was changed, with Altitude moved down the file. It was above class Duration, now is below.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, got it. Yes, this was originally added to the bottom of the file as a new constraint named Horizon, but then I realized after writing it that it basically replaced the existing Altitude constraint (which wasn't being used at all) so I deleted the one from above and renamed the new one I had written.

Copy link
Member Author

Choose a reason for hiding this comment

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

Alphabetical order probably makes the most sense.


def __init__(self, horizon=None, *args, **kwargs):
"""
Retrieves the coordinate list from the config file and validates it
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't appear to retrieve anything.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, forgot to update docstring, thanks.

for obs_name, observation in self.observations.items():
if obs_name in valid_obs:
self.logger.debug("\tObservation: {}".format(obs_name))

veto, score = constraint.get_score(
time, self.observer, observation, **common_properties)

self.logger.debug("\t\tScore: {}\tVeto: {}".format(score, veto))
self.logger.debug("\t\tScore: {:.05f}\tVeto: {}".format(score, veto))
Copy link
Contributor

Choose a reason for hiding this comment

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

Again with the leading tabs. I suppose it makes it easier to find... sometimes...

@@ -734,8 +736,20 @@ def _create_scheduler(self):
module = load_module(
'pocs.scheduler.{}'.format(scheduler_type))

obstruction_list = self.config['location'].get('obstructions', list())
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a description of the values in the list somewhere?

Copy link
Member Author

Choose a reason for hiding this comment

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

Just it the Horizon class. I haven't taken the step to add these to the config yet so will do that soon.

Copy link
Contributor

@jamessynge jamessynge Jan 17, 2018

Choose a reason for hiding this comment

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

Maybe a comment here pointing to the Horizon class? Or a call to the Horizon class here, so that it is obvious where to look. E.g.

horizon = horizon_utils.load_horizon_from_config(
    self.config['location'], default_horizon=30.)

@@ -0,0 +1,88 @@
import numpy as np
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm thinking about how to produce these from other info, like the azimuth and height above "ground" of the obstruction, and the height above ground of the mount/cameras (probably the lowest height).

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean how to produce a Horizon automatically? That's partly what #364 is about.

Copy link
Contributor

Choose a reason for hiding this comment

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

Not precisely; I meant "get horizon from measurements" as opposed to "get horizon from image". If the latter is going to be easy to achieve, great. But if it will be a while, then I could ask one of the student's I'm working with to help with measuring the space so we can build the former. I could ask him about implementing it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Regarding why this might be useful: the big obstruction next to PAN006 has a constant height, but its altitude at different azimuths will be very different. We could encode it with 5 measurements:

  1. Height of wall.
  2. Compass angle and distance to start of wall.
  3. Compass angle and distance to end of wall.

Copy link
Member Author

Choose a reason for hiding this comment

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

Got it. We should capture that in a wiki page or document so have an Issue in #367.

wtgee added 3 commits January 17, 2018 13:42
this is a holdover from the branch from before astroplan switched
how the moon works
@lspitler
Copy link
Collaborator

Only aspect I don't see (it might be elsewhere in dispatch) is whether the field of view of the particular imaging system being used is factored into the horizon. For Huntsman this is tiny compared to Panoptes so we can go much closer to the horizon. Won't add a to-do for this as I don't know if it is already taken care of.

@wtgee
Copy link
Member Author

wtgee commented Jan 18, 2018

Only aspect I don't see (it might be elsewhere in dispatch) is whether the field of view of the particular imaging system being used is factored into the horizon. For Huntsman this is tiny compared to Panoptes so we can go much closer to the horizon. Won't add a to-do for this as I don't know if it is already taken care of.

No, this is a good point and I mean to put an Issue in for it. We consider this to be the center of the image, which of course is not ideal for PANOPTES. I'll make the issue.

@codecov
Copy link

codecov bot commented Jan 19, 2018

Codecov Report

Merging #368 into develop will increase coverage by 0.39%.
The diff coverage is 100%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop     #368      +/-   ##
===========================================
+ Coverage    68.98%   69.38%   +0.39%     
===========================================
  Files           58       59       +1     
  Lines         4640     4690      +50     
  Branches       641      650       +9     
===========================================
+ Hits          3201     3254      +53     
+ Misses        1266     1265       -1     
+ Partials       173      171       -2
Impacted Files Coverage Δ
pocs/scheduler/observation.py 93.44% <ø> (ø) ⬆️
pocs/utils/horizon.py 100% <100%> (ø)
pocs/scheduler/constraint.py 96.05% <100%> (+1.6%) ⬆️
pocs/observatory.py 83.81% <100%> (+0.53%) ⬆️
pocs/scheduler/dispatch.py 98.03% <100%> (+1.96%) ⬆️
pocs/utils/error.py 94.23% <0%> (+0.23%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 055cf9c...95c73de. Read the comment docs.

@wtgee
Copy link
Member Author

wtgee commented Jan 19, 2018

Going to merge this just because we definitely have a need on PAN001, PAN006, and Huntsman. :)

horizon

@wtgee wtgee merged commit d00eaae into panoptes:develop Jan 19, 2018
@wtgee wtgee deleted the brendan-o-horizonFeatures branch January 19, 2018 09:39
@wtgee wtgee mentioned this pull request Jan 24, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants