Skip to content
Snippets Groups Projects
Commit c2314caa authored by Simon Wittl's avatar Simon Wittl
Browse files

readme update

parent df8bbede
No related branches found
No related tags found
No related merge requests found
image: ubuntu:latest
stages:
- code_embed
- ruff
variables:
GIT_STRATEGY: clone
code_embedder:
stage: code_embed
script:
- cd code-embedder/
- poetry install --only main
- README_PATHS=$(find .. -maxdepth 1 -name "*.md" -print)
- poetry run python ./src/main.py --readme-paths $README_PATHS
- cd ..
- README_PATHS=$(find . -maxdepth 1 -name "*.md" -print)
- git add $README_PATHS
- git diff --staged
- export BRANCH_NAME="${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:-$CI_COMMIT_REF_NAME}"
- echo "branch name $BRANCH_NAME"
- git remote set-url origin "https://oauth2:${PERSONAL_ACCESS_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git"
- echo "https://oauth2:${PERSONAL_ACCESS_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git"
- if ! git diff --cached --exit-code; then
git commit -m "Apply Code Embedder";
git push origin HEAD:$BRANCH_NAME;
else
echo "No changes to commit";
fi
before_script:
- apt-get update && apt-get install -y curl git python3 python3-pip
- curl -sSL https://install.python-poetry.org | python3 -
- export PATH="$HOME/.local/bin:$PATH"
- git clone https://github.com/kvankova/code-embedder.git --branch "v0.5.2"
- git config --global user.email $GITLAB_USER_EMAIL
- git config --global user.name $GITLAB_USER_NAME
only:
- merge_requests
ruff_linter:
stage: ruff
script:
- curl -LsSf https://astral.sh/uv/install.sh | sh
- source $HOME/.local/bin/env
- uv tool run ruff check
before_script:
- apt-get update && apt-get install -y curl
only:
- merge_requests
# Json Datadefinition
![](./examples/logo.svg)
This repository contains `.h5` I/O utilities for the RoboCT group at Deggendorf. The data structure is auto generated from [THD JSON](https://mygit.th-deg.de/roboct/definitions/json_schemas).
For information of the data structure please look at `THD JSON`.
This repository contains `.h5` I/O utilities for the RoboCT group at Deggendorf. The data structure is auto generated from [THD JSON](https://mygit.th-deg.de/roboct-public/roboct-schemas).
For information of the data structure / group names please look at `THD JSON`.
## Examples
The main groups for a RoboCT project can be seen here [here](./examples/README.md).
You can explore small dataset with the HDF5 Viewer.
![](./examples/h5_viewer.png)
## Usage
### Initialize a File
```python:../scripts/generate_example_projection.py
from h5py import File
import numpy as np
from h5schemas.projection.add_projection import (
init_projection_dataset,
add_projection_sample,
)
def main():
# Generate a file in write mode.
test_file = File("./examples/projection.h5", "w")
# Initialize the .H5 structure
init_projection_dataset(test_file, False, (128, 128), (0.139, 0.139))
# Add dummy projections
add_projection_sample(
test_file,
1e5 * np.random.random((128, 128)),
[0.0, 1.0, 2.0],
[3.0, 4.0, 5.0, 6.0],
[7.0, 8.0, 9.0],
[10.0, 11.0, 12.0, 13],
)
add_projection_sample(
test_file,
1e5 * np.random.random((128, 128)),
np.array([0.0, 1.0, 2.0]),
np.array([3.0, 4.0, 5.0, 6.0]),
np.array([7.0, 8.0, 9.0]),
np.array([10.0, 11.0, 12.0, 13]),
voltage_kv=100,
)
# Access data
print(test_file["/image/image_array"][...])
if __name__ == "__main__":
main()
```
### Append new Group
```python:../scripts/add_joint_states_to_projection.py
from h5py import File
import numpy as np
from h5schemas.projection.add_projection import (
add_projection_sample,
)
from h5schemas.thd_joint_states.add_thd_joint_states import (
init_thd_joint_states,
add_thd_joint_states_sample,
)
def main():
# Generate a file in write mode.
test_file = File("./examples/projection.h5", "a")
# Add a new projection sample
add_projection_sample(
test_file,
1e5 * np.random.random((128, 128)),
[0.0, 1.0, 2.0],
[3.0, 4.0, 5.0, 6.0],
[7.0, 8.0, 9.0],
[10.0, 11.0, 12.0, 13],
)
# Add a new group
init_thd_joint_states(test_file)
add_thd_joint_states_sample(test_file, *np.arange(15))
if __name__ == "__main__":
main()
```
### Slice / Load a Dataset
```python:../scripts/load_slice.py
from h5py import File
from h5schemas.load_utilities.projection import extract_projection, GeomOptions
def main():
# Load the second projection from the dataset
test_file = File("./examples/projection.h5", "r")
projection = extract_projection(test_file, 1, GeomOptions.PROJECTION_GEOMETRY)
print(projection.image_array.shape)
# Load the first to projections an slice the projection data [20:50, 50:100:2]
projection = extract_projection(
test_file,
slice(0, 2),
GeomOptions.PROJECTION_GEOMETRY,
crop=(slice(20, 50), slice(50, 100, 2)),
)
print(projection.image_array.shape)
if __name__ == "__main__":
main()
```
\ No newline at end of file
dump.txt 0 → 100644
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
```bash
.\examples\projection.h5 (5 objects)
├── detector (2 objects)
│ ├── image_dimensions_px (2 objects)
│ │ ├── u (1,), int32
│ │ └── v (1,), int32
│ └── pixel_pitch_mm (2 objects)
│ ├── u (1,), float64
│ └── v (1,), float64
├── image (2 objects)
│ ├── header (2 objects)
│ │ ├── timestamp (2,), float64
│ │ └── uuid (2,), |S100
│ └── image_array (2, 128, 128), uint16
├── projection_geometry (6 objects)
│ ├── detector_center_orientation_quat (4 objects)
│ │ ├── w (2,), float64
│ │ ├── x (2,), float64
│ │ ├── y (2,), float64
│ │ └── z (2,), float64
│ ├── detector_center_position_mm (3 objects)
│ │ ├── x (2,), float64
│ │ ├── y (2,), float64
│ │ └── z (2,), float64
│ ├── detector_center_rotation_matrix (2 objects)
│ │ ├── u (3 objects)
│ │ │ ├── x (0,), float64
│ │ │ ├── y (0,), float64
│ │ │ └── z (0,), float64
│ │ └── v (3 objects)
│ │ ├── x (0,), float64
│ │ ├── y (0,), float64
│ │ └── z (0,), float64
│ ├── focal_spot_orientation_quat (4 objects)
│ │ ├── w (2,), float64
│ │ ├── x (2,), float64
│ │ ├── y (2,), float64
│ │ └── z (2,), float64
│ ├── focal_spot_position_mm (3 objects)
│ │ ├── x (2,), float64
│ │ ├── y (2,), float64
│ │ └── z (2,), float64
│ └── header (2 objects)
│ ├── timestamp (2,), float64
│ └── uuid (2,), |S100
├── projection_geometry_nominal (6 objects)
│ ├── detector_center_orientation_quat (4 objects)
│ │ ├── w (2,), float64
│ │ ├── x (2,), float64
│ │ ├── y (2,), float64
│ │ └── z (2,), float64
│ ├── detector_center_position_mm (3 objects)
│ │ ├── x (2,), float64
│ │ ├── y (2,), float64
│ │ └── z (2,), float64
│ ├── detector_center_rotation_matrix (2 objects)
│ │ ├── u (3 objects)
│ │ │ ├── x (0,), float64
│ │ │ ├── y (0,), float64
│ │ │ └── z (0,), float64
│ │ └── v (3 objects)
│ │ ├── x (0,), float64
│ │ ├── y (0,), float64
│ │ └── z (0,), float64
│ ├── focal_spot_orientation_quat (4 objects)
│ │ ├── w (2,), float64
│ │ ├── x (2,), float64
│ │ ├── y (2,), float64
│ │ └── z (2,), float64
│ ├── focal_spot_position_mm (3 objects)
│ │ ├── x (2,), float64
│ │ ├── y (2,), float64
│ │ └── z (2,), float64
│ └── header (2 objects)
│ ├── timestamp (2,), float64
│ └── uuid (2,), |S100
└── source (2 objects)
├── current_ma (256,), float64
└── voltage_kv (256,), float64
```
\ No newline at end of file
examples/h5_viewer.png

268 KiB

No preview for this file type
......@@ -9,6 +9,7 @@ authors = [
requires-python = ">=3.10"
dependencies = [
"h5py>=3.13.0",
"h5tree>=1.0",
"jsonref>=1.1.0",
"numpy==2.0.2",
"pandas>=2.2.3",
......
from h5py import File
import numpy as np
from h5schemas.projection.add_projection import (
init_projection_dataset,
add_projection_sample,
)
from h5schemas.thd_joint_states.add_thd_joint_states import (
......@@ -14,16 +13,7 @@ def main():
# Generate a file in write mode.
test_file = File("./examples/projection.h5", "a")
# Initialize the .H5 structure
init_projection_dataset(test_file, False, (128, 128), (0.139, 0.139))
# # Add joint states group
# joint_states_group = test_file.require_group("/joint_states/")
# Init joint states group
init_thd_joint_states(test_file)
# Add dummy projections 1
# Add a new projection sample
add_projection_sample(
test_file,
1e5 * np.random.random((128, 128)),
......@@ -32,22 +22,10 @@ def main():
[7.0, 8.0, 9.0],
[10.0, 11.0, 12.0, 13],
)
add_thd_joint_states_sample(test_file, *np.arange(15))
# # Add dummy projections 2
# add_projection_sample(
# test_file,
# 1e5 * np.random.random((128, 128)),
# np.array([0.0, 1.0, 2.0]),
# np.array([3.0, 4.0, 5.0, 6.0]),
# np.array([7.0, 8.0, 9.0]),
# np.array([10.0, 11.0, 12.0, 13]),
# voltage_kv=100,
# )
# add_thd_joint_states_sample(joint_states_group, *np.arange(15, 30))
# # Access data
# print(test_file["/image/image_array"][...])
# Add a new group
init_thd_joint_states(test_file)
add_thd_joint_states_sample(test_file, *np.arange(15))
if __name__ == "__main__":
......
from h5py import File
from h5schemas.load_utilities.projection import extract_projection, GeomOptions
def main():
# Load the second projection from the dataset
test_file = File("./examples/projection.h5", "r")
projection = extract_projection(test_file, 1, GeomOptions.PROJECTION_GEOMETRY)
print(projection.image_array.shape)
# Load the first to projections an slice the projection data [20:50, 50:100:2]
projection = extract_projection(
test_file,
slice(0, 2),
GeomOptions.PROJECTION_GEOMETRY,
crop=(slice(20, 50), slice(50, 100, 2)),
)
print(projection.image_array.shape)
if __name__ == "__main__":
main()
from h5schemas.load_utilities.projection_geometry import extract_projection_geometry, ProjectionGeometry
from h5schemas.load_utilities.projection_geometry import (
extract_projection_geometry,
ProjectionGeometry,
)
from h5py import Group
import numpy as np
from typing import NamedTuple, ClassVar, Literal
......@@ -24,13 +27,20 @@ class Projection(NamedTuple):
timestamp: np.ndarray
def extract_projection(h5_group: Group, indices: slice | int, projection_geometry_group: str = GeomOptions.PROJECTION_GEOMETRY, crop: list[slice] | None = None) -> Projection:
def extract_projection(
h5_group: Group,
indices: slice | int,
projection_geometry_group: str = GeomOptions.PROJECTION_GEOMETRY,
crop: list[slice] | None = None,
) -> Projection:
if crop is None:
crop = (slice(0, None, 1), slice(0, None, 1))
if len(crop) != 3 and isinstance(indices, slice):
crop = (slice(0, None), crop[0], crop[1])
projection_geometry = extract_projection_geometry(h5_group[projection_geometry_group], indices)
projection_geometry = extract_projection_geometry(
h5_group[projection_geometry_group], indices
)
uuid = h5_group["image"]["header"]["uuid"][indices]
timestamp = h5_group["image"]["header"]["timestamp"][indices]
image = h5_group["image"]["image_array"][indices][crop]
......@@ -51,6 +61,11 @@ if __name__ == "__main__":
print(projection)
print(projection.image_array.shape)
projection = extract_projection(test_file, slice(0, 2), GeomOptions.PROJECTION_GEOMETRY, crop=(slice(20, 50), slice(50, 100)))
projection = extract_projection(
test_file,
slice(0, 2),
GeomOptions.PROJECTION_GEOMETRY,
crop=(slice(20, 50), slice(50, 100)),
)
print(projection)
print(projection.image_array.shape)
......@@ -14,7 +14,9 @@ class ProjectionGeometry(NamedTuple):
timestamp: np.ndarray
def extract_projection_geometry(h5_group: Group, indices: slice | int) -> ProjectionGeometry:
def extract_projection_geometry(
h5_group: Group, indices: slice | int
) -> ProjectionGeometry:
detector_center_position_mm = extract_vector(
h5_group["detector_center_position_mm"], indices, CommonVectors.XYZ
)
......
......@@ -97,6 +97,7 @@ version = "0.1.22"
source = { editable = "." }
dependencies = [
{ name = "h5py" },
{ name = "h5tree" },
{ name = "jsonref" },
{ name = "numpy" },
{ name = "pandas" },
......@@ -107,6 +108,7 @@ dependencies = [
[package.metadata]
requires-dist = [
{ name = "h5py", specifier = ">=3.13.0" },
{ name = "h5tree", specifier = ">=1.0" },
{ name = "jsonref", specifier = ">=1.1.0" },
{ name = "numpy", specifier = "==2.0.2" },
{ name = "pandas", specifier = ">=2.2.3" },
......@@ -114,6 +116,19 @@ requires-dist = [
{ name = "thd-json", git = "https://mygit.th-deg.de/roboct-public/roboct-schemas" },
]
[[package]]
name = "h5tree"
version = "1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "h5py" },
{ name = "termcolor" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ab/9b/ea46f715d5c5059de88ca2f87a63e7cb9a54f2a6e6cf56e88234730b179a/h5tree-1.0.tar.gz", hash = "sha256:d3c6ac2c647ebf4ba37ee91bdbd30ba147e68b0449c05ce1fe2ff9e7e61d8e12", size = 3418 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d6/f6/949bb1616da797ffe2badb6d09ee9664387c27105c28bac59917467c6254/h5tree-1.0-py3-none-any.whl", hash = "sha256:e7b83c6ea25fbd40dc05e8cf182aa43bde9bae19d88f7bed0308ff621d5c337e", size = 3466 },
]
[[package]]
name = "hatchling"
version = "1.27.0"
......@@ -697,6 +712,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/89/fd/62f31643596f6ab71fc6d2a87acdee0bc01a03fbe1a7f3f6dc0c91e2546d/tables-3.10.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:757c6ea257c174af8036cf8f273ede756bbcd6db5ac7e2a4d64e788b0f371152", size = 7527953 },
]
[[package]]
name = "termcolor"
version = "2.5.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/37/72/88311445fd44c455c7d553e61f95412cf89054308a1aa2434ab835075fc5/termcolor-2.5.0.tar.gz", hash = "sha256:998d8d27da6d48442e8e1f016119076b690d962507531df4890fcd2db2ef8a6f", size = 13057 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7f/be/df630c387a0a054815d60be6a97eb4e8f17385d5d6fe660e1c02750062b4/termcolor-2.5.0-py3-none-any.whl", hash = "sha256:37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8", size = 7755 },
]
[[package]]
name = "thd-json"
version = "0.1.14"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment