Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@Czaki
Copy link
Collaborator

@Czaki Czaki commented Sep 26, 2024

Use color associated with the channel in napari reader plugin.

Summary by Sourcery

Add functionality to use channel-associated colors in napari layers by adjusting hex color codes. Enhance the _hex_to_rgb function to support additional hex code formats and update tests accordingly.

New Features:

  • Integrate color adjustment for image layers in the napari reader plugin, using the color associated with the channel.

Enhancements:

  • Improve the _hex_to_rgb function to handle 4 and 8 character hex codes, ensuring proper conversion and validation.

Tests:

  • Expand tests for the _hex_to_rgb function to include cases for 4 and 8 character hex codes, ensuring correct functionality and error handling.

Summary by CodeRabbit

  • New Features

    • Introduced adjust_color function to modify color strings based on length, enhancing color handling.
    • Updated _hex_to_rgb function to support additional hexadecimal color formats.
  • Bug Fixes

    • Improved validation for hex color codes, ensuring robust error handling for various input lengths.
  • Tests

    • Added new test cases for _hex_to_rgb to validate behavior with hex codes including alpha channels.
    • Enhanced tests for layer creation and colormap validation in image processing.

@Czaki Czaki added this to the 0.15.4 milestone Sep 26, 2024
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Sep 26, 2024

Reviewer's Guide by Sourcery

This pull request enhances the image color handling in the napari reader plugin. It introduces a new function to adjust color values and modifies existing functions to support both RGB and RGBA color formats. The changes primarily affect how colors are processed and applied to image layers in napari.

Sequence Diagram

sequenceDiagram
    participant Client
    participant _image_to_layers
    participant adjust_color
    participant Image

    Client->>_image_to_layers: Create layers
    _image_to_layers->>Image: get_colors()
    Image-->>_image_to_layers: Return colors
    _image_to_layers->>adjust_color: Adjust color
    adjust_color-->>_image_to_layers: Return adjusted color
    _image_to_layers->>Client: Return layers with adjusted colors
Loading

File-Level Changes

Change Details Files
Introduced color adjustment function for napari layers
  • Added new function 'adjust_color' to handle different color formats
  • Modified '_image_to_layers' function to use adjusted colors
  • Updated 'colormap' parameter in layer creation to use image colors
package/PartSegCore/napari_plugins/loader.py
Extended hex color code parsing to support RGBA format
  • Modified '_hex_to_rgb' function to handle 4-digit and 8-digit hex codes
  • Updated length checks in the function to accommodate new formats
package/PartSegImage/image.py
Updated unit tests for hex color parsing
  • Added test cases for 4-digit and 8-digit hex color codes
  • Modified existing test case for invalid hex code format
package/tests/test_PartSegImage/test_image.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 26, 2024

Warning

Rate limit exceeded

@Czaki has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 12 minutes and 5 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Files that changed from the base of the PR and between d34bc47 and 21813e7.

Walkthrough

The changes introduce a new function adjust_color in loader.py to modify color strings by removing alpha channels based on specific lengths. Additionally, the _hex_to_rgb function in image.py has been updated to handle more hexadecimal formats, allowing for 3 and 4 character inputs. The test suite in test_image.py has been enhanced with new test cases to validate these modifications, ensuring proper functionality of the color handling features. Furthermore, the test fixtures in conftest.py have been improved to support channel-specific metadata.

Changes

File Change Summary
package/PartSegCore/napari_plugins/loader.py Added adjust_color function to modify color strings and updated _image_to_layers to utilize this function. Defined add_color conditionally based on napari version.
package/PartSegImage/image.py Modified _hex_to_rgb to accept additional hexadecimal formats and adjusted validation for input lengths.
package/tests/test_PartSegImage/test_image.py Introduced new test cases for _hex_to_rgb to validate behavior with hex codes including alpha channels and updated error checking for invalid formats.
package/tests/conftest.py Enhanced image data handling in fixtures by specifying spacing and adding channel_info for better image representation in tests.
package/tests/test_PartSegCore/test_napari_plugins.py Updated tests to reflect changes in layer creation and added assertions for colormap names to ensure correct functionality after modifications.

