-
Notifications
You must be signed in to change notification settings - Fork 49
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
Conversation
* 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`.
it use `load_config` * Update pocs_shell
@@ -152,7 +153,8 @@ class PocsShell(Cmd): | |||
simulator = [] | |||
|
|||
try: | |||
observatory = Observatory(simulator=simulator) | |||
cameras = create_cameras_from_config() | |||
observatory = Observatory(simulator=simulator, cameras=cameras) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
pocs/camera/__init__.py
Outdated
|
||
|
||
def create_cameras_from_config(config=None, logger=None, **kwargs): | ||
"""Creates a camera object(s) |
There was a problem hiding this comment.
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.
pocs/camera/__init__.py
Outdated
def create_cameras_from_config(config=None, logger=None, **kwargs): | ||
"""Creates a camera object(s) | ||
|
||
Loads the cameras via the configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drop this line.
pocs/camera/__init__.py
Outdated
|
||
Note: | ||
This does not actually make a connection to the camera. To do so, | ||
call 'camera.connect()' explicitly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... on each camera.
pocs/camera/__init__.py
Outdated
automatically discover the ports. | ||
|
||
Returns: | ||
OrderedDict: An ordered dictionary of created camera objects. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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. :)
pocs/camera/__init__.py
Outdated
if not config: | ||
config = load_config(**kwargs) | ||
|
||
if 'cameras' not in config: |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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): |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
* Fixing docstrings
* Return empty OrderedDict based on config information being present
(I thought I wrote this already but don't see) @jamessynge this is a bit inconsistent with 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 |
Codecov Report
@@ 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
Continue to review full report at Codecov.
|
There was a problem hiding this 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.
pocs/camera/__init__.py
Outdated
|
||
Note: | ||
This does not actually make a connection to the camera. To do so, | ||
call 'camera.connect()' explicitly on each camera. |
There was a problem hiding this comment.
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.
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. |
create_cameras_from_config
function. This is basically copied over from the_create_cameras
that was inObservatory
, with no intended behavior change.Observatory
.observatory.primary_camera
will now always return a camera ifobservatory.has_cameras
. If no primary camera was set, the first camera in the list will become the primary.