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

Option to superimpose labels on wells #24

Closed
kalekundert opened this issue Mar 16, 2022 · 7 comments
Closed

Option to superimpose labels on wells #24

kalekundert opened this issue Mar 16, 2022 · 7 comments

Comments

@kalekundert
Copy link
Owner

Sometimes it's easier to read a plate map with the labels superimposed on each cell, rather than coloring each cell and having a color bar off to the right. Specifically, this is the case when there are lots of different labels with no intrinsic ordering, and all of the labels are short. I ran into this when I was making a map for a 24-well block of cultures I was growing, and each culture had a name like "sN", where N is a 1-3 digit number.

In order to support this, I'd have to add a "visualization" section to the file. Maybe meta.visualization or meta.labels, since meta is already kind-of a grab-bag of thinks that have meaning to wellmap.

@bwolfe-benchling
Copy link

I looked at this a little bit and it seems like providing an argument ito the show() method in plot.py might be the most straightforward way to enable this. I have tested an approach that superimposes the labels and uses the lightness of the background color to dynamically set the font color to white or black.

A few details that need to be considered though:

  • Font size 6 using the default font on my system was easiest to read but is too large to support a sample id like sN123
    font6_cell25

  • Font size 5 fits (barely) but for me is a bit of eye strain to read on screen
    font5_cell25

  • Font size 6 and adjusting the cell size from 0.25 to 0.35 looks nice (Is there a compelling reason that cell size needs to be 0.25?)
    font6_cell35

@kalekundert what do you think? Thoughts on cell size vs. font size or the approach to using a boolean flag on the show method to indicate how labels should be handled?

@kalekundert
Copy link
Owner Author

Looks nice! I like the dynamic white/black text. Sorry I haven't gotten around to adding this feature yet, but I'd be happy to review a PR.

The issue with just adding an argument to show() is that the command-line wellmap program wouldn't have any way of knowing when to render labels like this. That's why I think there has to be some sort of option for this in the TOML file itself. Of course, implementing this option would probably involve adding an argument to show().

Now that I'm thinking about it, instead of just adding an argument for superimposing labels, it would be better to add a "style" argument that could control all aspects of the plot. Basically, a style would be a custom object that specifies color maps, labeling strategies, cell/margin/padding sizes, etc. It could even specify different values for different attributes (i.e. superimpose labels for the "sample name" attribute, but not for the "concentration" attribute). Here's some pseudo-code showing how this might work:

style = Style()

# Change the color map for all attributes:
style.color_map = 'rainbow'

# Only superimpose labels for this attribute:
style['sample name'].superimpose_labels = True

show('path/to/layout.toml', style=style)

Since we want the user to be able to specify style information in the TOML file itself, it would probably make sense to have load() parse that information and return a style object (in addition to everything else). The wellmap GUI would then be able to get this style, update it according to any command-line arguments it received, then pass it on to plot_layout().

Regarding cell/font sizes, I like the idea of adding style options for (i) every size that goes into formatting the plot, so the user can tinker with things until they get a layout that works for them and (ii) the algorithm to apply when not all the labels fit in their cells.
Some options for this algorithm might be:

  • Do nothing, just let the text overflow the cell.
  • Truncate overflowing labels. This might be useful for long labels that can be distinguished by just the first few characters.
  • Shrink overflowing labels. The nice thing about this is that it'll only affect the big labels, so the overall plot can stay compact and readable if most of the labels won't need to be shrunk.
  • Expand all the cells to accommodate the biggest label. This could produce comical results for really long labels, but could work for some layouts.

If all these options were available, then I think a good default would be the 0.25" cells with size 6 text and either the "do nothing" or "shrink big labels" algorithm. That would be consistent with "normal" plots and readable for small labels. For larger labels, it'd be up to the user to decide what exactly they want.

Anyways, I know I really expanded the scope of this issue here, so don't feel obligated to submit a PR implementing all this. That said, I probably won't want to merge a change that just adds a boolean argument to show() now, because that feels like it would be a step in the wrong direction. I'd definitely merge a change that adds a style object, though, even if it didn't do anything else. Let me know if you want to do that, otherwise I might work on it this weekend.

