Source code for species.core.species_init

"""
Module for setting up species in the working folder.
"""

import json
import socket
import urllib.request

from configparser import ConfigParser
from os import environ
from pathlib import Path, PosixPath, WindowsPath

import h5py

from beartype import beartype
from beartype.typing import Optional, Union

from .._version import __version__, __version_tuple__


[docs] class SpeciesInit: """ Class for initiating species by creating the database and configuration file in case they are not present in the working folder, and creating the data folder for storage of input data. """ @beartype def __init__( self, config_file: Optional[Union[str, PosixPath, WindowsPath]] = None, database_file: Optional[Union[str, PosixPath, WindowsPath]] = None, ) -> None: """ Parameters ---------- config_file : str, PosixPath, WindowsPath, None Path to the configuration file that is stored as `species_config.ini`. Setting the argument enables reading a configuration file at a different path than the current working directory. The default location (i.e. the working folder of your script or notebook) is used by setting the argument to ``None``. database_file : str, PosixPath, WindowsPath, None Path to the HDF5 database that is stored as `species_database.hdf5`. Setting the argument will overwrite the database path in the configuration file. The path from the configuration file is used if the argument of ``database_file`` is set to ``None``. Returns ------- NoneType None """ print("=======\nspecies\n=======") # Check if there is a new version available species_version = ( f"{__version_tuple__[0]}." f"{__version_tuple__[1]}." f"{__version_tuple__[2]}" ) try: pypi_url = "https://pypi.org/pypi/species/json" with urllib.request.urlopen(pypi_url, timeout=1.0) as open_url: url_content = open_url.read() url_data = json.loads(url_content) pypi_version = url_data["info"]["version"] except (urllib.error.URLError, socket.timeout): pypi_version = None if pypi_version is not None: pypi_split = pypi_version.split(".") current_split = species_version.split(".") new_major = (pypi_split[0] == current_split[0]) & ( pypi_split[1] > current_split[1] ) new_minor = ( (pypi_split[0] == current_split[0]) & (pypi_split[1] == current_split[1]) & (pypi_split[2] > current_split[2]) ) if new_major | new_minor: print(f"\n-> species v{pypi_version} is available!") print(f"\nVersion: {__version__}") working_folder = Path.cwd() print(f"Working folder: {working_folder}") if config_file is None: config_file = working_folder / "species_config.ini" elif isinstance(config_file, str): config_file = Path(config_file) environ["SPECIES_CONFIG"] = str(config_file) config = ConfigParser(allow_no_value=True) if config_file.exists(): print(f"\nConfiguration file: {config_file}") else: print("\nCreating species_config.ini...", end="", flush=True) config.add_section("species") # config.set('species', '; File with the HDF5 database') config.set("species", "database", "species_database.hdf5") # config.set('species', '; File with the HDF5 database') config.set("species", "data_folder", "./data/") # config.set('species', '; File with the HDF5 database') config.set("species", "vega_mag", "0.03") with open(config_file, "w", encoding="utf-8") as file_obj: config.write(file_obj) print(" [DONE]") config.read(config_file) config_update = False if database_file is None: if "database" in config["species"]: database_file = Path(config["species"]["database"]) else: database_file = Path("./species_database.hdf5") config.set("species", "database", "species_database.hdf5") config_update = True else: if isinstance(database_file, str): config.set("species", "database", database_file) database_file = Path(database_file) else: config.set("species", "database", str(database_file)) config_update = True if "data_folder" in config["species"]: data_folder = Path(config["species"]["data_folder"]) else: data_folder = Path("./data/") config.set("species", "data_folder", "./data/") config_update = True if "vega_mag" in config["species"]: vega_mag = config["species"]["vega_mag"] else: vega_mag = 0.03 config.set("species", "vega_mag", "0.03") config_update = True if config_update: # If condition is needed because the file should # not be opened when using MPI and the config # file is already present and no need to update with open(config_file, "w", encoding="utf-8") as file_obj: config.write(file_obj) if database_file.exists(): print(f"Database file: {database_file}") else: print("Creating species_database.hdf5...", end="", flush=True) h5_file = h5py.File(database_file, "w") h5_file.close() print(" [DONE]") try: from mpi4py import MPI mpi_rank = MPI.COMM_WORLD.Get_rank() MPI.COMM_WORLD.Barrier() except ImportError: mpi_rank = 0 # Add samples to the database if mpi_rank == 0: with h5py.File(database_file, "a") as hdf5_file: if "configuration" in hdf5_file: del hdf5_file["configuration"] config_group = hdf5_file.create_group("configuration") config_group.attrs["config_file"] = str(config_file) config_group.attrs["database_file"] = str(database_file) config_group.attrs["data_folder"] = str(data_folder) if data_folder.exists(): print(f"Data folder: {data_folder}") else: print("Creating data folder...", end="", flush=True) data_folder.mkdir() print(" [DONE]") print("\nConfiguration settings:") print(f" - Database: {database_file}") print(f" - Data folder: {data_folder}") print(f" - Magnitude of Vega: {vega_mag}") try: from mpi4py import MPI # Rank of this process in a communicator mpi_rank = MPI.COMM_WORLD.Get_rank() # Number of processes in a communicator mpi_size = MPI.COMM_WORLD.Get_size() print("\nMultiprocessing: mpi4py installed") print(f"Process number {mpi_rank+1:d} out of {mpi_size:d}...") except ImportError: print("\nMultiprocessing: mpi4py not installed")