Where
What happens
The module angle is computed with std::atan2(r, hycal_z), which gives radians. It is passed as theta_deg, and ExpectedEnergy multiplies it by DEG2RAD again. The angle actually used is therefore 57x too small (under 0.08 deg), so E_expect is effectively the 0-degree value for every module.
The bias is computed as E_recon / E_expect - 1. Because E_expect is too high, the stored bias is too low by the elastic e-p kinematic falloff at that module's angle. HyCalEnergyBias::correction_factor() applies 1/(1+bias) without any normalization, so with energy_bias_correction enabled the corrected cluster energies come out too high by the same amount.
Size of the error on E_expect. This uses the tool's module selection (|x|, |y| between 2 and 16 module widths, which gives 1008 modules from 0.48 to 4.15 deg) and hycal_z = 6265.887 mm:
| Ebeam |
E_expect used (all modules) |
correct at 2.42 deg |
correct at 4.15 deg |
| 2239.51 MeV |
2237.45 |
2232.70 (-0.21%) |
2223.49 (-0.62%) |
| 3488.43 MeV |
3486.37 |
3474.85 (-0.33%) |
3452.63 (-0.97%) |
| 728.9 MeV |
726.84 |
726.34 (-0.07%) |
725.35 (-0.20%) |
With the X17 geometry (hycal_z = 7530.681 mm) the largest error at 2.24 GeV is -0.43%, at 3.46 deg.
The same wrong E_expect also seeds fitPeak. It sets the denominator of the h2_bowl_shape_W* plots too, which are drawn on a 0.98 to 1.02 color scale.
The committed database/energy_bias/2p2GeV_ep.json looks consistent with this. The average of the central 3x3 cells per module falls with angle: -0.07% at 0.4-1.0 deg, -0.18% at 2.0-2.5 deg, -0.32% at 2.5-3.0 deg and -0.44% at 3.0-3.5 deg. The predicted offset in the same bins is -0.02%, -0.18%, -0.27% and -0.33%.
Evidence
// hycal_energy_bowl_shape.cpp:375-376
const double angle = std::atan2(std::sqrt(module->x * module->x + module->y * module->y), gRunConfig.hycal_z);
const double expected_energy = analysis::PhysicsTools::ExpectedEnergy(angle, gRunConfig.Ebeam, "ep");
// PhysicsTools.cpp:284-286
float PhysicsTools::ExpectedEnergy(float theta_deg, float Ebeam, const std::string &type)
{
float theta = theta_deg * DEG2RAD;
Other callers convert to degrees first, for example hycal_Erecon_check.cpp#L318-L322 (... * 180.0f / M_PI) and physics_calib.cpp#L594-L596.
Suggested fix
Convert to degrees at both call sites, the same way hycal_Erecon_check does:
const double theta_deg = std::atan2(
std::sqrt(module->x * module->x + module->y * module->y),
gRunConfig.hycal_z) * 180.0 / M_PI;
... ExpectedEnergy(theta_deg, gRunConfig.Ebeam, "ep");
Then regenerate database/energy_bias/*.json from the fixed tool. The current tables carry the angle-dependent offset described above.
Status
Still present on the dedup-refactor branch. Both call sites were deliberately left unchanged there so that the refactor would not change the tool's output.
Where
ExpectedEnergy(float theta_deg, ...)expects degreesWhat happens
The module angle is computed with
std::atan2(r, hycal_z), which gives radians. It is passed astheta_deg, andExpectedEnergymultiplies it byDEG2RADagain. The angle actually used is therefore 57x too small (under 0.08 deg), soE_expectis effectively the 0-degree value for every module.The bias is computed as
E_recon / E_expect - 1. BecauseE_expectis too high, the stored bias is too low by the elastic e-p kinematic falloff at that module's angle.HyCalEnergyBias::correction_factor()applies1/(1+bias)without any normalization, so withenergy_bias_correctionenabled the corrected cluster energies come out too high by the same amount.Size of the error on
E_expect. This uses the tool's module selection (|x|, |y| between 2 and 16 module widths, which gives 1008 modules from 0.48 to 4.15 deg) andhycal_z = 6265.887mm:With the X17 geometry (
hycal_z = 7530.681mm) the largest error at 2.24 GeV is -0.43%, at 3.46 deg.The same wrong
E_expectalso seedsfitPeak. It sets the denominator of theh2_bowl_shape_W*plots too, which are drawn on a 0.98 to 1.02 color scale.The committed
database/energy_bias/2p2GeV_ep.jsonlooks consistent with this. The average of the central 3x3 cells per module falls with angle: -0.07% at 0.4-1.0 deg, -0.18% at 2.0-2.5 deg, -0.32% at 2.5-3.0 deg and -0.44% at 3.0-3.5 deg. The predicted offset in the same bins is -0.02%, -0.18%, -0.27% and -0.33%.Evidence
Other callers convert to degrees first, for example hycal_Erecon_check.cpp#L318-L322 (
... * 180.0f / M_PI) and physics_calib.cpp#L594-L596.Suggested fix
Convert to degrees at both call sites, the same way
hycal_Erecon_checkdoes:Then regenerate
database/energy_bias/*.jsonfrom the fixed tool. The current tables carry the angle-dependent offset described above.Status
Still present on the
dedup-refactorbranch. Both call sites were deliberately left unchanged there so that the refactor would not change the tool's output.