You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
3.4 KiB

10 months ago
  1. import uproot
  2. import awkward as ak
  3. from pathlib import Path
  4. from scipy.optimize import curve_fit
  5. import numpy as np
  6. import pandas as pd
  7. from math import ceil
  8. import argparse
  9. def fastSigmoid(x, p0, p1, p2):
  10. return p0 + p1 * x / (1 + abs(p2 * x))
  11. def parameterise_hough_histogram(
  12. input_file: str = "data/param_data_selected_all_p.root",
  13. tree_name: str = "Selected",
  14. n_bins_start: int = 900,
  15. hist_range: tuple[float, float] = (-3000.0, 3000.0),
  16. first_bin_center: float = 2.5,
  17. ) -> Path:
  18. """Function to parameterise the binning of the Hough histogram using the occupancy on the reference plane.
  19. Args:
  20. input_file (str, optional): Defaults to "data/param_data_selected_all_p.root".
  21. tree_name (str, optional): Defaults to "Selected".
  22. n_bins_start (int, optional): Starting (minimal) number of bins in histogram. Defaults to 900.
  23. hist_range (tuple[float, float], optional): Range in mm the histogram covers. Defaults to (-3000.0, 3000.0).
  24. first_bin_center (float, optional): Calculated bin center at lower range. Defaults to 2.5.
  25. Returns:
  26. Path: Path to cpp code file.
  27. """
  28. input_tree = uproot.open({input_file: tree_name})
  29. # this is an event list of dictionaries containing awkward arrays
  30. array = input_tree.arrays()
  31. array = array[[field for field in ak.fields(array) if "scifi_hit" not in field]]
  32. df = ak.to_pandas(array)
  33. selection = (df["x_ref"] > hist_range[0]) & (df["x_ref"] < hist_range[1])
  34. data = df.loc[selection, "x_ref"]
  35. _, equal_bins = pd.qcut(data, q=n_bins_start, retbins=True)
  36. bin_numbering = np.arange(0, n_bins_start + 1)
  37. equalbins_center = equal_bins[int(n_bins_start / 10) : int(9 * n_bins_start / 10)]
  38. bin_numbering_center = bin_numbering[
  39. int(n_bins_start / 10) : int(9 * n_bins_start / 10)
  40. ]
  41. func = fastSigmoid
  42. popt, _ = curve_fit(func, xdata=equalbins_center, ydata=bin_numbering_center)
  43. print("Parameterisation for central occupancy:")
  44. print("fastSigmoid(x,", *popt, ")")
  45. print("Scan shift to match first bin center ...")
  46. shift = 0.0
  47. while func(hist_range[0], popt[0] + shift, *popt[1:]) < first_bin_center:
  48. shift += 0.1
  49. popt[0] += shift - 0.1
  50. popt[2] = abs(popt[2])
  51. print("shifted: fastSigmoid(x,", *popt, ")")
  52. n_bins_final = ceil(func(hist_range[1], *popt))
  53. print(
  54. "Final number of bins:",
  55. n_bins_final,
  56. "including offset of",
  57. int(first_bin_center),
  58. )
  59. comment = f"// p[0] + p[1] * x / (1 + p[2] * abs(x)) for nBins = {n_bins_final}\n"
  60. cpp = (
  61. "constexpr auto p = std::array{"
  62. + ", ".join([str(p) + "f" for p in popt])
  63. + "};"
  64. )
  65. outpath = Path("parameterisations/result/hough_histogram_binning_params.hpp")
  66. outpath.parent.mkdir(parents=True, exist_ok=True)
  67. with open(outpath, "w") as result:
  68. result.writelines([comment, cpp])
  69. return outpath
  70. if __name__ == "__main__":
  71. parser = argparse.ArgumentParser()
  72. parser.add_argument(
  73. "--input-file",
  74. type=str,
  75. help="Path to the input file",
  76. required=False,
  77. )
  78. parser.add_argument(
  79. "--tree-name",
  80. type=str,
  81. help="Path to the input file",
  82. required=False,
  83. )
  84. args = parser.parse_args()
  85. args_dict = {arg: val for arg, val in vars(args).items() if val is not None}
  86. outfile = parameterise_hough_histogram(**args_dict)