def test_scipy_1d_interpolator_nonstandard_args(self): """Verify Scipy1dInterpolator accepts/refuses argument correctly.""" table = File(self.dirs["lhc_wg"] / "13TeVn2x1wino_cteq_pm.csv")["xsec"] fit = Scipy1dInterpolator().interpolate(table) for m in ["f0", "fp", "fm", "unc_p_at", "unc_m_at", "tuple_at"]: test_method = getattr(fit, m) value = test_method(333.3) if m == "tuple_at": # the output should be (3,) array (or 3-element tuple) assert numpy.array(value).shape == (3, ) else: # the output should be float or ndarray with 0-dim, not arrays. assert self._is_scalar_number(value) # method should accept 0-dim ndarray assert test_method(numpy.array(333.3)) == value # method should accept arrays assert test_method([333.3]) == value assert test_method(numpy.array([333.3])) == value # method should accept keyword arguments assert test_method(m_wino=333.3) == value # method should not accept arrays or numpy.ndarray with >0 dim. for bad_input in ([[333.3]], [333.3, 350]): with pytest.raises(TypeError): test_method(bad_input) with pytest.raises(TypeError): test_method(numpy.array(bad_input)) with pytest.raises(TypeError): test_method(m_wino=bad_input)
def test_scipy_1d_interpolator(self): """Verify Scipy1dInterpolator.""" table = File(self.dirs["lhc_wg"] / "13TeVn2x1wino_cteq_pm.csv")["xsec"] for kind in ["linear", "akima", "spline", "pchip"]: for axes in ["linear", "log", "loglog", "loglinear"]: fit = Scipy1dInterpolator(kind, axes).interpolate(table) # on the grid points: # 300.0: 379.23, -0.47, -4.8, 0.4, 4.7 == 379.23 -18.29 +17.89 # 325.0: 276.17, -0.44, -5.1, 0.4, 4.8 == 276.17 -14.14 +13.30 assert fit.tuple_at(300) == pytest.approx( (379.23, 17.89, -18.29), abs=0.01) assert fit(325) == pytest.approx(276.17, abs=0.01) assert fit.unc_p_at(325) == pytest.approx(+13.30, abs=0.01) assert fit.unc_m_at(325) == pytest.approx(-14.14, abs=0.01) # interpolation: for uncertainty, returns sensible results assert 13.30 < fit.unc_p_at(312.5) < 17.89 assert 14.14 < -fit.unc_m_at(312.5) < 18.29 if kind == "linear": if axes == "linear": x, y = (300 + 325) / 2, (379.23 + 276.17) / 2 elif axes == "loglinear": x, y = (300 * 325)**0.5, (379.23 + 276.17) / 2 elif axes == "log": x, y = (300 + 325) / 2, (379.23 * 276.17)**0.5 else: x, y = (300 * 325)**0.5, (379.23 * 276.17)**0.5 assert fit(x) == pytest.approx(y, abs=0.01) else: assert 276.17 < fit(312.5) < 379.23
def show(**kw): # type: (Any)->None """Show the cross-section table with combined uncertainties.""" _configure_logger() # handle arguments try: table_path, info_path = utility.get_paths(kw["table"], kw["info"]) except (FileNotFoundError, RuntimeError) as e: click.echo(e.__repr__()) # py2 exit(1) try: data_file = File(table_path, info_path) except (ValueError, TypeError) as e: click.echo(e.__repr__()) # py2 exit(1) click.echo(data_file.dump()) exit(0)
def get(context, **kw): # type: (Any, Any)->None """Get cross-section value using interpolation.""" _configure_logger() # handle arguments args = kw["args"] or [] value_name = kw["name"] or _DEFAULT_VALUE_NAME try: table_path, info_path = utility.get_paths(kw["table"], kw["info"]) data_file = File(table_path, info_path) except (FileNotFoundError, RuntimeError, ValueError, TypeError) as e: click.echo(repr(e)) exit(1) try: table = data_file.tables[value_name] except KeyError as e: logger.critical("Data file does not contain specified table.") click.echo(repr(e)) exit(1) # without arguments or with invalid number of arguments, show the table information. if len(args) != len(data_file.info.parameters): _display_usage_for_file(context, data_file, **kw) exit(1) # data evaluation if len(args) == 1: interp = Scipy1dInterpolator( axes="loglog", kind="spline") # type: AbstractInterpolator else: wrapper = AxesWrapper(["log" for _ in args], "log") kind = "spline33" if len(args) == 2 else "linear" interp = ScipyGridInterpolator(axes_wrapper=wrapper, kind=kind) cent, u_p, u_m = interp.interpolate(table).tuple_at(*kw["args"]) # display if kw["simplest"]: click.echo(cent) elif kw["simple"]: click.echo("{} +{} -{}".format(cent, u_p, abs(u_m))) else: relative = bool(kw.get("relative", False)) unit = table.unit if kw["unit"] else None click.echo(utility.value_format(cent, u_p, u_m, unit, relative)) exit(0)
def sieve(ctx, *args, **kwargs): # type: ignore """Plot multiple interpolation results of 1d grid.""" pdf = PdfPages(kwargs["output"]) if kwargs["output"] else None if kwargs["all"]: for _key, table in _all_tables_iter(): try: choose_validator(table)(pdf).sieve(table) except ValueError as e: print(e) elif kwargs["table"]: table = File(*Util.get_paths(kwargs["table"])).tables["xsec"] try: choose_validator(table)(pdf).sieve(table) except ValueError as e: print(e) else: click.echo("table path or --all option must be required.") if pdf: pdf.close()
def test_scipy_grid_interpolator(self): """Verify ScipyGridInterpolator.""" table = File(self.dirs["fastlim8mod"] / "sg_8TeV_NLONLL_modified.xsec")["xsec"] midpoint = { "linear": lambda x, y: (x + y) / 2, "log": lambda x, y: (x * y)**0.5, } for x1a, x2a, ya in itertools.product(["linear", "log"], repeat=3): for kind in ["linear", "spline"]: wrapper = AxesWrapper([x1a, x2a], ya) fit = ScipyGridInterpolator(kind, wrapper).interpolate(table) # on the grid points: # 700 1400 0.0473379597888 0.00905940683923 # 700 1450 0.0382279746207 0.0075711349465 # 750 1400 0.0390134257995 0.00768847466247 # 750 1450 0.0316449395656 0.0065050745643 assert fit.tuple_at(700, 1400) == pytest.approx( (0.04734, 0.00906, -0.00906), abs=0.00001) assert fit(700, 1400) == pytest.approx(0.04734, abs=0.00001) assert fit.unc_p_at(700, 1400) == pytest.approx(+0.00906, abs=0.00001) assert fit.unc_m_at(700, 1400) == pytest.approx(-0.00906, abs=0.00001) # interpolation: for uncertainty, returns sensible results for interp_axis in (1, 2): x1 = midpoint[x1a](700, 750) if interp_axis == 1 else 700 x2 = midpoint[x2a](1400, 1450) if interp_axis == 2 else 1400 y_upperend = 0.0390134 if interp_axis == 1 else 0.03822797 if kind == "linear": assert fit(x1, x2) == pytest.approx(midpoint[ya]( 0.0473379, y_upperend), abs=0.00001) else: assert y_upperend < fit(x1, x2) < 0.047337959 assert 0.0075711 < fit.unc_p_at(x1, x2) < 0.0090594 assert 0.0075711 < -fit.unc_m_at(x1, x2) < 0.0090594 assert 0.0316449 < fit(725, 1425) < 0.0473378 assert 0.0065051 < fit.unc_p_at(725, 1425) < 0.0090594 assert 0.0065051 < -fit.unc_m_at(725, 1425) < 0.0090594
def compare(ctx, *args, **kwargs): # type: ignore """Plot multiple interpolation results.""" pdf = PdfPages(kwargs["output"]) if kwargs["output"] else None if kwargs["all"]: for key, table in _all_tables_iter(): try: choose_validator(table)(pdf).compare(table, key) except ValueError as e: print(e) elif kwargs["table"]: nllfast = (kwargs["table"] if kwargs["table"] in susy_cross_section.config.table_names else None) table = File(*Util.get_paths(kwargs["table"])).tables["xsec"] try: choose_validator(table)(pdf).compare(table, nllfast_cache_key=nllfast) except ValueError as e: print(e) else: click.echo("table path or --all option must be required.") if pdf: pdf.close()
def test_scipy_grid_interpolator_nonstandard_args(self): """Verify ScipyGridInterp accepts/refuses args correctly.""" table = File(self.dirs["fastlim8mod"] / "sg_8TeV_NLONLL_modified.xsec")["xsec"] for kind in ["linear", "spline"]: fit = ScipyGridInterpolator(kind).interpolate(table) for m in ["f0", "fp", "fm", "unc_p_at", "unc_m_at", "tuple_at"]: test_method = getattr(fit, m) value = test_method(777, 888) if m == "tuple_at": # the output should be (3,) array (or 3-element tuple) assert numpy.array(value).shape == (3, ) else: # it is a scalar assert self._is_scalar_number(value) # method should accept keyword arguments assert test_method(msq=777, mgl=888) == value assert test_method(mgl=888, msq=777) == value assert test_method(777, mgl=888) == value # method should not accept invalid arrays or numpy.ndarray with >0 dim. for bad_input in ([[777]], [[777, 888], [789, 890]], [777, 888, 999]): with pytest.raises((ValueError, TypeError, IndexError)): test_method(bad_input) with pytest.raises((ValueError, TypeError, IndexError)): test_method(numpy.array(bad_input)) with pytest.raises(TypeError): test_method(777, 888, m_wino=100) with pytest.raises(TypeError): test_method(777, m_wino=100) with pytest.raises(TypeError): test_method(m_wino=100) with pytest.raises((IndexError, TypeError)): test_method() with pytest.raises((IndexError, TypeError)): test_method(777)
def _all_tables_iter(table_name="xsec"): for key in susy_cross_section.config.table_names: paths = susy_cross_section.config.table_paths(key) logger.info("Evaluating: {}".format(paths[0])) yield key, File(*paths).tables[table_name]
def export(context, **kw): # type: (Any, Any)->None """Export cross-section table.""" _configure_logger() # handle arguments value_name = kw["name"] or _DEFAULT_VALUE_NAME try: table_path, info_path = utility.get_paths(kw["table"], kw["info"]) data_file = File(table_path, info_path) except (FileNotFoundError, RuntimeError, ValueError, TypeError) as e: click.echo(repr(e)) exit(1) try: table = data_file.tables[value_name] except KeyError as e: logger.critical("Data file does not contain specified table.") click.echo(repr(e)) exit(1) header = table.header() records = table.to_records() n_columns = len(header) units = ["" for i in header] if kw["unit"]: try: units = [" " + u for u in table.units()] except RuntimeError: logger.warning( "Unit information not available for specified table.") if kw["format"] == "TSV" or kw["format"] == "CSV": sep = "\t" if kw["format"] == "TSV" else "," click.echo(sep.join(header)) for i_record in range( len(records)): # As mypy.records does not have __iter__ record = records[i_record] line = [] # type: List[str] for i, v in enumerate(record): if i < n_columns - 2: line.append(str(v) + units[i]) # key & value elif kw["unc"]: line.append(f"{v:.5g}{units[-1]}") # unc click.echo(sep.join(line)) elif kw["format"] == "Math": # Mathematica def concat(c): # type: (List[str])->str return " {" + ", ".join(c) + "}" lines = [concat([f'"{s}"' for s in header[:-2]])] # header for i_record in range(len(records)): r = records[i_record] if kw["unc"]: value = f"Around[{r[-3]}, {{{r[-1]:.5g}, {r[-2]:.5g}}}]" else: value = str(r[-3]) value = value.replace("e", "*^") + units[-1] # Mathematica "E" notation keys = [ f"{v}{units[i]}" for i, v in enumerate(r) if i < n_columns - 3 ] keys.append(value) lines.append(concat(keys)) click.echo("{\n" + ",\n".join(lines) + "\n}") exit(0)