import pkg_resources
if pkg_resources.get_distribution('CGRtools').version.split('.')[:2] != ['4', '0']:
    print('WARNING. Tutorial was tested on 4.0 version of CGRtools')
else:
    print('Welcome!')

# load data for tutorial
from pickle import load
from traceback import format_exc

with open('molecules.dat', 'rb') as f:
    molecules = load(f) # list of MoleculeContainer objects
with open('reactions.dat', 'rb') as f:
    reactions = load(f) # list of ReactionContainer objects

m2, m3 = molecules[1:3] # molecule
m7 = m3.copy()
m7.standardize()
r1 = reactions[0] # reaction
m5, m6 = r1.reactants[:2]
m8 = m7.substructure([4, 5, 6, 7, 8, 9])
m9 = m6.substructure([5, 6,7, 8]) # acid
m10 =  r1.products[0].copy()

benzene = m3.substructure([4,5,6,7,8,9])
cgr1 = m7 ^ m8 
carb = m10.substructure([5,7,2])

from CGRtools.containers import *

"""
Explanation: 4. Isomorphism

(c) 2019, 2020 Dr. Ramil Nugmanov;
(c) 2019 Dr. Timur Madzhidov; Ravil Mukhametgaleev

Installation instructions of CGRtools package information and tutorial's files see on https://github.com/stsouko/CGRtools
NOTE: Tutorial should be performed sequentially from the start. Random cell running will lead to unexpected results.
End of explanation
"""


m7

m8

benzene

# isomorphism operations
print(benzene < m7)  # benzene is substructure of m7
print(benzene > m7)  # benzene is not superstructure of m7
print(benzene <= m7) # benzene is substructure/or same structure of m7
print(benzene >= m7) # benzene is not superstructure/or same structure of m7
print(benzene < m8) # benzene is not substructure of m8. it's equal
print(benzene <= m8)

m5

m6

"""
Explanation: 4.1. Molecules Isomorphism
CGRtools has simple substructure/structure isomorphism API.
Note, that atoms are matched in subgraph isomorphism only if they have same charge/multiplicity and isotope options.
End of explanation
"""


next(m5.get_mapping(m6))  # mapping of m5 substructure into m2 superstructure

for m in m5.get_mapping(m6):  # iterate over all possible substructure mappings
    print(m)

next(benzene.get_mapping(m8))  # mapping of benzene into m8 - also benzene.

"""
Explanation: Mappings of substructure or structure to structure can be returned using substructure.get_mapping(structure) method. Method acts as generator.
This functionality was developed to reorder atoms of two MoleculeContainers in the same order (the dictionary that is given by this method could be directly fed to remap function, see above) for some reaction handling issues.
End of explanation
"""


try:            # it is not possible to match molecule and reaction. Error is returned
    m6 < r1
except TypeError:
    print(format_exc())

r1 # see structure in products

m6 # substructure used. One can see, they should not match

any(m6 < m for m in r1.products) # check if any molecule from product side has m6 as substructure

"""
Explanation: 4.2. Reactions
ReactionContainers do not support isomorphism due to ambiguity. But molecules in reaction can be matched.
End of explanation
"""


cgr1

cgr_q = cgr1.substructure([10, 4])
cgr_q  # prepare CGR Query with carbon - nitrogen bond breaking

cgr_q <= cgr1  # found substructure!

"""
Explanation: 4.3 CGR
Substructure search is possible with CGRContainer. API is the same as for molecules.
Matching CGR into CGR only possible.
Equal atoms in isomorphism is atoms with same charge/radical and isotope numbers in reactant and product states
End of explanation
"""


carb_q = m10.substructure([5,7,2], as_query=True)
carb_q # notice that one of oxygen atom has 2 neighbors. Only ester could fit this restriction.

m9 # acid

m10 # ether

carb

"""
Explanation: 4.4 Queries
Queries (QueryContainer, QueryCGRContainer) is special objects wich takes into account neighbors and hybridization state of atoms in molecules or CGRs.
Queries can be generated from molecules or CGRs by substructure method with as_query argument or by union with QueryContainer object
End of explanation
"""


carb < m9 # carb is molecule. It fit this molecule as well.

carb < m10 # carb is a substructure of m10

"""
Explanation: Molecules isomorphism don't take into account neighbors and hybridization
End of explanation
"""


carb_q < m9 # now neighbors and hybridization are taken into account.

"""
Explanation: One need to convert molecule into QueryContainer object. In this case number of neighbors and hybridization data will be taken into account upon substructure search.
End of explanation
"""


carb_q < m10 # ester matches to query.

"""
Explanation: Acid m9 has hydroxyl group with one non-hydrogen neighbor. Our query requires existence of one oxygen atom with two neighbors.
End of explanation
"""


