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

[Bug]: float ROI positions lose precision due to uint32 conversion during export #1922

Closed
3 tasks done
RR-N opened this issue Jun 20, 2024 · 2 comments
Closed
3 tasks done
Assignees
Labels
category: question questions about code or code behavior priority: medium non-critical problem and/or affecting only a small set of NWB users

Comments

@RR-N
Copy link

RR-N commented Jun 20, 2024

What happened?

I have a float32 array describing 3D positions (x, y, z). I'm trying to save these to an existing NWB file as such:

NeuroPALTracks = ImageSegmentation(
    name='TrackedNeurons',
)

trackIDs = PlaneSegmentation(
    name='TrackedNeuronROIs',
    description='Neuron centers as tracked throughout GCaMP video. Formatted as (x, y, z, t)',
    imaging_plane=calc_imaging_vol,
)

for eachNeuron in range(len(wlid)):
    trackIDs.add_roi(voxel_mask=[[x[eachNeuron], y[eachNeuron], z[eachNeuron], t[eachNeuron]]])

label = []
for eachNeuron in range(len(wlid)):
    label.append(name[wlid[eachNeuron]])

trackIDs.add_column(
    name='TrackedNeuronIDs',
    description='Neuron ID labels for tracked neuron rois.',
    data=label,
    index=False,
)

NeuroPALTracks.add_plane_segmentation(trackIDs)
nwbfile.processing['CalciumActivity'].add(NeuroPALTracks)

nwbfile.set_modified()
with NWBHDF5IO(output_path, mode='w') as export_io:
    export_io.export(src_io=read_io, nwbfile=nwbfile)

When I then try to load the updated file, I find that all values have been converted into uint32 and thus floored to 0. I've tried explicitly converting values to native float first as such:

for eachNeuron in range(len(wlid)):
    trackIDs.add_roi(voxel_mask=[[float(x[eachNeuron]), float(y[eachNeuron]), float(z[eachNeuron]), float(t[eachNeuron])]])

But that yielded no results. I noticed that I seem to be able to write floats to the file is by passing its value directly, i.e.

for eachNeuron in range(len(wlid)):
    trackIDs.add_roi(voxel_mask=[[float(x[eachNeuron]), float(y[eachNeuron]), float(z[eachNeuron]), 0.053589]])

Will result in (0, 0, 0, 0.053589.) in the updated file. This made me think that maybe the bug stems from an issue referencing the array, but no matter what combination of the above I try, if I specify a variable, I run into this bug:

for eachNeuron in range(len(x)):
    a = float(str(x[eachNeuron]))
    b = float(y[eachNeuron])
    trackIDs.add_roi(voxel_mask=[[a, b, float(z[eachNeuron]), t[eachNeuron]]])

Yields (0, 0, 0, 0.). I've copied minimum reproducible code into a jupyter notebook and uploaded that alongside a copy of my NWB file (stripped of unpublished data) here.

Steps to Reproduce

https://github.com/RR-N/issue-demo/blob/main/conversion_bug_demo.ipynb

Traceback

No response

Operating System

Windows

Python Executable

Python

Python Version

3.10

Package Versions

2to3==1.0
absl-py==1.4.0
accessible-pygments==0.0.4
acvl-utils==0.2
aiobotocore==2.13.0
aiohttp==3.9.5
aioitertools==0.11.0
aiosignal==1.3.1
alabaster==0.7.13
alembic==1.10.3
altgraph==0.17.3
annotated-types==0.7.0
anyio==3.6.2
appdirs==1.4.4
argon2-cffi==21.3.0
argon2-cffi-bindings==21.2.0
arrow==1.2.3
asciitree==0.3.3
asgiref==3.6.0
astor==0.8.1
asttokens==2.2.1
astunparse==1.6.3
async-timeout==4.0.3
attrs==21.4.0
Babel==2.12.1
backcall==0.2.0
batchgenerators==0.25
bcrypt==3.2.2
beautifulsoup4==4.10.0
bidsschematools==0.7.2
bleach==6.0.0
blosc2==2.0.0
boto3==1.26.118
botocore==1.34.106
bqplot==0.12.40
cachetools==5.0.0
certifi==2021.10.8
cffi==1.15.1
chardet==3.0.4
charset-normalizer==2.0.12
ci-info==0.3.0
clearml==1.10.3
click==8.1.3
click-didyoumean==0.3.0
cloudpickle==2.2.1
cmaes==0.9.1
colorama==0.4.6
colorlog==6.7.0
comm==0.1.3
connected-components-3d==3.10.5
contextlib2==21.6.0
contourpy==1.0.7
cryptography==40.0.2
csbdeep==0.7.4
cx-Freeze==6.14.9
cx-Logging==3.1.0
cycler==0.11.0
Cython==3.0.2
dandi==0.62.2
dandischema==0.10.1
databricks-cli==0.17.6
dataclasses==0.6
debugpy==1.6.7
decorator==5.1.1
defusedxml==0.7.1
dicom2nifti==2.4.8
dicomweb-client==0.56.2
discord==1.7.3
discord-ui==5.1.6
discord.py==2.3.0
diskcache==5.6.1
distlib==0.3.6
dnspython==2.3.0
docker==6.0.1
docopt==0.6.2
docutils==0.18.1
dynamic-network-architectures==0.2
ecdsa==0.18.0
einops==0.6.1
email-validator==2.0.0.post2
entrypoints==0.4
et-xmlfile==1.1.0
etelemetry==0.3.0
executing==1.2.0
expiring-dict==1.1.0
expiringdict==1.2.1
fastapi==0.78.0
fasteners==0.18
fastjsonschema==2.16.3
filelock==3.7.1
fire==0.5.0
Flask==2.2.3
flatbuffers==23.3.3
fonttools==4.39.3
fqdn==1.5.1
frozenlist==1.3.3
fscacher==0.3.0
fsspec==2024.6.0
furl==2.1.3
future==0.18.3
gast==0.4.0
gdown==4.7.1
gevent==22.10.2
ghp-import==2.1.0
girder-client==3.1.14
gitdb==4.0.10
GitPython==3.1.31
google==3.0.0
google-api-core==2.7.1
google-api-python-client==2.42.0
google-auth==2.6.2
google-auth-httplib2==0.1.0
google-auth-oauthlib==0.4.6
google-cloud-core==2.3.3
google-pasta==0.2.0
googleapis-common-protos==1.56.0
graphviz==0.20.1
greenlet==2.0.2
grpcio==1.54.0
gspread==5.3.0
h11==0.12.0
h5py==3.10.0
hdmf==3.13.0
highdicom==0.21.1
httpcore==0.15.0
httplib2==0.20.4
httpx==0.23.0
huggingface-hub==0.16.4
humanize==4.6.0
idna==3.3
imagecodecs==2023.3.16
imageio==2.27.0
imagesize==1.4.1
importlib-metadata==6.5.0
interleave==0.2.1
ipydatawidgets==4.3.5
ipykernel==6.22.0
ipython==8.12.0
ipython-genutils==0.2.0
ipyvolume==0.6.3
ipyvue==1.9.2
ipyvuetify==1.8.10
ipywebrtc==0.6.0
ipywidgets==8.0.6
isodate==0.6.1
isoduration==20.11.0
itk==5.3.0
itk-core==5.3.0
itk-filtering==5.3.0
itk-io==5.3.0
itk-numerics==5.3.0
itk-registration==5.3.0
itk-segmentation==5.3.0
itsdangerous==2.1.2
jaraco.classes==3.2.3
jedi==0.18.2
Jinja2==3.1.2
jmespath==1.0.1
joblib==1.2.0
json-tricks==3.16.1
jsonpointer==2.3
jsonschema==3.2.0
jupyter==1.0.0
jupyter-book==0.15.1
jupyter-cache==0.6.1
jupyter-console==6.6.3
jupyter-events==0.6.3
jupyter-http-over-ws==0.0.8
jupyter_client==8.2.0
jupyter_core==5.3.0
jupyter_server==2.5.0
jupyter_server_terminals==0.4.4
jupyterlab-pygments==0.2.2
jupyterlab-widgets==3.0.7
keras==2.10.0
Keras-Preprocessing==1.1.2
keyring==23.13.1
keyrings.alt==4.2.0
kiwisolver==1.4.4
latexcodec==2.0.1
Levenshtein==0.21.0
lib==4.0.0
libclang==16.0.0
libs==0.0.10
lief==0.13.0
lightning-utilities==0.8.0
linecache2==1.0.0
linkify-it-py==2.0.2
llvmlite==0.40.0
lmdb==1.4.1
Mako==1.2.4
Markdown==3.4.3
markdown-it-py==2.2.0
MarkupSafe==2.1.2
matplotlib==3.8.3
matplotlib-inline==0.1.6
mccabe==0.7.0
mdit-py-plugins==0.3.5
mdurl==0.1.2
MedPy==0.4.0
mistune==2.0.5
mlflow==2.3.0
monai==1.1.0
monai-deploy-app-sdk==0.5.0
monai-weekly==1.2.dev2316
monailabel==0.6.0
more-itertools==9.1.0
mpmath==1.3.0
msgpack==1.0.5
multidict==6.0.2
munch==2.5.0
munkres==1.1.4
myst-nb==0.17.2
myst-parser==0.18.1
mystmd==1.1.49
natsort==8.3.1
nbclassic==0.5.5
nbclient==0.7.3
nbconvert==7.6.0
nbdiff==1.0.3
nbformat==5.8.0
nd2reader==3.3.0
ndx-multichannel-volume==0.1.12
nest-asyncio==1.5.6
networkx==3.1
nibabel==5.1.0
ninja==1.10.2.3
nltk==3.8.1
nni==2.10
nnunetv2==2.1
notebook==6.5.4
notebook_shim==0.2.2
numba==0.57.0
numcodecs==0.11.0
numexpr==2.8.5
numpy==1.23.4
numpymaxflow==0.0.5
nwbinspector==0.4.37
oauth2client==4.1.3
oauthlib==3.2.0
opencv-python==4.5.5.64
opencv-python-headless==4.5.5.64
openpyxl==3.1.2
openslide-python==1.1.2
opt-einsum==3.3.0
optuna==3.1.1
orderedmultidict==1.0.1
packaging==23.1
pandas==1.4.2
pandocfilters==1.5.0
parameterized==0.9.0
parso==0.8.3
passlib==1.7.4
pathlib2==2.3.7.post1
pefile==2023.2.7
pickleshare==0.7.5
Pillow==9.4.0
pillow-jpls==1.2.0
PIMS==0.6.1
pims-nd2==1.1
pipreqs==0.4.13
pipreqsnb==0.2.4
platformdirs==3.2.0
plotext==5.2.8
plotly==5.15.0
pretrainedmodels==0.7.4
prettytable==3.7.0
prometheus-client==0.16.0
prompt-toolkit==3.0.38
protobuf==3.19.6
psutil==5.9.6
psycopg2==2.9.6
pure-eval==0.2.2
py-cpuinfo==9.0.0
py2exe==0.13.0.0
pyarrow==11.0.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pybtex==0.24.0
pybtex-docutils==1.0.2
pycodestyle==2.10.0
pycparser==2.21
pycryptodomex==3.17
pydantic==2.7.4
pydantic_core==2.18.4
pydata-sphinx-theme==0.13.3
pydicom==2.3.0
pydicom-seg==0.4.0
pyflakes==3.0.1
Pygments==2.15.1
pyinstaller==6.6.0
pyinstaller-hooks-contrib==2024.5
PyJWT==2.4.0
pymongo==4.4.1
pynetdicom==2.0.2
pynrrd==0.4.3
pynwb==2.6.0
pyout==0.7.3
pyparsing==3.0.7
PyQt5==5.15.9
pyqt5-plugins==5.15.9.2.3
PyQt5-Qt5==5.15.2
PyQt5-sip==12.13.0
pyqt5-tools==5.15.9.3.3
pyreadline3==3.4.1
pyreqs==0.1.1
pyrsistent==0.19.3
PySocks==1.7.1
python-dateutil==2.8.2
python-dotenv==0.20.0
python-gdcm==3.0.21
python-jose==3.3.0
python-json-logger==2.0.7
python-Levenshtein==0.21.0
python-multipart==0.0.5
PythonWebHDFS==0.2.3
pythreejs==2.4.2
pytorch-ignite==0.4.10
pytorch-lightning==1.9.5
pytz==2022.1
PyWavelets==1.4.1
pywin32==306
pywin32-ctypes==0.2.2
pywinpty==2.0.10
PyYAML==6.0
pyzmq==25.0.2
qgrid==1.3.1
qt5-applications==5.15.2.2.3
qt5-tools==5.15.2.1.3
qtconsole==5.4.4
QtPy==2.4.1
querystring-parser==1.2.4
rapidfuzz==3.0.0
regex==2023.3.23
requests==2.27.1
requests-oauthlib==1.3.1
requests-toolbelt==0.9.1
responses==0.23.1
retrying==1.3.4
rfc3339-validator==0.1.4
rfc3986==1.5.0
rfc3986-validator==0.1.1
rfc3987==1.3.8
rsa==4.8
ruamel.yaml==0.17.21
ruamel.yaml.clib==0.2.7
s3fs==2024.6.0
s3transfer==0.6.0
safetensors==0.3.2
schedule==1.1.0
schema==0.7.5
scikit-image==0.19.3
scikit-learn==1.2.1
scipy==1.10.0
seaborn==0.12.2
semantic-version==2.10.0
Send2Trash==1.8.0
setuptools-scm==7.1.0
sh==2.0.3
Shapely==1.8.2
SimpleITK==2.2.1
simplejson==3.19.1
six==1.16.0
slicerator==1.1.0
smmap==5.0.0
sniffio==1.3.0
snowballstemmer==2.2.0
sortedcontainers==2.4.0
soupsieve==2.3.1
Sphinx==5.0.2
sphinx-book-theme==1.0.1
sphinx-comments==0.0.3
sphinx-copybutton==0.5.2
sphinx-jupyterbook-latex==0.5.2
sphinx-multitoc-numbering==0.1.3
sphinx-thebe==0.2.1
sphinx-togglebutton==0.3.2
sphinx_design==0.3.0
sphinx_external_toc==0.3.1
sphinxcontrib-applehelp==1.0.4
sphinxcontrib-bibtex==2.5.0
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
SQLAlchemy==2.0.9
sqlparse==0.4.4
stack-data==0.6.2
stardist==0.8.5
starlette==0.19.1
strict-rfc3339==0.7
sympy==1.11.1
tables==3.8.0
tabulate==0.9.0
tdqm==0.0.1
tenacity==8.2.2
tensorboard==2.10.1
tensorboard-data-server==0.6.1
tensorboard-plugin-wit==1.8.1
tensorboardX==2.6
tensorflow==2.10.0
tensorflow-estimator==2.10.0
tensorflow-io-gcs-filesystem==0.31.0
tensortools==0.4
termcolor==2.2.0
terminado==0.17.1
threadpoolctl==3.1.0
tifffile==2023.4.12
timeloop==1.0.2
tinycss2==1.2.1
tokenizers==0.12.1
tomli==2.0.1
tomlkit==0.11.7
torch==2.0.0+cu118
torchaudio==2.0.1+cu118
torchmetrics==0.11.4
torchvision==0.15.1+cu118
tornado==6.3
tqdm==4.65.0
traceback2==1.4.0
traitlets==5.9.0
traittypes==0.2.1
transformers==4.31.0
typeguard==3.0.2
types-pkg-resources==0.1.3
types-PyYAML==6.0.12.9
typing_extensions==4.7.1
tzdata==2023.3
uc-micro-py==1.0.2
unittest2==1.1.0
uri-template==1.2.0
uritemplate==4.1.1
urllib3==1.26.9
uvicorn==0.17.6
virtualenv==20.21.0
waitress==2.1.2
watchdog==2.1.8
wcwidth==0.2.6
webcolors==1.13
webencodings==0.5.1
websocket-client==1.5.1
websockets==11.0.2
Werkzeug==2.2.3
widgetsnbextension==4.0.7
WMI==1.5.1
wordcloud==1.9.2
wrapt==1.15.0
xmltodict==0.13.0
yacs==0.1.8
yarg==0.1.9
yarl==1.9.4
zarr==2.14.2
zarr-checksum==0.4.0
zephir==1.0.4
zipp==3.15.0
zope.event==4.6
zope.interface==6.0

