@@ -507,27 +507,24 @@ public boolean mergeStructure(SubunitCluster other, SubunitClustererParameters p
507507 }
508508 }
509509
510- AFPChain afp = aligner .align (this .subunits .get (this .representative )
511- .getRepresentativeAtoms (),
512- other .subunits .get (other .representative )
513- .getRepresentativeAtoms ());
510+ AFPChain afp = aligner .align (this .subunits .get (this .representative ).getRepresentativeAtoms (),
511+ other .subunits .get (other .representative ).getRepresentativeAtoms ());
514512
513+ String pairName = this .subunits .get (this .representative ).getName () + "-" + other .subunits .get (other .representative ).getName ();
515514 if (afp .getOptLength () < 1 ) {
516515 // alignment failed (eg if chains were too short)
517516 throw new StructureException (
518- String .format ("Subunits failed to align using %s" , params .getSuperpositionAlgorithm ()));
517+ String .format ("Subunits %s failed to align using %s" , pairName , params .getSuperpositionAlgorithm ()));
519518 }
520519
521520 // Convert AFPChain to MultipleAlignment for convenience
522521 MultipleAlignment msa = new MultipleAlignmentEnsembleImpl (
523522 afp ,
524523 this .subunits .get (this .representative ).getRepresentativeAtoms (),
525- other .subunits .get (other .representative )
526- .getRepresentativeAtoms (), false )
527- .getMultipleAlignment (0 );
524+ other .subunits .get (other .representative ).getRepresentativeAtoms (),
525+ false ).getMultipleAlignment (0 );
528526
529- double structureCoverage = Math .min (msa .getCoverages ().get (0 ), msa
530- .getCoverages ().get (1 ));
527+ double structureCoverage = Math .min (msa .getCoverages ().get (0 ), msa .getCoverages ().get (1 ));
531528
532529 if (params .isUseStructureCoverage () && structureCoverage < params .getStructureCoverageThreshold ()) {
533530 return false ;
@@ -543,8 +540,7 @@ public boolean mergeStructure(SubunitCluster other, SubunitClustererParameters p
543540 return false ;
544541 }
545542
546- logger .info (String .format ("SubunitClusters are structurally similar with "
547- + "%.2f RMSD %.2f coverage" , rmsd , structureCoverage ));
543+ logger .info ("SubunitClusters {} are structurally similar with [ {} ] RMSD and [ {} ] coverage" , pairName , String .format ("%.2f" , rmsd ), String .format ("%.2f" , structureCoverage ));
548544
549545 // Merge clusters
550546 List <List <Integer >> alignedRes = msa .getBlock (0 ).getAlignRes ();
@@ -565,13 +561,18 @@ public boolean mergeStructure(SubunitCluster other, SubunitClustererParameters p
565561
566562 // Only consider residues that are part of the SubunitCluster
567563 if (this .subunitEQR .get (this .representative ).contains (thisIndex )
568- && other .subunitEQR .get (other .representative ).contains (
569- otherIndex )) {
564+ && other .subunitEQR .get (other .representative ).contains (otherIndex )) {
570565 thisAligned .add (thisIndex );
571566 otherAligned .add (otherIndex );
572567 }
573568 }
574569
570+ // this can happen in very rare cases, e.g. 9y9z when merging E_1 into the cluster D_1, OM_1, Y_1
571+ if (thisAligned .isEmpty () && otherAligned .isEmpty ()) {
572+ logger .warn ("No equivalent aligned atoms found between SubunitClusters {} via structure alignment. Will not merge the second one into the first." , pairName );
573+ return false ;
574+ }
575+
575576 updateEquivResidues (other , thisAligned , otherAligned );
576577
577578 this .method = SubunitClustererMethod .STRUCTURE ;
@@ -602,18 +603,12 @@ private void updateEquivResidues(SubunitCluster other, List<Integer> thisAligned
602603 Collections .sort (otherRemove );
603604 Collections .reverse (otherRemove );
604605
605- for (int t = 0 ; t < thisRemove .size (); t ++) {
606- for (List <Integer > eqr : this .subunitEQR ) {
607- int column = thisRemove .get (t );
608- eqr .remove (column );
609- }
606+ for (int column : thisRemove ) {
607+ this .subunitEQR .forEach (eqr -> eqr .remove (column ));
610608 }
611609
612- for (int t = 0 ; t < otherRemove .size (); t ++) {
613- for (List <Integer > eqr : other .subunitEQR ) {
614- int column = otherRemove .get (t );
615- eqr .remove (column );
616- }
610+ for (int column : otherRemove ) {
611+ other .subunitEQR .forEach (eqr -> eqr .remove (column ));
617612 }
618613
619614 // The representative is the longest sequence
0 commit comments