trxrdpy 3.2.2__tar.gz → 3.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/PKG-INFO +5 -1
  2. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/README.md +4 -0
  3. trxrdpy-3.3.0/docs/manual/XRDpy_manual.pdf +0 -0
  4. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/pyproject.toml +4 -1
  5. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/ESRF_ID09/azimint.py +72 -11
  6. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/_shared_2d/azimint.py +60 -12
  7. trxrdpy-3.3.0/src/trxrdpy/analysis/calibration.py +1908 -0
  8. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/common/azimint_utils.py +29 -0
  9. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/common/calibration_utils.py +21 -15
  10. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/common/fitting_utils.py +67 -5
  11. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/common/plot_utils.py +27 -2
  12. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/differential_analysis.py +78 -13
  13. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/fitting.py +39 -6
  14. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/main_window.py +281 -8
  15. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/services/calibration_service.py +10 -0
  16. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/state.py +9 -0
  17. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/tabs/calibration_tab.py +300 -38
  18. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/tabs/differential_tab.py +146 -56
  19. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/tabs/fitting_tab.py +408 -196
  20. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/tabs/pattern_creation_tab.py +10 -10
  21. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/tabs/session_tab.py +25 -5
  22. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/tabs/viewer_tab.py +114 -25
  23. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/widgets/experiment_widgets.py +42 -56
  24. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/widgets/multi_experiment_widgets.py +48 -30
  25. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy.egg-info/PKG-INFO +5 -1
  26. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy.egg-info/SOURCES.txt +1 -0
  27. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/tests/test_calibration_2d_cake.py +187 -0
  28. trxrdpy-3.2.2/src/trxrdpy/analysis/calibration.py +0 -938
  29. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/setup.cfg +0 -0
  30. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/__init__.py +0 -0
  31. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/ESRF_ID09/__init__.py +0 -0
  32. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/ESRF_ID09/datared.py +0 -0
  33. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/MaxIV_FemtoMAX/__init__.py +0 -0
  34. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/MaxIV_FemtoMAX/azimint.py +0 -0
  35. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/MaxIV_FemtoMAX/datared.py +0 -0
  36. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/MaxIV_FemtoMAX/datared_utils.py +0 -0
  37. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/MaxIV_FemtoMAX/ping_references_default.csv +0 -0
  38. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/Spring8_SACLA/__init__.py +0 -0
  39. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/Spring8_SACLA/azimint.py +0 -0
  40. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/Spring8_SACLA/datared.py +0 -0
  41. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/Spring8_SACLA/pbs/parallel_job_sender.sh +0 -0
  42. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/__init__.py +0 -0
  43. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/_shared_2d/__init__.py +0 -0
  44. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/common/__init__.py +0 -0
  45. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/common/differential_analysis_utils.py +0 -0
  46. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/common/general_utils.py +0 -0
  47. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/common/paths.py +0 -0
  48. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/__init__.py +0 -0
  49. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/defaults.py +0 -0
  50. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/runtime_guard.py +0 -0
  51. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/services/__init__.py +0 -0
  52. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/services/differential_service.py +0 -0
  53. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/services/facility_service.py +0 -0
  54. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/services/fitting_service.py +0 -0
  55. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/services/integration_service.py +0 -0
  56. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/services/path_service.py +0 -0
  57. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/services/preparation_service.py +0 -0
  58. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/style.py +0 -0
  59. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/tabs/__init__.py +0 -0
  60. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/tabs/preparation_tab.py +0 -0
  61. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/utils.py +0 -0
  62. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/widgets/__init__.py +0 -0
  63. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/widgets/facility_widgets.py +0 -0
  64. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/widgets/log_widget.py +0 -0
  65. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/widgets/parameter_widgets.py +0 -0
  66. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/widgets/path_widgets.py +0 -0
  67. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/widgets/polarization_widget.py +0 -0
  68. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/analysis/gui/widgets/task_output_dialog.py +0 -0
  69. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/__init__.py +0 -0
  70. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/cif.py +0 -0
  71. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/detector.py +0 -0
  72. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/diffractometers.py +0 -0
  73. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/experiment.py +0 -0
  74. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/geometry.py +0 -0
  75. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/__init__.py +0 -0
  76. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/main_window.py +0 -0
  77. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/services/__init__.py +0 -0
  78. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/services/path_service.py +0 -0
  79. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/services/simulation_service.py +0 -0
  80. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/state.py +0 -0
  81. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/style.py +0 -0
  82. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/tabs/__init__.py +0 -0
  83. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/tabs/polycrystalline_tab.py +0 -0
  84. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/tabs/single_crystal_tab.py +0 -0
  85. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/widgets/__init__.py +0 -0
  86. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/widgets/geometry_panel.py +0 -0
  87. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/gui/widgets/matrix_rotation_window.py +0 -0
  88. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/plot.py +0 -0
  89. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/polycrystalline.py +0 -0
  90. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/poni.py +0 -0
  91. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/sample.py +0 -0
  92. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/single_crystal.py +0 -0
  93. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy/simulation/utils.py +0 -0
  94. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy.egg-info/dependency_links.txt +0 -0
  95. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy.egg-info/entry_points.txt +0 -0
  96. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy.egg-info/requires.txt +0 -0
  97. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/src/trxrdpy.egg-info/top_level.txt +0 -0
  98. {trxrdpy-3.2.2 → trxrdpy-3.3.0}/tests/test_id09_datared_io.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trxrdpy
3
- Version: 3.2.2
3
+ Version: 3.3.0
4
4
  Summary: Python toolkit for time-resolved X-ray diffraction simulation and beamline-dependent analysis workflows.
5
5
  Author: Julio Guzman-Brambila
6
6
  License-Expression: CC-BY-4.0
@@ -58,6 +58,10 @@ Source code: https://github.com/julioguzmanb/XRDpy
58
58
 
59
59
  - **Project concept DOI (all versions):** https://doi.org/10.5281/zenodo.18634909
60
60
 
61
+ ## Manual
62
+
63
+ - **User manual PDF:** [`docs/manual/XRDpy_manual.pdf`](docs/manual/XRDpy_manual.pdf)
64
+
61
65
  ---
62
66
 
63
67
  ## Main capabilities
@@ -15,6 +15,10 @@ Source code: https://github.com/julioguzmanb/XRDpy
15
15
 
16
16
  - **Project concept DOI (all versions):** https://doi.org/10.5281/zenodo.18634909
17
17
 
18
+ ## Manual
19
+
20
+ - **User manual PDF:** [`docs/manual/XRDpy_manual.pdf`](docs/manual/XRDpy_manual.pdf)
21
+
18
22
  ---
19
23
 
20
24
  ## Main capabilities
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "trxrdpy"
7
- version = "3.2.2"
7
+ version = "3.3.0"
8
8
  description = "Python toolkit for time-resolved X-ray diffraction simulation and beamline-dependent analysis workflows."
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.10"
@@ -84,3 +84,6 @@ include = ["trxrdpy", "trxrdpy.*"]
84
84
  [tool.setuptools.package-data]
85
85
  "trxrdpy.analysis.Spring8_SACLA" = ["pbs/*.sh"]
86
86
  "trxrdpy.analysis.MaxIV_FemtoMAX" = ["*.csv"]
