Source code for bpf90tools.tools._airemlf90

#!/usr/bin/env python
# coding: utf-8

# Copyright (C) 2025-2026 Igor Loschinin.
# Distributed under the lgplv3 software license, see the accompanying
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.

__author__ = "Igor Loschinin (igor.loschinin@gmail.com)"
__all__ = ("AIremlf90", )

from pathlib import Path

from ._if90 import If90
from .settings import (
	AIREMLF90,
	RENF90_PAR,
	AIREMLF90_LOG
)
from ..utils import (
	run_app,
	CheckMixin,
	transform
)
from ..parsers import (
	PVar,
	Variance
)


[docs] class AIremlf90(If90, CheckMixin): """ A modification of REMLF90 with computing by the Average-Information Algorithm. For most problems, it converges in far fewer rounds than EM REML as implemented in REMLF90. While typically REMLF90 takes 50-300 rounds to converge, AIREMLF90 converges in 5-15 rounds and to a higher accuracy. For selected problems, AI REML fails to converge when the covariance matrix is close to non-positive definite. """ def __init__( self, *, app: str, work_dir: str | Path, fn_par: str | None = None ) -> None: """ :param app: - The name of the program :param work_dir: - Directory where all programs and files are located :param fn_par: - The name of the parameter file with settings """ If90.__init__(self, app=app, work_dir=work_dir, fn_par=fn_par) self.__parser = PVar()
[docs] def run(self) -> bool: """ Calculate variance the method aireml. :return: Returns true if the program started and ran without errors else false. :raise: Exceptions when files do not exist. """ if isinstance(self._work_dir, str): self._work_dir = Path(self._work_dir) if not self._work_dir.is_absolute(): self._work_dir = self._work_dir.absolute() if not self.is_dir(self._work_dir): raise OSError("Directory does not exist.") # Define file param if self._par_file is not None: _config = self._work_dir / self._par_file else: _config = self._work_dir / RENF90_PAR if not self.is_file(_config): raise OSError("File is not found. The first run renum!") # Run app if self._app != transform(AIREMLF90): raise ValueError(f"The program being run is not {self._app}.") _app_file = self._work_dir / self._app if not run_app(_app_file, _config, dir_cwd=self._work_dir): return False # Getting variance _file_log = self._work_dir / AIREMLF90_LOG if not self.is_file(_file_log): raise OSError("airemlf90.log file is not found.") if not self.__parser.parse_file(_file_log): return False return True
@property def variance(self) -> Variance | None: return self.__parser.values