Possibly related PRs

🐇 In the land of colors bright,
A function hops with pure delight.
Adjusting hues with careful grace,
Removing channels from their place.
Tests now check with joyful cheer,
For every shade, we hold so dear! 🌈


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @Czaki - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟡 General issues: 2 issues found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment to tell me if it was helpful.

from PartSegCore.mask.io_functions import MaskProjectTuple


def adjust_color(color):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider a more robust approach for color adjustment

The current implementation may lead to unexpected results by simply truncating the alpha channel. Consider handling alpha channels more explicitly or using a color library for more robust color manipulations.

def adjust_color(color: str) -> str:
    from colorsys import rgb_to_hls, hls_to_rgb

    def hex_to_rgb(hex_color):
        return tuple(int(hex_color[i:i+2], 16) for i in (1, 3, 5))

    def rgb_to_hex(rgb):
        return f"#{''.join([f'{int(x):02x}' for x in rgb])}"

    if color.startswith("#") and len(color) >= 7:
        rgb = hex_to_rgb(color[:7])

"""
hex_code = hex_code.lstrip("#")

if len(hex_code) == 3:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Improve handling of hex codes with alpha channels

While the function now accepts 4-digit and 8-digit hex codes, it still only returns RGB values, discarding any alpha information. Consider extending the function to handle and return alpha channel information when present.

def hex_to_rgb(hex_code):
    """Convert hex color code to RGB tuple."""
    hex_code = hex_code.lstrip("#")

    if len(hex_code) in {3, 4, 6, 8}:
        if len(hex_code) < 5:
            hex_code = "".join([c * 2 for c in hex_code])
        rgb = tuple(int(hex_code[i:i+2], 16) for i in (0, 2, 4))
        if len(hex_code) == 8:
            return rgb + (int(hex_code[6:8], 16),)
        return rgb

@Czaki Czaki changed the title Use image color when add layer to napari feat: Use image color when add layer to napari Sep 26, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (3)
package/PartSegCore/napari_plugins/loader.py (1)

Line range hint 1-124: Summary of changes and next steps

The changes in this file successfully implement the PR objective of incorporating channel colors when adding layers to napari. The new adjust_color function and its integration into _image_to_layers achieve this goal.

However, there are opportunities for improvement:

  1. Enhance the robustness and clarity of the adjust_color function as suggested earlier.
  2. Verify the compatibility of the adjusted colors with napari's color handling.
  3. Consider adding unit tests for the new adjust_color function and the modified _image_to_layers function to ensure correct behavior and prevent regressions.

To further improve the code:

  1. Consider moving the color adjustment logic to a separate module dedicated to color operations if it's likely to be used elsewhere in the project.
  2. If this color adjustment is specific to napari integration, consider adding a comment explaining its purpose and any napari-specific color format requirements.

Once these improvements are made, the changes will be more robust and maintainable.

package/tests/test_PartSegImage/test_image.py (1)

703-706: LGTM! Good additions to test cases.

The new test cases for hex color codes with alpha channels (#ff0000ff and #b00f) are valuable additions. They improve the coverage of the _hex_to_rgb function by testing its ability to handle 8-digit hex codes and 4-digit shorthand codes with alpha.

The modification of the ValueError test case is also correct, as "#b0000" is indeed an invalid hex code, while the previous "#b000" was actually valid.

Consider adding a test case for a 4-digit hex code without alpha, such as "#0f0f", to ensure complete coverage of all valid hex code formats.

Also applies to: 709-709

package/PartSegImage/image.py (1)

976-978: LGTM! Consider adding support for alpha channel.

The changes to the _hex_to_rgb function improve its flexibility by accepting hex codes with 3, 4, 6, or 8 characters. The logic for handling short-form hex codes is correct, and the error handling for invalid hex code lengths is appropriate.

Consider extending the function to support the alpha channel for 4 and 8 character hex codes. This could be done by returning a tuple of 4 values (R, G, B, A) when an alpha channel is present. Here's a suggested implementation:

 def _hex_to_rgb(hex_code: str) -> tuple[int, int, int]:
-    """
-    Convert a hex color code to an RGB tuple.
+    """
+    Convert a hex color code to an RGB or RGBA tuple.
 
-    :param str hex_code: The hex color code, either short form (#RGB) or long form (#RRGGBB)
-    :return: A tuple containing the RGB values (R, G, B)
+    :param str hex_code: The hex color code, either short form (#RGB or #RGBA) or long form (#RRGGBB or #RRGGBBAA)
+    :return: A tuple containing the RGB or RGBA values (R, G, B) or (R, G, B, A)
     """
     hex_code = hex_code.lstrip("#")
 
     if len(hex_code) in {3, 4}:
         hex_code = "".join([c * 2 for c in hex_code])
     elif len(hex_code) not in {6, 8}:
         raise ValueError(f"Invalid hex code format: {hex_code}")
 
