22Plots of relations between data PDFs and fits.
33"""
44
5- from __future__ import generator_stop
6-
75from collections import defaultdict
86from collections .abc import Sequence
97import itertools
2523from reportengine .floatformatting import format_number
2624from validphys import plotutils
2725from validphys .checks import check_not_using_pdferr
26+ from validphys .commondata import loaded_commondata_with_cuts
2827from validphys .core import CutsPolicy , MCStats , cut_mask , load_commondata
28+ from validphys .covmats import shifts_from_systematics
2929from validphys .plotoptions .core import get_info , kitable , transform_result
3030from validphys .results import chi2_stat_labels , chi2_stats
31- from validphys .sumrules import POL_LIMS , partial_polarized_sum_rules
31+ from validphys .sumrules import POL_LIMS
3232from validphys .utils import sane_groupby_iter , scale_from_grid , split_ranges
33- from validphys .commondata import loaded_commondata_with_cuts
34- from validphys .covmats import shifts_from_systematics
3533
3634log = logging .getLogger (__name__ )
3735
@@ -226,12 +224,12 @@ def check_normalize_to(ns, **kwargs):
226224# TODO: This interface is horrible.
227225# We need to think how to adapt it to make this use case easier
228226def _plot_fancy_impl (
229- results ,
230- commondata ,
231- cutlist ,
232- normalize_to : (int , type (None )) = None ,
233- labellist = None ,
234- with_shift : bool = True ,
227+ results ,
228+ commondata ,
229+ cutlist ,
230+ normalize_to : (int , type (None )) = None ,
231+ labellist = None ,
232+ with_shift : bool = True ,
235233):
236234 """Implementation of the data-theory comparison plots. Providers are
237235 supposed to call (yield from) this.
@@ -253,8 +251,8 @@ def _plot_fancy_impl(
253251 (from the PDF names) if None is given.
254252 with_shift: bool
255253 This option specifies wheter one wants (True) or not (False) to shift
256- the theoretical predictions by a shift due to the correlated part of
257- the experimental uncertainty. The default is True.
254+ the theoretical predictions by a shift due to the correlated part of
255+ the experimental uncertainty. The default is True.
258256 Returns
259257 -------
260258 A generator over figures.
@@ -266,13 +264,13 @@ def _plot_fancy_impl(
266264 ndata = len (table )
267265
268266 # Compute shifts due to the correlated part of the exp cov matrix
269- lcd_wc = loaded_commondata_with_cuts (commondata ,cutlist [0 ])
267+ lcd_wc = loaded_commondata_with_cuts (commondata , cutlist [0 ])
270268 theory_predictions = results [1 ].central_value
271-
269+
272270 # This is easier than cheking every time
273271 if labellist is None :
274272 labellist = [None ] * len (results )
275-
273+
276274 if normalize_to is not None :
277275 norm_result = results [normalize_to ]
278276 mask = cut_mask (cutlist [normalize_to ])
@@ -282,7 +280,7 @@ def _plot_fancy_impl(
282280 err [mask ] = norm_result .std_error
283281 # We modify the table, so we pass only the label columns
284282 norm_cv , _ = transform_result (cv , err , table .iloc [:, :nkinlabels ], info )
285-
283+
286284 cvcols = []
287285
288286 # Compute systematic shifts
@@ -291,30 +289,32 @@ def _plot_fancy_impl(
291289 # the final plot.
292290 if with_shift :
293291 try :
294- shifts , alpha = shifts_from_systematics (lcd_wc ,theory_predictions )
292+ shifts , alpha = shifts_from_systematics (lcd_wc , theory_predictions )
295293 except np .linalg .LinAlgError :
296- log .warning ("Error occurred in computing systematic shifts for " \
297- f"{ info .ds_metadata .name } . These will be disregarded in the plots." )
294+ log .warning (
295+ "Error occurred in computing systematic shifts for "
296+ f"{ info .ds_metadata .name } . These will be disregarded in the plots."
297+ )
298298 with_shift = False
299-
299+
300300 for i , (result , cuts ) in enumerate (zip (results , cutlist )):
301301 # We modify the table, so we pass only the label columns
302302 mask = cut_mask (cuts )
303303 cv = np .full (ndata , np .nan )
304304 err = np .full (ndata , np .nan )
305305 # Shift the theory when with_shift option is True
306- if i == 1 and with_shift :
306+ if i == 1 and with_shift :
307307 cv [mask ] = result .central_value - shifts
308308 else :
309- cv [mask ] = result .central_value
309+ cv [mask ] = result .central_value
310310 # Retain only the uncorrelated part of the error if shifting the data
311- if i == 0 and with_shift :
311+ if i == 0 and with_shift :
312312 err [mask ] = alpha
313313 else :
314314 err [mask ] = result .std_error
315315
316316 cv , err = transform_result (cv , err , table .iloc [:, :nkinlabels ], info )
317-
317+
318318 # By doing tuple keys we avoid all possible name collisions
319319 cvcol = ('cv' , i )
320320 if normalize_to is None :
@@ -326,7 +326,7 @@ def _plot_fancy_impl(
326326 cvcols .append (cvcol )
327327
328328 figby = sane_groupby_iter (table , info .figure_by )
329-
329+
330330 for samefig_vals , fig_data in figby :
331331 # Nothing to plot if all data is cut away
332332 if np .all (np .isnan (fig_data [cvcols ])):
@@ -341,7 +341,9 @@ def _plot_fancy_impl(
341341 else :
342342 shift_label = "(unshifted)"
343343 ax .set_title (
344- "{} {} {}" .format (info .dataset_label , info .group_label (samefig_vals , info .figure_by ), shift_label )
344+ "{} {} {}" .format (
345+ info .dataset_label , info .group_label (samefig_vals , info .figure_by ), shift_label
346+ )
345347 )
346348
347349 lineby = sane_groupby_iter (fig_data , info .line_by )
@@ -373,7 +375,7 @@ def _plot_fancy_impl(
373375 # and follow the cycle for
374376 # the rest.
375377 next_color = itertools .chain (['#262626' ], plotutils .color_iter ())
376-
378+
377379 for i , (res , lb , color ) in enumerate (zip (results , labellist , next_color )):
378380 if labels :
379381 if lb :
@@ -382,7 +384,7 @@ def _plot_fancy_impl(
382384 label = res .label
383385 else :
384386 label = None
385-
387+
386388 cv = line_data [('cv' , i )].values
387389 err = line_data [('err' , i )].values
388390 ax .errorbar (
@@ -556,7 +558,7 @@ def plot_fancy_dataspecs(
556558 - or None (default) to plot absolute values.
557559
558560 ``with_shift`` be either:
559-
561+
560562 - True (default): this shifts theoretical predictions by an amount that
561563 depends on the correlated part of the experimental uncertainty,
562564 according to Eqs.(7)-(9) of arXiv:hep-ph/0201195. In this case only
@@ -1344,7 +1346,7 @@ def _check_display_cuts_requires_use_cuts(display_cuts, use_cuts):
13441346
13451347@make_argcheck
13461348def _check_marker_by (marker_by ):
1347- markers = ('process type' , 'experiment' , 'dataset' , 'group' )
1349+ markers = ('process type' , 'experiment' , 'dataset' , 'group' , 'kinematics' )
13481350 if marker_by not in markers :
13491351 raise CheckError ("Unknown marker_by value" , marker_by , markers )
13501352
@@ -1403,7 +1405,8 @@ def plot_xq2(
14031405 will be displaed and marked.
14041406
14051407 The points are grouped according to the `marker_by` option. The possible
1406- values are: "process type", "experiment", "group" or "dataset".
1408+ values are: "process type", "experiment", "group" or "dataset" for discrete
1409+ colors, or "kinematics" for coloring by 1/(Q2(1-x))
14071410
14081411 Some datasets can be made to appear highlighted in the figure: Define a key
14091412 called ``highlight_datasets`` containing the names of the datasets to be
@@ -1534,6 +1537,7 @@ def plot_xq2(
15341537
15351538 xh = defaultdict (list )
15361539 q2h = defaultdict (list )
1540+ cvdict = defaultdict (list )
15371541
15381542 if not highlight_datasets :
15391543 highlight_datasets = set ()
@@ -1564,6 +1568,8 @@ def next_options():
15641568 elif marker_by == "group" :
15651569 # if group is None then make sure that shows on legend.
15661570 key = str (group )
1571+ elif marker_by == "kinematics" :
1572+ key = None
15671573 else :
15681574 raise ValueError ('Unknown marker_by value' )
15691575
@@ -1579,6 +1585,7 @@ def next_options():
15791585 xdict = x
15801586 q2dict = q2
15811587
1588+ cvdict [key ].append (commondata .load ().get_cv ())
15821589 xdict [key ].append (fitted [0 ])
15831590 q2dict [key ].append (fitted [1 ])
15841591 if display_cuts :
@@ -1593,6 +1600,13 @@ def next_options():
15931600 else :
15941601 # This is to get the label key
15951602 coords = [], []
1603+ if marker_by == "kinematics" :
1604+ ht_magnitude = np .concatenate (cvdict [key ]) / (coords [1 ] * (1 - coords [0 ]))
1605+ out = ax .scatter (
1606+ * coords , marker = '.' , c = ht_magnitude , cmap = "viridis" , norm = mcolors .LogNorm ()
1607+ )
1608+ clb = fig .colorbar (out )
1609+ clb .ax .set_title (r'$F_\mathrm{exp}\frac{1}{Q^2(1-x)}$' )
15961610 ax .plot (* coords , label = key , markeredgewidth = 1 , markeredgecolor = None , ** key_options [key ])
15971611
15981612 # Iterate again so highlights are printed on top.
0 commit comments