Skip to content

Decorrelate N3LO IHOU - #388

Open
jekoorn wants to merge 12 commits into
masterfrom
4ihou
Open

Decorrelate N3LO IHOU#388
jekoorn wants to merge 12 commits into
masterfrom
4ihou

Conversation

@jekoorn

@jekoorn jekoorn commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Closes #328

n3lo_cf_variation seems to be a single number, although I believe it should be 4 numbers: (C2g, C2q, CLg, CLq), i.e. one per coefficient we want to vary

@felixhekhorn felixhekhorn added bug Something isn't working enhancement New feature or request labels Aug 12, 2026
@jekoorn

jekoorn commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

currently it looks like the light coefficient functions support no variation at all, e.g. looking at https://github.com/NNPDF/yadism/blob/master/src/yadism/coefficient_functions/light/kernels.py#L78 vs https://github.com/NNPDF/yadism/blob/master/src/yadism/coefficient_functions/heavy/kernels.py#L76 . do we want to implement this as well at the same time?

@jekoorn jekoorn self-assigned this Aug 12, 2026
Comment thread src/yadism/runner.py Outdated
Comment thread src/yadism/runner.py Outdated
@juanrojochacon

Copy link
Copy Markdown

currently it looks like the light coefficient functions support no variation at all, e.g. looking at https://github.com/NNPDF/yadism/blob/master/src/yadism/coefficient_functions/light/kernels.py#L78 vs https://github.com/NNPDF/yadism/blob/master/src/yadism/coefficient_functions/heavy/kernels.py#L76 . do we want to implement this as well at the same time?

@jekoorn the light coefficient functions at N3LO are known exactly so no, they should not be varied in any way. IHOUs are only required for the N3LO massive coefficient functions

@jekoorn

jekoorn commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

How does the code distinguish between whether an FL or F2 component is called? I don't really see how I should tell the code to use C2g vs CLg

Comment thread src/yadism/runner.py Outdated
@juanrojochacon

Copy link
Copy Markdown

Felix will confirm, but I think that the distinction is made through

kind = esf.info.obs_name.kind at the top of generate, which is then used in import_pc_module(kind, esf.process). So indeed it is ok that you don't see the distinction there

Comment thread src/yadism/coefficient_functions/heavy/kernels.py
@felixhekhorn

Copy link
Copy Markdown
Collaborator

Please remember to resolve the conversations, which you believe to have addressed

@felixhekhorn

Copy link
Copy Markdown
Collaborator

Also please don't code only in the void - at some point you need to actually run locally yourself! this is to say: you still have syntax errors

@jekoorn

jekoorn commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Also please don't code only in the void

yeah sorry for the mess, my editor didn't catch the syntax errors for some reason. I am apparently rusty after the holidays🙃

Another question: Do we only require a variation in the case that we evaluate F2 and FL? Not the others? (Are they known already?)
And if so, I think with the if/else statements it's a bit messy. But it looks like the other components don't use it, so it doesn't matter what we pass.

@juanrojochacon

Copy link
Copy Markdown

yes, only F2 and FL, xF3 is not relevant here

Comment thread src/yadism/coefficient_functions/asy/kernels.py Outdated
Comment thread src/yadism/runner.py

@felixhekhorn felixhekhorn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Let me ask again: have you actually run this code? and check e.g. that when you put different numbers this is propagated down to adani correctly?

Comment thread src/yadism/coefficient_functions/asy/kernels.py Outdated
Comment thread tests/yadism/cf/test_nc_kernels.py Outdated
@jekoorn

jekoorn commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

have you actually run this code?

I am currently checking this with pinefarm (since I have to generate grids anyway and needed a pipeline). But probably it's easier to do this with yadism standalone 🙈

@jekoorn

jekoorn commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

There are still some NaNs spawning, apparently. I will investigate this..
A fresh yadism also gets NaNs though, so I am not sure to what extent the NaNs are "supposed" to be there or not..

@Radonirinaunimi

Copy link
Copy Markdown
Member

There are still some NaNs spawning, apparently. I will investigate this.. A fresh yadism also gets NaNs though, so I am not sure to what extent the NaNs are "supposed" to be there or not..

Could you please provide more details (which cards are you using, do the NaNs appear for specific processes/datasets/variations, etc.)? There are some NaNs that are fine (such as at very low $Q^2$) and there are some that are dangerous. From the recent grid computations, the latter should no longer appear.

@jekoorn

jekoorn commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Could you please provide more details (which cards are you using, do the NaNs appear for specific processes/datasets/variations, etc.)?

Sure!
For checking whether the variations produce different outputs, instead of using cards, I am using my own script that computes the structure functions. Just electron-proton collision at 1TeV.
I am integrating $Q^2$ from as low as 2.0, and x > 1e-6. I am using the theory cards from NNPDF/nnpdf#2494 but with the CF variations put in.
The broader issue is here that the outputs from different variations still yield the exact same output. I am wondering now if the setup I use for checking this is actually sufficient.
See https://vp.nnpdf.science/nVd3gBnfT2S-psG9B5g5gQ==/ for the script
Probably a good check would be whether running with actual pinecards yields NaNs, but for now I wanted to check whether the CF variations do what they are supposed to.

@felixhekhorn

Copy link
Copy Markdown
Collaborator

The broader issue is here that the outputs from different variations still yield the exact same output.

I suggest to put a debugger (or print or whatever) here

"C2g", nf=self.nf, variation=self.n3lo_cf_variation

and check what variation arrives there and then what you get back

Also do you get finite numbers with the default settings? i.e. without any variation? so we know the problem is with the variations (and not with something else)

@jekoorn

jekoorn commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

put a debugger (or print or whatever) here

nothing looks to arrive there, with whatever variation I put in. Probably explains why the calculations yield the same result between different variations. It makes me doubt whether the correlated variations were even doing what they should in the first place, before starting this implementation.

With default settings I also get NaNs, but to be precise: they don't appear in the output, it's just a notification that the runner passes:

 took 6.43 s
[14:03:10] CRITICAL Some NaNs are encountered and set to zero!                                                                                                                                                         runner.py:224
           CRITICAL Some NaNs are encountered and set to zero!                                                                                                                                                         runner.py:224
           CRITICAL Some NaNs are encountered and set to zero!                                                                                                                                                         runner.py:224
           CRITICAL Some NaNs are encountered and set to zero!                                                                                                                                                         runner.py:224
           CRITICAL Some NaNs are encountered and set to zero!

@Radonirinaunimi

Copy link
Copy Markdown
Member

put a debugger (or print or whatever) here

nothing looks to arrive there, with whatever variation I put in. Probably explains why the calculations yield the same result between different variations. It makes me doubt whether the correlated variations were even doing what they should in the first place, before starting this implementation.

With default settings I also get NaNs, but to be precise: they don't appear in the output, it's just a notification that the runner passes:

 took 6.43 s
[14:03:10] CRITICAL Some NaNs are encountered and set to zero!                                                                                                                                                         runner.py:224
           CRITICAL Some NaNs are encountered and set to zero!                                                                                                                                                         runner.py:224
           CRITICAL Some NaNs are encountered and set to zero!                                                                                                                                                         runner.py:224
           CRITICAL Some NaNs are encountered and set to zero!                                                                                                                                                         runner.py:224
           CRITICAL Some NaNs are encountered and set to zero!

These NaNs are fine (as I per above) so you shouldn't worry about those. They are in the regions where pQCD breaks down and these warnings are just there warn people that these regions are probed.

@felixhekhorn

felixhekhorn commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

They are in the regions where pQCD breaks down and these warnings are just there warn people that these regions are probed.

@Radonirinaunimi I think you put these warnings there in the first place, right? so you know that they are in this region? because this can not be inferred from the output ... (i.e. if we have the kinematics in hand there it might be good to echo them alongside 🙃 )

nothing looks to arrive there, with whatever variation I put in. Probably explains why the calculations yield the same result between different variations. It makes me doubt whether the correlated variations were even doing what they should in the first place, before starting this implementation.

@jekoorn then a) you should check on master what you get there (and confirm or reject your doubts) and b) then you "just" need to trace their way back and e.g. check what you get immediately inside yadism = in the runner e.g. here

if isinstance(theory["n3lo_cf_variation"], int):

@jekoorn

jekoorn commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

on it @felixhekhorn

@Radonirinaunimi

Copy link
Copy Markdown
Member

@Radonirinaunimi I think you put these warnings there in the first place, right? so you know that they are in this region? because this can not be inferred from the output ... (i.e. if we have the kinematics in hand there it might be good to echo them alongside 🙃 )