-    return int(hex_code[:2], 16), int(hex_code[2:4], 16), int(hex_code[4:6], 16)
+    rgb = tuple(int(hex_code[i:i+2], 16) for i in (0, 2, 4))
+    if len(hex_code) == 8:
+        return rgb + (int(hex_code[6:8], 16),)
+    return rgb

This change would make the function more versatile while maintaining backwards compatibility.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 416dde7 and edc344f.

📒 Files selected for processing (3)
  • package/PartSegCore/napari_plugins/loader.py (2 hunks)
  • package/PartSegImage/image.py (1 hunks)
  • package/tests/test_PartSegImage/test_image.py (1 hunks)
🔇 Additional comments (2)
package/PartSegCore/napari_plugins/loader.py (1)

39-39: Verify color compatibility with napari

The integration of the adjust_color function in the _image_to_layers function aligns well with the PR objective of incorporating the channel color when adding a layer to napari.

To ensure compatibility, please verify that:

  1. The adjusted colors are always in a format that napari can interpret correctly.
  2. This change doesn't negatively impact existing color handling in napari.

You can run the following script to check the usage and impact of this change:

This will help identify any potential conflicts or areas that might need additional testing.

✅ Verification successful

Color Integration Verified

The addition of the adjust_color function in the _image_to_layers method has been successfully verified. The function is correctly integrated, and existing color handling within napari remains unaffected. Comprehensive tests related to color management are present, ensuring that the changes are well-supported.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the usage of adjust_color and potential impacts

# Search for other usages of adjust_color
echo "Searching for other usages of adjust_color:"
rg "adjust_color\(" --type python

# Search for napari color handling to check for potential conflicts
echo "\nSearching for napari color handling:"
rg "colormap" --type python

# Search for tests related to color handling
echo "\nSearching for color-related tests:"
rg "test.*color" --type python

Length of output: 456


Script:

#!/bin/bash
# Description: Re-attempt searching with explicit Python file patterns

# Search for other usages of adjust_color in Python files
echo "Searching for other usages of adjust_color in Python files:"
fd --extension py --type file | xargs rg "adjust_color\("

# Search for napari color handling to check for potential conflicts in Python files
echo "\nSearching for napari color handling in Python files:"
fd --extension py --type file | xargs rg "colormap"

# Search for tests related to color handling in Python files
echo "\nSearching for color-related tests in Python files:"
fd --extension py --type file | xargs rg "test.*color"

Length of output: 48516

package/PartSegImage/image.py (1)

976-978: Verify the impact of _hex_to_rgb changes on existing code.

The changes to the _hex_to_rgb function improve its flexibility, but we should ensure that this doesn't unintentionally affect other parts of the codebase that may be using this function.

Let's run a quick check to find all occurrences of _hex_to_rgb in the codebase:

Please review the results of this search to ensure that all usages of _hex_to_rgb are compatible with the new implementation.

✅ Verification successful

Impact of _hex_to_rgb Changes Verified Successfully.

All usages of the _hex_to_rgb function have been reviewed, and existing functionality remains intact without introducing any issues.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all occurrences of _hex_to_rgb in the codebase
# Expected result: A list of files and line numbers where _hex_to_rgb is used

rg --type python '_hex_to_rgb'

Length of output: 61


Script:

#!/bin/bash
# Description: Find all occurrences of _hex_to_rgb in Python files using the correct type alias
# Expected result: A list of files and line numbers where _hex_to_rgb is used

rg --type py '_hex_to_rgb'

Length of output: 1098

Comment on lines 10 to 16
def adjust_color(color):
if color.startswith("#"):
if len(color) == 9:
return color[:7]
if len(color) == 5:
return color[:4]
return color
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve robustness and clarity of the adjust_color function

The new adjust_color function has a few areas for improvement:

  1. The function doesn't validate the input color format, which could lead to unexpected behavior with invalid inputs.
  2. The purpose of truncating a 5-character color to 4 characters is unclear and may not be the intended behavior.
  3. The function name doesn't clearly indicate that it's potentially truncating the color.

Consider the following improvements:

  1. Add input validation to ensure the color is in a valid format.
  2. Clarify or reconsider the handling of 5-character colors.
  3. Rename the function to better reflect its purpose, e.g., truncate_color_alpha.

Here's a suggested implementation:

def truncate_color_alpha(color: str) -> str:
    """
    Truncate the alpha channel from hex color strings.
    
    :param color: A string representing a color in hex format.
    :return: The color string with the alpha channel removed, if present.
    :raises ValueError: If the input is not a valid hex color string.
    """
    if not isinstance(color, str):
        raise ValueError("Color must be a string")
    
    if color.startswith("#"):
        if len(color) == 9:  # #RRGGBBAA
            return color[:7]  # Return #RRGGBB
        elif len(color) == 7:  # #RRGGBB
            return color
        elif len(color) == 5:  # #RGBA
            return f"#{color[1]}{color[1]}{color[2]}{color[2]}{color[3]}{color[3]}"  # Expand to #RRGGBB
        elif len(color) == 4:  # #RGB
            return color
    
    # If it's not a hex color or doesn't need truncation, return as is
    return color

This implementation adds input validation, handles 5-character colors by expanding them to 6 characters (which is more common for hex shorthand notation), and includes a docstring for clarity.

@codecov
Copy link

codecov bot commented Sep 26, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 93.13%. Comparing base (416dde7) to head (21813e7).
Report is 29 commits behind head on develop.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #1200   +/-   ##
========================================
  Coverage    93.12%   93.13%           
========================================
  Files          210      210           
  Lines        33121    33149   +28     
========================================
+ Hits         30845    30873   +28     
  Misses        2276     2276           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
package/tests/conftest.py (1)

85-97: LGTM: Enhanced stack_image fixture with channel-specific metadata.

The stack_image fixture has been successfully updated to include channel-specific metadata, which aligns with the PR objective of incorporating channel colors when adding layers to napari. The changes improve the image representation and support better testing of color-related functionality.

A minor suggestion for consistency:

Consider using the same format for both color map hex codes. Currently, you're using an 8-character hex code for the first channel and a 4-character hex code for the second channel. For consistency, you might want to use 8-character hex codes for both:

 channel_info=[
-    ChannelInfo(name="channel 1", color_map="#00FF00FF"),
-    ChannelInfo(name="channel 2", color_map="#00FF"),
+    ChannelInfo(name="channel 1", color_map="#00FF00FF"),
+    ChannelInfo(name="channel 2", color_map="#0000FFFF"),
 ],

This change would ensure that both color maps are represented in the same format, potentially preventing any issues with color interpretation in different parts of the codebase.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 24f781f and 8e1eb08.

📒 Files selected for processing (3)
  • package/PartSegCore/napari_plugins/loader.py (2 hunks)
  • package/tests/conftest.py (3 hunks)
  • package/tests/test_PartSegCore/test_napari_plugins.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package/PartSegCore/napari_plugins/loader.py
🔇 Additional comments (7)
package/tests/test_PartSegCore/test_napari_plugins.py (5)

34-34: Colormap assertion added for the first layer

The new assertion checks that the colormap name of the first layer (l1) is "green". This aligns with the PR objective of incorporating channel colors when adding layers to napari.


