def add_shape_to_detector( builder: NexusBuilder, detector_group: h5py.Group, detector_ids: np.ndarray, voxels: np.ndarray, vertices: np.ndarray, offsets: Tuple[np.ndarray, np.ndarray, np.ndarray], ): builder.add_dataset(detector_group, "x_pixel_offset", offsets[0], {"units": "m"}) builder.add_dataset(detector_group, "y_pixel_offset", offsets[1], {"units": "m"}) builder.add_dataset(detector_group, "z_pixel_offset", offsets[2], {"units": "m"}) winding_order = voxels.flatten().astype(np.int32) vertices_in_face = 4 faces = np.arange(0, winding_order.size, vertices_in_face) shape_group = builder.add_nx_group(detector_group, "detector_shape", "NXoff_geometry") builder.add_dataset(shape_group, "vertices", vertices.astype(np.float64)) builder.add_dataset(shape_group, "winding_order", winding_order) builder.add_dataset(shape_group, "faces", faces.astype(np.int32)) builder.add_dataset(shape_group, "detector_faces", detector_ids.astype(np.int32)) builder.add_dataset( detector_group, "detector_number", np.unique(detector_ids[:, 1]).astype(np.int32), ) transforms_group = builder.add_nx_group(detector_group, "transformations", "NXtransformations") builder.add_transformation( transforms_group, "translation", -4.1, "m", [0.0, 0.0, 1.0], name="translation", ) return transforms_group
def add_voxel_detector(nexus_builder: NexusBuilder, n_voxels: int = 3): detector_group = nexus_builder.add_detector_minimal( "voxel geometry detector", 1) vertices = np.array([[0.0, 0.0, 0.0]]) off_faces = np.empty((0, 4), dtype=int) detector_numbers = np.arange(n_voxels) detector_faces = np.empty((0, 2), dtype=int) for voxel_number in range(n_voxels): # Each voxel is a regular octahedron new_vertices = np.array([ [0.0, 0.0, 1.0 - 2 * voxel_number], [1.0, 0.0, 0.0 - 2 * voxel_number], [0.0, 1.0, 0.0 - 2 * voxel_number], [-1.0, 0.0, 0.0 - 2 * voxel_number], [0.0, -1.0, 0.0 - 2 * voxel_number], [0.0, 0.0, -1.0 - 2 * voxel_number], ]) vertices = np.append(vertices[:-1, :], new_vertices, axis=0) # Number of vertices followed by vertex indices for each face # the first column doesn't end up in the NeXus file dataset new_off_faces = np.array([ [3, 1 + 5 * voxel_number, 5 * voxel_number, 4 + 5 * voxel_number], [3, 4 + 5 * voxel_number, 5 * voxel_number, 3 + 5 * voxel_number], [3, 3 + 5 * voxel_number, 5 * voxel_number, 2 + 5 * voxel_number], [3, 2 + 5 * voxel_number, 5 * voxel_number, 1 + 5 * voxel_number], [ 3, 1 + 5 * voxel_number, 5 + 5 * voxel_number, 2 + 5 * voxel_number ], [ 3, 2 + 5 * voxel_number, 5 + 5 * voxel_number, 3 + 5 * voxel_number ], [ 3, 3 + 5 * voxel_number, 5 + 5 * voxel_number, 4 + 5 * voxel_number ], [ 3, 4 + 5 * voxel_number, 5 + 5 * voxel_number, 1 + 5 * voxel_number ], ]) off_faces = np.append(off_faces, new_off_faces, axis=0) detector_number = detector_numbers[voxel_number] # Map 8 faces to each detector number new_detector_faces = np.array([ [detector_number * 8, detector_number], [1 + detector_number * 8, detector_number], [2 + detector_number * 8, detector_number], [3 + detector_number * 8, detector_number], [4 + detector_number * 8, detector_number], [5 + detector_number * 8, detector_number], [6 + detector_number * 8, detector_number], [7 + detector_number * 8, detector_number], ]) detector_faces = np.append(detector_faces, new_detector_faces, axis=0) nexus_builder.add_shape(detector_group, "detector_shape", vertices, off_faces, detector_faces) nexus_builder.add_dataset(detector_group, "detector_number", detector_numbers) transform_group = nexus_builder.add_nx_group(detector_group, "transformations", "NXtransformation") position = nexus_builder.add_transformation( transform_group, "translation", np.array([2.0]), units="m", vector=[1.0, 0.0, 1.0], name="position", ) nexus_builder.add_dataset(detector_group, "depends_on", position.name) # Record the voxel positions x_offsets = 1.1 * np.ones(n_voxels, dtype=float) y_offsets = 2.2 * np.ones(n_voxels, dtype=float) z_offsets = np.arange(-n_voxels, n_voxels, 2.0, dtype=float) nexus_builder.add_dataset(detector_group, "x_pixel_offset", x_offsets) nexus_builder.add_dataset(detector_group, "y_pixel_offset", y_offsets) nexus_builder.add_dataset(detector_group, "z_pixel_offset", z_offsets) write_to_off_file(f"{n_voxels}_voxels.off", vertices.shape[0], off_faces.shape[0], vertices, off_faces)