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

Remove camera creation from Observatory #612

Merged
merged 22 commits into from
Sep 27, 2018
Merged

Conversation

wtgee
Copy link
Member

@wtgee wtgee commented Sep 20, 2018

  • First step toward pulling cameras out of Observatory.
  • Basic create_cameras_from_config function. This is basically copied over from the _create_cameras that was in Observatory, with no intended behavior change.
  • Creation removed from Observatory .
  • Add/remove camera methods.
  • Updates to observatory init (and testing).
  • Behavior Change Accessing observatory.primary_camera will now always return a camera if observatory.has_cameras. If no primary camera was set, the first camera in the list will become the primary.

* First step toward pulling cameras out of Observatory.
* Basic `create_cameras_from_config` function.
* Removed from `Observatory` (not getters/setters yet)
* Adding tests related to adding/removing cameras
* Updates to observatory init (and testing)
* **Behavior Change** Accessing `observatory.primary_camera` will now
always return a camera if `observatory.has_cameras`.
@@ -152,7 +153,8 @@ class PocsShell(Cmd):
simulator = []

try:
observatory = Observatory(simulator=simulator)
cameras = create_cameras_from_config()
observatory = Observatory(simulator=simulator, cameras=cameras)
Copy link
Contributor

Choose a reason for hiding this comment

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

FWIW, while thinking about adding a supervisor and better messaging, and also while reviewing Anthony's distributed cameras PR (which includes a nameserver), I wondered about introducing some kind of device registry. Something we can discuss in the future.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I think we will definitely want to change how the Observatory interacts with and discovers devices. Hopefully this gets us closer to doing that.



def create_cameras_from_config(config=None, logger=None, **kwargs):
"""Creates a camera object(s)
Copy link
Contributor

Choose a reason for hiding this comment

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

Creates camera object(s) based on the config.

def create_cameras_from_config(config=None, logger=None, **kwargs):
"""Creates a camera object(s)

Loads the cameras via the configuration.
Copy link
Contributor

Choose a reason for hiding this comment

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

Drop this line.


Note:
This does not actually make a connection to the camera. To do so,
call 'camera.connect()' explicitly.
Copy link
Contributor

Choose a reason for hiding this comment

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

... on each camera.

automatically discover the ports.

Returns:
OrderedDict: An ordered dictionary of created camera objects.
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the key? And why is it ordered?

Copy link
Contributor

Choose a reason for hiding this comment

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

Or None if there are no cameras declared in the config.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added docs to describe. Changed so that an empty OrderedDict is returned instead of None and updated docs.

# Assign an auto-detected port. If none are left, skip
if auto_detect:
try:
camera_port = ports.pop()
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 perplexed by this. If the config file lists two canon cameras with the prefixes of their serial numbers, how do we know the order in which to pop the ports?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is only if auto_detect is true, which means that it is ignoring the config. Serial number is set when camera object is initialized by lookup (via gphoto2)

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah. Then I may have misunderstood how to auto_detect and primary work. I included the serial number prefixes and primary:True in pocs_local.yaml on PAN006. My goal is to make sure that a specific camera is treated as primary every time. And ideally we'd get a warning if a specified camera is not found, or if another camera is found.

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 think #95 is still true unfortunately. This function could certainly be cleaned up some. Happy to do it here if we want just to make sure it gets done soon but I imagine it will all need to be revisited anyway if we set up separate process controls for the camera. Which hopefully happens soon. :)

if not config:
config = load_config(**kwargs)

if 'cameras' not in config:
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this not after the line: camera_info = kwargs_or_config('cameras')

self._primary_camera = None
self._create_cameras(**kwargs)
if not cameras:
cameras = OrderedDict()
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not just raise an exception?

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 could. create_dome_from_config is returning None so I'll go for consistency with that (although see comment below).

# Device Getters/Setters
##########################################################################

def add_camera(self, cam_name, camera):
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you intend these two add/remove methods to be used to dynamically add and remove cameras during operation?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, eventually that would be the goal.

@@ -25,7 +26,11 @@ def simulator():
@pytest.fixture
def observatory(config, simulator):
"""Return a valid Observatory instance with a specific config."""
obs = Observatory(config=config, simulator=simulator, ignore_local_config=True)
cameras = create_cameras_from_config(config)
Copy link
Contributor

Choose a reason for hiding this comment

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

local=False

Or some such to prevent the pocs_local.yaml from being picked up?

Copy link
Member Author

Choose a reason for hiding this comment

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

Doesn't the config fixture handle that?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, it may do so. NM.

@wtgee
Copy link
Member Author

wtgee commented Sep 21, 2018

(I thought I wrote this already but don't see) @jamessynge this is a bit inconsistent with create_dome_from_config and we should standardize. Here I do not require the config parameter and instead pull from our config files if nothing is given. I prefer this but would more prefer all our (eventual) create utils are the same.

Also, as per comments above, we should figure out the behavior if nothing is found. I suppose it makes some sense for the camera to raise an error as it's hard to have an observatory without a camera whereas it's okay to have None for a dome. Still, I think the utils should act the same and we should handle the differences when called. Thoughts?

@wtgee wtgee added the Camera label Sep 22, 2018
@codecov
Copy link

codecov bot commented Sep 23, 2018

Codecov Report

Merging #612 into develop will decrease coverage by 0.99%.
The diff coverage is 61.53%.

Impacted file tree graph

@@           Coverage Diff            @@
##           develop     #612   +/-   ##
========================================
- Coverage    67.28%   66.29%   -1%     
========================================
  Files           65       65           
  Lines         5692     5729   +37     
  Branches       798      805    +7     
========================================
- Hits          3830     3798   -32     
- Misses        1653     1718   +65     
- Partials       209      213    +4
Impacted Files Coverage Δ
pocs/utils/__init__.py 80.28% <ø> (+0.28%) ⬆️
pocs/version.py 100% <100%> (ø) ⬆️
pocs/camera/__init__.py 56.98% <56.04%> (-43.02%) ⬇️
pocs/observatory.py 75.58% <80%> (-0.82%) ⬇️
pocs/utils/images/__init__.py 61.2% <0%> (-12.57%) ⬇️
pocs/state/states/default/pointing.py 38.46% <0%> (-5.77%) ⬇️
pocs/camera/simulator.py 94.54% <0%> (-5.46%) ⬇️
pocs/camera/camera.py 84.73% <0%> (-5.27%) ⬇️

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 92e7f2c...831c04b. Read the comment docs.

Copy link
Collaborator

@AnthonyHorton AnthonyHorton 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. This new framework will be really useful for refactoring my distributed camera code to allow for camera addition/removal without restarting everything from scratch every time.


Note:
This does not actually make a connection to the camera. To do so,
call 'camera.connect()' explicitly on each camera.
Copy link
Collaborator

@AnthonyHorton AnthonyHorton Sep 26, 2018

Choose a reason for hiding this comment

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

I don't think this is true, yet. All the existing camera classes (and associated focuser classes) call their own connect() method from their __init__(). I think you know that though, because I didn't spot any calls of camera.connect() in the diff!

On a related note, those calls to camera.connect() should be done in parallel as for some of the supported hardware that triggers an initialisation process that takes quite a while and we can significantly speed up startup by doing all the cameras at the same time.

@wtgee
Copy link
Member Author

wtgee commented Sep 26, 2018

This new framework will be really useful for refactoring my distributed camera code to allow for camera addition/removal without restarting everything from scratch every time.

I would prefer to merge this before #547 so we can keep some things cleaner, but it will definitely be the bigger change for you. I'll go ahead and get this merged though so that work can start.

@AnthonyHorton
Copy link
Collaborator

I would prefer to merge this before #547 so we can keep some things cleaner, but it will definitely be the bigger change for you. I'll go ahead and get this merged though so that work can start.

Oh, absolutely. What I meant by my comment was just that I'm especially keen to see this merged as soon as possible so that I can use it as a guide for refactoring of #547, which (unlike this PR) is still some way off being ready to merge.

@wtgee wtgee merged commit aeffd99 into panoptes:develop Sep 27, 2018
@wtgee wtgee deleted the camera-di branch September 27, 2018 00:41
wtgee added a commit that referenced this pull request Sep 30, 2018
AnthonyHorton pushed a commit to AstroHuntsman/POCS that referenced this pull request Oct 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants