Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fibers and ToFD calibration, parameter and Tracking update. #842

Draft
wants to merge 2 commits into
base: dev
Choose a base branch
from

Conversation

enlorenz
Copy link

Fibers and ToFD calibration, parameter and Tracking update.

Fibers:
Adjusted parameter calculation and application. Minor changes, ToF and ToT calculation now consistent.

ToFD:
Cal2Hit adjusted to be used with new parameter structure. Adjusted mathematical operations, and introduced some failsafes.
Code is not "clean" yet, but needed so that the parameters can be used for further analysis.
Cal2HitPar is in a "running" state and delivers parameters for "s522/s509". Not advised to use for other experiments yet. Code needs a proper re-work, before it is safe for general use.
Individual calibration steps/functions with minor changes. introduced higher order correction step using physics data.

Fragment tracker:
Standalone task. Uses Fibers and ToFD to track fragments behind GLAD and calculate in real time observables and deliver PID. Still under development.

Checklist:

Enis Lorenz and others added 2 commits April 11, 2023 15:01
Minor changes to fiber and tofd cal2hit. ClockTDC fine time in timestitch corrected

minor changes

general update of tofd and fibers

Add files via upload

Adjusted Cal2Hit to be congruent with new calibration procedure.

Made recent changes to ToFD and Fiber Cal2Hit work in newer R3BRoot framework
Comment on lines 194 to 202

header = dynamic_cast<R3BEventHeader*>(mgr->GetObject("EventHeader."));
header = (R3BEventHeader*)mgr->GetObject("EventHeader.");
R3BLOG_IF(fatal, NULL == header, "EventHeader. not found");

fCalItems = dynamic_cast<TClonesArray*>(mgr->GetObject("TofdCal"));
fCalItems = (TClonesArray*)mgr->GetObject("TofdCal");
R3BLOG_IF(fatal, NULL == fCalItems, "TofdCal not found");

fCalTriggerItems = dynamic_cast<TClonesArray*>(mgr->GetObject("TofdTriggerCal"));
fCalTriggerItems = (TClonesArray*)mgr->GetObject("TofdTriggerCal");
R3BLOG_IF(fatal, NULL == fCalTriggerItems, "TofdTriggerCal not found");
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't quite understand here. Why do you change dynamic_cast back to C-style cast?

Copy link
Contributor

Choose a reason for hiding this comment

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

This is something general in the PR, I guess Enis started with these improvements some months ago before the current implementation based on "dynamic_cast".

Copy link
Contributor

@YanzhaoW YanzhaoW Apr 11, 2023

Choose a reason for hiding this comment

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

I see. But should the PR be rebased on the HEAD of dev branch?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, rebase the dev branch is the best

@YanzhaoW
Copy link
Contributor

2000 warnings for a PR with 5000+ lines of changes. Both are too big for a PR. But as I have suggested in the last meeting, if you want to disable the clang-tidy warnings for a code block, you can do:

// NOLINTBEGIN

// ... code block ...

// NOLINTEND

I would still suggest you should fix the warnings as many as possible.

Copy link

@lbott193 lbott193 left a comment

Choose a reason for hiding this comment

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

I only had a quick look at Tofd so far.
Also, I could not check if your changes produce different results than my code.
I will try to get it running and message you then.

Not advised to use for other experiments yet. Code needs a proper re-work, before it is safe for general use.

If your code should be used for those two experiments only, why not introduce ExpId dependent functions, or do you plan to make it compatible for other experiments?
What are the

higher order correction step using physics data

did the number of calibration parameters change, are thy now used in a different way? I might have missed it, because comparing the two versions is not easy due to a lot of changes. Maybe you can show this in one of the next analysis meetings?

I don't know if one should merge if there are hundreds of lines commented and you say the code is not "clean" or it is "running". Why not create a branch and let people who need the code pull from your fork, create a WIP or something.

Comment on lines +447 to +454
if(top_tot > c_range_ns/10){
top_tot = bot_tot;
if(!both) nev_lmt++;
}
if(bot_tot > c_range_ns/10){
bot_tot = top_tot;
if(!both) nev_lmb++;
}

Choose a reason for hiding this comment

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

Does this yield to expected results?
I guess at least charge and y-position will be all over the place for those events.
What do you gain from using those events / how many times does this occur?
Will you use calibration parameters from the correct side later on in the code?

Copy link
Author

Choose a reason for hiding this comment

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

Good point, I need to re-check if this still holds up. This piece of code is (at least) a relic of the investigation of missed leading edges, which lead to unreasonably high ToTs. 1/10th of the range is an arbitrary threshold, but it is a clear indicator if the ToT of one side is way too high. Setting it to the same value as the other pmt at least allows for some recycling of said event.

The occurrences are low though: ~0.092% topside, ~0.094% bottomside and ~0.028% both sides.

Comment on lines +548 to +549
// qb = TMath::Sqrt(Ctop_tot * Cbot_tot) /
qb = TMath::Sqrt(Ctop_tot * Cbot_tot) *

Choose a reason for hiding this comment

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

Why change this?
This changes calculation of charge completely. Has the parameter calculation also changed?
What about backward compatibility?
Is it necessary to change hit parameters for other users?
It is also different from the other method in lines 560 and 566 which still uses /

Copy link
Author

Choose a reason for hiding this comment

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

As Andrea mentioned further below, using / did not yield correct results. Using the multiplication on the other hand made the channels converge. As I did not change the shape of the parameters themselves, it should be backwards compatible still in this case.
I did not further explore the double exponential, therefore I don't know if there it should be a / or *

Copy link
Contributor

Choose a reason for hiding this comment

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

In this case, I agree with Lukas. Multiplying is incorrect

Copy link
Author

Choose a reason for hiding this comment

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

"In this case" meaning for the double exponential? Or for the "smiley function" too?

}

qb = qb / 200.;

Choose a reason for hiding this comment

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

Why is the calculated charge divided by 200 or 400?
Shouldn't it be already calibrated by now?

Copy link
Author

Choose a reason for hiding this comment

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

This is one of the points that are (for now) hard coded and need to be resolved. The Charge alignment is run over scaled qb, so this needs to be scaled to the same level. 200 is arbitrary and is roughly the mean ToT value of Oxygen in this calibration.

}

qb = qb / 200.;
if(qb > 70.) qb = qb / 200.;

Choose a reason for hiding this comment

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

After you divided by 200 you still expect charges greater than 70 and divide them by 200 again?
Why?

Copy link
Author

Choose a reason for hiding this comment

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

It appeared that sometimes the ToTs carry another factor of said scaling factor. Where this comes from is not clear at the moment, but dividing those events again by 200 solves the issue, 70 is chosen randomly as it just says "sufficiently high". But these two lines should just be considered a "hot fix".

