Skip to content

Transfer reaction kinematics implementation#111

Open
carlottaporzio wants to merge 14 commits into
Miniball:mainfrom
carlottaporzio:TransferProduct
Open

Transfer reaction kinematics implementation#111
carlottaporzio wants to merge 14 commits into
Miniball:mainfrom
carlottaporzio:TransferProduct

Conversation

@carlottaporzio

@carlottaporzio carlottaporzio commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Modified the TransferReaction function to do the full kinematics reconstruction of ejectile, from measured recoil information:

  • Used TLorentzVector class to do the maths.
  • Introduced a GetInitialEnergyFromDeltaE function to get the full alpha energy from the energy deposited in CD layer only, to overcome pileup issues etc. with PAD energy. This relies on a set of graphs "Eloss vs Einitial" (one for each strip, given its effective thickness) that are also printed out, so that the user can check that the (user-defined) initial energy range is ok for the graphs to be monotonic (or at least monotonic in the relevant energy range for their experiment).

Added some histograms to check results of kinematics reconstruction: beta of ejectile, excitation energy of ejectile, reconstructed recoil energy vs theta, reconstructed ejectile energy vs theta. Also filled the pE_theta_recoil histogram for the transfer reaction case (before it was filled only for Coulex).

As the Doppler modes numbering resulted a bit confusing when trying to pass from a Coulex to a transfer reaction logic, where you measure (at least in cluster transfer, but I assume this is a more general statement) the recoil/light particle and reconstruct ejectile info from that, I added two extra Doppler modes. These are meant to apply uniquely to transfer reactions. They are:

  • 6 = reconstruct ejectile energy after target (plunger experiment: energy after target)
  • 7 = if degrader is defined, reconstruct ejectile energy after degrader, correcting for energy loss in degrader (plunger experiment: energy after degrader)

Note that in practice I am actually only calling the option if doppler_mode == 7 in case we need to calculate energy loss through the degrader, but I never write anywhere if doppler_mode == 6, so maybe I am missing something on correct implementation? Inputs are welcome.

Inputs on the entire logic are welcome.

@warr

warr commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

It would be useful to have a description of what the function does at the start, rather than just what inspired the method. Also the kinflag parameter was previously documented, but not used. Now it is not documented, but I think it would be better to "@param kinflag is no longer used"

@warr

warr commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

The original code set the recoil energy appropriately for the Doppler mode, after it had backtracked to the target position. Now it just leaves it with the energy at the target position. I'm not sure anyone will need this energy right now (e.g. if the recoil was excited and gammas needed Doppler correction, which is clearly not the case with very light ions), but the energy at each step backtracked from the CD to the centre of target is known, so it is just a matter of storing it at each step and then setting the final recoil energy appropriately for the Doppler mode.

@warr

warr commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

I think we need a way to let the user chose between the determination of the total energy after the CD dead layer from the CD + PAD energy or from the extrapolation of the CD energy using SRIM.

@lpgaff

lpgaff commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

In creating the "Eloss vs Einitial" graphs, they become dual valued because the same energy loss can be obtained by a low energy particle that is fully stopped and a high energy particle that punches through. We are only interested in the punch throughs when using this function, right? Or rather, it is only going to be relevant for events where Eloss < Einitial. So we can make a condition when inverting the plots that you only take data points that have Eloss < Einitial and you will not have the dual valued problem, but you can still scan over the full range from 1 keV to 10 GeV (or one point for every line in the SRIM file?).

However, the user still has the problem that they need to interpret their data correctly! I expect what we should do is instruct the user to run the analysis twice, one assuming the alphas are fully stopped and one assuming they are punching through, and then manually pick the relevant strips from each of the two analyses. This means we need a switch with/like the DopplerMode flag (maybe?!) to decide what to assume here.

Also, we should remember that Einitial in this case is always after the energy loss in the dead layer too.

(will look at kinematics next...)

@lpgaff

lpgaff commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Also, we should remember that Einitial in this case is always after the energy loss in the dead layer too.

Sorry, you have done this correctly, I misread it first time around

Comment thread src/Reaction.cc Outdated
int n = 0;
for( double E = transfer_recoil_range[0]; E <= transfer_recoil_range[1]; E += 500 ){ // sampling over user-defined energy range (default 15e3-150e3 keV), where Eloss vs E is monotonic, so can be inverted
dE = GetEnergyLoss(E, cd_eff_thick, gStopping[4]);
gEloss_E[i]->SetPoint(n, E, dE);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can change n to gEloss_E[i]->GetNpoints(), or something which is more efficient and accurate if you are filling two graphs with a different a number if you add a condition on if( dE < E )

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also TGraph::AddPoint since about root 6.24, which is:
virtual void AddPoint(Double_t x, Double_t y) { SetPoint(fNpoints, x, y); }

@lpgaff lpgaff Jul 9, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. That does the same thing, but if we use AddPoint in this code, it restricts the ROOT version rather unnecessarily. In the SRIM functions, we reverted back from AddPoint exactly for this reason

Comment thread src/Reaction.cc Outdated
Co-authored-by: Liam Gaffney <[email protected]>
Comment thread src/Reaction.cc Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants