Program: 16679
Project: 16679
Buggy source:
/** 
 * After the alignment changes (optAln, optLen, blockNum, at a minimum), many other properties which depend on the superposition will be invalid. This method re-runs a rigid superposition over the whole alignment and repopulates the required properties, including RMSD (TotalRMSD) and TM-Score.
 * @param afpChain
 * @param ca1
 * @param ca2 Second set of ca atoms. Will be modified based on the superposition
 * @throws StructureException
 * @see {@link CECalculator#calc_rmsd(Atom[],Atom[],int,boolean)}contains much of the same code, but stores results in a CECalculator instance rather than an AFPChain
 */
public static void updateSuperposition(AFPChain afpChain,Atom[] ca1,Atom[] ca2) throws StructureException {
  afpChain.setCa1Length(ca1.length);
  afpChain.setCa2Length(ca2.length);
  int[] focusRes1=afpChain.getFocusRes1();
  int[] focusRes2=afpChain.getFocusRes2();
  if (focusRes1 == null) {
    focusRes1=new int[afpChain.getCa1Length()];
    afpChain.setFocusRes1(focusRes1);
  }
  if (focusRes2 == null) {
    focusRes2=new int[afpChain.getCa2Length()];
    afpChain.setFocusRes2(focusRes2);
  }
  if (afpChain.getNrEQR() == 0)   return;
  Atom[] ca1aligned=new Atom[afpChain.getOptLength()];
  Atom[] ca2aligned=new Atom[afpChain.getOptLength()];
  int pos=0;
  int[] blockLens=afpChain.getOptLen();
  int[][][] optAln=afpChain.getOptAln();
  assert(afpChain.getBlockNum() <= optAln.length);
  for (int block=0; block < afpChain.getBlockNum(); block++) {
    for (int i=0; i < blockLens[block]; i++) {
      int pos1=optAln[block][0][i];
      int pos2=optAln[block][1][i];
      Atom a1=ca1[pos1];
      Atom a2=(Atom)ca2[pos2].clone();
      ca1aligned[pos]=a1;
      ca2aligned[pos]=a2;
      pos++;
    }
  }
  if (pos != afpChain.getOptLength()) {
    logger.warn("String_Node_Str" + pos + "String_Node_Str"+ afpChain.getOptLength());
    ca1aligned=(Atom[])resizeArray(ca1aligned,pos);
    ca2aligned=(Atom[])resizeArray(ca2aligned,pos);
  }
  SVDSuperimposer svd=new SVDSuperimposer(ca1aligned,ca2aligned);
  Matrix matrix=svd.getRotation();
  Atom shift=svd.getTranslation();
  Matrix[] blockMxs=new Matrix[afpChain.getBlockNum()];
  Arrays.fill(blockMxs,matrix);
  afpChain.setBlockRotationMatrix(blockMxs);
  Atom[] blockShifts=new Atom[afpChain.getBlockNum()];
  Arrays.fill(blockShifts,shift);
  afpChain.setBlockShiftVector(blockShifts);
  for (  Atom a : ca2aligned) {
    Calc.rotate(a,matrix);
    Calc.shift(a,shift);
  }
  double rmsd=SVDSuperimposer.getRMS(ca1aligned,ca2aligned);
  double tmScore=SVDSuperimposer.getTMScore(ca1aligned,ca2aligned,ca1.length,ca2.length);
  afpChain.setTotalRmsdOpt(rmsd);
  afpChain.setTMScore(tmScore);
  double[] blockRMSD=new double[afpChain.getBlockNum()];
  double[] blockScore=new double[afpChain.getBlockNum()];
  for (int k=0; k < afpChain.getBlockNum(); k++) {
    Atom[] ca1block=new Atom[afpChain.getOptLen()[k]];
    Atom[] ca2block=new Atom[afpChain.getOptLen()[k]];
    int position=0;
    for (int i=0; i < blockLens[k]; i++) {
      int pos1=optAln[k][0][i];
      int pos2=optAln[k][1][i];
      Atom a1=ca1[pos1];
      Atom a2=(Atom)ca2[pos2].clone();
      ca1block[position]=a1;
      ca2block[position]=a2;
      position++;
    }
    if (position != afpChain.getOptLen()[k]) {
      logger.warn("String_Node_Str" + pos + "String_Node_Str"+ afpChain.getOptLen()[k]);
      ca1block=(Atom[])resizeArray(ca1block,position);
      ca2block=(Atom[])resizeArray(ca2block,position);
    }
    SVDSuperimposer svdb=new SVDSuperimposer(ca1block,ca2block);
    Matrix matrixb=svdb.getRotation();
    Atom shiftb=svdb.getTranslation();
    afpChain.getBlockRotationMatrix()[k]=matrixb;
    afpChain.getBlockShiftVector()[k]=shiftb;
    afpChain.setBlockShiftVector(blockShifts);
    for (    Atom a : ca2block) {
      Calc.rotate(a,matrixb);
      Calc.shift(a,shiftb);
    }
    double rmsdb=SVDSuperimposer.getRMS(ca1block,ca2block);
    double tmScoreb=SVDSuperimposer.getTMScore(ca1block,ca2block,ca1.length,ca2.length);
    blockRMSD[k]=rmsdb;
    blockScore[k]=tmScoreb;
  }
  afpChain.setOptRmsd(blockRMSD);
  afpChain.setBlockRmsd(blockRMSD);
  afpChain.setBlockScore(blockScore);
}

