2525package org .biojava .nbio .protmod .structure ;
2626
2727import org .biojava .nbio .structure .*;
28+ import org .biojava .nbio .structure .io .mmcif .MetalBondParser ;
29+ import org .biojava .nbio .structure .io .mmcif .chem .MetalBondDistance ;
2830
2931import java .util .ArrayList ;
3032import java .util .Collections ;
3133import java .util .List ;
34+ import java .util .Map ;
3235
3336public final class StructureUtil {
3437 private StructureUtil () {
@@ -53,7 +56,11 @@ public static StructureGroup getStructureGroup(Group group, boolean isAminoAcid)
5356 * @return the {@link StructureAtom} of the atom.
5457 */
5558 public static StructureAtom getStructureAtom (Atom atom , boolean isParentAminoAcid ) {
56- StructureGroup strucGroup = getStructureGroup (atom .getGroup (), isParentAminoAcid );
59+
60+ Group g = atom .getGroup ();
61+ String chainId = g .getChainId ();
62+ StructureGroup strucGroup = getStructureGroup (g , isParentAminoAcid );
63+ strucGroup .setChainId (chainId );
5764 return new StructureAtom (strucGroup , atom .getName ());
5865 }
5966
@@ -104,6 +111,8 @@ public static double getAtomDistance(Atom atom1, Atom atom2) {
104111 public static Atom [] findNearestAtomLinkage (final Group group1 , final Group group2 ,
105112 List <String > potentialNamesOfAtomOnGroup1 , List <String > potentialNamesOfAtomOnGroup2 ,
106113 final boolean ignoreNCLinkage , double bondLengthTolerance ) {
114+
115+
107116 List <Atom []> linkages = findAtomLinkages (group1 , group2 ,
108117 potentialNamesOfAtomOnGroup1 , potentialNamesOfAtomOnGroup2 ,
109118 ignoreNCLinkage , bondLengthTolerance );
@@ -216,31 +225,96 @@ public static List<Atom[]> findAtomLinkages(final Group group1,
216225 public static Atom [] findLinkage (final Group group1 , final Group group2 ,
217226 String nameOfAtomOnGroup1 , String nameOfAtomOnGroup2 ,
218227 double bondLengthTolerance ) {
219- Atom [] ret = new Atom [2 ];
220- double distance ;
221228
229+ Atom [] ret = new Atom [2 ];
222230
223231 ret [0 ] = group1 .getAtom (nameOfAtomOnGroup1 );
224232 ret [1 ] = group2 .getAtom (nameOfAtomOnGroup2 );
233+
225234 if (ret [0 ]==null || ret [1 ]==null ) {
226235 return null ;
227236 }
228237
229- distance = Calc .getDistance (ret [0 ], ret [1 ]);
230238
239+ Atom a1 = ret [0 ];
240+ Atom a2 = ret [1 ];
231241
242+ boolean hasBond = a1 .hasBond (a2 );
232243
233- float radiusOfAtom1 = ret [0 ].getElement ().getCovalentRadius ();
234- float radiusOfAtom2 = ret [1 ].getElement ().getCovalentRadius ();
244+ if ( hasBond ) {
245+
246+ return ret ;
247+ }
248+
249+ // is it a metal ?
250+
251+ if ( a1 .getElement ().isMetal () || a2 .getElement ().isMetal ()){
252+
253+ MetalBondDistance defined = getMetalDistanceCutoff (a1 .getElement ().name (),a2 .getElement ().name ());
254+
255+ if ( defined != null ) {
256+
257+ if (hasMetalBond (a1 , a2 , defined ))
258+ return ret ;
259+ else
260+ return null ;
261+ }
235262
236- if (Math .abs (distance -radiusOfAtom1 -radiusOfAtom2 )
237- > bondLengthTolerance ) {
238- return null ;
239263 }
240264
265+ // not a metal
266+
267+ double distance = Calc .getDistance (a1 , a2 );
268+
269+ float radiusOfAtom1 = ret [0 ].getElement ().getCovalentRadius ();
270+ float radiusOfAtom2 = ret [1 ].getElement ().getCovalentRadius ();
271+
272+ if (Math .abs (distance - radiusOfAtom1 - radiusOfAtom2 )
273+ > bondLengthTolerance ) {
274+ return null ;
275+ }
276+
277+
241278 return ret ;
242279 }
243280
281+ private static boolean hasMetalBond (Atom a1 , Atom a2 , MetalBondDistance definition ) {
282+
283+ double distance = Calc .getDistance (a1 ,a2 );
284+
285+ Float min = definition .getLowerLimit ();
286+ Float max = definition .getUpperLimit ();
287+
288+ return ( min < distance && max > distance );
289+
290+ }
291+
292+ private static MetalBondDistance getMetalDistanceCutoff (String name1 , String name2 ) {
293+ Map <String ,List <MetalBondDistance >> defs = MetalBondParser .getMetalBondDefinitions ();
294+
295+ List <MetalBondDistance > distances = defs .get (name1 );
296+
297+ if ( distances == null ){
298+
299+ distances = defs .get (name2 );
300+ String tmp = name1 ;
301+ name2 = name1 ;
302+ name1 = tmp ;
303+ }
304+ if ( distances == null ){
305+ return null ;
306+ }
307+
308+ for ( MetalBondDistance d : distances ){
309+ if ( name1 .equalsIgnoreCase (d .getAtomType1 ()) && name2 .equalsIgnoreCase (d .getAtomType2 ()) )
310+ return d ;
311+ }
312+
313+ // no matching atom definitions found
314+ return null ;
315+
316+ }
317+
244318 /**
245319 *
246320 * @param group a {@link Group}.
0 commit comments