Yes, I agree. I should have printed out the kinematics alongside for full transparency and certainty. Since we are at it, I would suggest to add this in this PR.

Comment thread src/yadism/runner.py Outdated
@jekoorn

jekoorn commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

For debugging purposes, which FNS should I use? In some cases the code simply breaks, which probably has to do with not choosing the appropriate nf, in combination with the FNS. At least the variations look like they're activated with the FFN0 scheme.
Maybe in the end, seeing what happens with a full pinefarm run is best after all.

@felixhekhorn

Copy link
Copy Markdown
Collaborator

For debugging purposes, which FNS should I use?

I suggest FFNS3, so FNS: FFNS + NfFF: 3 (check that you actually pass by where you want). FFN0 would work as well and you would just end up then on the asy side. Then later in the real world we should also test full FONLL (which is a combination of FFNS and FFN0).

Maybe in the end, seeing what happens with a full pinefarm run is best after all.

This would be (very likely) directly the FONLL case. However, since FONLL has multiple ingredients that might make debugging more complicated ... but actually, you could also just use the correct FFNS theory card there (courtesy of NNPDF/nnpdf#2498)

Comment thread src/yadism/runner.py Outdated
@jekoorn

jekoorn commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

This exact FFNS theory card with FFNS3 fails, for some reason. Also on the master branch without the n3lo_cf_variation : [0,0,0,0], with the same error. See here

 • F2_charm at 1 pts

                                                                                                                       Calculation
yadism took off! please stay tuned ...
a heavy vv gluon is made, with variation -1
Traceback (most recent call last):
  File "/data/theorie/jkoorn/git/yad-4ihou/run.py", line 150, in <module>
    F2_tot, FL, F2_c, FL_c = runner(
                             ~~~~~~^
        Ebeam=1000,
        ^^^^^^^^^^^
    ...<6 lines>...
        theory_path=f"/data/theorie/jkoorn/git/yad-4ihou/{theory}.yaml"
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/data/theorie/jkoorn/git/yad-4ihou/run.py", line 135, in runner
    F2_c = compute_observable("F2_charm", xgrid, Q2grid, Ebeam, PTO, channel, particle, target,runningscales, PDF, theory_path)
  File "/data/theorie/jkoorn/git/yad-4ihou/run.py", line 77, in compute_observable
    output = yadism.run_yadism(theory, observable)
  File "/data/theorie/jkoorn/git/yad-4ihou/src/yadism/__init__.py", line 31, in run_yadism
    return runner.get_result()
           ~~~~~~~~~~~~~~~~~^^
  File "/data/theorie/jkoorn/git/yad-4ihou/src/yadism/runner.py", line 292, in get_result
    results[idx] = elem.get_result()
                   ~~~~~~~~~~~~~~~^^
  File "/data/theorie/jkoorn/git/yad-4ihou/src/yadism/esf/esf.py", line 189, in get_result
    self.compute_local()
    ~~~~~~~~~~~~~~~~~~^^
  File "/data/theorie/jkoorn/git/yad-4ihou/src/yadism/esf/esf.py", line 143, in compute_local
    val, err = conv.convolve_vector(
               ~~~~~~~~~~~~~~~~~~~~^
        rsl, self.info.configs.managers["interpolator"], convolution_point
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/data/theorie/jkoorn/git/yad-4ihou/src/yadism/esf/conv.py", line 230, in convolve_vector
    c, e = convolution(cf, convolution_point, polynomial_f)
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/data/theorie/jkoorn/git/yad-4ihou/src/yadism/esf/conv.py", line 151, in convolution
    res, err = scipy.integrate.quad(
               ~~~~~~~~~~~~~~~~~~~~^
        quad_ker,
        ^^^^^^^^^
    ...<4 lines>...
        points=breakpoints,
        ^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/data/theorie/jkoorn/miniconda/envs/yadism-d/lib/python3.13/site-packages/scipy/integrate/_quadpack_py.py", line 479, in quad
    retval = _quad(func, a, b, args, full_output, epsabs, epsrel, limit,
                   points)
  File "/data/theorie/jkoorn/miniconda/envs/yadism-d/lib/python3.13/site-packages/scipy/integrate/_quadpack_py.py", line 639, in _quad
    return _quadpack._qagpe(func, a, b, the_points, args, full_output,
           ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                            epsabs, epsrel, limit)
                            ^^^^^^^^^^^^^^^^^^^^^^
TypeError: only 0-dimensional arrays can be converted to Python scalars

If you have an idea what is going wrong here I would be very happy to continue working on this but I think I am currently too lost by which FNS's work and which don't 😅

At least I'venow verified that the correct variations are passed to the correct places, so at least the original goal of this test has been succesful!

@felixhekhorn

Copy link
Copy Markdown
Collaborator

ehm, I'm confused, because I have seen numbers from @evagroenendijk supposedly using that card - @evagroenendijk can you please confirm?

That being said, the error sounds more like a local problem: are you sure your runcards are 100% correct? the question is in particular for the types: are things which should be a scalar number just that and not some array? (For dumping runcards to file even np.float vs. Python float makes a difference, but I think that should not be a problem here.) However, doing remote debugging is tricky 🙃 ... actually, the type mismatch might also be at the bottom (so where we are interested in).

At least I'venow verified that the correct variations are passed to the correct places, so at least the original goal of this test has been succesful!

a good thing for sure, but you know people (meaning Juan 🙈 ) want to see the real deal

@jekoorn

jekoorn commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

However, doing remote debugging is tricky 🙃

I understand, of course, but since it's apparently an issue that only pops up with some FNS's (code runs fine under ZM-VFNS), I was hoping...

But if @evagroenendijk has a runscript with this card that works, so much the better!

@evagroenendijk

Copy link
Copy Markdown

@jekoorn @felixhekhorn Indeed I use exactly that theory card and it works fine. I think it's a compatibility issue between numpy and the scipy integration. I reproduce your error when using numpy v2.4, I myself was using v2.2.6 and then it does work (I think v2.4 numpy outputs an array somewhere while v2.2.6 outputs a value)

@felixhekhorn

Copy link
Copy Markdown
Collaborator

I think it's a compatibility issue between numpy and the scipy integration

ooh, you are saying this is a side effect of our Python (and dependencies) upgrade ... in particular #383

Okay, so we need to sort that out. I would suggest to solve this issue first (starting from master branch) and then rebase/merge this one on top afterwards so the two things get disentangled.

Sigh... if only yadism would have some sort of benchmarks, e.g. here #162 or also just in pinefarm, which would run on a regular basis and where we would detect such problems ...

@jekoorn

jekoorn commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Okay, so we need to sort that out.

Will be addressed in #389

@felixhekhorn felixhekhorn changed the title N3LO IHOU are correlated Decorrelate N3LO IHOU Aug 28, 2026
@felixhekhorn

Copy link
Copy Markdown
Collaborator

then rebase/merge this one on top afterwards

please still check explicitly that you get different numbers for different variations (and they are not crazy different)

@jekoorn

jekoorn commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Differences are in the 10-30% range when comparing the correlated vs uncorrelated min/max variations - typically the uncorrelated variations (squares summed) are slightly smaller. I'm thinking about how to properly present the results, but I can just link a file with a plaintext table that I made using pineappl diff.
Btw, all using Eva's nice benchmark runcards.

@felixhekhorn

Copy link
Copy Markdown
Collaborator

Differences are in the 10-30% range when comparing the correlated vs uncorrelated min/max variations

Can we be a bit more specific? for which observable? for which kinematics? we are talking only about the N3LO corrections (and not the full thing), right?

I'm thinking about how to properly present the results, but I can just link a file with a plaintext table that I made using pineappl diff.

If you can come up quickly with some clever representation, fine, else also plain text files will do for now. Then for the 4.1 paper we need to do something more clever 🙃

@jekoorn

jekoorn commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

for which observable? for which kinematics?

In this case, I used Eva's runcards for the N3LO benchmark to compute F2C and FLC. To get the N3LO corrections, should I just subtract the NNLO component? And do these observables suffice, or do we want an actual cross-section in the end?

@felixhekhorn

Copy link
Copy Markdown
Collaborator

In this case, I used Eva's runcards for the N3LO benchmark to compute F2C and FLC.

in principle fine, but we need to remember, that some of the kinematics are just unreachable by HERA

And do these observables suffice, or do we want an actual cross-section in the end?

thus, it might make also sense to look at the true settings as well. We can start with the easy thing first (just F2+FL). For the paper we need the real thing.

To get the N3LO corrections, should I just subtract the NNLO component?

Yes. Also PineAPPL can do it directly (I think). Both things (total and relative) are interesting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

N3LO IHOU are correlated

5 participants