Fixed version (ground truth):
/** 
 * After the alignment changes (optAln, optLen, blockNum, at a minimum), many other properties which depend on the superposition will be invalid. This method re-runs a rigid superposition over the whole alignment and repopulates the required properties, including RMSD (TotalRMSD) and TM-Score.
 * @param afpChain
 * @param ca1
 * @param ca2 Second set of ca atoms. Will be modified based on the superposition
 * @throws StructureException
 * @see {@link CECalculator#calc_rmsd(Atom[],Atom[],int,boolean)}contains much of the same code, but stores results in a CECalculator instance rather than an AFPChain
 */
public static void updateSuperposition(AFPChain afpChain,Atom[] ca1,Atom[] ca2) throws StructureException {
  afpChain.setCa1Length(ca1.length);
  afpChain.setCa2Length(ca2.length);
  int[] focusRes1=afpChain.getFocusRes1();
  int[] focusRes2=afpChain.getFocusRes2();
  if (focusRes1 == null) {
    focusRes1=new int[afpChain.getCa1Length()];
    afpChain.setFocusRes1(focusRes1);
  }
  if (focusRes2 == null) {
    focusRes2=new int[afpChain.getCa2Length()];
    afpChain.setFocusRes2(focusRes2);
  }
  if (afpChain.getNrEQR() == 0)   return;
  Atom[] ca1aligned=new Atom[afpChain.getOptLength()];
  Atom[] ca2aligned=new Atom[afpChain.getOptLength()];
  int pos=0;
  int[] blockLens=afpChain.getOptLen();
  int[][][] optAln=afpChain.getOptAln();
  assert(afpChain.getBlockNum() <= optAln.length);
  for (int block=0; block < afpChain.getBlockNum(); block++) {
    for (int i=0; i < blockLens[block]; i++) {
      int pos1=optAln[block][0][i];
      int pos2=optAln[block][1][i];
      Atom a1=ca1[pos1];
      Atom a2=(Atom)ca2[pos2].clone();
      ca1aligned[pos]=a1;
      ca2aligned[pos]=a2;
      pos++;
    }
  }
  if (pos != afpChain.getOptLength()) {
    logger.warn("String_Node_Str" + pos + "String_Node_Str"+ afpChain.getOptLength());
    ca1aligned=(Atom[])resizeArray(ca1aligned,pos);
    ca2aligned=(Atom[])resizeArray(ca2aligned,pos);
  }
  SVDSuperimposer svd=new SVDSuperimposer(ca1aligned,ca2aligned);
  Matrix matrix=svd.getRotation();
  Atom shift=svd.getTranslation();
  Matrix[] blockMxs=new Matrix[afpChain.getBlockNum()];
  Arrays.fill(blockMxs,matrix);
  afpChain.setBlockRotationMatrix(blockMxs);
  Atom[] blockShifts=new Atom[afpChain.getBlockNum()];
  Arrays.fill(blockShifts,shift);
  afpChain.setBlockShiftVector(blockShifts);
  for (  Atom a : ca2aligned) {
    Calc.rotate(a,matrix);
    Calc.shift(a,shift);
  }
  double rmsd=SVDSuperimposer.getRMS(ca1aligned,ca2aligned);
  double tmScore=SVDSuperimposer.getTMScore(ca1aligned,ca2aligned,ca1.length,ca2.length);
  afpChain.setTotalRmsdOpt(rmsd);
  afpChain.setTMScore(tmScore);
  double[] blockRMSD=new double[afpChain.getBlockNum()];
  double[] blockScore=new double[afpChain.getBlockNum()];
  for (int k=0; k < afpChain.getBlockNum(); k++) {
    Atom[] ca1block=new Atom[afpChain.getOptLen()[k]];
    Atom[] ca2block=new Atom[afpChain.getOptLen()[k]];
    int position=0;
    for (int i=0; i < blockLens[k]; i++) {
      int pos1=optAln[k][0][i];
      int pos2=optAln[k][1][i];
      Atom a1=ca1[pos1];
      Atom a2=(Atom)ca2[pos2].clone();
      ca1block[position]=a1;
      ca2block[position]=a2;
      position++;
    }
    if (position != afpChain.getOptLen()[k]) {
      logger.warn("String_Node_Str" + pos + "String_Node_Str"+ afpChain.getOptLen()[k]);
      ca1block=(Atom[])resizeArray(ca1block,position);
      ca2block=(Atom[])resizeArray(ca2block,position);
    }
    SVDSuperimposer svdb=new SVDSuperimposer(ca1block,ca2block);
    Matrix matrixb=svdb.getRotation();
    Atom shiftb=svdb.getTranslation();
    for (    Atom a : ca2block) {
      Calc.rotate(a,matrixb);
      Calc.shift(a,shiftb);
    }
    double rmsdb=SVDSuperimposer.getRMS(ca1block,ca2block);
    double tmScoreb=SVDSuperimposer.getTMScore(ca1block,ca2block,ca1.length,ca2.length);
    blockRMSD[k]=rmsdb;
    blockScore[k]=tmScoreb;
  }
  afpChain.setOptRmsd(blockRMSD);
  afpChain.setBlockRmsd(blockRMSD);
  afpChain.setBlockScore(blockScore);
}