Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR to verify disorders #63

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions scripts/multi_component_hydrogen_bond_propensity/ReadMe.md
Original file line number Diff line number Diff line change
@@ -47,6 +47,8 @@ optional arguments:
the directory of the desired coformer library
-f FAILURE_DIRECTORY, --failure_directory FAILURE_DIRECTORY
The location where the failures file should be generated
--force_run_disordered
Forces running the script on disordered entries. (NOT RECOMMENDED)
```

The default coformer library is the one supplied with your Mercury install
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@
import tempfile
import subprocess
import json
import warnings

import matplotlib

@@ -32,8 +33,6 @@
from ccdc.descriptors import CrystalDescriptors

try:
import warnings

with warnings.catch_warnings():
warnings.simplefilter("ignore", category=DeprecationWarning)
import docxtpl
@@ -314,14 +313,18 @@ def make_mc_report(identifier, results, directory, diagram_file, chart_file):
launch_word_processor(output_file)


def main(structure, work_directory, failure_directory, library, csdrefcode):
def main(structure, work_directory, failure_directory, library, csdrefcode, force_run):
# This loads up the CSD if a refcode is requested, otherwise loads the structural file supplied
if csdrefcode:
try:
crystal = io.CrystalReader('CSD').crystal(structure)
except RuntimeError:
print('Error! %s is not in the database!' % structure)
quit()
if io.CrystalReader('CSD').entry(structure).has_disorder and not force_run:
raise RuntimeError("Disorder can cause undefined behaviour. It is not advisable to run this "
"script on disordered entries.\n To force this script to run on disordered entries"
" use the flag --force_run_disordered.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are working on better disorder handling for structures already in the CSD so when that project is done this might need to be edited as it will be possible to run on one of the assemblies of the disordered molecule

Copy link
Contributor Author

@MilitaoLucas MilitaoLucas Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I looked into it and could not find on the documentation a way to do that. But if it is on the works that's nice. Will it automatically do it? Because if the script will have to be modified anyway after the fact, I don't see the problem in using this as a bandaid. Furthermore, someone could go on Mercury and create a mol2 without disorder for running. So I think this is a good solution for now. As having a warning is better than having weird errors pop up later. If it needs to be changed, it is trivial to get the file before this changes from git history.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already the option to do this for CIFs, with crystal.disordered_molecule, but not refcodes yet. It won't be automatic so it will still need a new edit but I agree that for now this works. Was just letting you know that at some point the handling of disorder will be better :)

else:
crystal = io.CrystalReader(structure)[0]

@@ -340,6 +343,11 @@ def main(structure, work_directory, failure_directory, library, csdrefcode):
# for each coformer in the library, make a pair file for the api/coformer and run a HBP calculation
for i, f in enumerate(coformer_files):
molecule_file, coformer_name = make_pair_file(api_molecule, tempdir, f, i + 1)
if not io.CrystalReader(f)[0].molecule.is_3d:
failure_warning = f"Could not run for {coformer_name} no 3d coordinates present."
failures.append(failure_warning)
warnings.warn(failure_warning)
continue
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not too sure about this one. We sometimes use the scripts on 2D structures when a crystal structure is not available. I see that it still runs but maybe we can have a flag to skip the warning and appending it to the error list. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will take a look. The main problem seems to be that I think it would be nice to have some file validation. I will close this PR, refactor a little my git history to make it so the improvements to error handling are in a separate commit and work on creating a better validation for files.

print(coformer_name)
crystal_reader = io.CrystalReader(molecule_file)
crystal = crystal_reader[0]
@@ -358,10 +366,11 @@ def main(structure, work_directory, failure_directory, library, csdrefcode):
tdata = get_mc_scores(propensities, crystal.identifier)
json.dump(tdata, file)
mc_dictionary[coformer_name] = get_mc_scores(propensities, crystal.identifier)
except RuntimeError:
except RuntimeError as error_message:
print("Propensity calculation failure for %s!" % coformer_name)
print(error_message)
mc_dictionary[coformer_name] = ["N/A", "N/A", "N/A", "N/A", "N/A", crystal.identifier]
failures.append(coformer_name)
failures.append(f"{coformer_name}: {error_message}")

# Make sense of the outputs of all the calculations
mc_hbp_screen = sorted(mc_dictionary.items(), key=lambda e: 0 if e[1][0] == 'N/A' else e[1][0], reverse=True)
@@ -411,6 +420,9 @@ def main(structure, work_directory, failure_directory, library, csdrefcode):
parser.add_argument('-f', '--failure_directory', type=str,
help='The location where the failures file should be generated')

parser.add_argument('--force_run_disordered', action="store_true",
help='Forces running the script on disordered entries. (NOT RECOMMENDED)', default=False)

args = parser.parse_args()
refcode = False
args.directory = os.path.abspath(args.directory)
@@ -424,4 +436,5 @@ def main(structure, work_directory, failure_directory, library, csdrefcode):
if not os.path.isdir(args.coformer_library):
parser.error('%s - library not found.' % args.coformer_library)

main(args.input_structure, args.directory, args.failure_directory, args.coformer_library, refcode)
main(args.input_structure, args.directory, args.failure_directory, args.coformer_library, refcode,
args.force_run_disordered)
Loading
Oops, something went wrong.