{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Get available `CMIP6` and `CORDEX` simulations\n", "\n", "`Downclim` allows you to easily access `CMIP6` and `CORDEX` simulations. \n", "\n", "This notebook shows how to get a list of available simulations for a given set of variables and regions. This is a prior step to actually download the data." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from __future__ import annotations\n", "\n", "from downclim.dataset.cmip6 import CMIP6Context\n", "from downclim.dataset.cordex import CORDEXContext\n", "from downclim.dataset.utils import Frequency, save_simulations_list\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`CMIP6Context` and `CORDEXContext` are the main classes to interact with `CMIP6` and `CORDEX` simulations. They are containers of all the information needed to proceed to your request." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CMIP6 simulations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To request CMIP6 simulations available on [Google Cloud File System (GCFS)](https://console.cloud.google.com/marketplace/product/noaa-public/cmip6), you must use the `CMIP6Context` class.\n", "\n", "You can use all classical fields for filtering CMIP6 simulations. Also, even though we use `GCFS`, and thus cannot guarantee full accordance with `ESGF` server, you can also check and filter CMIP6 data, e.g. here: https://esgf-node.ipsl.upmc.fr/search/cmip6-ipsl/.\n", "\n", "Here are the main fields you can use :" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'project': ['ScenarioMIP', 'CMIP'],\n", " 'institute': ['NOAA-GFDL', 'CMCC'],\n", " 'source': None,\n", " 'experiment': ['ssp126', 'historical'],\n", " 'ensemble': ['r1i1p1f1'],\n", " 'frequency': ,\n", " 'variable': ['tas', 'pr'],\n", " 'grid_label': 'gn'}" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cmip6_context = CMIP6Context(\n", " project = [\"ScenarioMIP\", \"CMIP\"],\n", " institute = [\"NOAA-GFDL\", \"CMCC\"],\n", " experiment = [\"ssp126\", \"historical\"],\n", " ensemble = \"r1i1p1f1\",\n", " frequency = Frequency.MONTHLY,\n", " variable = [\"tas\", \"pr\"],\n", " grid_label = \"gn\",\n", ")\n", "cmip6_context.model_dump()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can have more information about the fields you can provide to your `CMIP6Context` object :" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on class CMIP6Context in module downclim.dataset.cmip6:\n", "\n", "class CMIP6Context(pydantic.main.BaseModel)\n", " | CMIP6Context(\n", " | *,\n", " | project: list[str] | None = ['ScenarioMIP', 'CMIP'],\n", " | institute: list[str] | None = None,\n", " | source: list[str] | None = None,\n", " | experiment: list[str] | None = ['ssp245', 'historical'],\n", " | ensemble: list[str] | None = ['r1i1p1f1'],\n", " | frequency: downclim.dataset.utils.Frequency = ,\n", " | variable: list[str] | None = ['tas', 'pr'],\n", " | grid_label: str | None = None\n", " | ) -> None\n", " |\n", " | Context about the query on the CMIP6 dataset.\n", " |\n", " | Entries of the dictionary can be either `str` or `list` of `str` if multiple values are provided. These following keys are available. None are mandatory:\n", " |\n", " | - activity_id: str, e.g \"ScenarioMIP\", \"CMIP\"\n", " | - institution_id: str, e.g \"IPSL\", \"NCAR\"\n", " | - source_id: str, e.g \"IPSL-CM6A-LR\", \"CMCC-CM2-HR4\"\n", " | - experiment_id: str, e.g \"ssp126\", \"historical\"\n", " | - member_id: str, e.g \"r1i1p1f1\"\n", " | - table_id: str, e.g \"Amon\", \"day\"\n", " | - variable_id: str, e.g \"tas\", \"pr\"\n", " | - grid_label: str, e.g \"gn\", \"gr\"\n", " |\n", " | Method resolution order:\n", " | CMIP6Context\n", " | pydantic.main.BaseModel\n", " | builtins.object\n", " |\n", " | Methods defined here:\n", " |\n", " | list_available_simulations(\n", " | self,\n", " | cmip6_catalog_url: 'str' = 'https://storage.googleapis.com/cmip6/cmip6-zarr-consolidated-stores.csv'\n", " | ) -> 'pd.DataFrame'\n", " | List all available CMIP6 simulations available on Google Cloud Storage for a given set of context.\n", " |\n", " | Parameters\n", " | ----------\n", " | cmip6_catalog_url: str (default: DataProduct.CMIP6.url)\n", " | URL to the CMIP6 catalog on the Google Cloud File System.\n", " |\n", " | Returns:\n", " | -------\n", " | pd.DataFrame: DataFrame containing information about the available datasets matching\n", " |\n", " | ----------------------------------------------------------------------\n", " | Class methods defined here:\n", " |\n", " | to_list(v: 'Any') -> 'list[Any]'\n", " |\n", " | validate_experiment_id(v: 'str | Iterable[str] | None') -> 'list[str]'\n", " |\n", " | validate_list(v: 'Any') -> 'list[Any]'\n", " |\n", " | ----------------------------------------------------------------------\n", " | Data descriptors defined here:\n", " |\n", " | __weakref__\n", " | list of weak references to the object\n", " |\n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " |\n", " | Config = \n", " | Pydantic configuration for the DownClimContext class.\n", " |\n", " |\n", " | __abstractmethods__ = frozenset()\n", " |\n", " | __annotations__ = {'ensemble': 'list[str] | None', 'experiment': 'list...\n", " |\n", " | __class_vars__ = set()\n", " |\n", " | __private_attributes__ = {}\n", " |\n", " | __pydantic_complete__ = True\n", " |\n", " | __pydantic_computed_fields__ = {}\n", " |\n", " | __pydantic_core_schema__ = {'cls': 'Self'\n", " | Returns a shallow copy of the model.\n", " |\n", " | __deepcopy__(self, memo: 'dict[int, Any] | None' = None) -> 'Self'\n", " | Returns a deep copy of the model.\n", " |\n", " | __delattr__(self, item: 'str') -> 'Any'\n", " | Implement delattr(self, name).\n", " |\n", " | __eq__(self, other: 'Any') -> 'bool'\n", " | Return self==value.\n", " |\n", " | __getattr__(self, item: 'str') -> 'Any'\n", " |\n", " | __getstate__(self) -> 'dict[Any, Any]'\n", " | Helper for pickle.\n", " |\n", " | __init__(self, /, **data: 'Any') -> 'None'\n", " | Create a new model by parsing and validating input data from keyword arguments.\n", " |\n", " | Raises [`ValidationError`][pydantic_core.ValidationError] if the input data cannot be\n", " | validated to form a valid model.\n", " |\n", " | `self` is explicitly positional-only to allow `self` as a field name.\n", " |\n", " | __iter__(self) -> 'TupleGenerator'\n", " | So `dict(model)` works.\n", " |\n", " | __pretty__(self, fmt: 'typing.Callable[[Any], Any]', **kwargs: 'Any') -> 'typing.Generator[Any, None, None]' from pydantic._internal._repr.Representation\n", " | Used by devtools (https://python-devtools.helpmanual.io/) to pretty print objects.\n", " |\n", " | __replace__(self, **changes: 'Any') -> 'Self'\n", " | # Because we make use of `@dataclass_transform()`, `__replace__` is already synthesized by\n", " | # type checkers, so we define the implementation in this `if not TYPE_CHECKING:` block:\n", " |\n", " | __repr__(self) -> 'str'\n", " | Return repr(self).\n", " |\n", " | __repr_args__(self) -> '_repr.ReprArgs'\n", " |\n", " | __repr_name__(self) -> 'str' from pydantic._internal._repr.Representation\n", " | Name of the instance's class, used in __repr__.\n", " |\n", " | __repr_recursion__(self, object: 'Any') -> 'str' from pydantic._internal._repr.Representation\n", " | Returns the string representation of a recursive object.\n", " |\n", " | __repr_str__(self, join_str: 'str') -> 'str' from pydantic._internal._repr.Representation\n", " |\n", " | __rich_repr__(self) -> 'RichReprResult' from pydantic._internal._repr.Representation\n", " | Used by Rich (https://rich.readthedocs.io/en/stable/pretty.html) to pretty print objects.\n", " |\n", " | __setattr__(self, name: 'str', value: 'Any') -> 'None'\n", " | Implement setattr(self, name, value).\n", " |\n", " | __setstate__(self, state: 'dict[Any, Any]') -> 'None'\n", " |\n", " | __str__(self) -> 'str'\n", " | Return str(self).\n", " |\n", " | copy(\n", " | self,\n", " | *,\n", " | include: 'AbstractSetIntStr | MappingIntStrAny | None' = None,\n", " | exclude: 'AbstractSetIntStr | MappingIntStrAny | None' = None,\n", " | update: 'Dict[str, Any] | None' = None,\n", " | deep: 'bool' = False\n", " | ) -> 'Self'\n", " | Returns a copy of the model.\n", " |\n", " | !!! warning \"Deprecated\"\n", " | This method is now deprecated; use `model_copy` instead.\n", " |\n", " | If you need `include` or `exclude`, use:\n", " |\n", " | ```python {test=\"skip\" lint=\"skip\"}\n", " | data = self.model_dump(include=include, exclude=exclude, round_trip=True)\n", " | data = {**data, **(update or {})}\n", " | copied = self.model_validate(data)\n", " | ```\n", " |\n", " | Args:\n", " | include: Optional set or mapping specifying which fields to include in the copied model.\n", " | exclude: Optional set or mapping specifying which fields to exclude in the copied model.\n", " | update: Optional dictionary of field-value pairs to override field values in the copied model.\n", " | deep: If True, the values of fields that are Pydantic models will be deep-copied.\n", " |\n", " | Returns:\n", " | A copy of the model with included, excluded and updated fields as specified.\n", " |\n", " | dict(\n", " | self,\n", " | *,\n", " | include: 'IncEx | None' = None,\n", " | exclude: 'IncEx | None' = None,\n", " | by_alias: 'bool' = False,\n", " | exclude_unset: 'bool' = False,\n", " | exclude_defaults: 'bool' = False,\n", " | exclude_none: 'bool' = False\n", " | ) -> 'Dict[str, Any]'\n", " |\n", " | json(\n", " | self,\n", " | *,\n", " | include: 'IncEx | None' = None,\n", " | exclude: 'IncEx | None' = None,\n", " | by_alias: 'bool' = False,\n", " | exclude_unset: 'bool' = False,\n", " | exclude_defaults: 'bool' = False,\n", " | exclude_none: 'bool' = False,\n", " | encoder: 'Callable[[Any], Any] | None' = PydanticUndefined,\n", " | models_as_dict: 'bool' = PydanticUndefined,\n", " | **dumps_kwargs: 'Any'\n", " | ) -> 'str'\n", " |\n", " | model_copy(\n", " | self,\n", " | *,\n", " | update: 'Mapping[str, Any] | None' = None,\n", " | deep: 'bool' = False\n", " | ) -> 'Self'\n", " | Usage docs: https://docs.pydantic.dev/2.10/concepts/serialization/#model_copy\n", " |\n", " | Returns a copy of the model.\n", " |\n", " | Args:\n", " | update: Values to change/add in the new model. Note: the data is not validated\n", " | before creating the new model. You should trust this data.\n", " | deep: Set to `True` to make a deep copy of the model.\n", " |\n", " | Returns:\n", " | New model instance.\n", " |\n", " | model_dump(\n", " | self,\n", " | *,\n", " | mode: \"Literal['json', 'python'] | str\" = 'python',\n", " | include: 'IncEx | None' = None,\n", " | exclude: 'IncEx | None' = None,\n", " | context: 'Any | None' = None,\n", " | by_alias: 'bool' = False,\n", " | exclude_unset: 'bool' = False,\n", " | exclude_defaults: 'bool' = False,\n", " | exclude_none: 'bool' = False,\n", " | round_trip: 'bool' = False,\n", " | warnings: \"bool | Literal['none', 'warn', 'error']\" = True,\n", " | serialize_as_any: 'bool' = False\n", " | ) -> 'dict[str, Any]'\n", " | Usage docs: https://docs.pydantic.dev/2.10/concepts/serialization/#modelmodel_dump\n", " |\n", " | Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.\n", " |\n", " | Args:\n", " | mode: The mode in which `to_python` should run.\n", " | If mode is 'json', the output will only contain JSON serializable types.\n", " | If mode is 'python', the output may contain non-JSON-serializable Python objects.\n", " | include: A set of fields to include in the output.\n", " | exclude: A set of fields to exclude from the output.\n", " | context: Additional context to pass to the serializer.\n", " | by_alias: Whether to use the field's alias in the dictionary key if defined.\n", " | exclude_unset: Whether to exclude fields that have not been explicitly set.\n", " | exclude_defaults: Whether to exclude fields that are set to their default value.\n", " | exclude_none: Whether to exclude fields that have a value of `None`.\n", " | round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].\n", " | warnings: How to handle serialization errors. False/\"none\" ignores them, True/\"warn\" logs errors,\n", " | \"error\" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError].\n", " | serialize_as_any: Whether to serialize fields with duck-typing serialization behavior.\n", " |\n", " | Returns:\n", " | A dictionary representation of the model.\n", " |\n", " | model_dump_json(\n", " | self,\n", " | *,\n", " | indent: 'int | None' = None,\n", " | include: 'IncEx | None' = None,\n", " | exclude: 'IncEx | None' = None,\n", " | context: 'Any | None' = None,\n", " | by_alias: 'bool' = False,\n", " | exclude_unset: 'bool' = False,\n", " | exclude_defaults: 'bool' = False,\n", " | exclude_none: 'bool' = False,\n", " | round_trip: 'bool' = False,\n", " | warnings: \"bool | Literal['none', 'warn', 'error']\" = True,\n", " | serialize_as_any: 'bool' = False\n", " | ) -> 'str'\n", " | Usage docs: https://docs.pydantic.dev/2.10/concepts/serialization/#modelmodel_dump_json\n", " |\n", " | Generates a JSON representation of the model using Pydantic's `to_json` method.\n", " |\n", " | Args:\n", " | indent: Indentation to use in the JSON output. If None is passed, the output will be compact.\n", " | include: Field(s) to include in the JSON output.\n", " | exclude: Field(s) to exclude from the JSON output.\n", " | context: Additional context to pass to the serializer.\n", " | by_alias: Whether to serialize using field aliases.\n", " | exclude_unset: Whether to exclude fields that have not been explicitly set.\n", " | exclude_defaults: Whether to exclude fields that are set to their default value.\n", " | exclude_none: Whether to exclude fields that have a value of `None`.\n", " | round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].\n", " | warnings: How to handle serialization errors. False/\"none\" ignores them, True/\"warn\" logs errors,\n", " | \"error\" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError].\n", " | serialize_as_any: Whether to serialize fields with duck-typing serialization behavior.\n", " |\n", " | Returns:\n", " | A JSON string representation of the model.\n", " |\n", " | model_post_init(self, _BaseModel__context: 'Any') -> 'None'\n", " | Override this method to perform additional initialization after `__init__` and `model_construct`.\n", " | This is useful if you want to do some validation that requires the entire model to be initialized.\n", " |\n", " | ----------------------------------------------------------------------\n", " | Class methods inherited from pydantic.main.BaseModel:\n", " |\n", " | __class_getitem__(typevar_values: 'type[Any] | tuple[type[Any], ...]') -> 'type[BaseModel] | _forward_ref.PydanticRecursiveRef'\n", " |\n", " | __get_pydantic_core_schema__(\n", " | source: 'type[BaseModel]',\n", " | handler: 'GetCoreSchemaHandler',\n", " | /\n", " | ) -> 'CoreSchema'\n", " | Hook into generating the model's CoreSchema.\n", " |\n", " | Args:\n", " | source: The class we are generating a schema for.\n", " | This will generally be the same as the `cls` argument if this is a classmethod.\n", " | handler: A callable that calls into Pydantic's internal CoreSchema generation logic.\n", " |\n", " | Returns:\n", " | A `pydantic-core` `CoreSchema`.\n", " |\n", " | __get_pydantic_json_schema__(\n", " | core_schema: 'CoreSchema',\n", " | handler: 'GetJsonSchemaHandler',\n", " | /\n", " | ) -> 'JsonSchemaValue'\n", " | Hook into generating the model's JSON schema.\n", " |\n", " | Args:\n", " | core_schema: A `pydantic-core` CoreSchema.\n", " | You can ignore this argument and call the handler with a new CoreSchema,\n", " | wrap this CoreSchema (`{'type': 'nullable', 'schema': current_schema}`),\n", " | or just call the handler with the original schema.\n", " | handler: Call into Pydantic's internal JSON schema generation.\n", " | This will raise a `pydantic.errors.PydanticInvalidForJsonSchema` if JSON schema\n", " | generation fails.\n", " | Since this gets called by `BaseModel.model_json_schema` you can override the\n", " | `schema_generator` argument to that function to change JSON schema generation globally\n", " | for a type.\n", " |\n", " | Returns:\n", " | A JSON schema, as a Python object.\n", " |\n", " | __pydantic_init_subclass__(**kwargs: 'Any') -> 'None'\n", " | This is intended to behave just like `__init_subclass__`, but is called by `ModelMetaclass`\n", " | only after the class is actually fully initialized. In particular, attributes like `model_fields` will\n", " | be present when this is called.\n", " |\n", " | This is necessary because `__init_subclass__` will always be called by `type.__new__`,\n", " | and it would require a prohibitively large refactor to the `ModelMetaclass` to ensure that\n", " | `type.__new__` was called in such a manner that the class would already be sufficiently initialized.\n", " |\n", " | This will receive the same `kwargs` that would be passed to the standard `__init_subclass__`, namely,\n", " | any kwargs passed to the class definition that aren't used internally by pydantic.\n", " |\n", " | Args:\n", " | **kwargs: Any keyword arguments passed to the class definition that aren't used internally\n", " | by pydantic.\n", " |\n", " | construct(_fields_set: 'set[str] | None' = None, **values: 'Any') -> 'Self'\n", " |\n", " | from_orm(obj: 'Any') -> 'Self'\n", " |\n", " | model_construct(_fields_set: 'set[str] | None' = None, **values: 'Any') -> 'Self'\n", " | Creates a new instance of the `Model` class with validated data.\n", " |\n", " | Creates a new model setting `__dict__` and `__pydantic_fields_set__` from trusted or pre-validated data.\n", " | Default values are respected, but no other validation is performed.\n", " |\n", " | !!! note\n", " | `model_construct()` generally respects the `model_config.extra` setting on the provided model.\n", " | That is, if `model_config.extra == 'allow'`, then all extra passed values are added to the model instance's `__dict__`\n", " | and `__pydantic_extra__` fields. If `model_config.extra == 'ignore'` (the default), then all extra passed values are ignored.\n", " | Because no validation is performed with a call to `model_construct()`, having `model_config.extra == 'forbid'` does not result in\n", " | an error if extra values are passed, but they will be ignored.\n", " |\n", " | Args:\n", " | _fields_set: A set of field names that were originally explicitly set during instantiation. If provided,\n", " | this is directly used for the [`model_fields_set`][pydantic.BaseModel.model_fields_set] attribute.\n", " | Otherwise, the field names from the `values` argument will be used.\n", " | values: Trusted or pre-validated data dictionary.\n", " |\n", " | Returns:\n", " | A new instance of the `Model` class with validated data.\n", " |\n", " | model_json_schema(\n", " | by_alias: 'bool' = True,\n", " | ref_template: 'str' = '#/$defs/{model}',\n", " | schema_generator: 'type[GenerateJsonSchema]' = ,\n", " | mode: 'JsonSchemaMode' = 'validation'\n", " | ) -> 'dict[str, Any]'\n", " | Generates a JSON schema for a model class.\n", " |\n", " | Args:\n", " | by_alias: Whether to use attribute aliases or not.\n", " | ref_template: The reference template.\n", " | schema_generator: To override the logic used to generate the JSON schema, as a subclass of\n", " | `GenerateJsonSchema` with your desired modifications\n", " | mode: The mode in which to generate the schema.\n", " |\n", " | Returns:\n", " | The JSON schema for the given model class.\n", " |\n", " | model_parametrized_name(params: 'tuple[type[Any], ...]') -> 'str'\n", " | Compute the class name for parametrizations of generic classes.\n", " |\n", " | This method can be overridden to achieve a custom naming scheme for generic BaseModels.\n", " |\n", " | Args:\n", " | params: Tuple of types of the class. Given a generic class\n", " | `Model` with 2 type variables and a concrete model `Model[str, int]`,\n", " | the value `(str, int)` would be passed to `params`.\n", " |\n", " | Returns:\n", " | String representing the new class where `params` are passed to `cls` as type variables.\n", " |\n", " | Raises:\n", " | TypeError: Raised when trying to generate concrete names for non-generic models.\n", " |\n", " | model_rebuild(\n", " | *,\n", " | force: 'bool' = False,\n", " | raise_errors: 'bool' = True,\n", " | _parent_namespace_depth: 'int' = 2,\n", " | _types_namespace: 'MappingNamespace | None' = None\n", " | ) -> 'bool | None'\n", " | Try to rebuild the pydantic-core schema for the model.\n", " |\n", " | This may be necessary when one of the annotations is a ForwardRef which could not be resolved during\n", " | the initial attempt to build the schema, and automatic rebuilding fails.\n", " |\n", " | Args:\n", " | force: Whether to force the rebuilding of the model schema, defaults to `False`.\n", " | raise_errors: Whether to raise errors, defaults to `True`.\n", " | _parent_namespace_depth: The depth level of the parent namespace, defaults to 2.\n", " | _types_namespace: The types namespace, defaults to `None`.\n", " |\n", " | Returns:\n", " | Returns `None` if the schema is already \"complete\" and rebuilding was not required.\n", " | If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`.\n", " |\n", " | model_validate(\n", " | obj: 'Any',\n", " | *,\n", " | strict: 'bool | None' = None,\n", " | from_attributes: 'bool | None' = None,\n", " | context: 'Any | None' = None\n", " | ) -> 'Self'\n", " | Validate a pydantic model instance.\n", " |\n", " | Args:\n", " | obj: The object to validate.\n", " | strict: Whether to enforce types strictly.\n", " | from_attributes: Whether to extract data from object attributes.\n", " | context: Additional context to pass to the validator.\n", " |\n", " | Raises:\n", " | ValidationError: If the object could not be validated.\n", " |\n", " | Returns:\n", " | The validated model instance.\n", " |\n", " | model_validate_json(\n", " | json_data: 'str | bytes | bytearray',\n", " | *,\n", " | strict: 'bool | None' = None,\n", " | context: 'Any | None' = None\n", " | ) -> 'Self'\n", " | Usage docs: https://docs.pydantic.dev/2.10/concepts/json/#json-parsing\n", " |\n", " | Validate the given JSON data against the Pydantic model.\n", " |\n", " | Args:\n", " | json_data: The JSON data to validate.\n", " | strict: Whether to enforce types strictly.\n", " | context: Extra variables to pass to the validator.\n", " |\n", " | Returns:\n", " | The validated Pydantic model.\n", " |\n", " | Raises:\n", " | ValidationError: If `json_data` is not a JSON string or the object could not be validated.\n", " |\n", " | model_validate_strings(\n", " | obj: 'Any',\n", " | *,\n", " | strict: 'bool | None' = None,\n", " | context: 'Any | None' = None\n", " | ) -> 'Self'\n", " | Validate the given object with string data against the Pydantic model.\n", " |\n", " | Args:\n", " | obj: The object containing string data to validate.\n", " | strict: Whether to enforce types strictly.\n", " | context: Extra variables to pass to the validator.\n", " |\n", " | Returns:\n", " | The validated Pydantic model.\n", " |\n", " | parse_file(\n", " | path: 'str | Path',\n", " | *,\n", " | content_type: 'str | None' = None,\n", " | encoding: 'str' = 'utf8',\n", " | proto: 'DeprecatedParseProtocol | None' = None,\n", " | allow_pickle: 'bool' = False\n", " | ) -> 'Self'\n", " |\n", " | parse_obj(obj: 'Any') -> 'Self'\n", " |\n", " | parse_raw(\n", " | b: 'str | bytes',\n", " | *,\n", " | content_type: 'str | None' = None,\n", " | encoding: 'str' = 'utf8',\n", " | proto: 'DeprecatedParseProtocol | None' = None,\n", " | allow_pickle: 'bool' = False\n", " | ) -> 'Self'\n", " |\n", " | schema(by_alias: 'bool' = True, ref_template: 'str' = '#/$defs/{model}') -> 'Dict[str, Any]'\n", " |\n", " | schema_json(\n", " | *,\n", " | by_alias: 'bool' = True,\n", " | ref_template: 'str' = '#/$defs/{model}',\n", " | **dumps_kwargs: 'Any'\n", " | ) -> 'str'\n", " |\n", " | update_forward_refs(**localns: 'Any') -> 'None'\n", " |\n", " | validate(value: 'Any') -> 'Self'\n", " |\n", " | ----------------------------------------------------------------------\n", " | Readonly properties inherited from pydantic.main.BaseModel:\n", " |\n", " | __fields_set__\n", " |\n", " | model_computed_fields\n", " | Get metadata about the computed fields defined on the model.\n", " |\n", " | Deprecation warning: you should be getting this information from the model class, not from an instance.\n", " | In V3, this property will be removed from the `BaseModel` class.\n", " |\n", " | Returns:\n", " | A mapping of computed field names to [`ComputedFieldInfo`][pydantic.fields.ComputedFieldInfo] objects.\n", " |\n", " | model_extra\n", " | Get extra fields set during validation.\n", " |\n", " | Returns:\n", " | A dictionary of extra fields, or `None` if `config.extra` is not set to `\"allow\"`.\n", " |\n", " | model_fields\n", " | Get metadata about the fields defined on the model.\n", " |\n", " | Deprecation warning: you should be getting this information from the model class, not from an instance.\n", " | In V3, this property will be removed from the `BaseModel` class.\n", " |\n", " | Returns:\n", " | A mapping of field names to [`FieldInfo`][pydantic.fields.FieldInfo] objects.\n", " |\n", " | model_fields_set\n", " | Returns the set of fields that have been explicitly set on this model instance.\n", " |\n", " | Returns:\n", " | A set of strings representing the fields that have been set,\n", " | i.e. that were not filled from defaults.\n", " |\n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from pydantic.main.BaseModel:\n", " |\n", " | __dict__\n", " | dictionary for instance variables\n", " |\n", " | __pydantic_extra__\n", " |\n", " | __pydantic_fields_set__\n", " |\n", " | __pydantic_private__\n", " |\n", " | ----------------------------------------------------------------------\n", " | Data and other attributes inherited from pydantic.main.BaseModel:\n", " |\n", " | __hash__ = None\n", " |\n", " | __pydantic_root_model__ = False\n", "\n" ] } ], "source": [ "help(CMIP6Context)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Note \n", "You can also use a standard Python dictionary using the same fields as keys. However the `CMIP6Context` class provides a more user-friendly way to interact with the data, including automatic checking of the fields.\n", "\n", "Intermediate solution consist in using a dictionary to provide the fields, and then convert it to a `CMIP6Context` object:\n", "```\n", "my_dict = {\n", " 'experiment_id': 'historical',\n", " 'variable_id': 'tas',\n", " 'table_id': 'Amon',\n", " ...\n", "}\n", "cmip6_context = CMIP6Context(**my_dict)\n", "```\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once your context is correctly defined, you can check which simulations are available according to the filters you set in the context. " ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
projectinstitutesourceexperimentensembletablevariablegrid_labeldatanodedcpp_init_yearversiondomainproduct
0CMIPCMCCCMCC-CM2-SR5historicalr1i1p1f1Amontasgngs://cmip6/CMIP6/CMIP/CMCC/CMCC-CM2-SR5/histor...NaN20200616GLOBALoutput
1CMIPCMCCCMCC-CM2-SR5historicalr1i1p1f1Amonprgngs://cmip6/CMIP6/CMIP/CMCC/CMCC-CM2-SR5/histor...NaN20200616GLOBALoutput
2ScenarioMIPCMCCCMCC-CM2-SR5ssp126r1i1p1f1Amontasgngs://cmip6/CMIP6/ScenarioMIP/CMCC/CMCC-CM2-SR5...NaN20200717GLOBALoutput
3ScenarioMIPCMCCCMCC-CM2-SR5ssp126r1i1p1f1Amonprgngs://cmip6/CMIP6/ScenarioMIP/CMCC/CMCC-CM2-SR5...NaN20200717GLOBALoutput
4CMIPCMCCCMCC-ESM2historicalr1i1p1f1Amontasgngs://cmip6/CMIP6/CMIP/CMCC/CMCC-ESM2/historica...NaN20210114GLOBALoutput
5CMIPCMCCCMCC-ESM2historicalr1i1p1f1Amonprgngs://cmip6/CMIP6/CMIP/CMCC/CMCC-ESM2/historica...NaN20210114GLOBALoutput
6ScenarioMIPCMCCCMCC-ESM2ssp126r1i1p1f1Amonprgngs://cmip6/CMIP6/ScenarioMIP/CMCC/CMCC-ESM2/ss...NaN20210126GLOBALoutput
7ScenarioMIPCMCCCMCC-ESM2ssp126r1i1p1f1Amontasgngs://cmip6/CMIP6/ScenarioMIP/CMCC/CMCC-ESM2/ss...NaN20210126GLOBALoutput
\n", "
" ], "text/plain": [ " project institute source experiment ensemble table variable \\\n", "0 CMIP CMCC CMCC-CM2-SR5 historical r1i1p1f1 Amon tas \n", "1 CMIP CMCC CMCC-CM2-SR5 historical r1i1p1f1 Amon pr \n", "2 ScenarioMIP CMCC CMCC-CM2-SR5 ssp126 r1i1p1f1 Amon tas \n", "3 ScenarioMIP CMCC CMCC-CM2-SR5 ssp126 r1i1p1f1 Amon pr \n", "4 CMIP CMCC CMCC-ESM2 historical r1i1p1f1 Amon tas \n", "5 CMIP CMCC CMCC-ESM2 historical r1i1p1f1 Amon pr \n", "6 ScenarioMIP CMCC CMCC-ESM2 ssp126 r1i1p1f1 Amon pr \n", "7 ScenarioMIP CMCC CMCC-ESM2 ssp126 r1i1p1f1 Amon tas \n", "\n", " grid_label datanode \\\n", "0 gn gs://cmip6/CMIP6/CMIP/CMCC/CMCC-CM2-SR5/histor... \n", "1 gn gs://cmip6/CMIP6/CMIP/CMCC/CMCC-CM2-SR5/histor... \n", "2 gn gs://cmip6/CMIP6/ScenarioMIP/CMCC/CMCC-CM2-SR5... \n", "3 gn gs://cmip6/CMIP6/ScenarioMIP/CMCC/CMCC-CM2-SR5... \n", "4 gn gs://cmip6/CMIP6/CMIP/CMCC/CMCC-ESM2/historica... \n", "5 gn gs://cmip6/CMIP6/CMIP/CMCC/CMCC-ESM2/historica... \n", "6 gn gs://cmip6/CMIP6/ScenarioMIP/CMCC/CMCC-ESM2/ss... \n", "7 gn gs://cmip6/CMIP6/ScenarioMIP/CMCC/CMCC-ESM2/ss... \n", "\n", " dcpp_init_year version domain product \n", "0 NaN 20200616 GLOBAL output \n", "1 NaN 20200616 GLOBAL output \n", "2 NaN 20200717 GLOBAL output \n", "3 NaN 20200717 GLOBAL output \n", "4 NaN 20210114 GLOBAL output \n", "5 NaN 20210114 GLOBAL output \n", "6 NaN 20210126 GLOBAL output \n", "7 NaN 20210126 GLOBAL output " ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cmip6_simulations = cmip6_context.list_available_simulations()\n", "cmip6_simulations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CORDEX simulations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, you can use the `CORDEXContext` class to request CORDEX simulations available on `ESGF` nodes.\n", "\n", "To know more about CORDEX domains, you can check the [CORDEX domains website](https://cordex.org/domains/) to see to which domain your area of interest belongs." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To help you with the search fields, you can have a look on the `ESGF` search page, e.g. : https://esgf-node.ipsl.upmc.fr/search/cordex-ipsl/ ." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'project': ['CORDEX'],\n", " 'product': ['output'],\n", " 'domain': ['AUS-44'],\n", " 'institute': None,\n", " 'driving_model': None,\n", " 'experiment': ['rcp26', 'historical'],\n", " 'experiment_family': None,\n", " 'ensemble': ['r1i1p1'],\n", " 'rcm_name': None,\n", " 'rcm_version': None,\n", " 'frequency': ,\n", " 'variable': ['tas', 'tasmin', 'tasmax', 'pr'],\n", " 'variable_long_name': None}" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cordex_context = CORDEXContext(\n", " domain = \"AUS-44\",\n", " experiment = [\"rcp26\", \"historical\"],\n", " ensemble = \"r1i1p1\",\n", " frequency = Frequency.MONTHLY,\n", " variable = [\"tas\", \"tasmin\", \"tasmax\", \"pr\"],\n", ")\n", "cordex_context.model_dump()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'project': 'CORDEX',\n", " 'product': 'output',\n", " 'domain': 'AUS-44',\n", " 'institute': None,\n", " 'driving_model': None,\n", " 'experiment': ['rcp26', 'historical'],\n", " 'experiment_family': None,\n", " 'ensemble': 'r1i1p1',\n", " 'rcm_model': None,\n", " 'downscaling_realisation': None,\n", " 'time_frequency': 'mon',\n", " 'variable': ['tas', 'tasmin', 'tasmax', 'pr'],\n", " 'variable_long_name': None}" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cordex_context.model_dump()" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "ename": "ConnectionRefusedError", "evalue": "[Errno 61] Connection refused", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mConnectionRefusedError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[11], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m cordex_simulations \u001b[38;5;241m=\u001b[39m \u001b[43mcordex_context\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlist_available_simulations\u001b[49m\u001b[43m(\u001b[49m\u001b[43mesgf_credential\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m../../config/esgf_credential.yaml\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2\u001b[0m cordex_simulations\n", "File \u001b[0;32m~/Documents/Modeles/Codes/DownClim/src/downclim/dataset/cordex.py:224\u001b[0m, in \u001b[0;36mCORDEXContext.list_available_simulations\u001b[0;34m(self, esgf_credential, server)\u001b[0m\n\u001b[1;32m 221\u001b[0m context \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmodel_dump()\n\u001b[1;32m 223\u001b[0m \u001b[38;5;66;03m# esgf connection\u001b[39;00m\n\u001b[0;32m--> 224\u001b[0m conn \u001b[38;5;241m=\u001b[39m \u001b[43mconnect_to_esgf\u001b[49m\u001b[43m(\u001b[49m\u001b[43mesgf_credential\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mserver\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 225\u001b[0m \u001b[38;5;66;03m# list CORDEX datasets matching context\u001b[39;00m\n\u001b[1;32m 226\u001b[0m cordex_simulations \u001b[38;5;241m=\u001b[39m inspect_cordex(context\u001b[38;5;241m=\u001b[39mcontext, connector\u001b[38;5;241m=\u001b[39mconn)\n", "File \u001b[0;32m~/Documents/Modeles/Codes/DownClim/src/downclim/dataset/connectors.py:84\u001b[0m, in \u001b[0;36mconnect_to_esgf\u001b[0;34m(esgf_credential, server)\u001b[0m\n\u001b[1;32m 82\u001b[0m creds \u001b[38;5;241m=\u001b[39m yaml\u001b[38;5;241m.\u001b[39msafe_load(stream)\n\u001b[1;32m 83\u001b[0m lm \u001b[38;5;241m=\u001b[39m LogonManager()\n\u001b[0;32m---> 84\u001b[0m \u001b[43mlm\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlogon_with_openid\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 85\u001b[0m \u001b[43m \u001b[49m\u001b[43mopenid\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcreds\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mopenid\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 86\u001b[0m \u001b[43m \u001b[49m\u001b[43mpassword\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcreds\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mpassword\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 87\u001b[0m \u001b[43m \u001b[49m\u001b[43minteractive\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 88\u001b[0m \u001b[43m \u001b[49m\u001b[43mbootstrap\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 89\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 91\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m SearchConnection(server, distrib\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n", "File \u001b[0;32m~/miniconda3/envs/downclim/lib/python3.13/site-packages/pyesgf/logon.py:147\u001b[0m, in \u001b[0;36mLogonManager.logon_with_openid\u001b[0;34m(self, openid, password, bootstrap, update_trustroots, interactive)\u001b[0m\n\u001b[1;32m 136\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 137\u001b[0m \u001b[38;5;124;03mObtains ESGF credentials by detecting the MyProxy parameters from\u001b[39;00m\n\u001b[1;32m 138\u001b[0m \u001b[38;5;124;03mthe users OpenID. Some ESGF compatible OpenIDs do not contain enough\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 144\u001b[0m \u001b[38;5;124;03m ``interactive``, ``bootstrap`` and ``update_trustroots``.\u001b[39;00m\n\u001b[1;32m 145\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 146\u001b[0m username, myproxy \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_get_logon_details(openid)\n\u001b[0;32m--> 147\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlogon\u001b[49m\u001b[43m(\u001b[49m\u001b[43musername\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpassword\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmyproxy\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 148\u001b[0m \u001b[43m \u001b[49m\u001b[43mbootstrap\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbootstrap\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 149\u001b[0m \u001b[43m \u001b[49m\u001b[43mupdate_trustroots\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mupdate_trustroots\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 150\u001b[0m \u001b[43m \u001b[49m\u001b[43minteractive\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minteractive\u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/miniconda3/envs/downclim/lib/python3.13/site-packages/pyesgf/logon.py:184\u001b[0m, in \u001b[0;36mLogonManager.logon\u001b[0;34m(self, username, password, hostname, bootstrap, update_trustroots, interactive)\u001b[0m\n\u001b[1;32m 180\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m OpenidResolutionError(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mFull logon details not available\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 182\u001b[0m c \u001b[38;5;241m=\u001b[39m MyProxyClient(hostname\u001b[38;5;241m=\u001b[39mhostname, caCertDir\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mesgf_certs_dir)\n\u001b[0;32m--> 184\u001b[0m creds \u001b[38;5;241m=\u001b[39m \u001b[43mc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlogon\u001b[49m\u001b[43m(\u001b[49m\u001b[43musername\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpassword\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 185\u001b[0m \u001b[43m \u001b[49m\u001b[43mbootstrap\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbootstrap\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 186\u001b[0m \u001b[43m \u001b[49m\u001b[43mupdateTrustRoots\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mupdate_trustroots\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 187\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mopen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mesgf_credentials, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mwb\u001b[39m\u001b[38;5;124m'\u001b[39m) \u001b[38;5;28;01mas\u001b[39;00m fh:\n\u001b[1;32m 188\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m cred \u001b[38;5;129;01min\u001b[39;00m creds:\n", "File \u001b[0;32m~/miniconda3/envs/downclim/lib/python3.13/site-packages/myproxy/client/__init__.py:1453\u001b[0m, in \u001b[0;36mMyProxyClient.logon\u001b[0;34m(self, username, passphrase, credname, lifetime, keyPair, certReq, nBitsForKey, bootstrap, updateTrustRoots, authnGetTrustRootsCall, sslCertFile, sslKeyFile, sslKeyFilePassphrase)\u001b[0m\n\u001b[1;32m 1450\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1451\u001b[0m getTrustRootsKw \u001b[38;5;241m=\u001b[39m {}\n\u001b[0;32m-> 1453\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgetTrustRoots\u001b[49m\u001b[43m(\u001b[49m\u001b[43mwriteToCACertDir\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 1454\u001b[0m \u001b[43m \u001b[49m\u001b[43mbootstrap\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbootstrap\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1455\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mgetTrustRootsKw\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1457\u001b[0m lifetime \u001b[38;5;241m=\u001b[39m lifetime \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mproxyCertLifetime\n\u001b[1;32m 1459\u001b[0m \u001b[38;5;66;03m# Basic sanity check on username to avoid overhead on server\u001b[39;00m\n", "File \u001b[0;32m~/miniconda3/envs/downclim/lib/python3.13/site-packages/myproxy/client/__init__.py:1609\u001b[0m, in \u001b[0;36mMyProxyClient.getTrustRoots\u001b[0;34m(self, username, passphrase, writeToCACertDir, bootstrap)\u001b[0m\n\u001b[1;32m 1607\u001b[0m \u001b[38;5;66;03m# Set-up SSL connection\u001b[39;00m\n\u001b[1;32m 1608\u001b[0m conn \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_initConnection(verifyPeerWithTrustRoots\u001b[38;5;241m=\u001b[39m(\u001b[38;5;129;01mnot\u001b[39;00m bootstrap))\n\u001b[0;32m-> 1609\u001b[0m \u001b[43mconn\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhostname\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mport\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1611\u001b[0m \u001b[38;5;66;03m# send globus compatibility stuff\u001b[39;00m\n\u001b[1;32m 1612\u001b[0m conn\u001b[38;5;241m.\u001b[39mwrite(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39mGLOBUS_INIT_MSG)\n", "File \u001b[0;32m~/miniconda3/envs/downclim/lib/python3.13/site-packages/OpenSSL/SSL.py:2390\u001b[0m, in \u001b[0;36mConnection.connect\u001b[0;34m(self, addr)\u001b[0m\n\u001b[1;32m 2381\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 2382\u001b[0m \u001b[38;5;124;03mCall the :meth:`connect` method of the underlying socket and set up SSL\u001b[39;00m\n\u001b[1;32m 2383\u001b[0m \u001b[38;5;124;03mon the socket, using the :class:`Context` object supplied to this\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 2387\u001b[0m \u001b[38;5;124;03m:return: What the socket's connect method returns\u001b[39;00m\n\u001b[1;32m 2388\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 2389\u001b[0m _lib\u001b[38;5;241m.\u001b[39mSSL_set_connect_state(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_ssl)\n\u001b[0;32m-> 2390\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_socket\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mconnect\u001b[49m\u001b[43m(\u001b[49m\u001b[43maddr\u001b[49m\u001b[43m)\u001b[49m\n", "\u001b[0;31mConnectionRefusedError\u001b[0m: [Errno 61] Connection refused" ] } ], "source": [ "cordex_simulations = cordex_context.list_available_simulations(esgf_credential=\"../../config/esgf_credential.yaml\")\n", "cordex_simulations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This request returns no result. \n", "\n", "
\n", "Note \n", "Actually, there are `CORDEX` simulations matching all the requirements except the \"experiment\" one : there is no set with both 'rcp26' and 'historical' experiments.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Save your requested simulations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You now have two `DataFrames` containing the information about the simulations you requested. \n", "\n", "Of course, now you can manually remove any simulations you are not interested in.\n", "\n", "Finally, you can save them to a `csv` file to keep track of your request. This will be useful to process downloading and downscaling using `Downclim` later on." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "save_simulations_list(\n", " cordex_simulations = cordex_simulations,\n", " cmip6_simulations = cmip6_simulations,\n", " output_file = \"simulations_list.csv\"\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "downclim", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.2" } }, "nbformat": 4, "nbformat_minor": 2 }