36-39: Updated creation and assertions for the second layer

The second layer (l2) is now created from res[1] instead of res[2], and new assertions have been added to check its type, name, and colormap. This change reflects a reordering of the layers returned by project_to_layers and adds color information checking.


40-42: Updated creation and assertions for the third layer

The third layer (l3) is now created from res[2] and is asserted to be a Labels type with the name "ROI". This change is consistent with the reordering of layers in the project_to_layers output.


44-48: New layer added with assertions

A fourth layer (l4) has been added, created from res[3]. It's asserted to be a Labels type with the name "test" and is set to not be visible. This addition expands the test coverage to include all layers returned by project_to_layers.


34-48: Summary of changes in test_project_to_layers_analysis function

The modifications to this test function reflect significant changes in the project_to_layers function's output:

  1. Layer ordering has been updated.
  2. Color information (colormap) is now being checked for image layers.
  3. A new layer (l4) has been added to the test, expanding coverage.

These changes align well with the PR objective of incorporating channel colors when adding layers to napari. The test now provides more comprehensive coverage of the project_to_layers function's output.

package/tests/conftest.py (2)

28-28: LGTM: Import statement updated correctly.

The import statement has been updated to include ChannelInfo along with Image. This change is consistent with the modifications in the stack_image fixture and supports the enhanced functionality for channel-specific metadata.


Line range hint 1-97: Summary: Changes align with PR objectives and enhance testing capabilities.

The modifications to package/tests/conftest.py successfully implement the PR objective of incorporating channel colors when adding layers to napari. The changes are focused and improve the testing capabilities for color-related functionality. The updated stack_image fixture now includes channel-specific metadata, which will allow for more comprehensive testing of color handling in napari layers.

No major issues were found during the review. The only suggestion was a minor improvement for consistency in color map representation. Overall, these changes contribute positively to the project's testing framework and support the enhanced functionality described in the PR objectives.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (1)
package/PartSeg/common_gui/advanced_tabs.py (1)

278-282: LGTM! Consider a minor readability improvement.

The changes effectively implement the PR objective by including color information for each channel. This enhancement provides more detailed and useful information to the user.

For improved readability, consider using an f-string with line breaks:

text = ", ".join(
    f"{name}: {color}"
    for name, color in zip(self.settings.image.channel_names, self.settings.image.get_colors())
)
self.channel_info.setText(f"Channels with colors:\n{text}")

This change would display the channel information on a new line, potentially making it easier to read, especially when there are many channels.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 8e1eb08 and bab3447.

📒 Files selected for processing (2)
  • package/PartSeg/common_gui/advanced_tabs.py (1 hunks)
  • package/PartSegCore/napari_plugins/loader.py (2 hunks)
🔇 Additional comments (3)
package/PartSegCore/napari_plugins/loader.py (3)

2-2: LGTM: New imports are appropriate for the changes.

The new imports for version parsing and the Image type are relevant to the implemented changes. They support version-based conditional logic and improve type annotations.

Also applies to: 5-5, 10-10


69-69: LGTM: Proper integration of color handling in _image_to_layers.

The addition of **add_color(project_info.image, i) to the layer properties is a good way to incorporate the new color handling functionality. It ensures that color information is added when supported without affecting older versions.


Line range hint 1-150: LGTM: Overall structure and consistency maintained.

The file maintains a logical structure with the new additions. The use of type hints is consistent, and the changes are well-integrated without disrupting existing functionality. The focus on color handling and version compatibility is clear and appropriate.

Comment on lines 13 to 32
@typing.overload
def adjust_color(color: str) -> str: ...


@typing.overload
def adjust_color(color: typing.List[int]) -> typing.List[int]: ...


def adjust_color(color: typing.Union[str, typing.List[int]]) -> typing.Union[str, typing.List[int]]:
# as napari ignore alpha channel in color, and adding it to
# color cause that napari fails to detect that such colormap is already present
# in this function I remove alpha channel if it is present
if isinstance(color, str) and color.startswith("#"):
if len(color) == 9:
# case when color is in format #RRGGBBAA
return color[:7]
if len(color) == 5:
# case when color is in format #RGBA
return color[:4]
return color
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance adjust_color function for clarity and robustness.

The adjust_color function is a good addition, but consider the following improvements:

  1. Rename the function to better reflect its purpose, e.g., truncate_color_alpha.
  2. Add input validation for the list input type to ensure it contains valid color values.
  3. Consider handling 8-character hex codes (#RRGGBBAA) in addition to 9-character ones.
  4. Add a docstring to explain the function's purpose and behavior.

Here's a suggested implementation:

@typing.overload
def truncate_color_alpha(color: str) -> str: ...

@typing.overload
def truncate_color_alpha(color: typing.List[int]) -> typing.List[int]: ...

def truncate_color_alpha(color: typing.Union[str, typing.List[int]]) -> typing.Union[str, typing.List[int]]:
    """
    Truncate the alpha channel from color representations.
    
    For hex strings, removes the alpha channel if present.
    For integer lists, ensures the list has 3 elements (RGB).
    
    :param color: A string (hex color) or list of integers (RGB/RGBA values).
    :return: The color with the alpha channel removed, if present.
    :raises ValueError: If the input is invalid.
    """
    if isinstance(color, str):
        if color.startswith("#"):
            if len(color) in (9, 8):  # #RRGGBBAA or #RRGGBB
                return color[:7]
            if len(color) == 5:  # #RGBA
                return color[:4]
            if len(color) in (7, 4):  # #RRGGBB or #RGB
                return color
        raise ValueError(f"Invalid hex color format: {color}")
    elif isinstance(color, list):
        if len(color) == 4:
            return color[:3]
        if len(color) == 3:
            return color
        raise ValueError(f"Invalid color list length: {len(color)}")
    raise TypeError(f"Unsupported color type: {type(color)}")

This implementation adds input validation, handles various hex color formats, and includes a docstring for clarity.

Comment on lines 35 to 46
if parse_version(version("napari")) >= parse_version("0.4.19a1"):

def add_color(image: Image, idx: int) -> dict:
return {
"colormap": adjust_color(image.get_colors()[idx]),
}

else:

def add_color(image: Image, idx: int) -> dict: # noqa: ARG001
# Do nothing, as napari is not able to pass hex color to image
return {}
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve version-based add_color implementation.

The conditional definition of add_color is a good approach for maintaining compatibility. However, consider the following improvements:

  1. Add a comment explaining why older versions return an empty dict.
  2. Consider raising a warning for older versions to inform users about the lack of color support.
  3. Use a constant for the version number to improve maintainability.

Here's a suggested implementation:

NAPARI_COLOR_SUPPORT_VERSION = "0.4.19a1"

if parse_version(version("napari")) >= parse_version(NAPARI_COLOR_SUPPORT_VERSION):
    def add_color(image: Image, idx: int) -> dict:
        return {
            "colormap": truncate_color_alpha(image.get_colors()[idx]),
        }
else:
    import warnings

    def add_color(image: Image, idx: int) -> dict:
        warnings.warn(
            f"Napari version < {NAPARI_COLOR_SUPPORT_VERSION} does not support custom colormaps. "
            "Upgrade napari for full color support.",
            UserWarning
        )
        return {}

This implementation adds a warning for older versions and uses a constant for the version number.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, I do not want to emit warning, just not support.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Czaki, understood. I'll remember that you prefer not to emit warnings in such cases and just not support the feature.

(_/)
(._.)
('')('')


✏️ Learnings added
Learnt from: Czaki
PR: 4DNucleome/PartSeg#1200
File: package/PartSegCore/napari_plugins/loader.py:35-46
Timestamp: 2024-09-27T10:16:22.220Z
Learning: When handling version compatibility, prefer to avoid emitting warnings for unsupported features in older versions and simply not support the feature without warnings.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@sonarqubecloud
Copy link

@Czaki Czaki merged commit ebe8226 into develop Sep 27, 2024
53 checks passed
@Czaki Czaki deleted the set_color_from_metadata branch September 27, 2024 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant