Skip to content
Merged
Show file tree
Hide file tree
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
8 changes: 8 additions & 0 deletions scripts/ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ This folder contains scripts submitted by users or CCDC scientists for anyone to

- A short script to generate conformers with some rudimentary analysis for a single molecule.

## Conformer Filter Density

- A script to filter conformers based on a variety of torsion metrics.

## Create CASTEP Input

- Creates input files (`.cell` and `.param`) files for a given compound through Mercury.
Expand All @@ -19,6 +23,10 @@ This folder contains scripts submitted by users or CCDC scientists for anyone to

- Create GAUSSIAN input file (`.gjf`) for a given CSD refcode or `.mol2` file.

## Filter poses

- A script to filter docking poses based on torsion statistics

## Find Binding Conformation

- Generates idealized conformers for ligands and evaluates their RMSD to the conformation in the PDB.
Expand Down
36 changes: 36 additions & 0 deletions scripts/conformer_filter_density/ReadMe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Conformer Filter Density

Filter conformers using a variety of metrics described below.

A csv file will be produced with various points of analysis for unusual torsions. Optionally, files containing the
conformers which pass and fail within the limits can be written to files.

CCDC Python API Licence required, minimum version: 3.0.15

Script can be run with any multimolecule file e.g. sdf.
Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint] reported by reviewdog 🐶
MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]

Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint-fix] reported by reviewdog 🐶

Suggested change
Script can be run with any multimolecule file e.g. sdf.
Script can be run with any multimolecule file e.g. sdf.


## Instructions on Running

positional arguments: input molecule file

Input file (single- or multi-molecule file)

options:
* -h, --help; Show this help message and exit
Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint] reported by reviewdog 🐶
MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "* -h, --help; Show this help m..."]

Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint-fix] reported by reviewdog 🐶

Suggested change
* -h, --help; Show this help message and exit
* -h, --help; Show this help message and exit

* -m {absolute,relative}, --mode; Limit mode: absolute (fixed threshold) or relative (threshold based on
Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint] reported by reviewdog 🐶
MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]

molecule with fewest unusual torsions). WARNING: Relative mode may behave unexpectedly with conformers from
Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint] reported by reviewdog 🐶
MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]

Comment on lines +20 to +21
Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint-fix] reported by reviewdog 🐶

Suggested change
* -m {absolute,relative}, --mode; Limit mode: absolute (fixed threshold) or relative (threshold based on
molecule with fewest unusual torsions). WARNING: Relative mode may behave unexpectedly with conformers from
* -m {absolute,relative}, --mode; Limit mode: absolute (fixed threshold) or relative (threshold based on
molecule with fewest unusual torsions). WARNING: Relative mode may behave unexpectedly with conformers from

multiple input molecules (default: absolute)
* -l, --limit; Maximum number of unusual torsions for a passing molecule (default: 0)
* -d, --local-density; Local density threshold for classifying a torsion as unusual (default: 10.0)
* --incl-organometallics; Include organometallic compounds in the search (default: organic compounds only)
* --generalisation; Turn on generalisation for searches
* --successfn; Output file for molecules that pass the filter (default: successes.mol)
* --failurefn; Output file for molecules that fail the filter (default: failures.mol)
* -u, --unusual-torsions; Output CSV file for unusual torsion details (default: unusual_torsions.csv)


Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint] reported by reviewdog 🐶
MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2]

Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint-fix] reported by reviewdog 🐶

Suggested change

Originally created by Paul Sanschagrin
Updated by Chris Ringrose

For feedback or to report any issues please contact support@ccdc.cam.ac.uk

Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint-fix] reported by reviewdog 🐶

Suggested change

189 changes: 189 additions & 0 deletions scripts/conformer_filter_density/conformer_filter_density.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#!/usr/bin/env python3
#
# This script can be used for any purpose without limitation subject to the
# conditions at https://www.ccdc.cam.ac.uk/Community/Pages/Licences/v2.aspx
#
# This permission notice and the following statement of attribution must be
# included in all copies or substantial portions of this script.
#
# 2026-02-03: created by the Cambridge Crystallographic Data Centre

import argparse
import csv

from ccdc import conformer, io


def parse_args():
"""Parse command line arguments."""
parser = argparse.ArgumentParser(description=__doc__)

parser.add_argument('inmolfn',
metavar='<input molecule file>',
help='Input file (single- or multi-molecule file)')

parser.add_argument('-m', '--mode',
choices=['absolute', 'relative'],
default='absolute',
help='Limit mode: absolute (fixed threshold) or relative '
'(threshold based on molecule with fewest unusual torsions). '
'WARNING: Relative mode may behave unexpectedly with conformers '
'from multiple input molecules (default: %(default)s)')

parser.add_argument('-l', '--limit',
dest='torsion_limit',
type=int,
default=0,
metavar='<limit>',
help='Maximum number of unusual torsions for a passing molecule '
'(default: %(default)s)')

parser.add_argument('-d', '--local-density',
dest='local_density_threshold',
type=float,
default=10.0,
metavar='<threshold>',
help='Local density threshold for classifying a torsion as unusual '
'(default: %(default)s)')

parser.add_argument('--incl-organometallics',
dest='incl_organometallics',
action='store_true',
help='Include organometallic compounds in the search '
'(default: organic compounds only)')

parser.add_argument('--generalisation',
action='store_true',
help='Turn on generalisation for searches')