Comment on lines +476 to +482
auto bot_ns_walk = bot_ns - walk(Cbot_tot,
par->GetPar1Walk(),
par->GetPar2Walk(),
par->GetPar3Walk(),
par->GetPar4Walk(),
par->GetPar5Walk());
auto top_ns_walk = top_ns - walk(top_tot,
auto top_ns_walk = top_ns - walk(Ctop_tot,

Choose a reason for hiding this comment

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

Those variables are not used anywhere else in the code.
Is it known to the user, that walk corrections are not applied?

Copy link
Author

Choose a reason for hiding this comment

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

This fact should be mentioned clearly, I agree.

Choose a reason for hiding this comment

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

Is there a plan to fix this or are walk corrections done in other analysis steps like tracking?

R3BTofDHitModulePar* par;
for (Int_t j = 0; j < (fPaddlesPerPlane); j++)
{
if(j==45 || j == 46) continue;

Choose a reason for hiding this comment

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

why are there 45 or 46 paddles in a plane and why do they have to be skipped?

Copy link
Contributor

Choose a reason for hiding this comment

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

I assume this was a relic from a previous version or a sanity check. It should be removed

Comment on lines +1507 to +1517
gr1->Draw("AP");

fZfitType = "pol2";

// TF1* fitz = new TF1("fitz", "[0]*TMath::Power(x,[2])+[1]", min, max);
if (fZfitType != "pol1" && fZfitType != "pol2")
{
R3BLOG(error, "Fit " << fZfitType << " is not allowed, use pol1 or pol2 ");
return -1;
}
auto fitz = new TF1("fitz", fZfitType, min, max);

Choose a reason for hiding this comment

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

Interesting.
Did you notice an improvement over the function that I initially used?
Which was something like [0]*TMath::Power(x,[2])+[1] if I remember correctly?

Copy link
Author

Choose a reason for hiding this comment

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

Interestingly so. though calling "pol2" and [0]*TMath::Power(x,[2])+[1] should yield the same result, the latter for some reason did not fit consistently....

Choose a reason for hiding this comment

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

Ok, if it improves the fit it is of course better. But I would not expect same results. The function I used was an observation that the light quenching is almost linear in the ToFD case and not something quadratic or other models like Birk or so, as you can see in the Tofd paper https://repository.gsi.de/record/250622 figure 16. Some paddles saw more quenching others less, that's why I did fit the exponent itself.

Choose a reason for hiding this comment

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

Since you sent me your analysis report I think i finally understand why this is done with pol2 and pol1.
I think you've done some steps that are at best not necessary and ultimatly came to the same point I mentioned in the previous comment, but maybe we can discuss this somewhere else.

Comment on lines +1746 to +1747
fTofdTotLow = 100.;
fTofdTotHigh = 350.;

Choose a reason for hiding this comment

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

Why not use the user provided values?

Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't these be set in the macro? Depending on the experiment, the range is different

Copy link
Author

Choose a reason for hiding this comment

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

Yes they should. For some reason I needed to make sure at this point that these values are used.

Comment on lines +1870 to +1871
TF1* f2 = new TF1("f2", "pol3", min, max);
f2->SetParameters(para[0], para[1], para[2], para[3]);

Choose a reason for hiding this comment

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

Now I'm still unsure why you changed the charge calibration from division to multiplication of this function.
But maybe I missed something in your code.

Copy link
Contributor

Choose a reason for hiding this comment

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

Enis looked into this. When he flipped the sign, the data converged. Before that, it diverged

Choose a reason for hiding this comment

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

Interesting. Is there a mixup somewhere that causes this issue? I would expected something like I described in #842 (comment)

Choose a reason for hiding this comment

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

Some of your changes broke the github diff.
It is very difficult for me to compare the two versions, so some comments might not apply to your changes but were introduced earlier.

auto posToT = TMath::Log(top_tot / bot_tot);
fhSqrtQvsPosToT[iPlane - 1][iBar - 1]->Fill(posToT, sqrt(top_tot * bot_tot));

if((sqrt(top_tot*bot_tot)>fToTMin &&sqrt(top_tot*bot_tot)<fToTMax) || ToTexeption){
Copy link
Contributor

Choose a reason for hiding this comment

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

There are 3 identical if statements (if((sqrt(top_totbot_tot)>fToTMin &&sqrt(top_totbot_tot)<fToTMax) || ToTexeption)). Why?

ToTexeption (spelt incorrectly) is applied, but it's not clear why. When would the ToTexeption condition be added and when not?

If it's always false, why not just remove it?

if (!fTofdSmiley && fTofdQ > 0.1 && fParameter > 1)
{
LOG(debug) << "Prepare histo for double exponential fit";
auto par = fHitPar->GetModuleParAt(iPlane, iBar);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not make !TofdSmiley and fTofdQ>0.1 a consition within (fTofd > 0 && fParameter > 1)?

Why do you need the fTofdQ>0.1 requirement? Would !TofdSmiley be sufficient?

// get parameter
auto par = fHitPar->GetModuleParAt(iPlane, iBar);
if (!par)
{
Copy link
Contributor

Choose a reason for hiding this comment

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

Redeclaring auto par = fHitPar->GetModuleAt(iPlane, iBar) again. Could be added into 1 (fTofdQ > 0 && fParameter > 1)

auto tof = fTimeStitch->GetTime((top_ns + bot_ns) / 2. - fHeader->GetTStart(), "tamex", "vftx");
if((sqrt(top_tot*bot_tot)>fToTMin &&sqrt(top_tot*bot_tot)<fToTMax) || ToTexeption){
fh1_tofsync[iPlane - 1][iBar - 1]->Fill(tof);
fhTofsync[iPlane-1]->Fill(iBar,tof);
Copy link
Contributor

Choose a reason for hiding this comment

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

Same if statement on line 408 as 403

}
// Tof with respect LOS detector
if((sqrt(Ctop_tot*Cbot_tot)>fToTMin && sqrt(Ctop_tot*Cbot_tot)<fToTMax) /*|| ToTexeption*/){
auto tof = fTimeStitch->GetTime((top_ns + bot_ns) / 2. - fHeader->GetTStart(), "tamex", "vftx");
Copy link
Contributor

Choose a reason for hiding this comment

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

Again, repeated if statement...

}
}
}
if(fParameter==0){
Copy link
Contributor

Choose a reason for hiding this comment

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

What is fParameter=0? Does this need to be included?

if(fParameter==0){

if((sqrt(Ctop_tot*Cbot_tot)>fToTMin && sqrt(Ctop_tot*Cbot_tot)<fToTMax) || ToTexeption){
fh1_walk_t[iPlane-1][iBar-1]->Fill(Ctop_tot,top_ns);
Copy link
Contributor

Choose a reason for hiding this comment

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

😤



else if ((fTofdQ > 0 && fParameter > 1 && fParameter != 10) || fParameter == 3)
{
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this condition every entered?

The initial if statement is (fTofd>0 && fParameter>1 && fParameter!=10). fParameter==3 is greater than 1 and not 10

}
// Sync of one plane
if((sqrt(Ctop_tot*Cbot_tot)>fToTMin && sqrt(Ctop_tot*Cbot_tot)<fToTMax) || ToTexeption){
fhTsync[iPlane - 1]->Fill(iBar, THit);
Copy link
Contributor

Choose a reason for hiding this comment

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

😤


}
/* if(fParameter==5)
{
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this code needed? If not, just delete

}
}
void R3BTofDCal2HitPar::SetHistogramsNULL(Int_t iPlane, Int_t iBar){
fhTdiff[iPlane - 1] = NULL;
Copy link
Contributor

Choose a reason for hiding this comment

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

This could be done in the header using in the syntax:

TH1F *fhNameofHisto[NofPlanes][NofBars]{};

strName2 = (char*)malloc(255);
sprintf(strName1, "Time_Diff_Plane_%d", iPlane);
sprintf(strName2, "Time Diff Plane %d", iPlane);
fhTdiff[iPlane - 1] = new TH2F(strName1, strName2, 50, 0, 50, 4000, -20., 20.);
Copy link
Contributor

Choose a reason for hiding this comment

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

Could use a string instead. Would save 4 lines of code per Histogram declaration

}
if (NULL == fhTot2vsPos[iPlane - 1][iBar - 1] && !fTofdSmiley)
/* void R3BTofDCal2HitPar::calcwalk(Double_t totLow, Double_t totHigh)
{
Copy link
Contributor

Choose a reason for hiding this comment

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

Needed?


if (fParameter == 10)
{
// Determine time offset of the 2 PMTs of one paddle. This procedure
Copy link
Contributor

@ajedele ajedele Apr 12, 2023

Choose a reason for hiding this comment

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

It is only difference between fParameter==10 and fParameter==1 the difference in time between the up/down PMT? Does this need a separate step?

}*/
}
else if(fParameter == 0)
{
Copy link
Contributor

Choose a reason for hiding this comment

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

See previous fParameter==0 comment

{
for (Int_t j = 0; j < fPaddlesPerPlane; j++)
{
auto par = fHitPar->GetModuleParAt(i + 1, j + 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Where does the par get used in this loop?

Copy link
Author

Choose a reason for hiding this comment

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

Seven lines below as: par->SetTofSyncOffset(tof_offset - fMeanTof);

{

// LOG(info) << "Calling function smiley";
// Double_t para2[4];
Copy link
Contributor

Choose a reason for hiding this comment

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

See previous comments about commented code

Copy link
Contributor

Choose a reason for hiding this comment

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

Can change para2[4]; for (int i=0; i<4;i++) to para2[4]{};

Copy link
Author

Choose a reason for hiding this comment

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

Have split step "3" into two, the commented lines are in step "-3". For now leave it to be ignored. Can be removed, once the split is accepted.

@enlorenz
Copy link
Author

I only had a quick look at Tofd so far. Also, I could not check if your changes produce different results than my code. I will try to get it running and message you then.

Not advised to use for other experiments yet. Code needs a proper re-work, before it is safe for general use.

If your code should be used for those two experiments only, why not introduce ExpId dependent functions, or do you plan to make it compatible for other experiments? What are the

The code should be of course compatible with other experiments and especially for future experiments. Backwards compatibility is another question. I would like to avoid ExpID dependent functions, since most of the dependencies should be possible to have flags and/or variables set in the macro. Individual functions make the code unnecessarily blown up. If it is OK for everyone, I would actually like to make this code a WiP version, so that it can be merged in the future.

higher order correction step using physics data

did the number of calibration parameters change, are thy now used in a different way? I might have missed it, because comparing the two versions is not easy due to a lot of changes. Maybe you can show this in one of the next analysis meetings?

Yes, I will definitely present in detail what it is. Briefly, it is an extra calibration step which can or cannot be used, depending on the situation. This adjusts the values of the final charge parameters, so that the application of the parameters in the Cal2Hit itself does not change.

I don't know if one should merge if there are hundreds of lines commented and you say the code is not "clean" or it is "running". Why not create a branch and let people who need the code pull from your fork, create a WIP or something.

Yes, that should be the best option for now.

@ajedele
Copy link
Contributor

ajedele commented Apr 13, 2023

General comment/question (and maybe @lbott193 you can help): There are 2 ways to do the position dependent charge correction - smiley and double exponential. In theory, both should give the same results. Both are also present in the calibration.

However, the double exponential currently crashes because the parameters are not included in the R3BTofdHitPar or R3BTofdHitModulePar. The smiley, from my understand is also simpler and produces better results, faster.

Should we continue to support the double exponential if it's currently not possible to use?

@@ -193,6 +198,7 @@ class R3BTofDCal2HitPar : public FairTask
*/
Double_t walk(Double_t Q, Double_t par1, Double_t par2, Double_t par3, Double_t par4, Double_t par5);


/**
* Method for calculation of saturation.
Copy link
Contributor

Choose a reason for hiding this comment

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

I do not believe the saturation function is used. Are there plans to implement this or not? @lbott193

Copy link

@lbott193 lbott193 Apr 13, 2023

Choose a reason for hiding this comment

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

I think TofdCal2Hit was introduced in PR #90
There you can see that the saturation function is commented:
https://github.com/michael-heil/R3BRoot/blob/7f4b0d57dc2a9f2691dfdd7020a7da6a0553b967/tof/R3BTofdCal2Hit.cxx#L575-L577

I don't know how to track file changes on this webpage but I never used the saturation function, maybe @michael-heil can answer your question.

@lbott193
Copy link

General comment/question (and maybe @lbott193 you can help): There are 2 ways to do the position dependent charge correction - smiley and double exponential. In theory, both should give the same results. Both are also present in the calibration.

However, the double exponential currently crashes because the parameters are not included in the R3BTofdHitPar or R3BTofdHitModulePar. The smiley, from my understand is also simpler and produces better results, faster.

I can see them in the current R3BTofdHitModulePar.h they are named (maybe one should come up with more descriptive names):
fPar1a-c and fPar2a-c: https://github.com/R3BRootGroup/R3BRoot/blob/dev/tofd/pars/R3BTofDHitModulePar.h#L154-L155

Why it doesn't work anymore, I don't know.

Should we continue to support the double exponential if it's currently not possible to use?

Charge correction with tdfiff and double exponential was difficult in the past under certain circumstances, for example interference effects on the electronics card. The ToT method is less sensitive to such effects and at that time we got better results. You might want to check that for your setup and use the best option, that's why I left both methods in.

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.

5 participants