Code of Conduct

@RR-N RR-N changed the title [Bug]: numpy.float32 ROI positions lose precision due to uint32 conversion during export [Bug]: numpy.float ROI positions lose precision due to uint32 conversion during export Jun 20, 2024
@RR-N RR-N changed the title [Bug]: numpy.float ROI positions lose precision due to uint32 conversion during export [Bug]: float ROI positions lose precision due to uint32 conversion during export Jun 20, 2024
@stephprince
Copy link
Contributor

Hi @RR-N, thanks for submitting this issue and for sharing a great minimal working example and notebook!

In the nwb schema, a voxel mask is specified to be a list of indices and weights for the ROI (x, y, z, weight) as (uint32, uint32, uint32, float32):

So pynwb is expecting that your (x, y, z) coordinates are describing your ROI in terms of indices of your image data and is automatically converting them to uint32 when writing the file.

# e.g. a 3 x 1 x 1 voxel region of weight '0.5'
 voxel_mask = [
 (0, 0, 0, 0.5),
 (1, 0, 0, 0.5),
 (2, 0, 0, 0.5)
]
trackIDs.add_roi(voxel_mask=voxel_mask)

If you convert the float32 coordinates you have into the corresponding voxel indices of your images you should be able to add a voxel_mask with those values.

@stephprince stephprince added category: bug errors in the code or code behavior priority: medium non-critical problem and/or affecting only a small set of NWB users labels Jun 21, 2024
@rly rly added category: question questions about code or code behavior and removed category: bug errors in the code or code behavior labels Jun 27, 2024
@rly rly assigned rly and stephprince and unassigned rly Jun 27, 2024
@stephprince
Copy link
Contributor

I think this has been addressed so will close this issue for now. Please reopen if needed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category: question questions about code or code behavior priority: medium non-critical problem and/or affecting only a small set of NWB users
Projects
None yet
Development

No branches or pull requests

3 participants