Skip to content

Add PixelMap class#380

Merged
psomhorst merged 79 commits intodevelopfrom
feat_pixel_map
Aug 5, 2025
Merged

Add PixelMap class#380
psomhorst merged 79 commits intodevelopfrom
feat_pixel_map

Conversation

@psomhorst
Copy link
Copy Markdown
Contributor

@psomhorst psomhorst commented Jun 4, 2025

This PR introduces the PixelMap class for representation of a 2D array of pixel values. It includes math functions to add/subtract/divide/multiply with scalars, arrays or other PixelMaps. It includes a thresholding feature to set values below (or above) a threshold to np.nan. It includes an imshow method to make plotting the pixel map easy.

Subclasses set default values for plotting. There is a convert_to method to convert to different subclasses.

I defined a set of subclasses that can be expanded later.

  • TIVMap for TIV or amplitude maps
  • ODCLMap for overdistention/collapse maps
  • PerfusionMap for perfusion data
  • PendelluftMap for pendelluft data
  • SignedPendelluftMap for pendelluft data that include negative values indicating the direction of phase change
  • DifferenceMap for differences between other maps

I've written this according to some new 'best practice' rules:

  • At initialization, time (not the case here) and values can be supplied as positional arguments, the rest can only be supplied as keyword arguments.
  • All classes holding data and their attributes are frozen, i.e. immutable
  • Classes can be updated using an update method that returns a copy with the keyword arguments replacing attributes.

I included a test_pixelmap_imshow notebook with examples and tests for the visual part of imshow.

Included in this PR is a slight restructuring of the documentation. I can extract it to a different PR if necessary.

I've tried to keep with default colormaps, or use black -> color. However, I think these can be tweaked a bit further, e.g. with black -> color -> white. Any suggestions are welcome!

@psomhorst
Copy link
Copy Markdown
Contributor Author

psomhorst commented Jun 18, 2025

To be discussed:

I wrote an update method that can be used to create an updated version of a frozen object:

PixelMap(data, label="foo").update(label="bar") is the same as PixelMap(data, label="bar").

update internally uses dataclasses.replace. I thought the name update better described the functionality than replace. However, I just found out that copy.replace exists since Python 3.13, which does the same thing, and can be implemented in custom classes with a __replace__() method. Therefore, it seems replace is the proper term for this process.

I renamed update to __replace__ and let update refer to __replace__. This adds support for copy.replace(). However, maybe update should be renamed replace instead, since this is the probably way this will be called in all Python APIs in the future. (Currently, e.g. attrs calls this functionality evolve(), which is worse).

I think there are three options:

  1. Leave as is.
  2. Rename update() to replace().
  3. Add replace() and leave update() in place.

I still think update() is a better name, but replace() is going to be the standard, and therefore easier to explain. Having both is an option, but is less clear and more difficult to explain.
Since we want to implement this functionality in almost all other classes in eitprocessing, we should make a well-founded decision now.

@psomhorst psomhorst mentioned this pull request Jul 25, 2025
@psomhorst
Copy link
Copy Markdown
Contributor Author

@JulietteFrancovich Then, finally, this last (?) PR. I addressed your comments.

Could you check whether you agree with only a from_aggregate(...) function, or would prefer separate functions for mean, median, min, max, etc?

Also, this includes a TIVMap that could represent TIV or amplitude. Should we differentiate?

@psomhorst psomhorst mentioned this pull request Aug 4, 2025
@psomhorst psomhorst merged commit d8ed4d8 into develop Aug 5, 2025
3 checks passed
@psomhorst psomhorst deleted the feat_pixel_map branch August 5, 2025 09:54
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.

2 participants