pymmcore-plus / pymmcore-widgets

A set of Qt-based widgets onto the pymmcore-plus model
https://pymmcore-plus.github.io/pymmcore-widgets
Other
12 stars 7 forks source link

feat: reusable single-well calibration widget for plate calibration widget #353

Closed fdrgsp closed 4 months ago

fdrgsp commented 4 months ago

Closes #329

Screenshot 2024-07-21 at 10 01 49 PM

to run the example:

python examples/temp/well_calibration_widget.py

TODO:

codecov[bot] commented 4 months ago

Codecov Report

Attention: Patch coverage is 95.47739% with 9 lines in your changes missing coverage. Please review.

Project coverage is 90.70%. Comparing base (920ec4a) to head (7893077). Report is 13 commits behind head on main.

Files with missing lines Patch % Lines
src/pymmcore_widgets/hcs/_util.py 63.63% 8 Missing :warning:
...c/pymmcore_widgets/hcs/_well_calibration_widget.py 99.43% 1 Missing :warning:
Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #353 +/- ## ========================================== + Coverage 90.59% 90.70% +0.11% ========================================== Files 74 76 +2 Lines 8442 8641 +199 ========================================== + Hits 7648 7838 +190 - Misses 794 803 +9 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

tlambert03 commented 4 months ago

ok @fdrgsp, I made some changes (some kinda significant). please play with the behavior and see if I've made anything worse :joy:

tlambert03 commented 4 months ago

it does look a bit different:

Screenshot 2024-07-23 at 3 49 25 PM
fdrgsp commented 4 months ago

ok @fdrgsp, I made some changes (some kinda significant). please play with the behavior and see if I've made anything worse 😂

Looks good, the behavior is similar! Do you want to rename the set button to add when more than 1 point? and what do you think about centering the well name and icon?

tlambert03 commented 4 months ago

Do you want to rename the set button to add when more than 1 point?

I don't think so, since the behavior is always to "set" the currently selected row to the current core position.

what do you think about centering the well name and icon?

I undid that since i can imagine wanting to use it not centered (for example. in the context of the calibration widget, if it's off to the right)... in general, I'd prefer the widget that consumes this widget to make stylistic decisions, rather than this widget

tlambert03 commented 4 months ago

side note, played around a bit with autogenerating these svgs:

import math
import tempfile
from typing import Sequence

from qtpy.QtGui import QIcon
from qtpy.QtWidgets import QApplication, QPushButton

def circle_points_svg(
    view_box: int = 24,
    circle_radius: float = 8,
    line_width: float = 2,
    line_color: str = "#000000",
    num_points: int = 3,
    point_radius: float = 3,
    circle_color: str = "#00C600",
) -> str:
    vb = view_box
    svg = f"""<svg viewBox="0 0 {vb} {vb}" xmlns="http://www.w3.org/2000/svg">"""
    # Draw the circle
    svg += f"""<circle
        style="fill:none;stroke:{line_color};stroke-width:{line_width}"
        cx="{vb / 2}" cy="{vb / 2}" r="{circle_radius}" />
    """

    # Draw the points
    if num_points == 1:
        # draw a single point in the center
        svg += f"""<circle
            style="fill:{circle_color}"
            cx="{vb / 2}" cy="{vb / 2}" r="{point_radius}" />
        """
    else:
        for i in range(num_points):
            x = circle_radius * math.cos(2 * math.pi * i / num_points) + vb / 2
            y = circle_radius * math.sin(2 * math.pi * i / num_points) + vb / 2
            svg += f"""<circle
                style="fill:{circle_color}"
                cx="{x}" cy="{y}" r="{point_radius}" />
            """

    # Close the svg
    svg += "</svg>"
    return svg

def square_points_svg(
    view_box: int = 24,
    line_width: float = 1.6,
    asp_ratio: float = 1.1,
    line_color: str = "#000000",
    point_radius: float = 2.3,
    square_color: str = "#00C600",
    num_points: int = 4,
    coords: Sequence[tuple[float, float]] | None = None,
) -> str:
    vb = view_box
    svg = f"""<svg viewBox="0 0 {vb} {vb}" xmlns="http://www.w3.org/2000/svg">"""
    # Draw the square
    height = vb / 2
    width = height * asp_ratio
    left = (vb - width) / 2
    top = (vb - height) / 2
    svg += f"""<rect
        style="fill:none;stroke:{line_color};stroke-width:{line_width}"
        x="{left}" y="{top}" width="{width}" height="{height}" />
    """

    # Draw the points
    if coords is None:
        if num_points == 1:
            coords = [(vb / 2, vb / 2)]
        elif num_points == 2:
            # draw on opposite corners
            coords = [(vb / 4, vb / 4), (3 * vb / 4, 3 * vb / 4)]
        else:
            # Draw in the middle of top/left/bottom/right, slightly offset
            offset = 1.5
            coords = [
                (offset + left + width / 2, top),  # top - middle
                (left, height + offset),  # left - middle
                (left - offset + width / 2, 3 * top),  # bottom - middle
                (left + width, height - offset),  # right - middle
            ]

    for x, y in coords:
        svg += f"""<circle
            style="fill:{square_color}"
            cx="{x}" cy="{y}" r="{point_radius}" />
        """

    # Close the svg
    svg += "</svg>"
    return svg

def temp_svg_file(svg: str) -> str:
    f = tempfile.NamedTemporaryFile(suffix=".svg", delete=False)
    f.write(svg.encode())
    f.flush()
    return f.name

if __name__ == "__main__":
    app = QApplication([])
    widget = QPushButton()
    widget.setIcon(QIcon(temp_svg_file(square_points_svg())))
    widget.setIconSize(widget.size())
    widget.show()
    app.exec()

since these may not look good on a dark theme, for example...

tlambert03 commented 4 months ago

(let's deal with the icons later. it's fine to commit them here for now, and that code above can just live in this issue).

@fdrgsp, can you write tests enough to get coverage passing?

fdrgsp commented 4 months ago

@tlambert03 I've added fe tests 👍🏻

tlambert03 commented 4 months ago

I've added fe tests

fank you