Surely that line output.getAtom( atom.getAtomicNumber() -1 )

Was meant to use output.getAtomCount() -1

To get the last atom added?

On Mon, Sep 5, 2022, 6:44 AM John Mayfield <john.wilkinson...@gmail.com>
wrote:

> Yes and it's correct, your code is adding bonds to atoms which don't exist
> yet! You need to add the atoms of the bond before the bond - 0..k not k ..
> n.
>
> As an aside the Mappings API has this method
> already (toSubstructureStream()) if you're coming via CDK substructure
> Pattern (although it doesn't do the radials/lone pairs... possible but I
> never found a use to have them explicitly like that).
>
> In general this code is an inefficient way to build the container... I
> think it's O(N^3) - but perhaps only O(N^2) with AtomContainer2 :-). Much
> better to add all the atoms, record these in a set/map, then loop all the
> bonds. Optionally for best performance you should do this "resync"
> operation where you map the source => target AtomRef. Maybe we should add
> this to the ACmanipulator, I thought there was something similar
> already though.
>
> John
>
> public static IAtomContainer extractSubstructure(IAtomContainer source, 
> List<IAtom> atoms) {
>     IAtomContainer output = source.getBuilder().newAtomContainer();
>     Map<IAtom,IAtom> remap = new HashMap<>();
>     for (IAtom atom : atoms) {
>         output.addAtom(atom);
>         source.getConnectedLonePairsList(atom).forEach(output::addLonePair);
>         
> source.getConnectedSingleElectronsList(atom).forEach(output::addSingleElectron);
>         // resync: get the AtomRef in the context of the new container. This
>         // presumes atoms gets added at last position which is currently
>         // always the case
>         remap.put(atom, output.getAtom(atom.getAtomicNumber() - 1));
>     }
>     for (IBond bond : source.bonds()) {
>         IAtom beg = remap.get(bond.getBegin());
>         IAtom end = remap.get(bond.getEnd());
>         if (beg != null && end != null) {
>             output.addBond(bond);
>
>             // or the more efficient but you get a "NEW" bond so may need to 
> some fudging with
>             // setting aromatcity/ring membership etc, however if you're 
> selecting a substructure
>             // you MUST recalculate these anyways.
>             // output.addBond(beg.getIndex(), end.getIndex(), 
> bond.getOrder(), bond.getStereo());
>         }
>     }
>     return output;
> }
>
>
> On Mon, 5 Sept 2022 at 11:10, Uli Fechner <u...@pending.ai> wrote:
>
>>
>> Hi,
>>
>> I get a NoSuchAtomException when executing the following code (that I
>> inherited):
>>
>> public static IAtomContainer extractSubstructure(IAtomContainer source, 
>> List<IAtom> atoms) {
>>     IAtomContainer output = 
>> SilentChemObjectBuilder.getInstance().newAtomContainer();
>>     int k = 0;
>>     for (IAtom atom : atoms) {
>>         output.addAtom(atom);
>>         source.getConnectedLonePairsList(atom).forEach(lp -> 
>> output.addLonePair(lp));
>>         source.getConnectedSingleElectronsList(atom).forEach(se -> 
>> output.addSingleElectron(se));
>>         k++;
>>         for (int i = k; i < atoms.size(); i++) {
>>             IBond bond = source.getBond(atom, atoms.get(i));
>>             if (bond != null) {
>>                 output.addBond(bond);
>>             }
>>         }
>>     }
>>     return output;
>> }
>>
>> The stack trace starts at the line with
>> output.addBond(bond);
>>
>> and continues with the following lines:
>>
>> org.openscience.cdk.exception.NoSuchAtomException: Atom is not a member of 
>> this AtomContainer
>>      at 
>> app//org.openscience.cdk.silent.AtomContainer2.getAtomRef(AtomContainer2.java:185)
>>      at 
>> app//org.openscience.cdk.silent.AtomContainer2.newBondRef(AtomContainer2.java:221)
>>      at 
>> app//org.openscience.cdk.silent.AtomContainer2.addBond(AtomContainer2.java:908)
>>
>> The exception *isn't* thrown if I replace the instantiation of the
>> IAtomContainer output with
>> IAtomContainer output = new AtomContainer();
>> I understand that the exception has something to do with the way
>> AtomContainer2 is implemented, but I don't know how to switch to the
>> AtomContainer2 implementation and still retain the intent of the code -
>> which is to only add atoms, their connected LPs, their connected single
>> electrons and their connected bonds, but not connected atoms - to the
>> returned subgraph. Best
>> Uli
>>
>>
>> _______________________________________________
>> Cdk-user mailing list
>> Cdk-user@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/cdk-user
>>
> _______________________________________________
> Cdk-user mailing list
> Cdk-user@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/cdk-user
>
_______________________________________________
Cdk-user mailing list
Cdk-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/cdk-user

Reply via email to