-
Notifications
You must be signed in to change notification settings - Fork 5
Refactor API to remove in-place centroids, and update FFIMachine [do-NOT-merge] #54
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
base: master
Are you sure you want to change the base?
Conversation
There's a notebook here which shows how to use this PR for getting the TESS photometry out... |
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.
In the near future, we need to merge the changes from #60 including the perturbation API. I think after that the only 'big' changes to machine.py
are the way to compute the source_mask
and centroids
.
@property | ||
def dx(self): | ||
"""Delta RA, corrected for centroid shift""" | ||
if not sparse.issparse(self.dra): | ||
return self.dra - self.ra_centroid.value | ||
else: | ||
ra_offset = sparse.csr_matrix( | ||
( | ||
np.repeat( | ||
self.ra_centroid.value, | ||
self.dra.data.shape, | ||
), | ||
(self.dra.nonzero()), | ||
), | ||
shape=self.dra.shape, | ||
dtype=float, | ||
) | ||
return self.dra - ra_offset |
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 the core change to avoid in-place operation. Does this adds overhead when calling self.dx
, I don't think it'd matter much though, only for the case of large sparse data.
def _update_delta_arrays(self, frame_indices="mean"): | ||
if self.nsources * self.npixels < 1e7: | ||
self._update_delta_numpy_arrays() | ||
else: | ||
self._update_delta_sparse_arrays() |
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 this should be renamed to just _create_delta_*_arrays()
(or just _delta_*_arrays()
) there's no "update" happening there.
The frame_indices="mean"
argument I think is unnecessary now.
if frame_indices == "mean": | ||
frame_indices = np.where(self.time_mask)[0] |
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 isn't doing anything in the function.
plot=False, | ||
): | ||
"""Find the pixel mask that identifies pixels with contributions from ANY NUMBER of Sources | ||
def _get_source_mask(self, source_flux_limit=1): |
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 new version of _get_source_mask
looks "simpler" than the original one, I mean, with less tunable params, which I like.
Is iterating 2 times good to converge into a solid source_mask
?
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.
A diagnostic plot for this one would be great, something to check we are capturing well the f, r
dependency.
# mask out non finite values and background pixels | ||
k = (np.isfinite(wgts)) & ( | ||
self.uncontaminated_source_mask.multiply(self.flux[t]).data > 100 | ||
def _get_centroid(self, plot=False): |
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.
we need short documentation here
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.
Now, this method computes a single centroid value for all frames. Do we want to also have centroids in each frame?
return | ||
|
||
def _remove_background(self, mask=None): | ||
def _remove_background(self, mask=None, pixel_knot_spacing=10): |
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.
we can get rid of photutils
dependency
thumb = np.min(self.flux, axis=0).reshape(self.image_shape) | ||
gthumb = np.hypot(*np.gradient(thumb)) | ||
mask = ( | ||
~sigma_clip( | ||
np.ma.masked_array(gthumb, gthumb > 500), | ||
sigma=3, | ||
cenfunc=lambda x, axis: 0, | ||
).mask | ||
).ravel() | ||
self._remove_background(mask=mask) |
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 this can happens after super.__init__
now.
pixel_mask = self.non_sat_pixel_mask & self.non_bright_source_mask | ||
self.rough_mask = self.rough_mask.multiply(pixel_mask).tocsr() | ||
self.rough_mask.eliminate_zeros() | ||
self.source_mask = self.source_mask.multiply(pixel_mask).tocsr() | ||
self.source_mask.eliminate_zeros() | ||
self.uncontaminated_source_mask = self.uncontaminated_source_mask.multiply( | ||
pixel_mask | ||
).tocsr() | ||
self.uncontaminated_source_mask.eliminate_zeros() |
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 great, never thought on including the sat/bright pixel mask into the machine
mask, this way we can keep all original pixels and do nice image plots
😃
|
||
|
||
def _combine_A(A, poscorr=None, time=None): | ||
def _combine_A(A, time, poscorr=None): |
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 one will disappear after merging with perturbation API
) | ||
|
||
|
||
def _find_uncontaminated_pixels(mask): |
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 not convinced this one belongs here, it used t be a hidden method of machine.py
Extracted out of #54, this is just a slightly more robust version of this part of the code.
I isolate the efficient FFI changes and open a new PR #71. We'll keep this PR open for future reference when including the in-place operations and new source mask methods. |
This PR refactors a lot of our API to make sure we have no in-place centroids. Here are some top changes:
rough_mask
, which is our first pass at the maskingsource_mask
is now made in a slightly more robust and clear wayrtol
to clip out faint parts of the PSF. We just use theatol
, i.e. where the PSF has counts greater than some value.rough_mask
,source_mask
,uncontaminated_source_mask
) these areFalse
.This PR supersedes #48
To Do