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.

162 lines
5.0 KiB

10 months ago
  1. from parameterisations.utils.parse_regression_coef_to_array import (
  2. parse_regression_coef_to_array,
  3. )
  4. from parameterisations.utils.fit_linear_regression_model import (
  5. fit_linear_regression_model,
  6. )
  7. import uproot
  8. import argparse
  9. from pathlib import Path
  10. def parameterise_magnet_kink(
  11. input_file: str = "data/param_data_selected.root",
  12. tree_name: str = "Selected",
  13. per_layer=False,
  14. ) -> Path:
  15. """Function that calculates parameters for estimating the magnet kink z position.
  16. Args:
  17. input_file (str, optional): Defaults to "data/param_data_selected.root".
  18. tree_name (str, optional): Defaults to "Selected".
  19. per_layer (bool, optional): If true also calculates parameters per SciFi layer. Defaults to False.
  20. Returns:
  21. Path: Path to cpp code file.
  22. """
  23. input_tree = uproot.open({input_file: tree_name})
  24. # this is an event list of dictionaries containing awkward arrays
  25. array = input_tree.arrays()
  26. array["dSlope_fringe"] = array["tx_ref"] - array["tx"]
  27. # the magnet kink position is the point of intersection of the track tagents
  28. array["z_mag_x_fringe"] = (
  29. array["x"]
  30. - array["x_ref"]
  31. - array["tx"] * array["z"]
  32. + array["tx_ref"] * array["z_ref"]
  33. ) / array["dSlope_fringe"]
  34. array["dSlope_xEndT"] = array["tx_l11"] - array["tx"]
  35. array["dSlope_xEndT_abs"] = abs(array["dSlope_xEndT"])
  36. array["x_EndT_abs"] = abs(
  37. array["x_l11"] + array["tx_l11"] * (9410.0 - array["z_l11"]),
  38. )
  39. # the magnet kink position is the point of intersection of the track tagents
  40. array["z_mag_xEndT"] = (
  41. array["x"]
  42. - array["x_l11"]
  43. - array["tx"] * array["z"]
  44. + array["tx_l11"] * array["z_l11"]
  45. ) / array["dSlope_xEndT"]
  46. if per_layer:
  47. layered_features = [f"x_diff_straight_l{layer}" for layer in range(12)]
  48. rows = []
  49. for i, feat in enumerate(layered_features):
  50. scale = 3000
  51. if "dSlope" not in feat:
  52. array[f"x_l{i}_rel"] = array[f"x_l{i}"] / scale
  53. array[f"x_diff_straight_l{i}"] = (
  54. array[f"x_l{i}"]
  55. - array["x"]
  56. - array["tx"] * (array[f"z_l{i}"] - array["z"])
  57. )
  58. model, poly_features = fit_linear_regression_model(
  59. array,
  60. target_feat="z_mag_x_fringe",
  61. features=[
  62. "tx",
  63. "ty",
  64. feat,
  65. ],
  66. keep=[
  67. "tx^2",
  68. f"tx x_diff_straight_l{i}",
  69. "ty^2",
  70. f"x_diff_straight_l{i}^2",
  71. ],
  72. degree=2,
  73. fit_intercept=True,
  74. )
  75. rows.append(
  76. "{"
  77. + str(model.intercept_)
  78. + "f,"
  79. + ",".join([str(coef) + "f" for coef in model.coef_ if coef != 0.0])
  80. + "}",
  81. )
  82. cpp_decl = parse_regression_coef_to_array(
  83. model,
  84. poly_features,
  85. "zMagnetParamsLayers",
  86. rows=rows,
  87. )
  88. # now fit model for the reference plane
  89. model_ref, poly_features_ref = fit_linear_regression_model(
  90. array,
  91. target_feat="z_mag_x_fringe",
  92. features=["tx", "ty", "dSlope_fringe"],
  93. keep=["tx^2", "tx dSlope_fringe", "ty^2", "dSlope_fringe^2"],
  94. degree=2,
  95. fit_intercept=True,
  96. )
  97. cpp_ref = parse_regression_coef_to_array(
  98. model_ref,
  99. poly_features_ref,
  100. "zMagnetParamsRef",
  101. )
  102. model_endt, poly_features_endt = fit_linear_regression_model(
  103. array,
  104. target_feat="z_mag_xEndT",
  105. features=["tx", "dSlope_xEndT", "dSlope_xEndT_abs", "x_EndT_abs"],
  106. keep=["tx^2", "dSlope_xEndT^2", "dSlope_xEndT_abs", "x_EndT_abs"],
  107. degree=2,
  108. fit_intercept=True,
  109. )
  110. cpp_ref += parse_regression_coef_to_array(
  111. model_endt,
  112. poly_features_endt,
  113. "zMagnetParamsEndT",
  114. )
  115. outpath = Path("parameterisations/result/z_mag_kink_params.hpp")
  116. outpath.parent.mkdir(parents=True, exist_ok=True)
  117. with open(outpath, "w") as result:
  118. result.writelines(cpp_decl + cpp_ref if per_layer else cpp_ref)
  119. return outpath
  120. if __name__ == "__main__":
  121. parser = argparse.ArgumentParser()
  122. parser.add_argument(
  123. "--input-file",
  124. type=str,
  125. help="Path to the input file",
  126. required=False,
  127. )
  128. parser.add_argument(
  129. "--tree-name",
  130. type=str,
  131. help="Path to the input file",
  132. required=False,
  133. )
  134. args = parser.parse_args()
  135. args_dict = {arg: val for arg, val in vars(args).items() if val is not None}
  136. outfile = parameterise_magnet_kink(**args_dict)
  137. try:
  138. import subprocess
  139. # run clang-format for nicer looking result
  140. subprocess.run(
  141. [
  142. "clang-format",
  143. "-i",
  144. f"{outfile}",
  145. ],
  146. check=True,
  147. )
  148. except:
  149. pass