Public functions

This chapter gathers information about public functions that can be used in PLAMS scripts.

init(path=None, folder=None, config_settings=None, quiet=False, use_existing_folder=False)[source]

Initialize PLAMS environment. Set up the global config and its default JobManager.

This function only needs to be called to override default values on the global config, without interacting with it directly. For example, both of the following approaches are equivalent:

# Call to init
init(path="my/path", folder="my_folder", config_settings=my_settings)

# Direct modification of config
config.update(my_settings) # direct modification of config
config.default_jobmanager = JobManager(config.jobmanager, "my/path", "my_folder")

Note

A call to init() with no arguments is therefore a no-op, and is not required. It will however force initialisation of the lazy default JobManager. This is in contrast to AMS2024 and earlier versions, where this function had to be called before any other PLAMS command could be executed.

Parameters:
  • path (str | None) – for the default JobManager

  • folder (str | None) – for the default JobManager

  • use_existing_folder (bool) – for the default JobManager

  • config_settings (Dict | None) – Settings to update config with - these will overwrite any existing items

  • quiet (bool) – do not log header with information about the PLAMS environment

Return type:

None

finish(otherJM=None)[source]

Clean up the PLAMS environment. This can be explicitly called for Cleaning job folder to take place. If you used some other job managers than just the default one, they need to be passed as otherJM.

A call is registered to be performed at exit, which will perform cleaning for the default job manager.

Note

A call to finish() with no arguments once at the end of a script is therefore a no-op, and is not required. This is in contrast to AMS2024 and earlier versions, where this function had to be called at the end of a script for Cleaning job folder to take place.

Parameters:

otherJM (Iterable[JobManager] | None) – additional job managers used in a workflow to be cleaned

Return type:

None

load(filename)[source]

Load previously saved job from .dill file. This is just a shortcut for load_job() method of the default JobManager config.default_jobmanager.

Parameters:

filename (str) –

Return type:

Job | None

load_all(path, jobmanager=None)[source]

Load all jobs from path.

This function works as multiple executions of load_job(). It searches for .dill files inside the directory given by path, yet not directly in it, but one level deeper. In other words, all files matching path/*/*.dill are used. That way a path to the main working folder of a previously run script can be used to import all the jobs run by that script.

In case of partially failed MultiJob instances (some children jobs finished successfully, but not all) the function will search for .dill files in children folders. That means, if path/[multijobname]/ contains some subfolders (for children jobs) but does not contail a .dill file (the MultiJob was not fully successful), it will look into these subfolders. This behavior is recursive up to any folder tree depth.

The purpose of this function is to provide a quick way of restarting a script. Loading all successful jobs from the previous run prevents double work and allows the new execution of the script to proceed directly to the place where the previous execution failed.

Jobs are loaded using default job manager stored in config.default_jobmanager. If you wish to use a different one you can pass it as jobmanager argument of this function.

Returned value is a dictionary containing all loaded jobs as values and absolute paths to .dill files as keys.

Parameters:
Return type:

Dict[str, Job | JobDict]

read_molecules(folder, formats=None)[source]

Read all molecules from folder.

Read all the files present in folder with extensions compatible with Molecule.read. Returned value is a dictionary with keys being molecule names (filename without extension) and values being Molecule instances.

The optional argument formats can be used to narrow down the search to files with specified extensions:

molecules = read_molecules('mymols', formats=['xyz', 'pdb'])
Parameters:
Return type:

Dict[str, Molecule]

read_all_molecules_in_xyz_file(filename)[source]

The .xyz format allows to store multiple geometries on a single file (such file is essentially a concatenated series of xyz files)

This function returns a list of all molecules found in the file filename

filename: path (absolute or relative to the current working directory) to the xyz file.

Parameters:

filename (str) –

Return type:

List[Molecule]

Logging

PLAMS features a simple logging mechanism. All important actions happening in functions and methods register their activity using log messages. These massages can be printed to the standard output and/or saved to the logfile located in the main working folder.

Every log message has its “verbosity” defined as an integer number: the higher the number, the more detailed and descriptive the message is. In other words, it is a measure of importance of the message. Important events (like “job started”, “job finished”, “something went wrong”) should have low verbosity, whereas less crucial ones (for example “pickling of job X successful”) – higher verbosity. The purpose of that is to allow the user to choose how verbose the whole logfile is. Each log output (either file or stdout) has an integer number associated with it, defining which messages are printed to this channel (for example, if this number is 3, all messages with verbosity 3 or less are printed). That way using a smaller number results in the log being short and containing only the most relevant information while larger numbers produce longer and more detailed log messages.

The behavior of the logging mechanism is adjusted by config.log settings branch with the following keys:

  • file (integer) – verbosity of logs printed to the logfile in the main working folder.

  • stdout (integer) – verbosity of logs printed to the standard output.

  • time (boolean) – print time of each log event.

  • date (boolean) – print date of each log event.

Log messages used within the PLAMS code use four different levels of verbosity:

  • 1: important

  • 3: normal

  • 5: verbose

  • 7: debug

Even levels are left empty for the user. For example, if you find level 5 too verbose and still want to be able to switch on and off log messages of your own code, you can log them with verbosity 4.

Note

Your own code can (and should) contain some log() calls. They are very important for debugging purposes.

log(message, level=0)[source]

Log a message with verbosity level.

Logs are printed independently to the text logfile (a file called logfile in the main working folder) and to the standard output. If level is equal or lower than verbosity (defined by config.log.file or config.log.stdout) the message is printed. By convention in PLAMS, level should be between 0-7, with 0 indicating no logging and 7 indicating the most verbose logging. Date and/or time can be added based on config.log.date and config.log.time. All logging activity is thread safe.

Parameters:
  • message (str) –

  • level (int) –

Return type:

None

Binding decorators

Sometimes one wants to expand the functionality of a class by adding a new method or modifying an existing one. It can be done in a few different ways:

  • One can go directly to the source code defining the class and modify it there before running a script. Such a change is global – it affects all the future scripts, so in most cases it is not a good thing (for defining prerun(), for example).

  • Creating a subclass with new or modified method definitions is usually the best solution. It can be done directly in your script before the work is done. The newly defined class can be then used instead of the old one. However, this solution fails in some rare cases when a method needs to differ for different instances or when it needs to be changed during the runtime of the script.

  • PLAMS binding decorator add_to_instance() can be used.

Binding decorators associate methods to existing class instances without having to define a subclass. Such changes are visible only inside the script in which they are used.

The usage of the PLAMS add_to_instance() binding decorator is straightforward. You simply define a regular function somewhere inside your script and decorate it with add_to_instance(). The function needs to have a valid method syntax, so it should have self as the first argument and use it to reference the class instance.

add_to_instance(instance)[source]

Add decorated function as a method to one particular instance.

The decorated function should follow a method-like syntax, with the first argument self that references the class instance. Example usage:

results = myjob.run()

@add_to_instance(results)
def get_energy(self):
    return self.readkf('Energy', 'Bond Energy')

results.get_energy()

The added method is accessible only for that one particular instance and it overrides any methods with the same name defined on a class level (in original class’ source) or added with add_to_class() decorator.

If instance is an instance of Results or any of its subclasses, the added method will be wrapped with the thread safety guard (see Synchronization of parallel job executions).

Parameters:

instance (object) –

Return type:

Callable

Technical

The above decorator is in fact a decorator factory that, given an object (class or instance), produces a decorator that binds the function as a method of that object. The decorator is for adding instance methods only, it cannot be used for static or class methods.