forked from AllenNeuralDynamics/poisson-numcodecs
-
Notifications
You must be signed in to change notification settings - Fork 4
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
rename the package as anscombe_numcodecs
#17
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
349aaee
update package configration for "anscombe-numcodecs"
dimitri-yatsenko 33e8418
complete the renaming of the package
dimitri-yatsenko 33adadf
update the workbook to use the new package name
dimitri-yatsenko aef7b04
cleaned up dependencies
dimitri-yatsenko 0b0091a
attempt to fix github test workflow
dimitri-yatsenko 3a1eeb5
debugging test workflow
dimitri-yatsenko 345bc96
debugging test workflow
dimitri-yatsenko ecd5c4b
remove MacOS tests
dimitri-yatsenko c089605
typo in test workflow config
dimitri-yatsenko be7c5a1
debug test workflow
dimitri-yatsenko 20f2942
changed the datatype dimensions to uint32 to allow for large arrays
dimitri-yatsenko e5413c8
blackify
dimitri-yatsenko 7064aff
update workbook
dimitri-yatsenko File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,20 +3,37 @@ requires = ["setuptools>=61.0"] | |
build-backend = "setuptools.build_meta" | ||
|
||
[project] | ||
name = "poisson_numcodecs" | ||
version = "0.1.0" | ||
name = "anscombe_numcodecs" | ||
version = "0.1.2" | ||
authors = [ | ||
{ name="Jerome Lecoq", email="[email protected]" }, | ||
{ name = "Jerome Lecoq", email = "[email protected]" }, | ||
{ name = "Dimitri Yatsenko", email = "[email protected]" }, | ||
] | ||
description = "Numcodecs implementation of a poisson noise calibration." | ||
maintainers = [ | ||
{ name = "Dimitri Yatsenko", email = "[email protected]" }, | ||
] | ||
license = { file = "LICENSE" } | ||
description = "Numcodecs implementation for compressing photon-limited movies." | ||
readme = "README.md" | ||
requires-python = ">=3.8" | ||
keywords = ["video compression", "numcodecs", "zarr", "compression algorithms", "multimedia", "multiphoton microscopy"] | ||
classifiers = [ | ||
"Programming Language :: Python :: 3", | ||
"License :: OSI Approved :: MIT License", | ||
"Operating System :: OS Independent", | ||
"Topic :: Multimedia :: Video", | ||
"Topic :: Software Development :: Libraries", | ||
] | ||
|
||
dependencies = [ | ||
"numpy>=2.0", | ||
"numcodecs>=0.1", | ||
"scikit-learn", | ||
] | ||
|
||
# Dependencies will be managed via requirements.txt | ||
|
||
[project.urls] | ||
Homepage = "https://github.com/AllenNeuralDynamics/poisson-numcodecs" | ||
Issues = "https://github.com/AllenNeuralDynamics/poisson-numcodecs/issues" | ||
Homepage = "https://github.com/datajoint/anscombe-numcodecs" | ||
Source = "https://github.com/datajoint/anscombe-numcodecs" | ||
Issues = "https://github.com/datajoint/anscombe-numcodecs/issues" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
numpy | ||
numcodecs | ||
zarr | ||
matplotlib | ||
zarr>=2.18 | ||
scipy | ||
scikit-learn | ||
imageio | ||
matplotlib | ||
pytest>=7.0 | ||
pytest-cov | ||
black | ||
flake8 | ||
mypy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from .codec import AnscombeCodec | ||
from . import estimate | ||
|
||
__all__ = ["AnscombeCodec", "estimate"] |
73 changes: 42 additions & 31 deletions
73
src/poisson_numcodecs/codec.py → src/anscombe_numcodecs/codec.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,98 +1,109 @@ | ||
""" | ||
Numcodecs Codec implementation for Poisson noise calibration | ||
""" | ||
|
||
import numpy as np | ||
import numcodecs | ||
from numcodecs.abc import Codec | ||
|
||
|
||
def make_anscombe_lookup( | ||
sensitivity: float, | ||
input_max: int=0x7fff, | ||
zero_level: int=0, | ||
beta: float=0.5, | ||
output_type='uint8'): | ||
sensitivity: float, | ||
input_max: int = 0x7FFF, | ||
zero_level: int = 0, | ||
beta: float = 0.5, | ||
output_type="uint8", | ||
): | ||
""" | ||
Compute the Anscombe lookup table. | ||
The lookup converts a linear grayscale image into a uniform variance image. | ||
The lookup converts a linear grayscale image into a uniform variance image. | ||
:param sensitivity: the size of one photon in the linear input image. | ||
:param input_max: the maximum value in the input | ||
:param beta: the grayscale quantization step expressed in units of noise std dev | ||
""" | ||
xx = (np.r_[:input_max + 1] - zero_level) / sensitivity # input expressed in photon rates | ||
zero_slope = 1 / beta / np.sqrt(3/8) # slope for negative values | ||
xx = ( | ||
np.r_[: input_max + 1] - zero_level | ||
) / sensitivity # input expressed in photon rates | ||
zero_slope = 1 / beta / np.sqrt(3 / 8) # slope for negative values | ||
offset = zero_level * zero_slope / sensitivity | ||
lookup_table = np.round(offset + | ||
(xx < 0) * (xx * zero_slope) + | ||
(xx >= 0) * (2.0 / beta * (np.sqrt(np.maximum(0, xx) + 3/8) - np.sqrt(3/8)))) | ||
lookup_table = np.round( | ||
offset | ||
+ (xx < 0) * (xx * zero_slope) | ||
+ (xx >= 0) | ||
* (2.0 / beta * (np.sqrt(np.maximum(0, xx) + 3 / 8) - np.sqrt(3 / 8))) | ||
) | ||
lookup = lookup_table.astype(output_type) | ||
assert np.diff(lookup_table).min() >= 0, "non-monotonic lookup generated" | ||
return lookup | ||
|
||
|
||
def make_inverse_lookup(lookup_table: np.ndarray, output_type='int16') -> np.ndarray: | ||
def make_inverse_lookup(lookup_table: np.ndarray, output_type="int16") -> np.ndarray: | ||
"""Compute the inverse lookup table for a monotonic forward lookup table.""" | ||
_, inv1 = np.unique(lookup_table, return_index=True) # first entry | ||
_, inv2 = np.unique(lookup_table[::-1], return_index=True) # last entry | ||
inverse = (inv1 + lookup_table.size - 1 - inv2)/2 | ||
inverse = (inv1 + lookup_table.size - 1 - inv2) / 2 | ||
return inverse.astype(output_type) | ||
|
||
|
||
def lookup(movie: np.ndarray, lookup_table: np.ndarray) -> np.ndarray: | ||
"""Apply lookup table to movie""" | ||
return lookup_table[np.maximum(0, np.minimum(movie, lookup_table.size-1))] | ||
return lookup_table[np.maximum(0, np.minimum(movie, lookup_table.size - 1))] | ||
|
||
|
||
class PoissonCodec(Codec): | ||
class AnscombeCodec(Codec): | ||
"""Codec for 3-dimensional Filter. The codec assumes that input data are of shape: | ||
(time, x, y). | ||
|
||
Parameters | ||
---------- | ||
zero_level : float | ||
Signal level when no photons are recorded. | ||
Signal level when no photons are recorded. | ||
This should pre-computed or measured directly on the instrument. | ||
photon_sensitivity : float | ||
Conversion scalor to convert the measure signal into absolute photon numbers. | ||
This should pre-computed or measured directly on the instrument. | ||
""" | ||
|
||
codec_id = "poisson" | ||
|
||
def __init__(self, | ||
zero_level, | ||
photon_sensitivity, | ||
encoded_dtype='int8', | ||
decoded_dtype='int16', | ||
): | ||
def __init__( | ||
self, | ||
zero_level, | ||
photon_sensitivity, | ||
encoded_dtype="int8", | ||
decoded_dtype="int16", | ||
): | ||
self.zero_level = zero_level | ||
self.photon_sensitivity = photon_sensitivity | ||
self.encoded_dtype = encoded_dtype | ||
self.decoded_dtype = decoded_dtype | ||
|
||
def encode(self, buf: np.ndarray) -> np.ndarray: | ||
lookup_table = make_anscombe_lookup( | ||
self.photon_sensitivity, | ||
self.photon_sensitivity, | ||
output_type=self.encoded_dtype, | ||
zero_level=self.zero_level, | ||
) | ||
encoded = lookup(buf, lookup_table) | ||
shape = [encoded.ndim] + list(encoded.shape) | ||
shape = np.array(shape, dtype='uint8') | ||
shape = np.array(shape, dtype="uint32") | ||
return shape.tobytes() + encoded.astype(self.encoded_dtype).tobytes() | ||
|
||
def decode(self, buf: bytes, out=None) -> np.ndarray: | ||
lookup_table = make_anscombe_lookup( | ||
self.photon_sensitivity, | ||
self.photon_sensitivity, | ||
output_type=self.encoded_dtype, | ||
zero_level=self.zero_level, | ||
) | ||
inverse_table = make_inverse_lookup( | ||
lookup_table, | ||
output_type=self.decoded_dtype | ||
lookup_table, output_type=self.decoded_dtype | ||
) | ||
ndims = int(buf[0]) | ||
shape = [int(_) for _ in buf[1:ndims+1]] | ||
decoded = np.frombuffer(buf[ndims+1:], dtype=self.encoded_dtype).reshape(shape) | ||
ndims = np.frombuffer(buf[:4], "uint32")[0] | ||
shape = np.frombuffer(buf[4 : 4 * (ndims + 1)], "uint32") | ||
decoded = np.frombuffer( | ||
buf[(ndims + 1) * 4 :], dtype=self.encoded_dtype | ||
).reshape(shape) | ||
return lookup(decoded, inverse_table).astype(self.decoded_dtype) | ||
|
||
|
||
numcodecs.register_codec(PoissonCodec) | ||
numcodecs.register_codec(AnscombeCodec) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename this test as well?