87
+
88
+ [tool.setuptools.data-files]
89
+ "share/doc/trxrdpy" = ["docs/manual/XRDpy_manual.pdf"]
@@ -1053,6 +1053,11 @@ def plot_1D_abs_and_diffs_delay(
1053
1053
  vlines_bckg: Optional[Tuple[float, float]] = None,
1054
1054
  fs_or_ps: str = "ps",
1055
1055
  digits: int = 2,
1056
+ delay_offset_fs: float = 0.0,
1057
+ fluence_scale: float = 1.0,
1058
+ fluence_offset: float = 0.0,
1059
+ fluence_unit: str = "mJ/cm$^2$",
1060
+ max_curves: Optional[int] = None,
1056
1061
  title: Optional[str] = None,
1057
1062
  azim_offset_deg: float = -90.0,
1058
1063
  polarization_factor: Optional[float] = None,
@@ -1100,8 +1105,11 @@ def plot_1D_abs_and_diffs_delay(
1100
1105
  Control on-demand integration and replacement of cached XY files.
1101
1106
  xlim, ylim_top, ylim_diff, vlines_peak, vlines_bckg
1102
1107
  Axis limits and optional highlighted q intervals.
1103
- fs_or_ps, digits, title
1104
- Delay-label unit, rounding precision, and optional title.
1108
+ fs_or_ps, digits, delay_offset_fs, fluence_scale, fluence_offset,
1109
+ fluence_unit, max_curves, title
1110
+ Delay-label unit, rounding precision, display-only delay offset,
1111
+ display-only fluence title scale/offset, maximum displayed curves
1112
+ including reference, and optional title.
1105
1113
  azim_offset_deg, polarization_factor
1106
1114
  ID09 azimuth conversion and pyFAI polarization correction.
1107
1115
  save_plots, out_name, save_format, save_dpi, save_overwrite, save_base_dir
@@ -1249,8 +1257,19 @@ def plot_1D_abs_and_diffs_delay(
1249
1257
  q_norm_range=q_norm_range,
1250
1258
  )
1251
1259
 
1260
+ non_ref_delays = [
1261
+ int(x)
1262
+ for x in sorted(set(int(x) for x in delays_list))
1263
+ if int(x) != int(ref_delay_fs)
1264
+ ]
1265
+ max_non_ref = None if max_curves is None else max(int(max_curves) - 1, 0)
1266
+ non_ref_delays = common_azimint_utils.evenly_spaced_subset(
1267
+ non_ref_delays,
1268
+ max_non_ref,
1269
+ )
1270
+
1252
1271
  patterns = []
1253
- for d_fs in sorted(set(int(x) for x in delays_list)):
1272
+ for d_fs in non_ref_delays:
1254
1273
  if int(d_fs) == int(ref_delay_fs):
1255
1274
  continue
1256
1275
 
@@ -1270,13 +1289,14 @@ def plot_1D_abs_and_diffs_delay(
1270
1289
  normalize=bool(normalize),
1271
1290
  q_norm_range=q_norm_range,
1272
1291
  )
1273
- lab = f"{delay_label_value(d_fs, fs_or_ps=fs_or_ps, digits=digits)}"
1292
+ lab = f"{delay_label_value(d_fs + float(delay_offset_fs), fs_or_ps=fs_or_ps, digits=digits)}"
1274
1293
  patterns.append((lab, q, I))
1275
1294
 
1276
1295
  if title is None:
1296
+ display_fluence = float(fluence_mJ_cm2) * float(fluence_scale) + float(fluence_offset)
1277
1297
  title = (
1278
1298
  f"{sample_name}. {temperature_K}K.\n"
1279
- f"ex. wl={excitation_wl_nm}nm. flu={fluence_mJ_cm2} mJ/cm$^2$.\n"
1299
+ f"ex. wl={excitation_wl_nm}nm. flu={display_fluence:g} {fluence_unit}.\n"
1280
1300
  f"tw={time_window_fs}fs. azim=({azim_window[0]},{azim_window[1]})"
1281
1301
  )
1282
1302
 
@@ -1310,7 +1330,7 @@ def plot_1D_abs_and_diffs_delay(
1310
1330
  overwrite=save_overwrite,
1311
1331
  )
1312
1332
 
1313
- ref_label = f"ref: {delay_label_value(ref_delay_fs, fs_or_ps=fs_or_ps, digits=digits)}"
1333
+ ref_label = f"ref: {delay_label_value(ref_delay_fs + float(delay_offset_fs), fs_or_ps=fs_or_ps, digits=digits)}"
1314
1334
 
1315
1335
  fig, axes = plot_utils.Pattern1DPlotter().compare_to_reference(
1316
1336
  q_ref=q_ref,
@@ -1543,6 +1563,14 @@ def plot_1D_abs_and_diffs_fluence(
1543
1563
  vlines_peak: Optional[Tuple[float, float]] = None,
1544
1564
  vlines_bckg: Optional[Tuple[float, float]] = None,
1545
1565
  title: Optional[str] = None,
1566
+ fluence_scale: float = 1.0,
1567
+ fluence_offset: float = 0.0,
1568
+ delay_offset_fs: float = 0.0,
1569
+ fs_or_ps: str = "fs",
1570
+ digits: int = 2,
1571
+ fluence_digits: Optional[int] = None,
1572
+ fluence_unit: str = "mJ/cm$^2$",
1573
+ max_curves: Optional[int] = None,
1546
1574
  save_plots: bool = False,
1547
1575
  out_name: Optional[str] = None,
1548
1576
  save_format: str = "png",
@@ -1592,6 +1620,11 @@ def plot_1D_abs_and_diffs_fluence(
1592
1620
  Optional in-memory intensity normalization.
1593
1621
  xlim, ylim_top, ylim_diff, vlines_peak, vlines_bckg, title
1594
1622
  Axis limits, highlighted q regions, and figure title.
1623
+ fluence_scale, fluence_offset, delay_offset_fs, fs_or_ps, digits,
1624
+ fluence_digits, fluence_unit, max_curves
1625
+ Display-only fluence/delay corrections and curve-count limiting.
1626
+ ``digits`` controls the fixed-delay label; ``fluence_digits`` controls
1627
+ fluence labels in the legend.
1595
1628
  save_plots, out_name, save_format, save_dpi, save_overwrite, save_base_dir
1596
1629
  Figure-output controls.
1597
1630
 
@@ -1607,6 +1640,14 @@ def plot_1D_abs_and_diffs_fluence(
1607
1640
  FileNotFoundError
1608
1641
  If source or synthetic fluence data cannot be located.
1609
1642
  """
1643
+ def _fluence_display_label(value: float) -> str:
1644
+ ndig = digits if fluence_digits is None else fluence_digits
1645
+ try:
1646
+ rounded = round(float(value), int(ndig))
1647
+ except Exception:
1648
+ return f"{float(value):g}"
1649
+ return f"{rounded:g}"
1650
+
1610
1651
  pths = _resolve_paths(
1611
1652
  paths=paths,
1612
1653
  path_root=path_root,
@@ -1744,7 +1785,8 @@ def plot_1D_abs_and_diffs_fluence(
1744
1785
  delay_fs=int(delay_fs),
1745
1786
  paths=pths,
1746
1787
  )
1747
- ref_label = f"ref: {float(ref_f):g} mJ/cm$^2$"
1788
+ ref_f_display = float(ref_f) * float(fluence_scale) + float(fluence_offset)
1789
+ ref_label = f"ref: {_fluence_display_label(ref_f_display)} {fluence_unit}"
1748
1790
  ref_tag_for_file = f"fluence_{general_utils.fluence_tag_file(ref_f)}mJ"
1749
1791
  else:
1750
1792
  resolved_tag = None
@@ -1768,8 +1810,19 @@ def plot_1D_abs_and_diffs_fluence(
1768
1810
  q_norm_range=q_norm_range,
1769
1811
  )
1770
1812
 
1813
+ non_ref_fluences = [
1814
+ float(f)
1815
+ for f in sorted(fl_list)
1816
+ if not (ref_type_n == "fluence" and abs(float(f) - float(ref_f)) < 1e-12)
1817
+ ]
1818
+ max_non_ref = None if max_curves is None else max(int(max_curves) - 1, 0)
1819
+ non_ref_fluences = common_azimint_utils.evenly_spaced_subset(
1820
+ non_ref_fluences,
1821
+ max_non_ref,
1822
+ )
1823
+
1771
1824
  patterns = []
1772
- for f in sorted(fl_list):
1825
+ for f in non_ref_fluences:
1773
1826
  if ref_type_n == "fluence" and abs(float(f) - float(ref_f)) < 1e-12:
1774
1827
  continue
1775
1828
 
@@ -1789,12 +1842,20 @@ def plot_1D_abs_and_diffs_fluence(
1789
1842
  normalize=bool(normalize),
1790
1843
  q_norm_range=q_norm_range,
1791
1844
  )
1792
- patterns.append((f"{float(f):g}", q, I))
1845
+ f_display = float(f) * float(fluence_scale) + float(fluence_offset)
1846
+ patterns.append((_fluence_display_label(f_display), q, I))
1793
1847
 
1794
1848
  if title is None:
1849
+ display_delay_fs = int(delay_fs) + float(delay_offset_fs)
1850
+ display_delay = delay_label_value(
1851
+ display_delay_fs,
1852
+ fs_or_ps=fs_or_ps,
1853
+ digits=digits,
1854
+ )
1855
+ display_unit = general_utils.time_unit_label(fs_or_ps)
1795
1856
  title = (
1796
1857
  f"{sample_name}. {temperature_K}K.\n"
1797
- f"ex. wl={excitation_wl_nm}nm. delay={int(delay_fs)}fs.\n"
1858
+ f"ex. wl={excitation_wl_nm}nm. delay={display_delay:g} {display_unit}.\n"
1798
1859
  f"tw={time_window_fs}fs. azim=({azim_window[0]},{azim_window[1]})"
1799
1860
  )
1800
1861
 
@@ -1839,7 +1900,7 @@ def plot_1D_abs_and_diffs_fluence(
1839
1900
  ylim_diff=ylim_diff,
1840
1901
  vlines_peak=vlines_peak,
1841
1902
  vlines_bckg=vlines_bckg,
1842
- legend_title="Fluence [mJ/cm$^2$]",
1903
+ legend_title=f"Fluence [{fluence_unit}]",
1843
1904
  legend_loc="upper left",
1844
1905
  legend_outside=True,
1845
1906
  **save_kwargs,
@@ -278,6 +278,11 @@ def plot_1D_abs_and_diffs_delay(
278
278
  vlines_bckg: Optional[Tuple[float, float]] = None,
279
279
  fs_or_ps: str = "ps",
280
280
  digits: int = 2,
281
+ delay_offset_fs: float = 0.0,
282
+ fluence_scale: float = 1.0,
283
+ fluence_offset: float = 0.0,
284
+ fluence_unit: str = "mJ/cm$^2$",
285
+ max_curves: Optional[int] = None,
281
286
  title: Optional[str] = None,
282
287
  azim_offset_deg: float = -90.0,
283
288
  polarization_factor: Optional[float] = None,
@@ -313,8 +318,11 @@ def plot_1D_abs_and_diffs_delay(
313
318
  Intensity normalization and XY cache-generation controls.
314
319
  xlim, ylim_top, ylim_diff, vlines_peak, vlines_bckg
315
320
  Axis limits and optional marked q intervals.
316
- fs_or_ps, digits, title
317
- Delay display unit, label precision, and figure title.
321
+ fs_or_ps, digits, delay_offset_fs, fluence_scale, fluence_offset,
322
+ fluence_unit, max_curves, title
323
+ Delay display unit, label precision, display-only delay offset,
324
+ display-only fluence title scale/offset, maximum displayed curves
325
+ including reference, and figure title.
318
326
  azim_offset_deg, polarization_factor
319
327
  Azimuth-coordinate offset and optional polarization correction.
320
328
  save_plots, out_name, save_format, save_dpi, save_overwrite, save_base_dir
@@ -381,7 +389,7 @@ def plot_1D_abs_and_diffs_delay(
381
389
  )
382
390
 
383
391
  ref_label_val = azimint_utils.delay_label_value(
384
- ref_delay_fs,
392
+ ref_delay_fs + float(delay_offset_fs),
385
393
  fs_or_ps=fs_or_ps,
386
394
  digits=digits,
387
395
  )
@@ -409,8 +417,19 @@ def plot_1D_abs_and_diffs_delay(
409
417
  overwrite_xy=bool(overwrite_xy),
410
418
  )
411
419
 
420
+ non_ref_delays = [
421
+ int(d)
422
+ for d in delays_list
423
+ if not (ref_type_n == "delay" and int(d) == int(ref_value))
424
+ ]
425
+ max_non_ref = None if max_curves is None else max(int(max_curves) - 1, 0)
426
+ non_ref_delays = azimint_utils.evenly_spaced_subset(
427
+ sorted(non_ref_delays),
428
+ max_non_ref,
429
+ )
430
+
412
431
  patterns = []
413
- for d in delays_list:
432
+ for d in non_ref_delays:
414
433
  if ref_type_n == "delay" and int(d) == int(ref_value):
415
434
  continue
416
435
 
@@ -429,13 +448,18 @@ def plot_1D_abs_and_diffs_delay(
429
448
  compute_if_missing=bool(compute_if_missing),
430
449
  overwrite_xy=bool(overwrite_xy),
431
450
  )
432
- dd_val = azimint_utils.delay_label_value(int(d), fs_or_ps=fs_or_ps, digits=digits)
451
+ dd_val = azimint_utils.delay_label_value(
452
+ int(d) + float(delay_offset_fs),
453
+ fs_or_ps=fs_or_ps,
454
+ digits=digits,
455
+ )
433
456
  patterns.append((f"{dd_val}", q, I))
434
457
 
435
458
  if title is None:
459
+ display_fluence = float(fluence_mJ_cm2) * float(fluence_scale) + float(fluence_offset)
436
460
  title = (
437
461
  f"{sample_name}. {temperature_K}K.\n"
438
- f"ex. wl={excitation_wl_nm}nm. flu={fluence_mJ_cm2} mJ/cm$^2$.\n"
462
+ f"ex. wl={excitation_wl_nm}nm. flu={display_fluence:g} {fluence_unit}.\n"
439
463
  f"tw={time_window_fs}fs. azim=({azim_window[0]},{azim_window[1]})"
440
464
  )
441
465
 
@@ -619,7 +643,9 @@ def plot_1D_abs_and_diffs_fluence(
619
643
  delay_offset_fs: float = 0.0,
620
644
  fs_or_ps: str = "fs",
621
645
  digits: int = 2,
646
+ fluence_digits: Optional[int] = None,
622
647
  fluence_unit: str = "mJ/cm$^2$",
648
+ max_curves: Optional[int] = None,
623
649
  azim_offset_deg: float = -90.0,
624
650
  polarization_factor: Optional[float] = None,
625
651
  save_plots: bool = False,
@@ -654,9 +680,12 @@ def plot_1D_abs_and_diffs_fluence(
654
680
  Intensity normalization and XY cache-generation controls.
655
681
  xlim, ylim_top, ylim_diff, vlines_peak, vlines_bckg
656
682
  Axis limits and optional marked q intervals.
657
- title, fluence_scale, fluence_offset, delay_offset_fs, fs_or_ps, digits, fluence_unit
658
- Figure title and display-only fluence/delay corrections. File lookup
659
- still uses the stored ``delay_fs`` and ``fluences_mJ_cm2`` values.
683
+ title, fluence_scale, fluence_offset, delay_offset_fs, fs_or_ps, digits,
684
+ fluence_digits, fluence_unit, max_curves
685
+ Figure title and display-only fluence/delay corrections. ``digits``
686
+ controls the fixed-delay label; ``fluence_digits`` controls fluence
687
+ labels in the legend. File lookup still uses the stored ``delay_fs``
688
+ and ``fluences_mJ_cm2`` values.
660
689
  azim_offset_deg, polarization_factor
661
690
  Azimuth-coordinate offset and polarization correction.
662
691
  save_plots, out_name, save_format, save_dpi, save_overwrite, save_base_dir
@@ -677,6 +706,14 @@ def plot_1D_abs_and_diffs_fluence(
677
706
  FileNotFoundError
678
707
  If no matching fluence data can be found.
679
708
  """
709
+ def _fluence_display_label(value: float) -> str:
710
+ ndig = digits if fluence_digits is None else fluence_digits
711
+ try:
712
+ rounded = round(float(value), int(ndig))
713
+ except Exception:
714
+ return f"{float(value):g}"
715
+ return f"{rounded:g}"
716
+
680
717
  dataset_kwargs, legacy_kwargs = _resolve_path_config(
681
718
  paths=paths,
682
719
  path_root=path_root,
@@ -723,7 +760,7 @@ def plot_1D_abs_and_diffs_fluence(
723
760
  int(delay_fs),
724
761
  **dataset_kwargs,
725
762
  )
726
- ref_label = f"ref: {ref_f_display:g} {fluence_unit}"
763
+ ref_label = f"ref: {_fluence_display_label(ref_f_display)} {fluence_unit}"
727
764
  ref_tag_for_file = f"fluence_{general_utils.fluence_tag_file(ref_f)}mJ"
728
765
 
729
766
  else:
@@ -747,8 +784,19 @@ def plot_1D_abs_and_diffs_fluence(
747
784
  overwrite_xy=bool(overwrite_xy),
748
785
  )
749
786
 
787
+ non_ref_fluences = [
788
+ float(f)
789
+ for f in sorted(fl_list)
790
+ if not (ref_type_n == "fluence" and abs(float(f) - float(ref_value)) < 1e-12)
791
+ ]
792
+ max_non_ref = None if max_curves is None else max(int(max_curves) - 1, 0)
793
+ non_ref_fluences = azimint_utils.evenly_spaced_subset(
794
+ non_ref_fluences,
795
+ max_non_ref,
796
+ )
797
+
750
798
  patterns = []
751
- for f in sorted(fl_list):
799
+ for f in non_ref_fluences:
752
800
  if ref_type_n == "fluence" and abs(float(f) - float(ref_value)) < 1e-12:
753
801
  continue
754
802
 
@@ -768,7 +816,7 @@ def plot_1D_abs_and_diffs_fluence(
768
816
  overwrite_xy=bool(overwrite_xy),
769
817
  )
770
818
  f_display = float(f) * float(fluence_scale) + float(fluence_offset)
771
- patterns.append((f"{f_display:g}", q, I))
819
+ patterns.append((_fluence_display_label(f_display), q, I))
772
820
 
773
821
  if title is None:
774
822
  display_delay_fs = int(delay_fs) + float(delay_offset_fs)