• RE: Jupyter notebook for CSD-python-API

    Hi Frank,

    it should be possible to install Jupyter notebook into the CSD's miniconda:

    /path/to/csd/miniconda/bin/conda install jupyter

    then you can run:


    Best wishes



  • RE: SMILES code of MOF sub-database

    HI Frank,

    can you give me a REFCODE where the SMILES fails?  In general the smiles property of a molecule will return None if there are unknown atoms or unknown bonds in the structure.

    Best wishes


  • RE: CSD Python API on Linux

    Good to hear.  Let me know if any other problems crop up.

    Best wishes


  • RE: CSD Python API on Linux

    Hi Tahereh,

    on a linux system you will need to set the environment variable CSDHOME to point to where you installed the CSD:

    export CSDHOME=/..../CSD_2018

    which will enable the API to find the CSD and other files in your installation.

    Sorry about the mistake in the second form.  It should read

    source /.../CSD_2018/Python_API_2018/miniconda/bin/activate

    which will set the default python, here called 'base'.  This should appear at the start of your prompt string as (base) followed by the rest of the prompt string.

    Best wishes


  • RE: CSD Python API on Linux

    Hi Tahereh,

    you can run the script directly by:

    /.../Python API/miniconda/bin/python2 script.py

    or you can activate the python:

    /.../Python API/miniconda/bin/activate

    then run:

    python script.py

    I hope this is helpful.  If not, please get back to me.

    Best wishes



  • RE: BFDH Morphology

    Dear Vijay,

    the BFDH morphology has been implemented in the API but is currently restricted to research partners of the CCDC.  Since I can see from your registration that you are at the University of Strathclyde, I am afraid that licensing restrictions mean that you will be unable to perform these calculations at the moment.

    I will discuss with my managers when it will be possible to release this feature to a wider public.

    Best wishes


  • RE: about Halogen bond search

    I think you may not be searching for exactly what you want.  You search  successively for HC Br, HC I, NC Br, etc.  The following script is how I would cast your problem:

    from ccdc import io, search
    csd = io.EntryReader('csd')
    crystal = csd.crystal('ISIJEZ01')

    poss_donors = ['C', 'c', 'N', 'O']
    poss_acceptors = ['Br', 'I']
    vdw_radius = {
        'Br' : 1.85,
        'I'  : 1.98,
        'N'  : 1.55,
        'n'  : 1.55,
        'O'  : 1.52,
        'o'  : 1.52,
        'C'  : 1.70,
        'c'  : 1.70,

    all_hits = []
    for d in poss_donors:
        for a in poss_acceptors:
            searcher = search.SubstructureSearch()
            searcher.add_substructure(search.SMARTSSubstructure(d + 'H'))
            searcher.add_distance_constraint('DIST1', (0, 1), (1, 0), (0.0, vdw_radius[a] + vdw_radius[d]), 'intermolecular', vdw_corrected=False)
            searcher.add_angle_constraint('ANG1', (0, 0), (0, 1), (1, 0), (120, 180))

    print '\n'.join(str(h.match_atoms()) for h in all_hits)

    [Atom(C1), Atom(H1), Atom(I1)]
    [Atom(C2), Atom(H2), Atom(I1)]
    [Atom(C3), Atom(H3), Atom(I1)]
    [Atom(C4), Atom(H4), Atom(I1A)]

    Note that the distance constraint is between the donated H and the acceptor, and the angle is D-H-A.  This finds four hits as shown above.
    You may prefer to use Van der Waals correction on the distance constraint, which will automatically take care of the element types involved in the match:

    searcher.add_distance_constraint('DIST1', (0, 1), (1, 0), (-5, 0), 'intermolecular', vdw_corrected=True)

    Hope this is helpful, and please continue to ask me anything.


    Best wishes


  • RE: "A bond is not in the molecule"

    The problem is that crystal.molecule returns a fresh copy of a molecule object and so the bonds in crystal.molecule.bonds are in a different molecule from that on which you are calling remove_bonds.

    The solution is to extract the molecule once, then re-assign it to the crystal, i.e.

    mol = crystal.molecule

    mol.remove_bonds(b for b in mol.bonds if b.bond_type == 'Unknown')

    crystal.molecule = mol

    You may also consider using molecule.assign_bond_types('Unknown') which will deduce bond types where possible.

    I think the API might be a little nicer if the crystal object had methods to remove atoms and bonds.  I shall certainly consider it for a  future release.

    Best wishes



  • RE: why the default h-bond distance range is negative (-5.0, 0.0)?

    This is because the HBond may come from different symmetry transformed copies of the unit cell molecule.  The API seeks to provide only a single copy of each HBond, for example O1-H21-N2, though this behaviour can be changed.  To see all HBonds,

    hbonds = cry.hbonds(distance_range=(0, 5),  unique=False)
    for hb in hbonds:
        print hb, hb.length, vdw_correct(hb), hb.symmetry_operators[-1]

    So the O1-H21-N2 has a symmetry operator of  1-x,1-y,1-z.

    In the first example with a distance range of (-5, 0) O1-H21-N2 has a symmetry operator of x,y,z so they are the unit cell atoms.  It does not appear in the second list because the vdw-corrected distance is less than 0,

    from ccdc.descriptors import MolecularDescriptors as MD
    mol = cry.molecule

    MD.atom_distance(mol.atom('O1'), mol.atom('N2)) - mol.atom('O1').vdw_radius - mol.atom('N2').vdw_radius


    You can check other distances by instantiating the symmetry transformed molecule:

    symm_mol = cry.symmetric_molecule('1-x,1-y,1-z')


    Best wishes



  • RE: why the default h-bond distance range is negative (-5.0, 0.0)?

    One of the options to the detection of HBonds either in the crystal or in the molecule is whether or not the distance range is absolute or Van der Waals corrected, i.e. a distance minus the sum of the radii of the atoms concerned.  This is the default.  We can see this more clearly in the following script:

    from ccdc import io

    csd = io.EntryReader('csd')
    cry = csd.crystal('TEHREG')

    def vdw_correct(hb):
        return hb.length - hb.atoms[0].vdw_radius - hb.atoms[-1].vdw_radius

    hbonds_vdw = cry.hbonds(distance_range=(-5, 0))
    for hb in hbonds_vdw:
        print hb, hb.length, vdw_correct(hb)

    hbonds_vdw = cry.hbonds(distance_range=(0, 5))
    for hb in hbonds_vdw:
        print hb, hb.length, vdw_correct(hb)

    If you prefer, you may calculate HBonds with the absolute distance:

    hbonds_abs = cry.hbonds(distance_range=(0, 5), vdw_corrected=False)

    I hope this is helpful

    Best wishes