Skip to content

astra_process

Classes¤

AstraProcess ¤

AstraProcess(
    working_dir="",
    distribution_file="generator.in",
    run_file="photo_track.in",
    log_dir="log",
    log_file_name="log.log",
    run_number=None,
)

Bases: Core

Source code in common/astra_process.py
def __init__(self, working_dir="", distribution_file="generator.in", run_file="photo_track.in", log_dir="log", log_file_name="log.log", run_number=None) -> None:
    super().__init__(working_dir, distribution_file, run_file, log_dir, log_file_name)

    # Set run_number as a property, either take from the argument given or load from run_file
    c = adjust_settings.ChangeSettings(self.run_file)
    if run_number is not None:
        self.run_number = run_number
        self.set_run_number(run_number)
    else:
        self.run_number = int(c.read_setting("RUN"))

    # ASTRA programmes
    self.astra_program = self.working_dir.joinpath("Astra.exe")
    self.generator_program = self.working_dir.joinpath("generator.exe")
    self.fieldplot_program = self.working_dir.joinpath("fieldplot.exe")
    self.lineplot_program = self.working_dir.joinpath("lineplot.exe")

    self.perform_checks()

Functions¤

_find_parameter_definition_file ¤
_find_parameter_definition_file(parameter)

Method to find whether the parameter is defined in the self.run_file or in the self.distribution file

Parameters:

Name Type Description Default
parameter str

Parameter, whose definition file is to be found.

required

Returns:

Type Description
Path

pathlib.Path: pathlib.Path to the definition file

Source code in common/astra_process.py
def _find_parameter_definition_file(self, parameter:str) -> pathlib.Path:
    """Method to find whether the parameter is defined in the self.run_file or in
    the self.distribution file

    Args:
        parameter (str): Parameter, whose definition file is to be found.   

    Returns:
        pathlib.Path: pathlib.Path to the definition file
    """        
    # try to find it in the  run_file, if not succesful (c.find_setting returns None), try distribution_file
    c = adjust_settings.ChangeSettings(self.run_file)
    if c.find_setting(parameter) is None:
        c = adjust_settings.ChangeSettings(self.distribution_file)
        return self.distribution_file
    # this is to check if neither the parameter is neither in the run nor in the distribution file
    if c.find_setting(parameter) is None:
        self.logger.warning()(f"Parameter {parameter} was not found in the run nor the distribution file.")
        return None
    return self.run_file
change_parameter ¤
change_parameter(parameter, new_value)

Method to change a parameter in the input files.

Parameters:

Name Type Description Default
file (str, path)

Input file with the parameter.

required
parameter str

Parameter in the input file to be changed.

required
new_value (str, int, float)

New value of the parameter to be set.

required
Source code in common/astra_process.py
def change_parameter(self, parameter, new_value):
    """Method to change a parameter in the input files.

    Args:
        file (str, path): Input file with the parameter.
        parameter (str): Parameter in the input file to be changed.
        new_value (str, int, float): New value of the parameter to be set.
    """
    # skip if parameter is None
    if str(parameter).lower().strip() == "none":
        return

    # get the file where the parameter is defined
    parameter_file = self._find_parameter_definition_file(parameter)
    if parameter_file is None:
        self.logger.warning(f"Parameter {parameter} was not changes because it was not found.")
        return

    # changing the parameter
    c = adjust_settings.ChangeSettings(parameter_file)
    c.update(parameter, str(new_value))

    self.logger.info(
        f"Updated parameter {parameter} to: {new_value} in {c.file}.")
get_parameter_value ¤
get_parameter_value(parameter)

Method to get the value of the parameter.

Parameters:

Name Type Description Default
parameter str

Parameter, whose value is to be found.

required

Returns:

Name Type Description
str str

Value of the parameter (if found).

Source code in common/astra_process.py
def get_parameter_value(self, parameter: str) -> str:
    """Method to get the value of the parameter.

    Args:
        parameter (str): Parameter, whose value is to be found.

    Returns:
        str: Value of the parameter (if found).
    """
    # get the file where the parameter is defined        
    parameter_file = self._find_parameter_definition_file(parameter)
    # if not found, return None
    if parameter_file is None:
        return None
    else:
        # read the setting and return it
        c = adjust_settings.ChangeSettings(parameter_file)
        return c.read_setting(parameter)
increase_run_number ¤
increase_run_number()

Method to increase the run number.

Source code in common/astra_process.py
def increase_run_number(self):
    """Method to increase the run number.
    """
    c = adjust_settings.ChangeSettings(self.run_file)
    c.update("RUN", self.run_number+1)
    self.run_number += 1

    self.logger.info(f"Run number increased to {self.run_number}.")
