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

Find centre of rotation (tentative 2) #30

Merged
merged 22 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ include README.md
include *.yaml
recursive-include * *.yaml
recursive-include * *.yml
recursive-include tests *.py
recursive-include examples *.py
recursive-include tests *.png
recursive-include images *.png

recursive-exclude * __pycache__
recursive-exclude * *.py[co]
recursive-exclude docs *
recursive-exclude tests *
73 changes: 51 additions & 22 deletions derotation/analysis/full_derotation_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,20 @@
self.debugging_plots = self.config["debugging_plots"]

if self.debugging_plots:
self.debug_plots_folder = self.config["paths_write"][
"debug_plots_folder"
]
self.debug_plots_folder = Path(

Check warning on line 171 in derotation/analysis/full_derotation_pipeline.py

View check run for this annotation

Codecov / codecov/patch

derotation/analysis/full_derotation_pipeline.py#L171

Added line #L171 was not covered by tests
self.config["paths_write"]["debug_plots_folder"]
)
lauraporta marked this conversation as resolved.
Show resolved Hide resolved
Path(self.debug_plots_folder).mkdir(parents=True, exist_ok=True)

logging.info(f"Dataset {self.filename_raw} loaded")
logging.info(f"Filename: {self.filename}")

self.center_of_rotation = (

Check warning on line 179 in derotation/analysis/full_derotation_pipeline.py

View check run for this annotation

Codecov / codecov/patch

derotation/analysis/full_derotation_pipeline.py#L179

Added line #L179 was not covered by tests
self.num_lines_per_frame // 2,
lauraporta marked this conversation as resolved.
Show resolved Hide resolved
self.num_lines_per_frame // 2,
)
self.hooks = {}

Check warning on line 183 in derotation/analysis/full_derotation_pipeline.py

View check run for this annotation

Codecov / codecov/patch

derotation/analysis/full_derotation_pipeline.py#L183

Added line #L183 was not covered by tests

### ----------------- Analog signals processing pipeline ------------- ###
def process_analog_signals(self):
"""From the analog signals (frame clock, line clock, full rotation,
Expand Down Expand Up @@ -790,26 +796,39 @@
plt.savefig(self.debug_plots_folder / "rotation_angles.png")

### ----------------- Derotation ----------------- ###

def plot_max_projection_with_center(self):
lauraporta marked this conversation as resolved.
Show resolved Hide resolved
"""Plots the maximum projection of the image stack with the center
of rotation.
This plot will be saved in the debug_plots folder.
Please inspect it to check that the center of rotation is correctly
placed.
"""
logging.info("Plotting max projection with center...")

Check warning on line 807 in derotation/analysis/full_derotation_pipeline.py

View check run for this annotation

Codecov / codecov/patch

derotation/analysis/full_derotation_pipeline.py#L807

Added line #L807 was not covered by tests

max_projection = np.max(self.image_stack, axis=0)

Check warning on line 809 in derotation/analysis/full_derotation_pipeline.py

View check run for this annotation

Codecov / codecov/patch

derotation/analysis/full_derotation_pipeline.py#L809

Added line #L809 was not covered by tests

fig, ax = plt.subplots(1, 1, figsize=(5, 5))

Check warning on line 811 in derotation/analysis/full_derotation_pipeline.py

View check run for this annotation

Codecov / codecov/patch

derotation/analysis/full_derotation_pipeline.py#L811

Added line #L811 was not covered by tests

ax.imshow(max_projection, cmap="gray")
ax.scatter(

Check warning on line 814 in derotation/analysis/full_derotation_pipeline.py

View check run for this annotation

Codecov / codecov/patch

derotation/analysis/full_derotation_pipeline.py#L813-L814

Added lines #L813 - L814 were not covered by tests
self.center_of_rotation[0],
self.center_of_rotation[1],
color="red",
marker="x",
)

ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)

Check warning on line 822 in derotation/analysis/full_derotation_pipeline.py

View check run for this annotation

Codecov / codecov/patch

derotation/analysis/full_derotation_pipeline.py#L821-L822

Added lines #L821 - L822 were not covered by tests

ax.axis("off")

Check warning on line 824 in derotation/analysis/full_derotation_pipeline.py

View check run for this annotation

Codecov / codecov/patch

derotation/analysis/full_derotation_pipeline.py#L824

Added line #L824 was not covered by tests

plt.savefig(self.debug_plots_folder / "max_projection_with_center.png")

Check warning on line 826 in derotation/analysis/full_derotation_pipeline.py

View check run for this annotation

Codecov / codecov/patch

derotation/analysis/full_derotation_pipeline.py#L826

Added line #L826 was not covered by tests

def derotate_frames_line_by_line(self) -> np.ndarray:
"""Rotates the image stack line by line, using the rotation angles
by line calculated from the analog signals.

Description of the algorithm:
- takes one line from the image stack
- creates a new image with only that line
- rotates the line by the given angle
- substitutes the line in the new image
- adds the new image to the rotated image stack

Edge cases and how they are handled:
- the rotation starts in the middle of the image -> the previous lines
are copied from the first frame
- the rotation ends in the middle of the image -> the remaining lines
are copied from the last frame

Before derotation, it finds the image offset, which is the peak of
the gaussian mixture model fitted to the image histogram. It is
useful to fill in the blank pixels that appear during the derotation.
"""Wrapper for the function `derotate_an_image_array_line_by_line`.
Before calling the function, it finds the F0 image offset with
`find_image_offset`.
lauraporta marked this conversation as resolved.
Show resolved Hide resolved

Returns
-------
Expand All @@ -818,12 +837,22 @@
"""
logging.info("Starting derotation by line...")

if self.debugging_plots:
self.plot_max_projection_with_center()

Check warning on line 841 in derotation/analysis/full_derotation_pipeline.py

View check run for this annotation

Codecov / codecov/patch

derotation/analysis/full_derotation_pipeline.py#L841

Added line #L841 was not covered by tests

offset = self.find_image_offset(self.image_stack[0])

rotated_image_stack = derotate_an_image_array_line_by_line(
self.image_stack,
self.rot_deg_line,
blank_pixels_value=offset,
center=self.center_of_rotation,
plotting_hook_line_addition=self.hooks.get(
"plotting_hook_line_addition"
),
plotting_hook_image_completed=self.hooks.get(
"plotting_hook_image_completed"
),
)

logging.info("✨ Image stack rotated ✨")
Expand Down
Loading