Skip to content

Commit

Permalink
Merge pull request #151 from molssi-seamm/dev
Browse files Browse the repository at this point in the history
Extending and cleaning up handling of configurations
  • Loading branch information
seamm committed Oct 30, 2023
2 parents c78271c + c922d57 commit e11e98a
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 46 deletions.
6 changes: 6 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
=======
History
=======
2023.10.30 -- Extending and cleaning up handling of configurations
* Added ability to name systems and configurations with the IUPAC name, InChI, or
InChIKey of the configuration.
* Generally cleanedup and streamlined the code handling new systems and
configurations.

2023.9.26.1 -- Bugfix: system naming
* Fixed a bug with keeping the current name when updating a system.

Expand Down
40 changes: 20 additions & 20 deletions seamm/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ def set_gui_data(self, key, value, gui=None):
def get_system_configuration(
self,
P=None,
same_as=None,
same_as="current",
first=True,
**kwargs,
):
Expand All @@ -473,12 +473,12 @@ def get_system_configuration(
Parameters
----------
P : dict(str, any) = None
The diction of options and values. If none, the default system and
The dictionary of options and values. If none, the default system and
configuration are returned as-is.
same_as : _Configuration = None
same_as : _Configuration = "current""
Share atoms, bonds, or cell with this configuration, depending
on other flags. Defaults to None, which results in using the current
configuration
on other flags. Defaults to "current", which results in using the current
configuration. If None, an empty configuration is created/used
first : bool = True
First configuration of several, which can have different handling than
the subsequent ones.
Expand All @@ -491,12 +491,18 @@ def get_system_configuration(
# Get the system
system_db = self.get_variable("_system_db")

system = system_db.system
if system is None:
configuration = None
else:
configuration = system.configuration
if same_as == "current":
same_as = configuration

if P is None:
# Just return the current system and configuration, creating if needed.
system = system_db.system
if system is None:
system = system_db.create_system()
configuration = system.configuration
if configuration is None:
configuration = system.create_configuration()
else:
Expand All @@ -515,34 +521,28 @@ def get_system_configuration(
handling = "Create a new configuration"

if handling == "Overwrite the current configuration":
system = system_db.system
if system is None:
system = system_db.create_system()
configuration = system.configuration
if configuration is None:
configuration = system.create_configuration()
elif handling == "Create a new configuration":
system = system_db.system
if system is None:
system = system_db.create_system()
# See if sharing atoms, bonds and/or cell
if same_as is None:
current = system.configuration
if current is None:
configuration = system.create_configuration()
else:
configuration = system.copy_configuration(
current, make_current=True
)
configuration = system.create_configuration()
else:
configuration = system.copy_configuration(
configuration=same_as, make_current=True
)
elif handling == "Create a new system and configuration":
system = system_db.create_system()
configuration = system.copy_configuration(
configuration=same_as, make_current=True
)
if same_as is None:
configuration = system.create_configuration()
else:
configuration = system.copy_configuration(
configuration=same_as, make_current=True
)
else:
raise ValueError(
f"Do not understand how to handle the structure: '{handling}'"
Expand Down
27 changes: 26 additions & 1 deletion seamm/run_flowchart.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,32 @@ def run_from_jobserver():
db_path = sys.argv[3]
cmdline = sys.argv[4:]

run(job_id=job_id, wdir=wdir, db_path=db_path, in_jobserver=True, cmdline=cmdline)
with cd(wdir):
try:
run(
job_id=job_id,
wdir=wdir,
db_path=db_path,
in_jobserver=True,
cmdline=cmdline,
)
except Exception as e:
path = Path("job_data.json")
if path.exists():
with path.open("r") as fd:
fd.readline()
data = json.load(fd)
else:
data = {}

data["state"] = "error"
data["error type"] = type(e).__name__
data["error message"] = traceback.format_exc()
with path.open("w") as fd:
fd.write("!MolSSI job_data 1.0")
json.dump(data, fd, indent=3, sort_keys=True)
fd.write("\n")
raise


def run(
Expand Down
185 changes: 160 additions & 25 deletions seamm/standard_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
"keep current name",
"use SMILES string",
"use Canonical SMILES string",
"use IUPAC name",
"use InChI",
"use InChIKey",
),
"format_string": "s",
"description": "System name:",
Expand All @@ -70,6 +73,9 @@
"keep current name",
"use SMILES string",
"use Canonical SMILES string",
"use IUPAC name",
"use InChI",
"use InChIKey",
),
"format_string": "s",
"description": "Configuration name:",
Expand All @@ -78,7 +84,7 @@
}


def structure_handling_description(P):
def structure_handling_description(P, **kwargs):
"""Return a standard description for how the structure will be handled.
Parameters
Expand Down Expand Up @@ -106,28 +112,43 @@ def structure_handling_description(P):
raise ValueError(f"Do not understand how to handle the structure: '{handling}'")

sysname = P["system name"]
if sysname == "use SMILES string":
text += " The name of the system will be the SMILES string given."
if sysname == "keep current name":
text += " The name of the system will not be changed."
elif sysname == "use SMILES string":
text += " The name of the system will be its SMILES."
elif sysname == "use Canonical SMILES string":
text += " The name of the system will be the canonical SMILES of the structure."
text += " The name of the system will be its canonical SMILES."
elif sysname == "use IUPAC name":
text += " The name of the system will be its IUPAC name."
elif sysname == "use InChI":
text += " The name of the system will be its InChI."
elif sysname == "use InChIKey":
text += " The name of the system will be its InChIKey."
else:
text += f" The name of the system will be {sysname}."
tmp = safe_format(sysname, **kwargs)
text += f" The name of the system will be '{tmp}'."

confname = P["configuration name"]
if confname == "use SMILES string":
text += " The name of the configuration will be the SMILES string given."
if confname == "keep current name":
text += " The name of the configuration will not be changed."
elif confname == "use SMILES string":
text += " The name of the configuration will be its SMILES."
elif confname == "use Canonical SMILES string":
text += (
" The name of the configuration will be the canonical SMILES of the "
"structure."
)
text += " The name of the configuration will be its canonical SMILES."
elif confname == "use IUPAC name":
text += " The name of the configuration will be its IUPAC name."
elif confname == "use InChI":
text += " The name of the configuration will be its InChI."
elif confname == "use InChIKey":
text += " The name of the configuration will be its InChIKey."
else:
text += f" The name of the configuration will be {confname}."
tmp = safe_format(confname, **kwargs)
text += f" The name of the configuration will be '{tmp}'."

return text


def multiple_structure_handling_description(P):
def multiple_structure_handling_description(P, **kwargs):
"""Return a standard description for how the new structures will be handled.
Parameters
Expand All @@ -148,9 +169,9 @@ def multiple_structure_handling_description(P):
if handling == "Overwrite the current configuration":
text += "overwrite the current configuration."
elif handling == "Create a new configuration":
text += "created as a new configuration of the current system."
text += "be added as a new configuration of the current system."
elif handling == "Create a new system and configuration":
text += "created in a new system and configuration."
text += "be added as a new system and configuration."
else:
raise ValueError(f"Do not understand how to handle the structure: '{handling}'")

Expand All @@ -164,22 +185,136 @@ def multiple_structure_handling_description(P):
raise ValueError(f"Do not understand how to handle the structure: '{handling}'")

sysname = P["system name"]
if sysname == "use SMILES string":
text += " The name of the system will be the SMILES string given."
if sysname == "keep current name":
text += " The name of the system will not be changed."
elif sysname == "use SMILES string":
text += " The name of the system will be its SMILES."
elif sysname == "use Canonical SMILES string":
text += " The name of the system will be the canonical SMILES of the structure."
text += " The name of the system will be its canonical SMILES."
elif sysname == "use IUPAC name":
text += " The name of the system will be its IUPAC name."
elif sysname == "use InChI":
text += " The name of the system will be its InChI."
elif sysname == "use InChIKey":
text += " The name of the system will be its InChIKey."
else:
text += f" The name of the system will be {sysname}."
tmp = safe_format(sysname, **kwargs)
text += f" The name of the system will be '{tmp}'."

confname = P["configuration name"]
if confname == "use SMILES string":
text += " The name of the configuration will be the SMILES string given."
if confname == "keep current name":
text += " The name of the configuration will not be changed."
elif confname == "use SMILES string":
text += " The name of the configuration will be its SMILES."
elif confname == "use Canonical SMILES string":
text += (
" The name of the configuration will be the canonical SMILES of the "
"structure."
text += " The name of the configuration will be its canonical SMILES."
elif confname == "use IUPAC name":
text += " The name of the configuration will be its IUPAC name."
elif confname == "use InChI":
text += " The name of the configuration will be its InChI."
elif confname == "use InChIKey":
text += " The name of the configuration will be its InChIKey."
else:
tmp = safe_format(confname, **kwargs)
text += f" The name of the configuration will be '{tmp}'."

return text


def set_names(system, configuration, P, _first=True, **kwargs):
"""Set the names of the system and configuration.
Parameters
----------
system : _System
The system being named
configuration : _Configuration
The configuration being named
P : dict(str, any)
The dictionary of parameter values, which must contain the standard structure
handling parameters.
_first : bool
Whether this is the first or a subseqnet structure.
kwargs : {str: str}
keyword arguments providing values that may be substituted in the names.
Returns
-------
str
The text for printing.
"""
sysname = P["system name"]
if sysname == "keep current name":
pass
elif sysname == "use SMILES string":
system.name = configuration.smiles
elif sysname == "use Canonical SMILES string":
system.name = configuration.canonical_smiles
elif sysname == "use IUPAC name":
system.name = configuration.PC_iupac_name(fallback=configuration.formula[0])
elif sysname == "use InChI":
system.name = configuration.inchi
elif sysname == "use InChIKey":
system.name = configuration.inchikey
else:
system.name = safe_format(sysname, **kwargs)

confname = P["configuration name"]
if confname == "keep current name":
pass
elif confname == "use SMILES string":
configuration.name = configuration.smiles
elif confname == "use Canonical SMILES string":
configuration.name = configuration.canonical_smiles
elif confname == "use IUPAC name":
configuration.name = configuration.PC_iupac_name(
fallback=configuration.formula[0]
)
elif confname == "use InChI":
configuration.name = configuration.inchi
elif confname == "use InChIKey":
configuration.name = configuration.inchikey
else:
configuration.name = safe_format(confname, **kwargs)

if _first:
text = "The first structure "

handling = P["structure handling"]
if handling == "Overwrite the current configuration":
text += "overwrote the current configuration, and was"
elif handling == "Create a new configuration":
text += "was added as a new configuration of the current system"
elif handling == "Create a new system and configuration":
text += "was added as a new system and configuration "
else:
raise ValueError(
f"Do not understand how to handle the structure: '{handling}'"
)
else:
text += f" The name of the configuration will be {confname}."
handling = P["subsequent structure handling"]
text = "This subsequent structure was "
if handling == "Create a new configuration":
text += "created as a new configuration of the current system"
elif handling == "Create a new system and configuration":
text += "created in a new system and configuration"
else:
raise ValueError(
f"Do not understand how to handle the structure: '{handling}'"
)

text += f" named '{system.name}' / '{configuration.name}'."
return text


def safe_format(s, *args, **kwargs):
while True:
try:
return s.format(*args, **kwargs)
except KeyError as e:
e = e.args[0]
kwargs[e] = "{%s}" % e

0 comments on commit e11e98a

Please sign in to comment.