Skip to content
Snippets Groups Projects
Commit 247bb33e authored by wilsonm's avatar wilsonm
Browse files

update vp-nextfitruncard to use the API, update the relevant provider to be...

update vp-nextfitruncard to use the API, update the relevant provider to be able to update description and reformate provider plus docstring
parent 2d794c8a
No related branches found
No related tags found
1 merge request!929Use API in vp-nextfitruncard
...@@ -400,40 +400,64 @@ fmt = lambda a: float(significant_digits(a, 4)) ...@@ -400,40 +400,64 @@ fmt = lambda a: float(significant_digits(a, 4))
next_fit_eff_exps_table = collect("next_effective_exponents_table", ("fitpdfandbasis",)) next_fit_eff_exps_table = collect("next_effective_exponents_table", ("fitpdfandbasis",))
def next_effective_exponents_yaml(fit: FitSpec, next_fit_eff_exps_table):
"""-Returns a table in yaml format called NextEffExps.yaml
-Prints the yaml table in the report
using `effective_exponents_table` this provider outputs the yaml runcard to run
a fit with identical input as the specified `fit` with the t0 and preprocessing iterated.
This action must be used in a report and should be wrapped in a code block to be formatted def next_effective_exponents_yaml(
correctly, for example: fit: FitSpec, next_fit_eff_exps_table, _updated_description=None
):
"""
Using `effective_exponents_table` this provider outputs the yaml runcard
used to specify settings of ``fit`` but having iterated the following
sections:
- Modifies the random seeds
- Updates the preprocessing exponents
- Updates the description if ``_updated_description`` is provided
this should facilitate running a new fit with identical input settings
as the specified ``fit`` with the t0, seeds and preprocessing iterated.
This action can be used in a report but should be wrapped in a code block
to be formatted correctly, for example:
```yaml ```yaml
{@next_effective_exponents_runcard@} {@next_effective_exponents_runcard@}
``` ```
""" alternatively, using the API, the yaml dump returned by this function can
be written to a file e.g
>>> from validphys.api import API
>>> yaml_output = API.next_effective_exponents_yaml(
... fit=<fit name>,
... _updated_description="My iterated fit"
... )
>>> with open("output.yml", "w+") as f:
... f.write(yaml_output)
"""
df_effexps = next_fit_eff_exps_table[0] df_effexps = next_fit_eff_exps_table[0]
# Use round trip loader rather than safe_load in fit.as_input() # Use round trip loader rather than safe_load in fit.as_input()
with open(fit.path/'filter.yml', 'r') as f: with open(fit.path / "filter.yml", "r") as f:
filtermap = yaml.load(f, yaml.RoundTripLoader) filtermap = yaml.load(f, yaml.RoundTripLoader)
previous_exponents = filtermap['fitting']['basis'] previous_exponents = filtermap["fitting"]["basis"]
basis = filtermap['fitting']['fitbasis'] basis = filtermap["fitting"]["fitbasis"]
checked = check_basis(basis, None) checked = check_basis(basis, None)
basis = checked['basis'] basis = checked["basis"]
flavours = checked['flavours'] flavours = checked["flavours"]
runcard_flavours = basis.to_known_elements( runcard_flavours = basis.to_known_elements(
[ref_fl['fl'] for ref_fl in previous_exponents]).tolist() [ref_fl["fl"] for ref_fl in previous_exponents]
).tolist()
for fl in flavours: for fl in flavours:
alphas = df_effexps.loc[(f'${fl}$', r'$\alpha$')].values alphas = df_effexps.loc[(f"${fl}$", r"$\alpha$")].values
betas = df_effexps.loc[(f'${fl}$', r'$\beta$')].values betas = df_effexps.loc[(f"${fl}$", r"$\beta$")].values
previous_exponents[runcard_flavours.index(fl)]['smallx'] = [fmt(alpha) for alpha in alphas] previous_exponents[runcard_flavours.index(fl)]["smallx"] = [
previous_exponents[runcard_flavours.index(fl)]['largex'] = [fmt(beta) for beta in betas] fmt(alpha) for alpha in alphas
#iterate t0 ]
filtermap['datacuts']['t0pdfset'] = fit.name previous_exponents[runcard_flavours.index(fl)]["largex"] = [
fmt(beta) for beta in betas
]
# iterate t0
filtermap["datacuts"]["t0pdfset"] = fit.name
# Update seeds with pseudorandom numbers between 0 and 1e10 # Update seeds with pseudorandom numbers between 0 and 1e10
# Check if seeds exist especially since extra seeds needed in n3fit vs nnfit # Check if seeds exist especially since extra seeds needed in n3fit vs nnfit
...@@ -450,4 +474,8 @@ def next_effective_exponents_yaml(fit: FitSpec, next_fit_eff_exps_table): ...@@ -450,4 +474,8 @@ def next_effective_exponents_yaml(fit: FitSpec, next_fit_eff_exps_table):
if "filterseed" in closuretest_data: if "filterseed" in closuretest_data:
closuretest_data["filterseed"] = random.randrange(0, 1e10) closuretest_data["filterseed"] = random.randrange(0, 1e10)
# update description if necessary
if _updated_description is not None:
filtermap["description"] = _updated_description
return yaml.dump(filtermap, Dumper=yaml.RoundTripDumper) return yaml.dump(filtermap, Dumper=yaml.RoundTripDumper)
...@@ -19,19 +19,12 @@ import argparse ...@@ -19,19 +19,12 @@ import argparse
import os import os
import pathlib import pathlib
import sys import sys
import random
import logging import logging
import prompt_toolkit import prompt_toolkit
import NNPDF as nnpath
from reportengine.compat import yaml
from reportengine import colors from reportengine import colors
from reportengine.floatformatting import significant_digits
from validphys.eff_exponents import next_effective_exponents_table from validphys.api import API
from validphys.loader import Loader, PDFNotFound
from validphys.pdfbases import check_basis
# Take command line arguments # Take command line arguments
...@@ -97,94 +90,25 @@ def main(): ...@@ -97,94 +90,25 @@ def main():
# Check whether runcard with same name already exists in the path # Check whether runcard with same name already exists in the path
if runcard_path_out.exists() and not force: if runcard_path_out.exists() and not force:
log.error( log.error(
f"Destination path {runcard_path_out.absolute()} already exists. If you wish to " "Destination path %s already exists. If you wish to "
"overwrite it, use the --force option." "overwrite it, use the --force option.",
) runcard_path_out.absolute(),
sys.exit(1)
results_path = pathlib.Path(nnpath.get_results_path())
fit_path = results_path / input_fit
if not fit_path.is_dir():
log.error(
"Could not find the specified fit. The following path is not a directory: "
f"{fit_path.absolute()}. If the requested fit does exist, you can download it with "
"`vp-get fit <fit_name>`."
) )
sys.exit(1) sys.exit(1)
runcard_path_in = fit_path / "filter.yml"
with open(runcard_path_in, "r") as infile:
runcard_data = yaml.load(infile, Loader=yaml.RoundTripLoader)
log.info(f"Input runcard successfully read from {runcard_path_in.absolute()}.")
# Update runcard with settings needed for iteration
# Update description of fit interactively # Update description of fit interactively
description = runcard_data["description"] description = API.fit(fit=input_fit).as_input()["description"]
updated_description = interactive_description(description) updated_description = interactive_description(description)
runcard_data["description"] = updated_description
# Iterate t0
runcard_data["datacuts"]["t0pdfset"] = input_fit
# Update seeds with pseudorandom numbers between 0 and 1e10
# Check if seeds exist especially since extra seeds needed in n3fit vs nnfit
# Start with seeds in "fitting" section of runcard
fitting_data = runcard_data["fitting"]
fitting_seeds = ["seed", "trvlseed", "nnseed", "mcseed"]
for seed in fitting_seeds:
if seed in fitting_data:
fitting_data[seed] = random.randrange(0, 1e10)
# Next "closuretest" section of runcard
closuretest_data = runcard_data["closuretest"]
if "filterseed" in closuretest_data:
closuretest_data["filterseed"] = random.randrange(0, 1e10)
# Update preprocessing exponents
# Firstly, find new exponents from PDF set that corresponds to fit
basis = runcard_data["fitting"]["fitbasis"]
checked = check_basis(basis, None)
basis = checked["basis"]
flavours = checked["flavours"]
l = Loader()
try:
pdf = l.check_pdf(input_fit)
except PDFNotFound:
log.error(
f"Could not find the PDF set {input_fit}. If the requested PDF set does exist, you can "
"download it with `vp-get pdf <pdf_name>`."
)
sys.exit(1)
new_exponents = next_effective_exponents_table(
pdf=pdf, basis=basis, flavours=flavours
)
# Define function that we will use to round exponents to 4 significant figures iterated_runcard_yaml = API.next_effective_exponents_yaml(
rounder = lambda a: float(significant_digits(a, 4)) fit=input_fit, _updated_description=updated_description
)
# Update previous_exponents with new values
previous_exponents = runcard_data["fitting"]["basis"]
runcard_flavours = basis.to_known_elements(
[ref_fl["fl"] for ref_fl in previous_exponents]
).tolist()
for fl in flavours:
alphas = new_exponents.loc[(f"${fl}$", r"$\alpha$")].values
betas = new_exponents.loc[(f"${fl}$", r"$\beta$")].values
previous_exponents[runcard_flavours.index(fl)]["smallx"] = [
rounder(alpha) for alpha in alphas
]
previous_exponents[runcard_flavours.index(fl)]["largex"] = [
rounder(beta) for beta in betas
]
# Write new runcard to file # Write new runcard to file
with open(runcard_path_out, "w") as outfile: with open(runcard_path_out, "w") as outfile:
yaml.dump(runcard_data, outfile, Dumper=yaml.RoundTripDumper) outfile.write(iterated_runcard_yaml)
log.info(f"Runcard for iterated fit written to {runcard_path_out.absolute()}.") log.info("Runcard for iterated fit written to %s.", runcard_path_out.absolute())
# Open new runcard with default editor, or if one is not set, with vi # Open new runcard with default editor, or if one is not set, with vi
EDITOR = os.environ.get("EDITOR") if os.environ.get("EDITOR") else "vi" EDITOR = os.environ.get("EDITOR") if os.environ.get("EDITOR") else "vi"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment