<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Our test set here includes the 16 million molecules from the old ZINC clean set that could be successfully processed by the RDKit.
We use the Standard InChI that comes with ChEMBL and a non-standard InChI (options "/FixedH /SUU") that allows tautomers to be distinguished. Here's the sequence of psql commands used to generate that set
Step1:  Big caveat here
Step2:  grouping on the main layer
Step3:  Look at a few of the common main layer groups
Step4:  Charges
Step5:  Stereo grouping
Step6:  an aside
I discovered this little InChI pathology while doing this work. I spent a good half hour trying to track down the RDKit bug that made it happen before realizing that it's by design. Note that this is with FixedH InChIs.
Step7:  Sucks to be you if it's important to you that those molecules be different and you're using InChI.
Note that at least ZINC12405219 and ZINC19940218 are, according to ZINC, separately available from vendors
Isotopes
Step8:  No need here, this set has no labelled compounds. That's likely a property of how the ZINC clean set was constructed.
examples where the tautomerism leads to new tetrahedral symmetry
Step9:  Not much interesting there. There's no simple query to find questionable tautomer motion. 
<ASSISTANT_TASK:>
Python Code:
%sql postgresql://localhost/inchi_split \
    select count(*) from zinc_clean_nonstandard;
Explanation: Our test set here includes the 16 million molecules from the old ZINC clean set that could be successfully processed by the RDKit.
We use the Standard InChI that comes with ChEMBL and a non-standard InChI (options "/FixedH /SUU") that allows tautomers to be distinguished. Here's the sequence of psql commands used to generate that set:
End of explanation
d = %sql \
    select formula,count(zinc_id) freq from zinc_clean_nonstandard group by formula \
    order by freq desc limit 10;
d
Explanation: Big caveat here: I forgot the last commit in my loading script, so the last block of structures is missing.
Formula level grouping
End of explanation
d = %sql \
    select formula,skeleton,hydrogens,count(zinc_id) freq from zinc_clean_nonstandard group by \
    (formula,skeleton,hydrogens) \
    order by freq desc limit 10;
Explanation: grouping on the main layer
End of explanation
d[:5]
tpl=d[0][:-1]
print(tpl)
rows = %sql \
  select zinc_id,smiles from zinc_clean join zinc_clean_nonstandard using (zinc_id) where \
    (formula,skeleton,hydrogens) = :tpl 
cids = [x for x,y in rows][:9]
ms = [Chem.MolFromSmiles(y) for x,y in rows][:9]
Draw.MolsToGridImage(ms,legends=cids)
tpl=d[1][:-1]
print(tpl)
rows = %sql \
  select zinc_id,smiles from zinc_clean join zinc_clean_nonstandard using (zinc_id) where \
    (formula,skeleton,hydrogens) = :tpl
cids = [x for x,y in rows][:9]
ms = [Chem.MolFromSmiles(y) for x,y in rows][:9]
Draw.MolsToGridImage(ms,legends=cids)
tpl=d[4][:-1]
print(tpl)
rows = %sql \
  select zinc_id,smiles from zinc_clean join zinc_clean_nonstandard using (zinc_id) where \
    (formula,skeleton,hydrogens) = :tpl
cids = [x for x,y in rows][:9]
ms = [Chem.MolFromSmiles(y) for x,y in rows][:9]
Draw.MolsToGridImage(ms,legends=cids)
Explanation: Look at a few of the common main layer groups
End of explanation
d = %sql \
    select formula,skeleton,hydrogens,charge,protonation,count(zinc_id) freq from zinc_clean_nonstandard group by \
    (formula,skeleton,hydrogens,charge,protonation) \
    order by freq desc limit 10;
d[:5]
tpl=d[0][:-1]
tpl = tuple(x if x is not None else '' for x in tpl)
print(tpl)
rows = %sql \
  select zinc_id,smiles from zinc_clean join zinc_clean_nonstandard using (zinc_id) where \
    (formula,skeleton,hydrogens,coalesce(charge,''),coalesce(protonation,'')) = :tpl
cids = [x for x,y in rows][:9]
ms = [Chem.MolFromSmiles(y) for x,y in rows][:9]
Draw.MolsToGridImage(ms,legends=cids)
Explanation: Charges
End of explanation
d = %sql \
    select formula,skeleton,hydrogens,charge,protonation,stereo_bond,stereo_tet,stereo_m,stereo_s,count(zinc_id) freq \
    from zinc_clean_nonstandard where stereo_bond is not null or stereo_tet is not null \
    group by \
    (formula,skeleton,hydrogens,charge,protonation,stereo_bond,stereo_tet,stereo_m,stereo_s) \
    order by freq desc limit 10;
d[:5]
tpl=d[0][:-1]
tpl = tuple(x if x is not None else '' for x in tpl)
print(tpl)
rows = %sql \
  select zinc_id,smiles from zinc_clean join zinc_clean_nonstandard using (zinc_id) where \
    (formula,skeleton,hydrogens,\
     coalesce(charge,''),coalesce(protonation,''),coalesce(stereo_bond,''),\
     coalesce(stereo_tet,''),coalesce(stereo_m,''),coalesce(stereo_s,'')) = :tpl   
cids = [x for x,y in rows]
ms = [Chem.MolFromSmiles(y) for x,y in rows]
Draw.MolsToGridImage(ms,legends=cids)
tpl=d[1][:-1]
tpl = tuple(x if x is not None else '' for x in tpl)
print(tpl)
rows = %sql \
  select zinc_id,smiles from zinc_clean join zinc_clean_nonstandard using (zinc_id) where \
    (formula,skeleton,hydrogens,\
     coalesce(charge,''),coalesce(protonation,''),coalesce(stereo_bond,''),\
     coalesce(stereo_tet,''),coalesce(stereo_m,''),coalesce(stereo_s,'')) = :tpl   
cids = [x for x,y in rows]
ms = [Chem.MolFromSmiles(y) for x,y in rows]
Draw.MolsToGridImage(ms,legends=cids)
Explanation: Stereo grouping
End of explanation
td = %sql \
select t2.zinc_id,t2.nonstandard_inchi,t2.smiles from zinc_clean_nonstandard t1 join zinc_clean t2 using (zinc_id) \
where (formula,skeleton,hydrogens,charge)=\
('/C29H33N2','/c1-28(2)22-16-12-14-18-24(22)30(5)26(28)20-10-8-7-9-11-21-27-29(3,4)23-17-13-15-19-25(23)31(27)6',\
 '/h7-21H,1-6H3','/q+1')
print(td)
cids = [x for x,y,z in td]
ms = [Chem.MolFromSmiles(z) for x,y,z in td]
Draw.MolsToGridImage(ms,legends=cids)
Explanation: an aside
I discovered this little InChI pathology while doing this work. I spent a good half hour trying to track down the RDKit bug that made it happen before realizing that it's by design. Note that this is with FixedH InChIs.
End of explanation
%sql \
select count(*) \
    from zinc_clean_nonstandard where isotope is not null
Explanation: Sucks to be you if it's important to you that those molecules be different and you're using InChI.
Note that at least ZINC12405219 and ZINC19940218 are, according to ZINC, separately available from vendors
Isotopes
End of explanation
rows = %sql \
  select zinc_id,smiles,nonstandard_inchi from zinc_clean join zinc_clean_nonstandard using (zinc_id) where \
     fixedh_stereo_tet is not null and position('?' in fixedh_stereo_tet)<=0 and stereo_tet!=fixedh_stereo_tet 
len(rows)
cids = [x for x,y,z in rows][:10]
ms = [Chem.MolFromSmiles(y) for x,y,z in rows][:10]
Draw.MolsToGridImage(ms,legends=cids)
Explanation: No need here, this set has no labelled compounds. That's likely a property of how the ZINC clean set was constructed.
examples where the tautomerism leads to new tetrahedral symmetry
End of explanation
rows = %sql \
  select zinc_id,smiles,nonstandard_inchi from zinc_clean join zinc_clean_nonstandard using (zinc_id) where \
     fixedh_stereo_bond is not null and fixedh_stereo_bond!='/b' and position('?' in fixedh_stereo_bond)<=0 and stereo_bond!=fixedh_stereo_bond 
len(rows)
cids = [x for x,y,z in rows][:10]
ms = [Chem.MolFromSmiles(y) for x,y,z in rows][:10]
Draw.MolsToGridImage(ms,legends=cids)
Explanation: Not much interesting there. There's no simple query to find questionable tautomer motion. :-)
Examples where tautomerism leads to new bond stereochemistry
End of explanation
<END_TASK>