Program: 16995
Project: 16995
Buggy source:
/** 
 * Builds an   {@link AFPChain} from already-matched arrays of atoms and residues.
 * @param ca1 An array of atoms in the first structure
 * @param ca2 An array of atoms in the second structure
 * @param residues1 An array of  {@link ResidueNumber ResidueNumbers} in the first structure that are aligned. Only null ResidueNumbers are considered to be unaligned
 * @param residues2 An array of  {@link ResidueNumber ResidueNumbers} in the second structure that are aligned. Only null ResidueNumbers are considered to be unaligned
 */
private static AFPChain buildAlignment(Atom[] ca1,Atom[] ca2,ResidueNumber[] residues1,ResidueNumber[] residues2) throws StructureException {
  List<ResidueNumber> alignedResiduesList1=new ArrayList<ResidueNumber>();
  List<ResidueNumber> alignedResiduesList2=new ArrayList<ResidueNumber>();
  for (int i=0; i < residues1.length; i++) {
    if (residues1[i] != null && residues2[i] != null) {
      alignedResiduesList1.add(residues1[i]);
      alignedResiduesList2.add(residues2[i]);
    }
  }
  ResidueNumber[] alignedResidues1=alignedResiduesList1.toArray(new ResidueNumber[alignedResiduesList1.size()]);
  ResidueNumber[] alignedResidues2=alignedResiduesList2.toArray(new ResidueNumber[alignedResiduesList2.size()]);
  AFPChain afpChain=AlignmentTools.createAFPChain(ca1,ca2,alignedResidues1,alignedResidues2);
  if (alignedResidues1.length > 0 && alignedResidues2.length > 0) {
    Atom[] alignedAtoms1=getAligned(ca1,alignedResiduesList1);
    Atom[] alignedAtoms2=getAligned(ca2,alignedResiduesList2);
    SVDSuperimposer svd=new SVDSuperimposer(alignedAtoms1,alignedAtoms2);
    Matrix matrix=svd.getRotation();
    Atom shift=svd.getTranslation();
    Atom[] aligned2Clone=StructureTools.cloneCAArray(alignedAtoms2);
    for (    Atom atom : aligned2Clone) {
      Calc.rotate(atom,matrix);
      Calc.shift(atom,shift);
    }
    double rmsd=SVDSuperimposer.getRMS(alignedAtoms1,aligned2Clone);
    double tmScore=SVDSuperimposer.getTMScore(alignedAtoms1,aligned2Clone,ca1.length,ca2.length);
    for (    AFP afp : afpChain.getAfpSet()) {
      afp.setFragLen(1);
      afp.setM(matrix);
      afp.setRmsd(rmsd);
      afp.setScore(tmScore);
    }
    afpChain.setBlockShiftVector(new Atom[]{shift});
    afpChain.setBlockRotationMatrix(new Matrix[]{matrix});
    afpChain.setBlockRmsd(new double[]{rmsd});
    afpChain.setBlockGap(new int[]{afpChain.getGapLen()});
    afpChain.setBlockSize(new int[]{alignedAtoms1.length});
    afpChain.setTotalRmsdOpt(rmsd);
    afpChain.setTMScore(tmScore);
  }
 else {
    afpChain.setTMScore(0);
  }
  return afpChain;
}

Fixed version (ground truth):
/** 
 * Builds an   {@link AFPChain} from already-matched arrays of atoms and residues.
 * @param ca1 An array of atoms in the first structure
 * @param ca2 An array of atoms in the second structure
 * @param residues1 An array of  {@link ResidueNumber ResidueNumbers} in the first structure that are aligned. Only null ResidueNumbers are considered to be unaligned
 * @param residues2 An array of  {@link ResidueNumber ResidueNumbers} in the second structure that are aligned. Only null ResidueNumbers are considered to be unaligned
 */
private static AFPChain buildAlignment(Atom[] ca1,Atom[] ca2,ResidueNumber[] residues1,ResidueNumber[] residues2) throws StructureException {
  List<ResidueNumber> alignedResiduesList1=new ArrayList<ResidueNumber>();
  List<ResidueNumber> alignedResiduesList2=new ArrayList<ResidueNumber>();
  for (int i=0; i < residues1.length; i++) {
    if (residues1[i] != null && residues2[i] != null) {
      alignedResiduesList1.add(residues1[i]);
      alignedResiduesList2.add(residues2[i]);
    }
  }
  ResidueNumber[] alignedResidues1=alignedResiduesList1.toArray(new ResidueNumber[alignedResiduesList1.size()]);
  ResidueNumber[] alignedResidues2=alignedResiduesList2.toArray(new ResidueNumber[alignedResiduesList2.size()]);
  AFPChain afpChain=AlignmentTools.createAFPChain(ca1,ca2,alignedResidues1,alignedResidues2);
  if (alignedResidues1.length > 0 && alignedResidues2.length > 0) {
    AFPTwister.twistOptimized(afpChain,ca1,ca2);
    List<Group> hetatms2=new ArrayList<Group>();
    List<Group> nucs2=new ArrayList<Group>();
    Group g2=ca2[0].getGroup();
    Chain c2=null;
    if (g2 != null) {
      c2=g2.getChain();
      if (c2 != null) {
        hetatms2=c2.getAtomGroups("String_Node_Str");
        nucs2=c2.getAtomGroups("String_Node_Str");
      }
    }
    if (afpChain.getBlockNum() > 0) {
      if (hetatms2.size() > 0 || nucs2.size() > 0) {
        if (afpChain.getBlockRotationMatrix().length > 0) {
          Matrix m1=afpChain.getBlockRotationMatrix()[0];
          Atom vector1=afpChain.getBlockShiftVector()[0];
          for (          Group g : hetatms2) {
            Calc.rotate(g,m1);
            Calc.shift(g,vector1);
          }
          for (          Group g : nucs2) {
            Calc.rotate(g,m1);
            Calc.shift(g,vector1);
          }
        }
      }
    }
    double tmScore=AFPChainScorer.getTMScore(afpChain,ca1,ca2);
    afpChain.setTMScore(tmScore);
  }
 else {
    afpChain.setTMScore(0);
  }
  return afpChain;
}