log_input_file ¤
log_input_file(file_to_log)

Method to log file to log directory.

Parameters:

Name Type Description Default
file (str, path)

File to be logged.

required
Source code in common/astra_process.py
def log_input_file(self, file_to_log):
    """Method to log file to log directory.

    Args:
        file (str, path): File to be logged.
    """
    backed_input_file = self.log_dir.joinpath(file_to_log.name)
    # create filelock for save copy
    file_to_log_lock = self.acquire_fileLock(file_to_log)
    backed_input_file_lock = self.acquire_fileLock(backed_input_file)
    with file_to_log_lock:
        with backed_input_file_lock:
            self.logger.info(
                f"Logging input file {file_to_log.name} to {backed_input_file}.")

            # TODO: check if the file does not already exist -> prevent rewriting the file
            shutil.copy(file_to_log, backed_input_file)
perform_checks ¤
perform_checks()

Method to check if all ASTRA process can be run.

Raises:

Type Description
Exception

ASTRA programs are missing in the directory.

Exception

ASTRA and GENERATOR input files missing in the directory.

Source code in common/astra_process.py
def perform_checks(self) -> None:
    """Method to check if all ASTRA process can be run.

    Raises:
        Exception: ASTRA programs are missing in the directory.
        Exception: ASTRA and GENERATOR input files missing in the directory.
    """
    self.logger.debug("Running checks.")
    # check if ASTRA files exist
    for f in [self.astra_program, self.generator_program, self.fieldplot_program, self.lineplot_program]:
        if not f.is_file():
            raise Exception(
                f"Astra files are missing in the directory {self.working_dir}")

    # check if input files exist
    for f in [self.distribution_file, self.run_file]:
        if not f.is_file():
            raise Exception(
                f"Input files are missing in the directory {self.working_dir}")
    self.logger.debug("All checks completed - SUCCESS.")
run_astra ¤
run_astra(shell=True)

Runs the ASTRA programme on the run file.

Parameters:

Name Type Description Default
shell bool

If True, ASTRA console output will be logged. Defaults to True.

True
Source code in common/astra_process.py
def run_astra(self, shell=True) -> None:
    """Runs the ASTRA programme on the run file.

    Args:
        shell (bool, optional): If True, ASTRA console output will be logged. Defaults to True.
    """
    self.logger.info(
        f"(RUN {self.run_number}) Running astra with input file: {self.run_file}")

    self.log_input_file(self.run_file)
    p = subprocess.Popen([self.astra_program, self.run_file.stem], shell=shell,
                         stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=self.working_dir)
    # b to make it a bitlike object
    process_output, _ = p.communicate(input=b'\n')

    # log subprocess output
    for line in process_output.split(b"\n"):
        self.logger.info(line)
    self.logger.info(f"(RUN {self.run_number}) Astra run completed.")
run_generator ¤
run_generator(shell=True)

Runs the GENERATOR programme on the generator file.

Parameters:

Name Type Description Default
shell bool

If True, GENERATOR console output will be logged. Defaults to True.

True
Source code in common/astra_process.py
def run_generator(self, shell=True) -> None:
    """Runs the GENERATOR programme on the generator file. 

    Args:
        shell (bool, optional): If True, GENERATOR console output will be logged. Defaults to True.
    """

    self.logger.info(
        f"(RUN {self.run_number}) Running generator with input file: {self.distribution_file}")

    self.log_input_file(self.distribution_file)
    p = subprocess.Popen([self.generator_program, self.distribution_file.stem],
                         shell=shell, stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=self.working_dir)
    # b to make it a bitlike object
    process_output, _ = p.communicate(input=b'\n')

    # log subprocess output
    for line in process_output.split(b"\n"):
        self.logger.info(line)
    self.logger.info(f"(RUN {self.run_number}) Generator run completed.")
set_run_number ¤
set_run_number(new_run_number)

Method to set the run number to the new_run_number.

Parameters:

Name Type Description Default
new_run_number (str, int)

New run number to be set.

required
Source code in common/astra_process.py
def set_run_number(self, new_run_number):
    """Method to set the run number to the new_run_number.

    Args:
        new_run_number (str, int): New run number to be set.
    """
    c = adjust_settings.ChangeSettings(self.run_file)
    c.update("RUN", new_run_number)
    self.run_number = new_run_number

    self.logger.info(f"Run number set to {new_run_number}.")

Last update: October 31, 2023
Created: October 31, 2023