diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 15e348faed..0c70941a34 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,13 +12,13 @@ repos: - id: trailing-whitespace - repo: https://github.com/psf/black-pre-commit-mirror - rev: '24.10.0' + rev: '25.1.0' hooks: - id: black args: ['--config=./pyproject.toml'] - repo: https://github.com/pycqa/isort - rev: '5.13.2' + rev: '6.0.0' hooks: - id: isort args: ['--settings-path=./pyproject.toml'] diff --git a/extra_tests/regression_fits/no_csr.yml b/extra_tests/regression_fits/no_csr.yml index 47e7d4bd02..9d248f12d3 100644 --- a/extra_tests/regression_fits/no_csr.yml +++ b/extra_tests/regression_fits/no_csr.yml @@ -12,9 +12,8 @@ description: n3fit regression test # ewk: apply ewk k-factors # sys: systematics treatment (see systypes) dataset_inputs: -- { dataset: NMC, frac: 0.5 } -- { dataset: SLACP, frac: 0.5} - + - {dataset: NMC_NC_NOTFIXED_P_EM-SIGMARED, frac: 0.5, variant: legacy} + - {dataset: SLAC_NC_NOTFIXED_P_EM-F2, frac: 0.5, variant: legacy} ############################################################ datacuts: @@ -69,12 +68,12 @@ fitting: ############################################################ positivity: posdatasets: - - { dataset: POSF2U, maxlambda: 1e6 } # Positivity Lagrange Multiplier - - { dataset: POSDYS, maxlambda: 1e5 } + - {dataset: NNPDF_POS_2P24GEV_F2U, maxlambda: 1e6} + - {dataset: NNPDF_POS_2P24GEV_DYS, maxlambda: 1e5} integrability: integdatasets: - - {dataset: INTEGXT8, maxlambda: 1e2} + - {dataset: NNPDF_INTEG_3GEV_XT8, maxlambda: 1e2} ############################################################ debug: true diff --git a/n3fit/runcards/examples/nnpdf40-like.yml b/n3fit/runcards/examples/nnpdf40-like.yml index 30a96523be..558e60d38a 100644 --- a/n3fit/runcards/examples/nnpdf40-like.yml +++ b/n3fit/runcards/examples/nnpdf40-like.yml @@ -76,7 +76,7 @@ dataset_inputs: - {dataset: CMS_TTBAR_5TEV_TOT_X-SEC, frac: 0.75, variant: legacy} - {dataset: CMS_TTBAR_8TEV_2L_DIF_MTTBAR-YT-NORM, frac: 0.75, variant: legacy} - {dataset: CMS_TTBAR_13TEV_2L_DIF_YT, frac: 0.75, variant: legacy} -- {dataset: CMS_TTBAR_13TEV_LJ_2016_DIF_YTTBAR, frac: 0.75, variant: legacy} +- {dataset: CMS_TTBAR_13TEV_LJ_2016_DIF_YT, frac: 0.75, variant: legacy} - {dataset: CMS_SINGLETOP_7TEV_TCHANNEL-XSEC, frac: 0.75, variant: legacy} - {dataset: CMS_SINGLETOP_8TEV_TCHANNEL-XSEC, frac: 0.75, variant: legacy} - {dataset: CMS_SINGLETOP_13TEV_TCHANNEL-XSEC, frac: 0.75, variant: legacy} diff --git a/n3fit/runcards/hyperopt_studies/renew_hyperopt.yml b/n3fit/runcards/hyperopt_studies/renew_hyperopt.yml index 8bae9489b6..f8fd11034c 100644 --- a/n3fit/runcards/hyperopt_studies/renew_hyperopt.yml +++ b/n3fit/runcards/hyperopt_studies/renew_hyperopt.yml @@ -76,7 +76,7 @@ dataset_inputs: - {dataset: CMS_TTBAR_5TEV_TOT_X-SEC, frac: 0.75, cfac: [], variant: legacy} - {dataset: CMS_TTBAR_8TEV_2L_DIF_MTTBAR-YT-NORM, frac: 0.75, cfac: [], variant: legacy} - {dataset: CMS_TTBAR_13TEV_2L_DIF_YT, frac: 0.75, cfac: [], variant: legacy} -- {dataset: CMS_TTBAR_13TEV_LJ_2016_DIF_YTTBAR, frac: 0.75, cfac: [], variant: legacy} +- {dataset: CMS_TTBAR_13TEV_LJ_2016_DIF_YT, frac: 0.75, cfac: [], variant: legacy} - {dataset: CMS_SINGLETOP_7TEV_TCHANNEL-XSEC, frac: 0.75, cfac: [], variant: legacy} - {dataset: CMS_SINGLETOP_8TEV_TCHANNEL-XSEC, frac: 0.75, cfac: [], variant: legacy} - {dataset: CMS_SINGLETOP_13TEV_TCHANNEL-XSEC, frac: 0.75, cfac: [], variant: legacy} diff --git a/n3fit/runcards/hyperopt_studies/restricted_search_space_renew_hyperopt.yml b/n3fit/runcards/hyperopt_studies/restricted_search_space_renew_hyperopt.yml index 05c13c8695..e10800bea2 100644 --- a/n3fit/runcards/hyperopt_studies/restricted_search_space_renew_hyperopt.yml +++ b/n3fit/runcards/hyperopt_studies/restricted_search_space_renew_hyperopt.yml @@ -76,7 +76,7 @@ dataset_inputs: - {dataset: CMS_TTBAR_5TEV_TOT_X-SEC, frac: 0.75, cfac: [], variant: legacy} - {dataset: CMS_TTBAR_8TEV_2L_DIF_MTTBAR-YT-NORM, frac: 0.75, cfac: [], variant: legacy} - {dataset: CMS_TTBAR_13TEV_2L_DIF_YT, frac: 0.75, cfac: [], variant: legacy} -- {dataset: CMS_TTBAR_13TEV_LJ_2016_DIF_YTTBAR, frac: 0.75, cfac: [], variant: legacy} +- {dataset: CMS_TTBAR_13TEV_LJ_2016_DIF_YT, frac: 0.75, cfac: [], variant: legacy} - {dataset: CMS_SINGLETOP_7TEV_TCHANNEL-XSEC, frac: 0.75, cfac: [], variant: legacy} - {dataset: CMS_SINGLETOP_8TEV_TCHANNEL-XSEC, frac: 0.75, cfac: [], variant: legacy} - {dataset: CMS_SINGLETOP_13TEV_TCHANNEL-XSEC, frac: 0.75, cfac: [], variant: legacy} diff --git a/n3fit/src/n3fit/scripts/n3fit_exec.py b/n3fit/src/n3fit/scripts/n3fit_exec.py index 58942b32f4..c7fb995cbf 100755 --- a/n3fit/src/n3fit/scripts/n3fit_exec.py +++ b/n3fit/src/n3fit/scripts/n3fit_exec.py @@ -1,6 +1,6 @@ #!/usr/bin/env python """ - n3fit - performs fit using ml external frameworks +n3fit - performs fit using ml external frameworks """ import argparse @@ -19,7 +19,7 @@ from validphys.core import FitSpec from validphys.utils import yaml_safe -N3FIT_FIXED_CONFIG = dict(use_cuts='internal', use_t0=True, actions_=[]) +N3FIT_FIXED_CONFIG = dict(use_cuts='internal', use_t0=True, actions_=[], allow_legacy_names=False) FIT_NAMESPACE = "datacuts::theory::fitting " CLOSURE_NAMESPACE = "datacuts::theory::closuretest::fitting " @@ -159,7 +159,6 @@ def from_yaml(cls, o, *args, **kwargs): N3FIT_FIXED_CONFIG['use_thcovmat_in_sampling'] = thconfig.get( 'use_thcovmat_in_sampling', True ) - # Fitting flag file_content.update(N3FIT_FIXED_CONFIG) return cls(file_content, *args, **kwargs) diff --git a/nnpdf_data/nnpdf_data/__init__.py b/nnpdf_data/nnpdf_data/__init__.py index f12d3e0abc..154c75fa16 100644 --- a/nnpdf_data/nnpdf_data/__init__.py +++ b/nnpdf_data/nnpdf_data/__init__.py @@ -1,8 +1,11 @@ from functools import lru_cache +import logging import pathlib import yaml +log = logging.getLogger(__name__) + path_vpdata = pathlib.Path(__file__).parent path_commondata = path_vpdata / "commondata" @@ -18,6 +21,13 @@ } +@lru_cache +def _warn_old_names(): + log.warning( + "The usage of old names is deprecated and support will be dropped in future versions! Update your runcards" + ) + + @lru_cache def legacy_to_new_map(dataset_name, sys=None): """Find the new dataset name and variant corresponding to an old dataset @@ -35,6 +45,13 @@ def legacy_to_new_map(dataset_name, sys=None): ) variant += f"_{sys}" + # Deprecation notice + _warn_old_names() + warn_text = f"Please change {dataset_name} to {new_name}" + if variant is None: + warn_text += f" (variant: {variant})" + log.warning(warn_text) + return new_name, variant diff --git a/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/data_legacy_YTTBAR.yaml b/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/data_legacy_YT.yaml similarity index 100% rename from nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/data_legacy_YTTBAR.yaml rename to nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/data_legacy_YT.yaml diff --git a/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/kinematics_YTTBAR.yaml b/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/kinematics_YT.yaml similarity index 93% rename from nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/kinematics_YTTBAR.yaml rename to nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/kinematics_YT.yaml index 333211ec9d..a34cbc09c5 100644 --- a/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/kinematics_YTTBAR.yaml +++ b/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/kinematics_YT.yaml @@ -1,5 +1,5 @@ bins: -- y_ttBar: +- y_t: min: null mid: 0.1 max: null @@ -11,7 +11,7 @@ bins: min: null mid: 13000.0 max: null -- y_ttBar: +- y_t: min: null mid: 0.3 max: null @@ -23,7 +23,7 @@ bins: min: null mid: 13000.0 max: null -- y_ttBar: +- y_t: min: null mid: 0.5 max: null @@ -35,7 +35,7 @@ bins: min: null mid: 13000.0 max: null -- y_ttBar: +- y_t: min: null mid: 0.7 max: null @@ -47,7 +47,7 @@ bins: min: null mid: 13000.0 max: null -- y_ttBar: +- y_t: min: null mid: 0.9 max: null @@ -59,7 +59,7 @@ bins: min: null mid: 13000.0 max: null -- y_ttBar: +- y_t: min: null mid: 1.1 max: null @@ -71,7 +71,7 @@ bins: min: null mid: 13000.0 max: null -- y_ttBar: +- y_t: min: null mid: 1.3 max: null @@ -83,7 +83,7 @@ bins: min: null mid: 13000.0 max: null -- y_ttBar: +- y_t: min: null mid: 1.5 max: null @@ -95,7 +95,7 @@ bins: min: null mid: 13000.0 max: null -- y_ttBar: +- y_t: min: null mid: 1.7 max: null @@ -107,7 +107,7 @@ bins: min: null mid: 13000.0 max: null -- y_ttBar: +- y_t: min: null mid: 1.9 max: null @@ -119,7 +119,7 @@ bins: min: null mid: 13000.0 max: null -- y_ttBar: +- y_t: min: null mid: 2.25 max: null diff --git a/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/metadata.yaml b/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/metadata.yaml index 5bcc22265a..11ef1f73b5 100644 --- a/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/metadata.yaml +++ b/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/metadata.yaml @@ -1,6 +1,6 @@ setname: CMS_TTBAR_13TEV_LJ_2016_DIF -version: 1 -version_comment: Port of old commondata +version: 2 +version_comment: Port of old commondata, v2 corrected the observable_name nnpdf_metadata: nnpdf31_process: TOP experiment: CMS @@ -13,12 +13,12 @@ hepdata: url: '' version: -1 implemented_observables: -- observable_name: YTTBAR +- observable_name: YT observable: description: Heavy Quarks Production Single Quark Rapidity Distribution label: CMS $t\bar{t}$ absolute $|y_t|$ units: '' - process_type: HQP_YQQ + process_type: HQP_YQ tables: [] npoints: [] ndata: 11 @@ -27,16 +27,16 @@ implemented_observables: y_label: $d\sigma_{t\bar{t}}/d|y_t|$ (fb) figure_by: - sqrts - plot_x: y_ttBar + plot_x: y_t kinematic_coverage: - - y_ttBar + - y_t - m_t2 - sqrts kinematics: variables: - y_ttBar: - description: Variable y_ttBar - label: y_ttBar + y_t: + description: Variable y_t + label: y_t units: '' m_t2: description: Variable m_t2 @@ -46,7 +46,7 @@ implemented_observables: description: Variable sqrts label: sqrts units: '' - file: kinematics_YTTBAR.yaml + file: kinematics_YT.yaml theory: conversion_factor: 0.575431971 operation: 'null' @@ -56,6 +56,6 @@ implemented_observables: variants: legacy: data_uncertainties: - - uncertainties_legacy_YTTBAR.yaml - data_central: data_legacy_YTTBAR.yaml + - uncertainties_legacy_YT.yaml + data_central: data_legacy_YT.yaml ported_from: CMS_TTB_DIFF_13TEV_2016_LJ_TRAP diff --git a/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/uncertainties_legacy_YTTBAR.yaml b/nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/uncertainties_legacy_YT.yaml similarity index 100% rename from nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/uncertainties_legacy_YTTBAR.yaml rename to nnpdf_data/nnpdf_data/commondata/CMS_TTBAR_13TEV_LJ_2016_DIF/uncertainties_legacy_YT.yaml diff --git a/nnpdf_data/nnpdf_data/commondata/dataset_names.yml b/nnpdf_data/nnpdf_data/commondata/dataset_names.yml index 9230de6723..c042588342 100644 --- a/nnpdf_data/nnpdf_data/commondata/dataset_names.yml +++ b/nnpdf_data/nnpdf_data/commondata/dataset_names.yml @@ -330,7 +330,7 @@ CMS_SINGLETOP_TCH_TOT_7TEV: dataset: CMS_SINGLETOP_7TEV_TCHANNEL-XSEC variant: legacy CMS_TTB_DIFF_13TEV_2016_LJ_TRAP: - dataset: CMS_TTBAR_13TEV_LJ_2016_DIF_YTTBAR + dataset: CMS_TTBAR_13TEV_LJ_2016_DIF_YT variant: legacy POSDYS: dataset: NNPDF_POS_2P24GEV_DYS @@ -412,3 +412,6 @@ ATLAS_WJ_JET_8TEV_WM-PT: ATLAS_WJ_JET_8TEV_WP-PT: dataset: ATLAS_WJ_8TEV_WP-PT variant: legacy +CMS_TTBAR_13TEV_LJ_2016_DIF_YTTBAR: + dataset: CMS_TTBAR_13TEV_LJ_2016_DIF_YT + variant: legacy diff --git a/validphys2/examples/future_test_example.yaml b/validphys2/examples/future_test_example.yaml index 344cf01474..926252cbe6 100644 --- a/validphys2/examples/future_test_example.yaml +++ b/validphys2/examples/future_test_example.yaml @@ -105,7 +105,7 @@ dataset_inputs: - {dataset: CMS_TTBAR_5TEV_TOT_X-SEC, custom_group: NNPDF40 datasets, cfac: [QCD], variant: legacy} - {dataset: CMS_TTBAR_8TEV_2L_DIF_MTTBAR-YT-NORM, custom_group: NNPDF40 datasets, cfac: [QCD], variant: legacy} - {dataset: CMS_TTBAR_13TEV_2L_DIF_YT, custom_group: NNPDF40 datasets, cfac: [QCD], variant: legacy} - - {dataset: CMS_TTBAR_13TEV_LJ_2016_DIF_YTTBAR, custom_group: NNPDF40 datasets, cfac: [QCD], variant: legacy} + - {dataset: CMS_TTBAR_13TEV_LJ_2016_DIF_YT, custom_group: NNPDF40 datasets, cfac: [QCD], variant: legacy} - {dataset: CMS_SINGLETOP_7TEV_TCHANNEL-XSEC, custom_group: NNPDF40 datasets, cfac: [QCD], variant: legacy} - {dataset: CMS_SINGLETOP_8TEV_TCHANNEL-XSEC, custom_group: NNPDF40 datasets, cfac: [QCD], variant: legacy} - {dataset: CMS_SINGLETOP_13TEV_TCHANNEL-XSEC, custom_group: NNPDF40 datasets, cfac: [QCD], variant: legacy} diff --git a/validphys2/src/validphys/commondataparser.py b/validphys2/src/validphys/commondataparser.py index cc9ba23ac0..80350398ae 100644 --- a/validphys2/src/validphys/commondataparser.py +++ b/validphys2/src/validphys/commondataparser.py @@ -48,7 +48,7 @@ from validobj import ValidationError, parse_input from validobj.custom import Parser -from nnpdf_data import new_to_legacy_map, path_commondata +from nnpdf_data import legacy_to_new_map, new_to_legacy_map, path_commondata from nnpdf_data.utils import parse_yaml_inp from validphys.coredata import KIN_NAMES, CommonData from validphys.plotoptions.plottingoptions import PlottingOptions, labeler_functions @@ -819,9 +819,23 @@ def select_observable(self, obs_name_raw): try: observable = self.allowed_observables[obs_name] except KeyError: - raise ValueError( - f"The selected observable {obs_name_raw} does not exist in {self.setname}" - ) + std_err = f"The selected observable {obs_name_raw} does not exist in {self.setname}" + # If the error is due to the usage of an old name, give some extra information + name = f"{self.setname}_{obs_name_raw}" + new_name, map_variant = legacy_to_new_map(name, None) + if new_name == name: + # It was just a mistake, raise the original error + raise ValueError(std_err) + if map_variant is None: + dinput_str = f"- {{ dataset: {new_name} }}" + else: + dinput_str = f"- {{ dataset: {new_name}, variant: {map_variant} }}" + std_err += f""" +It might be that you used an older name for the dataset: '{name}'. +If this is a mistake, please use '{new_name}' instead. E.g., + {dinput_str} +""" + raise ValueError(std_err) # Now burn the _parent key into the observable and apply checks object.__setattr__(observable, "_parent", self) diff --git a/validphys2/src/validphys/config.py b/validphys2/src/validphys/config.py index 2a609a567a..771722b579 100644 --- a/validphys2/src/validphys/config.py +++ b/validphys2/src/validphys/config.py @@ -394,7 +394,7 @@ def produce_fitpdfandbasis(self, fitpdf, basisfromfit): return {**fitpdf, **basisfromfit} @element_of("dataset_inputs") - def parse_dataset_input(self, dataset: Mapping): + def parse_dataset_input(self, dataset: Mapping, allow_legacy_names: bool = True): """The mapping that corresponds to the dataset specifications in the fit files This mapping is such that @@ -458,17 +458,17 @@ def parse_dataset_input(self, dataset: Mapping): if variant is not None and sysnum is not None: raise ConfigError(f"The 'variant' and 'sys' keys cannot be used together ({name})") - # The old->new name can be used for two reasons: - # 1. To use the old names, in that case one recieves a name and, maybe a variant - # 2. To correct a wrong (but new-style) name. - # In both cases the varaint is overwritten if and only if the variant is None - name, map_variant = legacy_to_new_map(name, sysnum) - # legacy_dw trumps everything - if variant is None or map_variant == "legacy_dw": - variant = map_variant - - if sysnum is not None: - log.warning("The key 'sys' is deprecated and will soon be removed") + # The old -> new name mapping can only be used with allow_legacy_names = True + # which from 4.1 will default to False. + # It can be used in order to be able to use old runcard but it is not recommended. + if allow_legacy_names: + name, map_variant = legacy_to_new_map(name, sysnum) + # legacy_dw trumps everything + if variant is None or map_variant == "legacy_dw": + variant = map_variant + + if sysnum is not None: + log.warning("The key 'sys' is deprecated and will soon be removed") return DataSetInput( name=name, diff --git a/validphys2/src/validphys/loader.py b/validphys2/src/validphys/loader.py index 531a8e1ebb..04aea61667 100644 --- a/validphys2/src/validphys/loader.py +++ b/validphys2/src/validphys/loader.py @@ -18,7 +18,7 @@ import requests -from nnpdf_data import legacy_to_new_mapping, path_vpdata +from nnpdf_data import legacy_to_new_map, legacy_to_new_mapping, path_vpdata from reportengine import filefinder from validphys import lhaindex from validphys.commondataparser import load_commondata_old, parse_new_metadata, parse_set_metadata @@ -321,10 +321,8 @@ def available_datasets(self): """Provide all available datasets that were available before the new commondata was implemented and that have a translation. Returns old names - - TODO: This should be substituted by a subset of `implemented_dataset` that returns only - complete datasets. """ + # TODO: return new names... without loading the metadata... # Skip Positivity and Integrability skip = ["POS", "INTEG"] # Skip datasets for which a translation exists but were not implemented in the old way @@ -440,13 +438,16 @@ def check_commondata( # Get data folder and observable name and check for existence try: setfolder, observable_name = setname.rsplit("_", 1) + set_path = self.commondata_folder / setfolder + if not set_path.exists(): + # Go down to the exception + raise ValueError except ValueError: - raise DataNotFoundError( - f"Dataset {setname} not found. Is the name correct? Old commondata is no longer accepted" - ) - set_path = self.commondata_folder / setfolder - if not set_path.exists(): - raise DataNotFoundError(f"Dataset {setname} not found") + new_name, _ = legacy_to_new_map(setname, None) + err = "" + if new_name != setname: + err = f"\nNote that old names are no longer accepted. Perhaps you meant {new_name}" + raise DataNotFoundError(f"Dataset {setname} not found. Is the name correct? {err}") metadata_path = set_path / "metadata.yaml" metadata = parse_new_metadata(metadata_path, observable_name, variant=variant) diff --git a/validphys2/src/validphys/tests/test_loader.py b/validphys2/src/validphys/tests/test_loader.py index dead6222d4..322537a934 100644 --- a/validphys2/src/validphys/tests/test_loader.py +++ b/validphys2/src/validphys/tests/test_loader.py @@ -14,6 +14,8 @@ import pytest from nnpdf_data import legacy_to_new_map +from reportengine.configparser import ConfigError +from validphys.api import API from validphys.loader import NNPDF_DIR, FallbackLoader, FitNotFound from validphys.plotoptions.core import get_info, kitable from validphys.tests.conftest import FIT, FIT_3REPLICAS, THEORYID_NEW @@ -58,6 +60,17 @@ def test_load_fit(): l.check_fit(f"{FIT}/") +def test_load_old_error(data_config): + """Checks that when loading a dataset with an old name, it errors out + if ``allow_legacy_names`` is set to False""" + idict = {**data_config, "dataset_input": {"dataset": "LHCBZ940PB"}} + # This works + _ = API.dataset(**idict, allow_legacy_names=True) + # This doesn't + with pytest.raises(ConfigError): + _ = API.dataset(**idict, allow_legacy_names=False) + + ### nnprofile testing def _check_download_resource(results_dir, profile=None, res_type="fit", resource=FIT_3REPLICAS): """Downloads a resource (by default the fit FIT_3REPLICAS and