def _read_data(self): """Read data needed by this Reference Frame for calculating positions of sites Delegates to _read_data_<self.version> to read the actual data. Returns: Dict: Dictionary containing data about each site defined in this reference frame. """ trf = Configuration("trf_custom") trf.profiles = config.analysis.get("tech", value=self.version, default="").list trf_path = files.path("trf-custom") trf_local_path = files.path("trf-custom_local") trf.update_from_file(trf_path) dependencies.add(trf_path, label="trf") if trf_local_path.exists(): trf.update_from_file(trf_local_path) dependencies.add(trf_local_path, label="trf") data = dict() for section in trf.sections: info = { k: v for k, v in section.as_dict().items() if not k == "pos_itrs" } info["pos"] = np.array(section.pos_itrs.list, dtype=float) data[section.name] = info return data
def get_paths_with_label(file_path: Union[str, pathlib.Path], label_pattern: str) -> List[pathlib.Path]: """Find all paths with the given label Args: file_path: Path to dependency file. label_pattern: String with label or regular expression (e.g. 'gnss_rinex_nav_[MGE]' or 'gnss_rinex_nav_.'). Returns: List: List of file paths. """ label_re = re.compile( f"^{label_pattern}$") # ^ and $ is used to match the whole string # Make sure dependency file exists file_path = pathlib.Path(file_path) if not file_path.exists(): log.debug(f"Dependency file {file_path} does not exist") return [] # Find dependencies with the given label dependencies = Configuration.read_from_file("dependencies", file_path) paths = list() for file_path in dependencies.section_names: label = dependencies[file_path].label.str if label_re.match(label): paths.append(pathlib.Path(file_path)) return paths
def changed(file_path: Union[str, pathlib.Path], fast_check: bool = True) -> bool: """Check if the dependencies have changed Returns True if any of the files listed in the dependency file have changed, or if the dependency file itself does not exist. Args: file_path: Path to dependency file. fast_check: Fast check uses timestamps, slow check uses md5 checksums. Returns: True if any file has changed or if the dependecy file does not exist, False otherwise. """ # Make sure dependency file exists file_path = pathlib.Path(file_path) if not file_path.exists(): log.debug(f"Dependency file {file_path} does not exist") return True # Check if any dependencies have changed dependencies = Configuration.read_from_file("dependencies", file_path) for file_path in dependencies.section_names: previous_checksum = dependencies[file_path].checksum.str current_checksum = _file_info(file_path, fast_check=fast_check)["checksum"] if current_checksum != previous_checksum: log.debug( f"Dependency {file_path} changed from {previous_checksum} to {current_checksum}" ) return True return False
def update_tech_config(rundate, pipeline, **kwargs): file_vars = create_file_vars(rundate, pipeline, **kwargs) cfg_path = files.config.directory.replace( **file_vars).path / files.config.filename.replace(**file_vars).path with Configuration.update_on_file(cfg_path) as cfg: yield cfg
def changed(fast_check=True, **dep_vars): """Check if the dependencies of a model run have changed Returns True if any of the files in the dependency file have changed, or if the dependency file does not exist. Args: dep_vars: Variables specifying the model_run_depends-file. Returns: Boolean: True if any file has changed or if the dependecy file does not exist. """ # Make sure dependency file exists dependency_path = files.path("model_run_depends", file_vars=dep_vars) if not dependency_path.exists(): log.debug(f"Dependency file {dependency_path} does not exist") return True # Check if any dependencies have changed dependencies = Configuration.read_from_file("dependencies", dependency_path) for file_path in dependencies.section_names: previous_checksum = dependencies[file_path].checksum.str current_checksum = _file_info(file_path, fast_check=fast_check)["checksum"] if current_checksum != previous_checksum: log.debug(f"Dependency {file_path} changed from {previous_checksum} to {current_checksum}") return True return False
def _write(write_as_crash=True): """Write dependencies to file This function is called either when starting a new list of dependencies (with a call to `init`) or when the program exits (including with an error). If `write_as_crash` is True, a special dependency is stored that will force `changed` to return True. This will in particular make sure that a stage is rerun if it crashed the previous time it ran. Args: write_as_crash (Boolean): Whether to note that the current dependendee crashed. """ # Ignore dependency if no dependency variables are available (init_dependecies has not been called) if not _DEPENDENCY_FILE_VARS: return # Store timestamp of crash, this will also force the current stage to be rerun next time if write_as_crash: _CURRENT_DEPENDENCIES["CRASHED"] = _file_info("CRASHED", True, checksum="CRASHED") # No need to open and close files if there are no dependencies to store if not _CURRENT_DEPENDENCIES: return # Open dependency file or start from a fresh dictionary dependency_path = files.path("model_run_depends", file_vars=_DEPENDENCY_FILE_VARS) dependencies = Configuration.read_from_file("dependecies", dependency_path) # Update dependency information for file_path, info in _CURRENT_DEPENDENCIES.items(): dependencies.update_from_dict(info, section=file_path) _CURRENT_DEPENDENCIES.clear() # Write to dependency file dependencies.write_to_file(dependency_path)
def timestamps(rundate, pipeline, **kwargs): file_vars = create_file_vars(rundate, pipeline, **kwargs) ts_path = files.timestamp.directory.replace(**file_vars).path / files.timestamp.filename.replace(**file_vars).path cfg = Configuration.read_from_file("timestamps", ts_path) if "timestamps" in cfg.sections: return cfg.timestamps.as_dict() else: return dict()
def read_files_config(**path_vars): """Read Files-configuration""" files.clear() for file_path in config_paths("files", **path_vars): files.update_from_file(file_path, interpolate=False) set_file_vars() def read_there_config(**path_vars): """Read There-configuration""" there.clear() for file_path in config_paths("there", **path_vars): there.update_from_file(file_path, interpolate=True, case_sensitive=True) there.master_section = "general" # Add configurations as module variables where = Configuration("where") read_where_config() files = FileConfiguration("files") read_files_config() there = Configuration("there") read_there_config() analysis = Configuration("analysis") # Initialized by config.init later tech = Configuration("tech") # Initialized by config.init later tech.fallback_config = where
class Constant: _constants = Configuration("constant") def __init__(self) -> None: # Read constants from file package, _, name = __name__.rpartition(".") with importlib_resources.path(package, f"{name}.txt") as path: self.update_from_file(path) # Set default source self._source = "default" def update_from_file(self, file_path): """Update list of constants from file""" self._constants.update_from_file(file_path, case_sensitive=True) @property def source(self): return self._source def get(self, constant: str, source: str = None) -> float: """Get the value of one constant Note that if you need the default value of the constant (from the default source) it is typically better to read it as a property. That is, `constant.c` is preferred to `constant.get('c')`. Args: constant: Name of the constant. source: Source from which the constant is defined. Returns: Value of constant. """ source = self.source if source is None else source try: return self._constants[constant][source].float except exceptions.MissingSectionError: raise exceptions.UnknownConstantError( f"Constant {constant!r} is not defined in {', '.join(self._constants.sources)}" ) from None except exceptions.MissingEntryError: raise exceptions.UnknownConstantError( f"Constant {constant!r} is not defined by source {source!r} in {', '.join(self._constants.sources)}" ) from None def unit(self, constant: str) -> str: """Unit of constant""" try: return self._constants[constant].__unit__.str except exceptions.MissingSectionError: raise exceptions.UnknownConstantError( f"Constant {constant!r} is not defined in {', '.join(self._constants.sources)}" ) from None except exceptions.MissingEntryError: raise exceptions.UnitError( f"Constant {constant!r} has not defined a unit in {', '.join(self._constants.sources)}" ) from None @contextmanager def use_source(self, source: str) -> None: """Context manager for handling different sources Example: >>> constant.GM 398600441800000.0 >>> with constant.use_source("de430"): ... print(constant.GM) ... 398600435436000.0 Args: source: Name of source of constant. """ previous_source = self.source self._source = source try: yield None finally: self._source = previous_source def __getattr__(self, constant: str) -> float: """Get constant as an attribute with dot-notation""" if constant in self._constants.section_names: try: return self._constants[constant][self.source].float except exceptions.MissingEntryError: raise exceptions.UnknownConstantError( f"Constant {constant!r} is not defined by source {self.source!r} in " f"{', '.join(self._constants.sources)}") from None # Raise error for unknown attributes else: raise AttributeError( f"Constant {constant!r} is not defined in {', '.join(self._constants.sources)}" ) from None def __dir__(self) -> List[str]: """List all constants""" return super().__dir__() + list(self._constants.section_names) def __repr__(self): return f"{type(self).__name__}({', '.join(self._constants.sources)!r})"
for file_path in config_paths("files", **path_vars): files.update_from_file(file_path, interpolate=False) set_file_vars() def read_there_config(**path_vars): """Read There-configuration""" there.clear() for file_path in config_paths("there", **path_vars): there.update_from_file(file_path, interpolate=True, case_sensitive=True) there.master_section = "general" # Add configurations as module variables where = Configuration("where") read_where_config() files = FileConfiguration("files") read_files_config() there = Configuration("there") read_there_config() program = Configuration("program") # Initialized by config.init later analysis = Configuration("analysis") # Initialized by config.init later tech = Configuration("tech") # Initialized by config.init later tech.fallback_config = where session = Configuration("session")
where.master_section = "all" # Files-configuration files.clear() for file_path in config_paths("files"): files.update_from_file(file_path, interpolate=False) set_file_vars() # There-configuration there.clear() for file_path in config_paths("there"): there.update_from_file(file_path, interpolate=True, case_sensitive=True) there.master_section = "general" # Analysis, Tech and Session-configurations are initialised by config.init later analysis.clear() tech.clear() tech.fallback_config = where session.clear() # Add configurations as module variables where = Configuration("where") files = Configuration("files") program = Configuration("program") analysis = Configuration("analysis") tech = Configuration("tech") session = Configuration("session") there = Configuration("there") reset_config()