Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • roboct-public/roboct-schemas
1 result
Show changes
Showing
with 818 additions and 0 deletions
from thd_json.projection import get_projection_validator
from pathlib import Path
FILE = Path("./examples/generated/example_projection.json")
def main():
projection_validator = get_projection_validator()
projection_validator.file(FILE)
if __name__ == "__main__":
main()
from thd_json.projection import get_projection_validator
from pathlib import Path
FOLDER = Path("./examples/artist")
def main():
projection_validator = get_projection_validator()
projection_validator.folder(FOLDER)
if __name__ == "__main__":
main()
from .validation import Validator
__all__ = ["Validator"]
from thd_json import Validator
from pathlib import Path
import argparse
import numpy as np
from thd_json.dict_converter import detector_coord_to_dict
def get_detector_validator(json_suffix: str = "*.json") -> Validator:
return Validator(Path(__file__).parent / Path("detector.json"), json_suffix)
def detector_cli():
parser = argparse.ArgumentParser(
description="JSON THD Detector Validator CLI with uv."
)
parser.add_argument("folder", help="Folder to check.", type=str)
parser.add_argument(
"suffix", help="Projection suffix.", default="*.json", type=Path, nargs="?"
)
args = parser.parse_args()
suffix = str(args.suffix)
if not suffix.startswith("*"):
raise ValueError(f'The suffix must always start with: "*". \nIt is: {suffix}')
validator = get_detector_validator(suffix)
folder = Path(args.folder)
if not folder.exists():
raise FileNotFoundError(f"Folder: {folder} does not exist")
validator.folder(Path(args.folder))
def get_detector_dict(
image_dimensions_px: np.ndarray | float, pixel_pitch_mm: np.ndarray | int
):
if isinstance(image_dimensions_px, float):
image_dimensions_px = np.array([image_dimensions_px, image_dimensions_px])
if isinstance(pixel_pitch_mm, int):
pixel_pitch_mm = np.array([pixel_pitch_mm, pixel_pitch_mm])
detector_dict = dict()
detector_dict["pixel_pitch_mm"] = detector_coord_to_dict(pixel_pitch_mm)
detector_dict["image_dimensions_px"] = detector_coord_to_dict(image_dimensions_px)
return detector_dict
if __name__ == "__main__":
detector_cli()
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "THD Detector File Schema",
"type": "object",
"version": "0.1.9",
"date": "28.11.2024",
"properties": {
"pixel_pitch_mm": {
"type": "object",
"description": "Pixel pitch dimensions measured in millimeters.",
"properties": {
"u": {
"type": "number",
"description": "Pixel pitch in the x (width) dimension in millimeters.",
"minimum": 0.001
},
"v": {
"type": "number",
"description": "Pixel pitch in the y (height) dimension in millimeters.",
"minimum": 0.001
}
},
"required": [
"u",
"v"
]
},
"image_dimensions_px": {
"type": "object",
"description": "Image dimensions in pixels.",
"properties": {
"u": {
"type": "integer",
"description": "Width of the image in pixels.",
"minimum": 1
},
"v": {
"type": "integer",
"description": "Height of the image in pixels.",
"minimum": 1
}
},
"required": [
"u",
"v"
]
}
},
"required": [
"pixel_pitch_mm",
"image_dimensions_px"
],
"additionalProperties": false
}
\ No newline at end of file
import numpy as np
def detector_coord_to_dict(detector_coord: np.ndarray):
assert len(detector_coord.shape) == 1
assert detector_coord.shape[0] == 2
detector_coord = detector_coord.tolist()
return {"u": detector_coord[0], "v": detector_coord[1]}
def position_to_dict(position: np.ndarray):
assert len(position.shape) == 1
assert position.shape[0] == 3
assert position.dtype in [
np.float32,
np.float64,
], "Only np.float32 or np.float64 allowed."
position = position.tolist()
return {"x": position[0], "y": position[1], "z": position[2]}
def quaternion_to_dict(quaternion: np.ndarray):
assert len(quaternion.shape) == 1
assert quaternion.shape[0] == 4
assert quaternion.dtype in [
np.float32,
np.float64,
], "Only np.float32 or np.float64 allowed."
quaternion = quaternion.tolist()
return {
"x": quaternion[0],
"y": quaternion[1],
"z": quaternion[2],
"w": quaternion[3],
}
def dict_to_detector_coord(detector_coord_dict: dict):
detector_coord = np.zeros(2)
detector_coord[0] = detector_coord_dict["u"]
detector_coord[1] = detector_coord_dict["v"]
return detector_coord
def dict_to_position(position_dict: dict):
position = np.zeros(3)
position[0] = position_dict["x"]
position[1] = position_dict["y"]
position[2] = position_dict["z"]
return position
def dict_to_quaternion(quaternion_dict: dict):
quaternion = np.zeros(4)
quaternion[0] = quaternion_dict["x"]
quaternion[1] = quaternion_dict["y"]
quaternion[2] = quaternion_dict["z"]
quaternion[3] = quaternion_dict["w"]
return quaternion
if __name__ == "__main__":
pos = np.random.random(3).reshape((3,))
rot = np.random.random(4).reshape((4,))
pos_dict = position_to_dict(pos)
rot_dict = quaternion_to_dict(rot)
print(pos_dict)
print(rot_dict)
print(dict_to_position(pos_dict))
from thd_json import Validator
from pathlib import Path
import argparse
from dataclasses import dataclass
import uuid
from datetime import datetime, timedelta
@dataclass
class JsonHeader:
uuid: str
timestamp: str
def get_header_validator(json_suffix: str = "*.json") -> Validator:
return Validator(Path(__file__).parent / Path("header.json"), json_suffix)
def header_cli():
parser = argparse.ArgumentParser(
description="JSON THD Header Validator CLI with uv."
)
parser.add_argument("folder", help="Folder to check.", type=str)
parser.add_argument(
"suffix", help="Projection suffix.", default="*.json", type=Path, nargs="?"
)
args = parser.parse_args()
suffix = str(args.suffix)
if not suffix.startswith("*"):
raise ValueError(f'The suffix must always start with: "*". \nIt is: {suffix}')
validator = get_header_validator(suffix)
folder = Path(args.folder)
if not folder.exists():
raise FileNotFoundError(f"Folder: {folder} does not exist")
validator.folder(Path(args.folder))
def generate_header() -> JsonHeader:
generated_uuid = uuid.uuid1()
timestamp = (generated_uuid.time - 0x01B21DD213814000) / 1e7
datetime_from_uuid = datetime(1970, 1, 1) + timedelta(seconds=timestamp)
return JsonHeader(str(generated_uuid), str(datetime_from_uuid))
def generate_header_cli():
header = generate_header()
print(f"{header.uuid};{header.timestamp}")
if __name__ == "__main__":
header_cli()
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "THD Data Metadata Header File Schema",
"type": "object",
"version": "0.1.9",
"date": "28.11.2024",
"properties": {
"timestamp": {
"type": "string",
"description": "Timestamp, e.g. 2018-11-13T20:20:39+00:00",
"format": "date-time"
},
"uuid": {
"type": "string",
"description": "Unique identifier",
"format": "uuid"
}
},
"required": [
"uuid"
],
"additionalProperties": false
}
\ No newline at end of file
from thd_json import Validator
from pathlib import Path
import argparse
def get_image_validator(json_suffix: str = "*.json") -> Validator:
return Validator(Path(__file__).parent / Path("image.json"), json_suffix)
def image_cli():
parser = argparse.ArgumentParser(
description="JSON THD Image Validator CLI with uv."
)
parser.add_argument("folder", help="Folder to check.", type=str)
parser.add_argument(
"suffix", help="Projection suffix.", default="*.json", type=Path, nargs="?"
)
args = parser.parse_args()
suffix = str(args.suffix)
if not suffix.startswith("*"):
raise ValueError(f'The suffix must always start with: "*". \nIt is: {suffix}')
validator = get_image_validator(suffix)
folder = Path(args.folder)
if not folder.exists():
raise FileNotFoundError(f"Folder: {folder} does not exist")
validator.folder(Path(args.folder))
if __name__ == "__main__":
image_cli()
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "THD Projection Image File Schema",
"type": "object",
"version": "0.1.9",
"date": "28.11.2024",
"properties": {
"header": {
"$ref": "../header/header.json"
},
"image_path": {
"type": "string",
"description": "Path to TIFF file.",
"pattern": "^.*\\.(tif|tiff)$"
}
},
"required": [
"image_path"
],
"additionalProperties": false
}
\ No newline at end of file
import json
from pathlib import Path
def load_thd_meta_data(json_path: Path):
if not json_path.suffix.endswith("json"):
raise ValueError("Wrong data type. Input must be `.json`file.")
meta_data = json.load(json_path.open())
return meta_data
import numpy as np
from PIL import Image
from pathlib import Path
from .load_json import load_thd_meta_data
def load_thd_projection(json_path: Path):
meta_data = load_thd_meta_data(json_path)
image = np.asarray(Image.open(json_path.parent / meta_data["image"]["image_path"]))
return meta_data, image
from thd_json import Validator
from thd_json.header import JsonHeader, generate_header
from thd_json.projection_geometry import get_projection_geometry_dict
from thd_json.detector import get_detector_dict
from thd_json.header import JsonHeader, generate_header
from thd_json.projection_geometry import get_projection_geometry_dict
from thd_json.detector import get_detector_dict
from pathlib import Path
import argparse
import numpy as np
import numpy as np
def get_projection_validator(json_suffix: str = "*.json") -> Validator:
return Validator(Path(__file__).parent / Path("projection.json"), json_suffix)
def projection_cli():
parser = argparse.ArgumentParser(
description="JSON THD Projection Geometry Validator CLI with uv."
)
parser.add_argument("folder", help="Folder to check.", type=str)
parser.add_argument(
"suffix", help="Projection suffix.", default="*.json", type=Path, nargs="?"
)
args = parser.parse_args()
suffix = str(args.suffix)
if not suffix.startswith("*"):
raise ValueError(f'The suffix must always start with: "*". \nIt is: {suffix}')
validator = get_projection_validator(suffix)
folder = Path(args.folder)
if not folder.exists():
raise FileNotFoundError(f"Folder: {folder} does not exist")
validator.folder(Path(args.folder))
def get_projection_dict(
image_path: Path,
focal_spot_position_mm: np.ndarray,
detector_center_position_mm: np.ndarray,
detector_center_orientation_quat: np.ndarray,
image_dimensions_px: np.ndarray,
pixel_pitch_mm: np.ndarray,
header: JsonHeader | None = None,
focal_spot_orientation_quat: np.ndarray | None = None
):
if header is None:
header = generate_header()
projection = dict()
projection["projection_geometry"] = get_projection_geometry_dict(
focal_spot_position_mm,
detector_center_position_mm,
detector_center_orientation_quat,
header,
focal_spot_orientation_quat
)
projection['detector'] = get_detector_dict(image_dimensions_px, pixel_pitch_mm)
projection['image'] = {'image_path': str(image_path)}
return projection
if __name__ == "__main__":
projection_cli()
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "THD Projection File Schema",
"type": "object",
"version": "0.1.9",
"date": "28.11.2024",
"properties": {
"image": {
"$ref": "./image/image.json"
},
"projection_geometry": {
"$ref": "./projection_geometry/projection_geometry.json"
},
"projection_geometry_nominal": {
"$ref": "./projection_geometry/projection_geometry.json"
},
"detector": {
"$ref": "./detector/detector.json"
},
"source": {
"$ref": "./source/source.json"
}
},
"required": [
"projection_geometry",
"detector",
"image"
],
"additionalProperties": false
}
\ No newline at end of file
from thd_json import Validator
from pathlib import Path
import argparse
import numpy as np
from thd_json.header import JsonHeader, generate_header
from thd_json.dict_converter import (
position_to_dict,
quaternion_to_dict,
)
def get_projection_geometry_validator(json_suffix: str = "*.json") -> Validator:
return Validator(
Path(__file__).parent / Path("projection_geometry.json"), json_suffix
)
def projection_geometry_cli():
parser = argparse.ArgumentParser(
description="JSON THD Projection Geometry Validator CLI with uv."
)
parser.add_argument("folder", help="Folder to check.", type=str)
parser.add_argument(
"suffix", help="Projection suffix.", default="*.json", type=Path, nargs="?"
)
args = parser.parse_args()
suffix = str(args.suffix)
if not suffix.startswith("*"):
raise ValueError(f'The suffix must always start with: "*". \nIt is: {suffix}')
validator = get_projection_geometry_validator(suffix)
folder = Path(args.folder)
if not folder.exists():
raise FileNotFoundError(f"Folder: {folder} does not exist")
validator.folder(Path(args.folder))
def get_projection_geometry_dict(
focal_spot_position_mm: np.ndarray,
detector_center_position_mm: np.ndarray,
detector_center_orientation_quat: np.ndarray,
header: JsonHeader | None = None,
focal_spot_orientation_quat: np.ndarray | None = None
):
if header is None:
header = generate_header()
projection_geometry = dict()
projection_geometry["focal_spot_position_mm"] = position_to_dict(
focal_spot_position_mm
)
projection_geometry["detector_center_position_mm"] = position_to_dict(
detector_center_position_mm
)
projection_geometry["detector_center_orientation_quat"] = quaternion_to_dict(
detector_center_orientation_quat
)
if focal_spot_orientation_quat is not None:
projection_geometry["focal_spot_orientation_quat"] = quaternion_to_dict(
focal_spot_orientation_quat
)
projection_geometry["header"] = {"uuid": header.uuid}
return projection_geometry
if __name__ == "__main__":
projection_geometry_cli()
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "THD Projection Geometry File Schema",
"type": "object",
"version": "0.1.9",
"date": "28.11.2024",
"properties": {
"header": {
"$ref": "../header/header.json"
},
"focal_spot_position_mm": {
"type": "object",
"description": "Position of the focal spot in millimeters.",
"properties": {
"x": {
"type": "number",
"description": "X-coordinate of the focal spot position in millimeters."
},
"y": {
"type": "number",
"description": "Y-coordinate of the focal spot position in millimeters."
},
"z": {
"type": "number",
"description": "Z-coordinate of the focal spot position in millimeters."
}
},
"required": [
"x",
"y",
"z"
]
},
"focal_spot_orientation_quat": {
"type": "object",
"description": "Quaternion representing the focal spot orientation.",
"properties": {
"x": {
"type": "number",
"description": "X component of the quaternion."
},
"y": {
"type": "number",
"description": "Y component of the quaternion."
},
"z": {
"type": "number",
"description": "Z component of the quaternion."
},
"w": {
"type": "number",
"description": "W component of the quaternion."
}
},
"required": [
"x",
"y",
"z",
"w"
]
},
"detector_center_position_mm": {
"type": "object",
"description": "Center position of the detector in millimeters.",
"properties": {
"x": {
"type": "number",
"description": "X-coordinate of the detector center position in millimeters."
},
"y": {
"type": "number",
"description": "Y-coordinate of the detector center position in millimeters."
},
"z": {
"type": "number",
"description": "Z-coordinate of the detector center position in millimeters."
}
},
"required": [
"x",
"y",
"z"
]
},
"detector_center_orientation_quat": {
"type": "object",
"description": "Quaternion representing the detector's center orientation.",
"properties": {
"x": {
"type": "number",
"description": "X component of the quaternion."
},
"y": {
"type": "number",
"description": "Y component of the quaternion."
},
"z": {
"type": "number",
"description": "Z component of the quaternion."
},
"w": {
"type": "number",
"description": "W component of the quaternion."
}
},
"required": [
"x",
"y",
"z",
"w"
]
},
"detector_center_rotation_matrix": {
"type": "object",
"description": "Vectors representing the detector's rotation matrix.",
"properties": {
"u": {
"type": "object",
"description": "First vector of the rotation matrix.",
"properties": {
"x": {
"type": "number",
"description": "X component of the vector."
},
"y": {
"type": "number",
"description": "Y component of the vector."
},
"z": {
"type": "number",
"description": "Z component of the vector."
}
},
"required": [
"x",
"y",
"z"
]
},
"v": {
"type": "object",
"description": "Second vector of the rotation matrix.",
"properties": {
"x": {
"type": "number",
"description": "X component of the vector."
},
"y": {
"type": "number",
"description": "Y component of the vector."
},
"z": {
"type": "number",
"description": "Z component of the vector."
}
},
"required": [
"x",
"y",
"z"
]
}
},
"required": [
"u",
"v"
]
}
},
"required": [
"header",
"focal_spot_position_mm",
"detector_center_position_mm",
"detector_center_orientation_quat"
],
"additionalProperties": false
}
\ No newline at end of file
from thd_json import Validator
from pathlib import Path
import argparse
def get_roi_validator(json_suffix: str = "*.json") -> Validator:
return Validator(Path(__file__).parent / Path("roi.json"), json_suffix)
def roi_cli():
parser = argparse.ArgumentParser(description="JSON THD ROI Validator CLI with uv.")
parser.add_argument("folder", help="Folder to check.", type=str)
parser.add_argument(
"suffix", help="Projection suffix.", default="*.json", type=Path, nargs="?"
)
args = parser.parse_args()
suffix = str(args.suffix)
if not suffix.startswith("*"):
raise ValueError(f'The suffix must always start with: "*". \nIt is: {suffix}')
validator = get_roi_validator(suffix)
folder = Path(args.folder)
if not folder.exists():
raise FileNotFoundError(f"Folder: {folder} does not exist")
validator.folder(Path(args.folder))
if __name__ == "__main__":
roi_cli()
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "THD ROI File Schema",
"type": "object",
"version": "0.1.9",
"date": "28.11.2024",
"properties": {
"header": {
"$ref": "./header/header.json"
},
"volume": {
"$ref": "./volume/volume.json"
},
"roi_center_position_mm": {
"type": "array",
"description": "Position of the focal spot in millimeters.",
"items": {
"type": "number"
},
"minItems": 3,
"maxItems": 3
},
"roi_orientation_quat": {
"type": "array",
"description": "Quaternion representing the detector's center orientation.",
"items": {
"type": "number"
},
"minItems": 4,
"maxItems": 4
},
"roi_resolution_mm": {
"type": "array",
"description": "Center position of the detector in millimeters.",
"items": {
"type": "number"
},
"minItems": 3,
"maxItems": 3
},
"roi_voxels": {
"type": "array",
"description": "Center position of the detector in millimeters.",
"items": {
"type": "integer",
"minimum": 1
},
"minItems": 3,
"maxItems": 3
}
},
"required": [
"header",
"roi_center_position_mm",
"roi_orientation_quat",
"roi_resolution_mm",
"roi_voxels"
],
"additionalProperties": false
}
\ No newline at end of file