Skip to content

Commit d9d9da3

Browse files
authored
Merge branch 'FABLE-3DXRD:master' into master
2 parents a72b625 + 5d4867f commit d9d9da3

3 files changed

Lines changed: 56 additions & 28 deletions

File tree

ImageD11/forward_model/forward_projector.py

100755100644
Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
# Suitable for both s3DXRD using pencil beam and box-beam 3DXRD
55
# Haixing Fang, haixing.fang@esrf.fr
66
# Jan 2nd, 2025
7-
# updated on January 30, 2025
7+
# version 1.0: updated on January 30, 2025
8+
# version 1.1: fixed a bug with ray origin on December 10, 2025
89

910
import numpy as np
1011
from matplotlib import pyplot as plt
@@ -726,7 +727,7 @@ def read_cf(self):
726727
self.cf_4d = colfile_from_hdf(self.cf_4d_file)
727728
self.peaks_4d = io.convert_cf_to_fwd_peaks(self.cf_4d)
728729
if self.verbose >= 1:
729-
logging.info('loaded 4D peaks from {}'.format(self.cf_4d_file))
730+
logging.info('loaded 4D peaks from {}'.format(self.cf_4d_file))
730731
else:
731732
self.get_cf()
732733

@@ -973,11 +974,17 @@ def intersected_sample_pos(mask, dty = 0.0, y0_offset = 0.0, voxel_size = [1.0,
973974

974975
if not isinstance(voxel_size, np.ndarray):
975976
voxel_size = np.array(voxel_size, dtype='float')
977+
#Omega = forward_model.get_omega_matrix(np.deg2rad(-omega))
978+
#ray_direction = np.dot(Omega, [1.0, 0.0, 0.0])
979+
#grid_size = mask.shape
980+
#assert len(grid_size) == 3, "The input mask must be in 3D"
981+
#ray_origin = [0.0, -dty - y0_offset, 0.0]
982+
976983
Omega = forward_model.get_omega_matrix(np.deg2rad(-omega))
977984
ray_direction = np.dot(Omega, [1.0, 0.0, 0.0])
978985
grid_size = mask.shape
979986
assert len(grid_size) == 3, "The input mask must be in 3D"
980-
ray_origin = [0.0, -dty - y0_offset, 0.0]
987+
ray_origin = np.dot(Omega, [0.0, -dty - y0_offset, 0.0]) # the absolute distance between the ray and the rotation center keeps as a constant of dty+y0_offset
981988

982989
intersected_voxels = intersected_voxels_3d(grid_size, ray_origin, ray_direction, voxel_size = voxel_size,
983990
ray_size=ray_size, weight = weight, weight_pos = weight_pos, mask = mask, plot_flag = plot_flag)
@@ -1028,8 +1035,12 @@ def intersected_voxels_3d(grid_size, ray_origin, ray_direction, voxel_size = [1.
10281035
grid_extent = np.array(grid_size) * voxel_size
10291036
max_extent = np.linalg.norm(grid_extent)
10301037

1031-
t_values = np.linspace(-0.707 * max_extent + ray_origin[1], 0.707 * max_extent + ray_origin[1], int(max(grid_size)*1.414))
1032-
ray_shift = np.array([grid_size[1] / 2 + 0.5, grid_size[1] / 2 + 0.5, 0.0]) * voxel_size
1038+
#t_values = np.linspace(-0.707 * max_extent + ray_origin[1], 0.707 * max_extent + ray_origin[1], int(max(grid_size)*1.414))
1039+
#ray_shift = np.array([grid_size[1] / 2 + 0.5, grid_size[1] / 2 + 0.5, 0.0]) * voxel_size
1040+
#ray_path = np.array(ray_origin) / voxel_size + ray_shift + np.outer(t_values, ray_direction)
1041+
1042+
t_values = np.linspace(-0.707 * max_extent + np.linalg.norm(ray_origin), 0.707 * max_extent + np.linalg.norm(ray_origin), int(max(grid_size)*1.414))
1043+
ray_shift = np.array([grid_size[0] / 2 + 0.5, grid_size[1] / 2 + 0.5, 0.0]) * voxel_size
10331044
ray_path = np.array(ray_origin) / voxel_size + ray_shift + np.outer(t_values, ray_direction)
10341045

10351046
tol_distances = np.array(weight_pos)*ray_size
@@ -1348,11 +1359,11 @@ def ensure_2d_array(target_hkls):
13481359

13491360
def plot_fwd_peaks(fwd_peaks):
13501361
assert fwd_peaks.shape[1] == 25, "fwd_peaks shapes are not qualified"
1351-
f, ax = plt.subplots(1, 2, figsize=(15, 9))
1362+
f, ax = plt.subplots(1, 2, figsize=(12, 6))
13521363

13531364
sc = ax[0].scatter(fwd_peaks[:, 18], fwd_peaks[:, 19], c=fwd_peaks[:, 23], cmap='viridis', s=8)
13541365
ax[0].set_aspect('equal', 'box')
1355-
cb = f.colorbar(sc, ax=ax[0])
1366+
cb = f.colorbar(sc, ax=ax[0], fraction=0.046, pad=0.04)
13561367
# cb.set_label('Intensity', fontsize = 20)
13571368
cb.ax.tick_params(labelsize=14)
13581369
ax[0].set_xlabel('fc (pixel)', fontsize = 20)
@@ -1363,7 +1374,7 @@ def plot_fwd_peaks(fwd_peaks):
13631374

13641375
sc = ax[1].scatter(fwd_peaks[:, 5], fwd_peaks[:, 6], c=fwd_peaks[:, 23], cmap='viridis', s=8)
13651376
ax[1].set_aspect('equal', 'box')
1366-
cb = f.colorbar(sc, ax=ax[1])
1377+
cb = f.colorbar(sc, ax=ax[1], fraction=0.046, pad=0.04)
13671378
cb.set_label('Intensity', fontsize = 20)
13681379
cb.ax.tick_params(labelsize=14)
13691380
ax[1].set_xlabel('X (mm)', fontsize = 20)

ImageD11/forward_model/grainmaps.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,21 +94,27 @@ def convert2DS(self):
9494
convert tensor_map to a dictionary like DS, which is similar to fwd-DCT struct, easier for subsequent operation
9595
"""
9696
tensor_map = self.read_tensor_map()
97-
97+
tensor_map_flag = False
9898
for key in tensor_map.keys():
9999
if 'TensorMap' in key:
100100
print('Got the key name {}'.format(key))
101101
keyname = key
102+
tensor_map_flag = True
102103

103104
print('********************* Converting to DS format *****************************')
104105
keys_list = ['B', 'U', 'UB', 'UBI', 'eps_sample', 'euler', 'ipf_x', 'ipf_y', 'ipf_z', 'mt', 'nuniq', 'phase_ids', 'unitcell', 'intensity', 'labels']
105-
DS = {}
106-
for k in keys_list:
107-
if k in tensor_map[keyname]['maps'].keys():
108-
print('Loading {} with a shape of {} to DS ...'.format(k, tensor_map[keyname]['maps'][k].shape))
109-
DS[k] = tensor_map[keyname]['maps'][k]
110-
if 'step' in tensor_map[keyname].keys():
111-
DS['voxel_size'] = tensor_map[keyname]['step'] # [um/pixel]
106+
if tensor_map_flag:
107+
# it reads directly as a tensor map
108+
DS = {}
109+
for k in keys_list:
110+
if k in tensor_map[keyname]['maps'].keys():
111+
print('Loading {} with a shape of {} to DS ...'.format(k, tensor_map[keyname]['maps'][k].shape))
112+
DS[k] = tensor_map[keyname]['maps'][k]
113+
if 'step' in tensor_map[keyname].keys():
114+
DS['voxel_size'] = tensor_map[keyname]['step'] # [um/pixel]
115+
else:
116+
# the provided map is a DS-like dictionary map already
117+
DS = tensor_map
112118

113119

114120
DS['Rod'] = np.empty((DS['UBI'].shape[0], DS['UBI'].shape[1], DS['UBI'].shape[2], 3))

ImageD11/forward_model/test_forward_projector_to_cf.ipynb

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"# Test forward_projector.py\n",
99
"## Test to generate peaks forward computed from an experimentally reconstructed grain map and convert peaks to cf\n",
1010
"## Haixing Fang\n",
11-
"## Jan 2025"
11+
"## Created in Jan 2025\n",
12+
"## Updated in Dec 2025"
1213
]
1314
},
1415
{
@@ -160,7 +161,9 @@
160161
},
161162
"outputs": [],
162163
"source": [
163-
"fp = forward_projector.forward_projector(sample_filename, pars_filename, phase_name, detector_mask = None, to_sparse = False, **opts)"
164+
"# specify the output_folder according to your needs\n",
165+
"fp = forward_projector.forward_projector(sample_filename, pars_filename, phase_name, detector_mask = None,\n",
166+
" to_sparse = False, output_folder = None, **opts)"
164167
]
165168
},
166169
{
@@ -457,24 +460,25 @@
457460
{
458461
"cell_type": "code",
459462
"execution_count": null,
460-
"id": "704fba35-e632-4a7d-8b0e-39999bd26070",
461-
"metadata": {
462-
"tags": []
463-
},
463+
"id": "8a11ccca-482b-4fb6-bb00-67d2e093674f",
464+
"metadata": {},
464465
"outputs": [],
465466
"source": [
466-
"Al = ImageD11.unitcell.unitcell_from_parameters(pars)"
467+
"# load phases from parameter file\n",
468+
"ds.phases = ds.get_phases_from_disk()\n",
469+
"ds.phases.unitcells"
467470
]
468471
},
469472
{
470473
"cell_type": "code",
471474
"execution_count": null,
472-
"id": "cff1f3c5-b279-4bcb-880d-8f5eb04fd120",
473-
"metadata": {
474-
"tags": []
475-
},
475+
"id": "7c412300-017b-42d8-9602-8a513d4877a5",
476+
"metadata": {},
476477
"outputs": [],
477478
"source": [
479+
"phase_str = 'Al'\n",
480+
"Al = ds.phases.unitcells[phase_str]\n",
481+
"print(Al)\n",
478482
"Al.makerings(1.5)"
479483
]
480484
},
@@ -828,7 +832,14 @@
828832
"name": "python",
829833
"nbconvert_exporter": "python",
830834
"pygments_lexer": "ipython3",
831-
"version": "3.11.6"
835+
"version": "3.12.9"
836+
},
837+
"widgets": {
838+
"application/vnd.jupyter.widget-state+json": {
839+
"state": {},
840+
"version_major": 2,
841+
"version_minor": 0
842+
}
832843
}
833844
},
834845
"nbformat": 4,

0 commit comments

Comments
 (0)