@@ -373,28 +373,28 @@ def _gv_hadron_predictions(loaded_fk, gv1func, gv2func=None):
373373 # possible x1-x2 combinations (f1, f2, x1, x2)
374374 luminosity = np .einsum ("ijk, ijl->ijkl" , expanded_gv1 , expanded_gv2 )
375375
376- if not loaded_fk .legacy :
377- lx = len ( xgrid )
378- lc = len ( fl1 )
379- fktab = sigma . values . reshape ( - 1 , lx , lx , lc )
380- ret = np . einsum ( "rcab, nabc->nr" , luminosity , fktab )
381- return pd . DataFrame ( ret , index = loaded_fk . data_index )
382-
383- def appl ( df ):
384- # x1 and x2 are encoded as the first and second index levels.
385- xx1 = df .index .get_level_values (1 )
386- xx2 = df . index . get_level_values ( 2 )
387- # take the active combinations from the luminosity tensor
388- partial_lumi = luminosity [..., xx1 , xx2 ]
389- return pd . Series ( np . einsum ( "ijk,kj->i" , partial_lumi , df . values ))
390-
391- # The gv1/gv2 grids are arrays of shape (replicas, flavours<14>, xarray)
392- # the expanded gv1/gv2 instead are shaped according to the channels (which will match)
393- # therefore the luminosity is an array of shape (replicas, channels, x1, x2 )
394- # this needs to be matched with the fktable which for the old interface were not ordered
395- # and so the full dataframe needs to be used instead to keep track of the index
396-
397- return sigma . groupby ( level = 0 ). apply ( appl )
376+ if loaded_fk .legacy :
377+ # Old FkTables are singled out since they are not always sorted in x1/x2 so matching the
378+ # FkTable with the PDF grids (gv1/gv2) is done by means of dataframes, which is slow.
379+ # The gv1/gv2 grids are arrays of shape (replicas, flavours<14>, xarray )
380+ # the expanded gv1/gv2 instead are shaped according to the channels (which will match )
381+ # therefore the luminosity is an array of shape (replicas, channels, x1, x2 )
382+ def appl ( df ):
383+ # x1 and x2 are encoded as the first and second index levels.
384+ xx1 = df . index . get_level_values ( 1 )
385+ xx2 = df .index .get_level_values (2 )
386+ # take the active combinations from the luminosity tensor
387+ partial_lumi = luminosity [..., xx1 , xx2 ]
388+ return pd . Series ( np . einsum ( "ijk,kj->i" , partial_lumi , df . values ))
389+
390+ return sigma . groupby ( level = 0 ). apply ( appl )
391+
392+ # Pineappl FkTables are sorted and can be treated as numpy arrays
393+ lx = len ( xgrid )
394+ lc = len ( fl1 )
395+ fktab = sigma . values . reshape ( - 1 , lx , lx , lc )
396+ ret = np . einsum ( "rcab, nabc->nr" , luminosity , fktab )
397+ return pd . DataFrame ( ret , index = loaded_fk . data_index )
398398
399399
400400def _gv_dis_predictions (loaded_fk , gvfunc ):
@@ -410,18 +410,20 @@ def _gv_dis_predictions(loaded_fk, gvfunc):
410410 if sigma .empty :
411411 return pd .DataFrame (columns = range (gv .shape [0 ]))
412412
413- if not loaded_fk .legacy :
414- lx = len (xgrid )
415- fktab = sigma .values .reshape (- 1 , lx , len (fm ))
416- ret = np .einsum ("rfa, naf->nr" , gv , fktab )
417- return pd .DataFrame (ret , index = loaded_fk .data_index )
413+ if loaded_fk .legacy :
414+ # Old FkTable are not necessarily sorted in x and need to be treated as dataframes
415+ # See comment in `_gv_hadron_predictions` for more details
416+ def appl (df ):
417+ # x is encoded as the first index level.
418+ xind = df .index .get_level_values (1 )
419+ return pd .Series (np .einsum ("ijk,kj->i" , gv [:, :, xind ], df .values ))
418420
419- def appl (df ):
420- # x is encoded as the first index level.
421- xind = df .index .get_level_values (1 )
422- return pd .Series (np .einsum ("ijk,kj->i" , gv [:, :, xind ], df .values ))
421+ return sigma .groupby (level = 0 ).apply (appl )
423422
424- return sigma .groupby (level = 0 ).apply (appl )
423+ lx = len (xgrid )
424+ fktab = sigma .values .reshape (- 1 , lx , len (fm ))
425+ ret = np .einsum ("rfa, naf->nr" , gv , fktab )
426+ return pd .DataFrame (ret , index = loaded_fk .data_index )
425427
426428
427429def hadron_predictions (loaded_fk , pdf ):
0 commit comments