@bwolfe-benchling
Copy link

The rationale behind the boolean on show(), was that I could provide a default value of false. Then I could expose a command line argument to set the boolean as well.  This way you could control the inline vs. legend based labels either way.  Style object might not be too bad to implement, but then really increases complexity of command line args.

@kalekundert
Copy link
Owner Author

You're right, that would work. There still should be an option to control how the labels are rendered via the TOML file, since the best way of visualizing any layout is intrinsic to that layout, but it doesn't have to be implemented right away.

I still think that a plain boolean argument would be too simple: most layouts have many attributes and you'd only want to superimpose labels for some of them, so there would need to be a way to specify how to draw the labels on a per-attribute basis. I'm imagining command-line arguments something like this:

-s --superimpose-labels ATTRS
    Render the labels directly over each well, rather than in a legend off to the side.  Specify multiple attributes separated by commas.
-S --superimpose-all-labels
    Same as `-s`, but for all attributes.

This would mean that the argument to show() would have to be a list of strings, or a style object (which could manage this complexity internally).

I don't think the style argument would significantly increase the complexity of the command-line arguments. I assume you mean that there would be a lot more arguments than there currently are. But there wouldn't need to be an argument for every possible setting, just the ones that are likely to come up when setting up/analyzing an experiment. Right now I think that's just the color map, but with these superimposed labels that might also include cell size, labeling strategy, and label size. People can always fall back on the python API if they want something fancy.

The more I think about it, the more I like the idea of having a style object. Let me try to implement that today/tomorrow. I don't think it'll be too hard, and I have a pretty good idea of how I want to do it. I won't do any of the superimposed label stuff, I'll just refactor the existing functionality. Then hopefully you can make a PR with your work on the labels, and we can get it all merged.

@kalekundert
Copy link
Owner Author

I didn't quite finish adding the Style object over the weekend. The code is mostly written, but I still have to write some new documentation and update the R bindings. I am focusing on this, though, so hopefully it shouldn't be too much longer.

@alpha-1-centauri
Copy link

Hi Kale, has this been implemented (with exception of documentation)? This would very useful for some DoE experiments I am preparing and very keen to use your well-designed package for experimental protocols.

@kalekundert
Copy link
Owner Author

Ugh, I hate that I said I was almost done with this in February and now it's August. I appreciate the poke, though. I'll try to make some progress this week. That said, the code I've written so far just adds a Style object; it doesn't implement the superimposed labels. Adding the labels will be some more work.

kalekundert added a commit that referenced this issue Sep 13, 2023
This commit also adds some infrastructure to help with customizing the
appearance of layouts:

- The `extras` and `report_dependencies` arguments to `load()` are
  deprecated, and replaced by the new `meta` argument.

- Style objects can be specified in TOML files, in new [meta.style] and
  [meta.param_styles] tables.

- The `Style` class was rewritten to give it the ability to check for
  errors, and to merge styles.

Fixes #24
kalekundert added a commit that referenced this issue Sep 13, 2023
This commit also adds some infrastructure to help with customizing the
appearance of layouts:

- The `extras` and `report_dependencies` arguments to `load()` are
  deprecated, and replaced by the new `meta` argument.

- Style objects can be specified in TOML files, in new [meta.style] and
  [meta.param_styles] tables.

- The `Style` class was rewritten to give it the ability to check for
  errors, and to merge styles.

Fixes #24
kalekundert added a commit that referenced this issue Sep 13, 2023
This commit also adds some infrastructure to help with customizing the
appearance of layouts:

- The `extras` and `report_dependencies` arguments to `load()` are
  deprecated, and replaced by the new `meta` argument.

- Style objects can be specified in TOML files, in new [meta.style] and
  [meta.param_styles] tables.

- The `Style` class was rewritten to give it the ability to check for
  errors, and to merge styles.

Fixes #24
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

No branches or pull requests

3 participants