Bugfix/sci cam sign flip#124
Conversation
| make_property_helper('rot90') | ||
| make_property_helper('flip_x') | ||
| make_property_helper('flip_y') |
There was a problem hiding this comment.
Don't we want them to be read-only?
There was a problem hiding this comment.
good look, I agree and will update both here and in the flir_camera
|
@raphaelpclt brought up a good point that we currently have the functionality to update the offset_x and offset_y on the fly and these changes would result in unexpected behavior for that. We can define the offset_x and offset_y to be with respect to the transformed (rotated and/or flipped) coordinate system in the yml to preserve this functionality and then convert those values to camera array coordinates to be passed to the internal camera getROI functions. My only thoughts against this option are that we would then have two different offset_x and offset_y conventions that may lead to some confusion down the road |
|
@steigersg Yes, I want the I was for not even showing the actual We could use a suffix |
| img = np.flipud(img) | ||
| if self.flip_y: | ||
| img = np.fliplr(img) | ||
| return img |
There was a problem hiding this comment.
does not result in C Contiguous array - working on it
There was a problem hiding this comment.
This is expected and desired. This is what makes it fast to run multiple of these operations in a row.
|
Some benchmarks for just the nothing: only rot90: only flip_x: flip_x + flip_y: rot90 + flip_x: copy to contiguous array with rot90: copy to contiguous array without rot90: So the copy takes by far the most time. I just noticed that all these benchmarks were done with float64, not float32 dtype. But the copy takes about the same amount of time, likely because cache access in weird ordering takes the most time rather than the memory copying itself (ie. no/little acceleration from SIMD instructions or something). Losing a full millisecond is not great, but for these large array sizes, we're not gonna run that fast anyways. For smaller array sizes (eg. 312x312, float32 as for our zernike camera), the same benchmark is |
|
For comparison, on the same machine: submitting 1024x1024 float32 on data stream (which copies the data internally): copying 1024x1024 float32 with |
|
Just tested as well: using a.T (as an alternative to rot90) with ascontiguousarray: so the same speed as the rot90 for float32. |
…s and the x and y offsets to apply in camera array coordinates.
| self.rot90 = rot90 | ||
| self.flip_x = flip_x | ||
| self.flip_y = flip_y |
There was a problem hiding this comment.
I think you can set these straight from the config. I don't see a need to have them as local variables first. Also, this might need to be moved up to before you're actually setting offset_x/y and width/height on the camera, since they need these to exist.
| make_property_helper('rot90', read_only=True) | ||
| make_property_helper('flip_x', read_only=True) | ||
| make_property_helper('flip_y', read_only=True) |
There was a problem hiding this comment.
Do we need these as properties? Or can we have them in the CameraProxy object instead?
There was a problem hiding this comment.
I don't have an intuition for what the pros and cons of having them in the CameraProxy vs. here would be. I agree though they don't necessarily have to be properties since they're only used in the rot_flip_image and get_camera_offset functions and could easily be key word arguments in there
There was a problem hiding this comment.
To give some context, I'm not talking about Python properties. I'm talking about catkit2 properties, which is what the make_property_helper() function is creating. Those properties are available from the outside, ie. from client-side. Communication is done via TCP, which is not necessary. Since they are read-only and they are never meant to be changed/changable, their value can be purely gotten from the config file. Therefore, no communication between ServiceProxy and Service needs to take place, making it much easier to get the right value straight from the config in the ServiceProxy.
| """ | ||
| # Define the translation matrix T to get to the center of the ROI. | ||
| T = np.zeros((3, 3)) | ||
| np.fill_diagonal(T, 1) |
There was a problem hiding this comment.
I'd construct the matrix with np.eye(3) instead rather than creating them as zeros and then filling the diagonal with ones. The same for the other matrices.
There was a problem hiding this comment.
thanks! I forgot np.eye existed - updated that code for all the matrices where I wanted diagonals filled
| if self.flip_x: | ||
| # Define x reflection matrix. | ||
| X[0][0] = -1 | ||
|
|
||
| if self.flip_y: | ||
| # Define y reflection matrix. | ||
| Y[1][1] = -1 |
There was a problem hiding this comment.
Don't the flips also need translation matrices, since the flips are reflections around the centerlines of the images?
There was a problem hiding this comment.
good catch! moved the final translation to after the x and y flips
| self.width = self.config.get('width', self.sensor_width - offset_x) | ||
| self.height = self.config.get('height', self.sensor_height - offset_y) | ||
|
|
||
| offset_x, offset_y = self.get_camera_offset(offset_x, offset_y) |
There was a problem hiding this comment.
The properties height, width, offset_x and offset_y need to be modified instead. Otherwise, setting the offset_x and offset_y dynamically won't work as expected.
| self.width = self.config.get('width', self.sensor_width - offset_x) | ||
| self.height = self.config.get('height', self.sensor_height - offset_y) |
There was a problem hiding this comment.
Don't the width/height properties need to be changed as well? To exchange width/height that is.
There was a problem hiding this comment.
if rot90 is True I updated the code so that the width and height properties are swapped. This could cause issues though if the get_camera_offset function hasn't been called yet (since it needs to know the previous origin location) so I also added an in-line comment to warn agains this.
|
Should be superseded with camera base class #131 |
See affiliated PR on hicat-package2 (https://github.com/spacetelescope/hicat-package2/pull/480)
Add infrastructure in camera services to rotate and/or flip the images on the camera.
The camera rotation happens first and defines which camera axis (width or height) is aligned with the gravity vector of the testbed. Defining
rot90to beTruewill perform one counter-clockwise 90 degree rotation. If a clockwise rotation is desired thenflip_yshould also be set toTrue.The flips (
flip_x, andflip_y), with the exception of the example above, are meant to be defined with respect to the optical axis (e.g. whether a lens upstream of the camera has flipped the image).Notably
offset_xandoffset_yvalues are not changed with the reflections and rotations since these are fundamentally defined with respect to the camera array and the setters and getters for these values are directly given to the setROI functions in the vendor camera control software itself. I believe this is alright since finding these values should not have to occur very frequently and the user can take care to make sure they are defined with respect to the coordinate system of the camera itself.Tasks before review