protected Instance convertInstance(Instance instance) throws Exception {
    Instance	result;
    double[] 	newVals;
    Instance 	tempInst;
    double 	cumulative;
    int		i;
    int		j;
    double 	tempval;
    int		numAttsLowerBound;
    
    newVals  = new double[m_OutputNumAtts];
    tempInst = (Instance) instance.copy();

    m_ReplaceMissingFilter.input(tempInst);
    m_ReplaceMissingFilter.batchFinished();
    tempInst = m_ReplaceMissingFilter.output();

    if (m_Normalize) {
      m_NormalizeFilter.input(tempInst);
      m_NormalizeFilter.batchFinished();
      tempInst = m_NormalizeFilter.output();
    }

    m_NominalToBinaryFilter.input(tempInst);
    m_NominalToBinaryFilter.batchFinished();
    tempInst = m_NominalToBinaryFilter.output();

    if (m_AttributeFilter != null) {
      m_AttributeFilter.input(tempInst);
      m_AttributeFilter.batchFinished();
      tempInst = m_AttributeFilter.output();
    }

    if (m_HasClass)
      newVals[m_OutputNumAtts - 1] = instance.value(instance.classIndex());

    if (m_MaxAttributes > 0)
      numAttsLowerBound = m_NumAttribs - m_MaxAttributes;
    else
      numAttsLowerBound = 0;
    if (numAttsLowerBound < 0)
      numAttsLowerBound = 0;
    
    cumulative = 0;
    for (i = m_NumAttribs - 1; i >= numAttsLowerBound; i--) {
      tempval = 0.0;
      for (j = 0; j < m_NumAttribs; j++)
	tempval += m_Eigenvectors[j][m_SortedEigens[i]] * tempInst.value(j);

      newVals[m_NumAttribs - i - 1] = tempval;
      cumulative += m_Eigenvalues[m_SortedEigens[i]];
      if ((cumulative / m_SumOfEigenValues) >= m_CoverVariance)
	break;
    }

    // create instance
    if (instance instanceof SparseInstance)
      result = new SparseInstance(instance.weight(), newVals);
    else
      result = new Instance(instance.weight(), newVals);
    
    return result;
  }