parser.add_argument('--successfn',
default='successes.mol',
metavar='<file>',
help='Output file for molecules that pass the filter '
'(default: %(default)s)')

parser.add_argument('--failurefn',
default='failures.mol',
metavar='<file>',
help='Output file for molecules that fail the filter '
'(default: %(default)s)')

parser.add_argument('-u', '--unusual-torsions',
dest='unusualtorsionsfn',
default='unusual_torsions.csv',
metavar='<file>',
help='Output CSV file for unusual torsion details '
'(default: %(default)s)')

return parser.parse_args()


def create_mogul_engine(local_density_threshold, incl_organometallics, generalisation):
"""Create and configure a geometry analyser engine.

Args:
local_density_threshold: Threshold for classifying torsions as unusual
incl_organometallics: Whether to include organometallic compounds
generalisation: Whether to enable generalisation for searches

Returns:
Configured ccdc.conformer.GeometryAnalyser instance
"""
engine = conformer.GeometryAnalyser()

engine.settings.bond.analyse = False
engine.settings.angle.analyse = False
engine.settings.ring.analyse = False

engine.settings.torsion.local_density_threshold = local_density_threshold
engine.settings.generalisation = generalisation
engine.settings.organometallic_filter = 'all' if incl_organometallics else 'organics_only'

return engine


def analysis(torsion_limit, input_filename, mode, engine, success_file, failure_file, unusual_torsion_file):
"""Analyze molecules for unusual torsions and filter based on criteria.

Args:
torsion_limit: Maximum number of unusual torsions allowed
input_filename: Path to input molecule file
mode: 'absolute' or 'relative' filtering mode
engine: Configured GeometryAnalyser instance
success_file: Path to output file for passing molecules
failure_file: Path to output file for failing molecules
unusual_torsion_file: Path to CSV file for unusual torsion details
"""
# Analyze all molecules and collect unusual torsion data
molecules = []
min_unusual_torsions = float('inf')

with io.MoleculeReader(input_filename) as mol_reader:
for molecule in mol_reader:
molecule.standardise_aromatic_bonds()
molecule.standardise_delocalised_bonds()

geometry_analysed_molecule = engine.analyse_molecule(molecule)

molecule.unusual_torsions = [
t for t in geometry_analysed_molecule.analysed_torsions
if t.unusual and t.enough_hits
]
molecule.num_unusual_torsions = len(molecule.unusual_torsions)
molecules.append(molecule)

min_unusual_torsions = min(min_unusual_torsions, molecule.num_unusual_torsions)

# Write results
with io.MoleculeWriter(success_file) as passed_writer, \
io.MoleculeWriter(failure_file) as failed_writer, \
open(unusual_torsion_file, 'w', newline='') as csv_file:

csv_writer = csv.writer(csv_file)
csv_writer.writerow(['MoleculeIndex', 'Value', 'Zscore', 'LocalDensity', 'NumHits', 'Atoms'])

for idx, molecule in enumerate(molecules):
threshold = torsion_limit if mode == 'absolute' else min_unusual_torsions + torsion_limit
failed = molecule.num_unusual_torsions > threshold

if failed:
failed_writer.write(molecule)
for torsion in molecule.unusual_torsions:
csv_writer.writerow([
idx,
torsion.value,
torsion.z_score,
torsion.local_density,
torsion.nhits,
' '.join(torsion.atom_labels)
])
else:
passed_writer.write(molecule)


def run():
"""Main entry point for the script."""
args = parse_args()

if args.torsion_limit < 0:
raise ValueError('Torsion limit must be >= 0')

engine = create_mogul_engine(
args.local_density_threshold,
args.incl_organometallics,
args.generalisation
)

analysis(
args.torsion_limit,
args.inmolfn,
args.mode,
engine,
args.successfn,
args.failurefn,
args.unusualtorsionsfn,
)


if __name__ == '__main__':
run()
23 changes: 23 additions & 0 deletions scripts/filter_poses/ReadMe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Filter Poses

This is a short script to filter molecular poses in a multi-molecule file based on the torsion probabilities.
Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint] reported by reviewdog 🐶
MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]

Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint-fix] reported by reviewdog 🐶

Suggested change
This is a short script to filter molecular poses in a multi-molecule file based on the torsion probabilities.
This is a short script to filter molecular poses in a multi-molecule file based on the torsion probabilities.

Information will be printed to screen, or can be saved to a csv file.

CCDC Python API Licence required, minimum version: 3.0.15

Script can be run with any multimolecule file e.g. sdf.

## Instructions on Running

positional arguments:
* input file; Input file (multi-molecule file).
Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint] reported by reviewdog 🐶
MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "* input file; Input file (mult..."]

Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint-fix] reported by reviewdog 🐶

Suggested change
* input file; Input file (multi-molecule file).
* input file; Input file (multi-molecule file).


options:
* -h, --help; Show this help message and exit.
Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint] reported by reviewdog 🐶
MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "* -h, --help; Show this help m..."]

Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint-fix] reported by reviewdog 🐶

Suggested change
* -h, --help; Show this help message and exit.
* -h, --help; Show this help message and exit.

* -csv, --write-csv; Write a csv file for all the analysed conformers.

Originally written by Jason Cole
Updated by Chris Ringrose

For feedback or to report any issues please contact support@ccdc.cam.ac.uk

Copy link
Contributor

Choose a reason for hiding this comment

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

[markdownlint-fix] reported by reviewdog 🐶

Suggested change

Loading