Index: trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/Normalization.java
===================================================================
--- trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/Normalization.java	(revision 50)
+++ trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/Normalization.java	(revision 51)
@@ -17,8 +17,5 @@
 import org.apache.commons.collections4.list.SetUniqueList;
 
-import weka.core.Attribute;
-import weka.core.Instance;
 import weka.core.Instances;
-import weka.experiment.Stats;
 
 /**
@@ -35,39 +32,8 @@
     @Override
     public void apply(Instances testdata, SetUniqueList<Instances> traindataSet) {
-        final Attribute classAtt = testdata.classAttribute();
-
-        for (int i = 0; i < testdata.numAttributes(); i++) {
-            if (!testdata.attribute(i).equals(classAtt)) {
-                Stats teststats = testdata.attributeStats(i).numericStats;
-
-                double minVal = teststats.min;
-                double maxVal = teststats.max;
-
-                for (Instances traindata : traindataSet) {
-                    Stats trainstats = traindata.attributeStats(i).numericStats;
-                    if (minVal > trainstats.min) {
-                        minVal = trainstats.min;
-                    }
-                    if (maxVal < trainstats.max) {
-                        maxVal = trainstats.max;
-                    }
-                }
-
-                for (int j = 0; j < testdata.numInstances(); j++) {
-                    Instance inst = testdata.instance(j);
-                    double newValue = (inst.value(i) - minVal) / (maxVal - minVal);
-                    inst.setValue(i, newValue);
-                }
-
-                for (Instances traindata : traindataSet) {
-                    for (int j = 0; j < traindata.numInstances(); j++) {
-                        Instance inst = traindata.instance(j);
-                        double newValue = (inst.value(i) - minVal) / (maxVal - minVal);
-                        inst.setValue(i, newValue);
-                    }
-                }
-            }
+        NormalizationUtil.minMax(testdata);
+        for (Instances instances : traindataSet) {
+            NormalizationUtil.minMax(instances);
         }
-
     }
 
@@ -78,34 +44,6 @@
     @Override
     public void apply(Instances testdata, Instances traindata) {
-        final Attribute classAtt = testdata.classAttribute();
-
-        for (int i = 0; i < testdata.numAttributes(); i++) {
-            if (!testdata.attribute(i).equals(classAtt)) {
-                Stats teststats = testdata.attributeStats(i).numericStats;
-
-                double minVal = teststats.min;
-                double maxVal = teststats.max;
-
-                Stats trainstats = traindata.attributeStats(i).numericStats;
-                if (minVal > trainstats.min) {
-                    minVal = trainstats.min;
-                }
-                if (maxVal < trainstats.max) {
-                    maxVal = trainstats.max;
-                }
-
-                for (int j = 0; j < testdata.numInstances(); j++) {
-                    Instance inst = testdata.instance(j);
-                    double newValue = (inst.value(i) - minVal) / (maxVal - minVal);
-                    inst.setValue(i, newValue);
-                }
-
-                for (int j = 0; j < traindata.numInstances(); j++) {
-                    Instance inst = traindata.instance(j);
-                    double newValue = (inst.value(i) - minVal) / (maxVal - minVal);
-                    inst.setValue(i, newValue);
-                }
-            }
-        }
+        NormalizationUtil.minMax(testdata);
+        NormalizationUtil.minMax(traindata);
     }
 
Index: trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/NormalizationUtil.java
===================================================================
--- trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/NormalizationUtil.java	(revision 51)
+++ trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/NormalizationUtil.java	(revision 51)
@@ -0,0 +1,175 @@
+// Copyright 2015 Georg-August-Universität Göttingen, Germany
+//
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+
+package de.ugoe.cs.cpdp.dataprocessing;
+
+import org.apache.commons.collections4.list.SetUniqueList;
+
+import weka.core.Instance;
+import weka.core.Instances;
+
+/**
+ * <p>
+ * Helper class for normalization of data sets.
+ * </p>
+ * 
+ * @author Steffen Herbold
+ */
+public class NormalizationUtil {
+
+    /**
+     * <p>
+     * Min-Max normalization to scale all data to the interval [0,1] (N1 in Transfer Defect Learning
+     * by Nam et al.).
+     * </p>
+     *
+     * @param data
+     *            data that is normalized
+     */
+    public static void minMax(Instances data) {
+        for (int j = 0; j < data.numAttributes(); j++) {
+            if (data.classIndex() != j) {
+                double min = data.attributeStats(j).numericStats.min;
+                double max = data.attributeStats(j).numericStats.max;
+
+                for (int i = 0; i < data.numInstances(); i++) {
+                    Instance inst = data.instance(i);
+                    double newValue = (inst.value(j) - min) / (max - min);
+                    inst.setValue(j, newValue);
+                }
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * Z-Score normalization (N2 in Transfer Defect Learning by Nam et al.).
+     * </p>
+     *
+     * @param data
+     *            data that is normalized
+     */
+    public static void zScore(Instances data) {
+        final double[] mean = new double[data.numAttributes()];
+        final double[] std = new double[data.numAttributes()];
+
+        // get means and stddevs of data
+        for (int j = 0; j < data.numAttributes(); j++) {
+            if (data.classIndex() != j) {
+                mean[j] = data.meanOrMode(j);
+                std[j] = Math.sqrt(data.variance(j));
+            }
+        }
+        applyZScore(data, mean, std);
+    }
+
+    /**
+     * <p>
+     * Z-Score normalization using the mean and std of the training data (N3 in Transfer Defect
+     * Learning by Nam et al.).
+     * </p>
+     *
+     * @param testdata
+     *            test data of the target product
+     * @param traindata
+     *            training data
+     */
+    public static void zScoreTraining(Instances testdata, Instances traindata) {
+        final double[] mean = new double[testdata.numAttributes()];
+        final double[] std = new double[testdata.numAttributes()];
+
+        // get means of training
+        for (int j = 0; j < traindata.numAttributes(); j++) {
+            if (traindata.classIndex() != j) {
+                mean[j] = traindata.meanOrMode(j);
+                std[j] = Math.sqrt(traindata.variance(j));
+            }
+        }
+
+        applyZScore(testdata, mean, std);
+        applyZScore(traindata, mean, std);
+    }
+
+    /**
+     * <p>
+     * Z-Score normalization using the mean and std of the test data (N4 in Transfer Defect Learning
+     * by Nam et al.).
+     * </p>
+     *
+     * @param testdata
+     *            test data of the target product
+     * @param traindata
+     *            training data
+     */
+    public static void zScoreTarget(Instances testdata, Instances traindata) {
+        final double[] mean = new double[testdata.numAttributes()];
+        final double[] std = new double[testdata.numAttributes()];
+
+        // get means of testdata
+        for (int j = 0; j < testdata.numAttributes(); j++) {
+            if (testdata.classIndex() != j) {
+                mean[j] = testdata.meanOrMode(j);
+                std[j] = Math.sqrt(testdata.variance(j));
+            }
+        }
+
+        applyZScore(testdata, mean, std);
+        applyZScore(traindata, mean, std);
+    }
+
+    /**
+     * <p>
+     * Z-Score normalization using the mean and std of the test data (N4 in Transfer Defect Learning
+     * by Nam et al.).
+     * </p>
+     *
+     * @param testdata
+     *            test data of the target product
+     * @param traindata
+     *            training data
+     */
+    public static void zScoreTarget(Instances testdata, SetUniqueList<Instances> traindataSet) {
+        final double[] mean = new double[testdata.numAttributes()];
+        final double[] std = new double[testdata.numAttributes()];
+
+        // get means of testdata
+        for (int j = 0; j < testdata.numAttributes(); j++) {
+            if (testdata.classIndex() != j) {
+                mean[j] = testdata.meanOrMode(j);
+                std[j] = Math.sqrt(testdata.variance(j));
+            }
+        }
+
+        applyZScore(testdata, mean, std);
+        for (Instances traindata : traindataSet) {
+            applyZScore(traindata, mean, std);
+        }
+    }
+
+    /**
+     * <p>
+     * Internal helper function
+     * </p>
+     */
+    private static void applyZScore(Instances data, double[] mean, double[] std) {
+        for (int i = 0; i < data.numInstances(); i++) {
+            Instance instance = data.instance(i);
+            for (int j = 0; j < data.numAttributes(); j++) {
+                if (data.classIndex() != j) {
+                    instance.setValue(j, instance.value(j) - mean[j] / std[j]);
+                }
+            }
+        }
+    }
+}
Index: trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/TCAPlusNormalization.java
===================================================================
--- trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/TCAPlusNormalization.java	(revision 51)
+++ trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/TCAPlusNormalization.java	(revision 51)
@@ -0,0 +1,118 @@
+package de.ugoe.cs.cpdp.dataprocessing;
+
+import org.apache.commons.math3.ml.distance.EuclideanDistance;
+
+import weka.core.Instances;
+
+// normalization selected according to TCA+ rules (TCA has to be applied separately
+public class TCAPlusNormalization implements IProcessesingStrategy {
+
+    private class DistChar {
+        private final double mean;
+        private final double std;
+        private final double min;
+        private final double max;
+        private int num;
+        private DistChar(double mean, double std, double min, double max, int num) {
+            this.mean = mean;
+            this.std = std;
+            this.min = min;
+            this.max = max;
+            this.num = num;
+        }
+    }
+    
+    /**
+     * Does not have parameters. String is ignored.
+     * 
+     * @param parameters
+     *            ignored
+     */
+    @Override
+    public void setParameter(String parameters) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void apply(Instances testdata, Instances traindata) {
+        applyTCAPlus(testdata, traindata);
+    }
+    
+    private void applyTCAPlus(Instances testdata, Instances traindata) {
+        DistChar dcTest = datasetDistance(testdata);
+        DistChar dcTrain = datasetDistance(traindata);
+        
+        // RULE 1:
+        if( 0.9*dcTrain.mean<=dcTest.mean && 1.1*dcTrain.mean>=dcTest.mean &&
+            0.9*dcTrain.std<=dcTest.std && 1.1*dcTrain.std>=dcTest.std) {
+            // do nothing
+        }
+        // RULE 2:
+        else if((0.4*dcTrain.min>dcTest.min || 1.6*dcTrain.min<dcTest.min) &&
+                (0.4*dcTrain.max>dcTest.max || 1.6*dcTrain.min<dcTest.max) &&
+                (0.4*dcTrain.min>dcTest.num || 1.6*dcTrain.min<dcTest.num)) {
+            NormalizationUtil.minMax(testdata);
+            NormalizationUtil.minMax(traindata);
+        }
+        // RULE 3:
+        else if((0.4*dcTrain.std>dcTest.std && dcTrain.num<dcTest.num) || 
+                (1.6*dcTrain.std<dcTest.std)&& dcTrain.num>dcTest.num) {
+            NormalizationUtil.zScoreTraining(testdata, traindata);
+        }
+        // RULE 4:
+        else if((0.4*dcTrain.std>dcTest.std && dcTrain.num>dcTest.num) || 
+                (1.6*dcTrain.std<dcTest.std)&& dcTrain.num<dcTest.num) {
+            NormalizationUtil.zScoreTarget(testdata, traindata);
+        }
+        //RULE 5:
+        else {
+            NormalizationUtil.zScore(testdata);
+            NormalizationUtil.zScore(traindata);
+        }
+    }
+    
+    private DistChar datasetDistance(Instances data) {
+        double distance;
+        double sumAll = 0.0;
+        double sumAllQ = 0.0;
+        double min = Double.MAX_VALUE;
+        double max = Double.MIN_VALUE;
+        int numCmp = 0;
+        int l = 0;
+        double[] inst1 = new double[data.numAttributes()-1];
+        double[] inst2 = new double[data.numAttributes()-1];
+        EuclideanDistance euclideanDistance = new EuclideanDistance();
+        for( int i=0; i<data.numInstances(); i++ ) {
+            l=0;
+            for( int k=0; k<data.numAttributes(); k++ ) {
+                if( k!=data.classIndex() ) {
+                    inst1[l] = data.instance(i).value(k);
+                }
+            }
+            for( int j=0; j<data.numInstances(); j++ ) {
+                l=0;
+                for( int k=0; k<data.numAttributes(); k++ ) {
+                    if( k!=data.classIndex() ) {
+                        inst2[l] = data.instance(j).value(k);
+                    }
+                }
+                distance = euclideanDistance.compute(inst1, inst2);
+                sumAll += distance;
+                sumAllQ += distance*distance;
+                numCmp++;
+                if( distance < min ) {
+                    min = distance;
+                }
+                if( distance > max ) {
+                    max = distance;
+                }
+            }
+        }
+        double mean = sumAll / numCmp;
+        double std = Math.sqrt((sumAllQ-(sumAll*sumAll)/numCmp) *
+                                  (1.0d / (numCmp - 1)));
+        return new DistChar(mean, std, min, max, data.numInstances());
+    }
+
+}
Index: trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/ZScoreNormalization.java
===================================================================
--- trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/ZScoreNormalization.java	(revision 50)
+++ trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/ZScoreNormalization.java	(revision 51)
@@ -17,6 +17,4 @@
 import org.apache.commons.collections4.list.SetUniqueList;
 
-import weka.core.Attribute;
-import weka.core.Instance;
 import weka.core.Instances;
 
@@ -45,7 +43,7 @@
     @Override
     public void apply(Instances testdata, SetUniqueList<Instances> traindataSet) {
-        normalize(testdata);
+        NormalizationUtil.zScore(testdata);
         for (Instances instances : traindataSet) {
-            normalize(instances);
+            NormalizationUtil.zScore(instances);
         }
     }
@@ -57,35 +55,6 @@
     @Override
     public void apply(Instances testdata, Instances traindata) {
-        normalize(testdata);
-        normalize(traindata);
+        NormalizationUtil.zScore(testdata);
+        NormalizationUtil.zScore(traindata);
     }
-
-    private void normalize(Instances instances) {
-        instances.toString();
-        final Attribute classAttribute = instances.classAttribute();
-
-        final double[] means = new double[instances.numAttributes()];
-        final double[] stddevs = new double[instances.numAttributes()];
-
-        // get means and stddevs of data
-        for (int j = 0; j < instances.numAttributes(); j++) {
-            if (instances.attribute(j) != classAttribute) {
-                means[j] = instances.meanOrMode(j);
-                stddevs[j] = Math.sqrt(instances.variance(j));
-            }
-        }
-        for (int i = 0; i < instances.numAttributes(); i++) {
-            if (!instances.attribute(i).equals(classAttribute)) {
-                for (int j = 0; j < instances.numInstances(); j++) {
-                    Instance inst = instances.get(i);
-                    double newValue = (inst.value(i) - means[i]) / stddevs[i];
-                    if (newValue == Double.NaN) {
-                        System.out.println("foooooo");
-                    }
-                    inst.setValue(i, newValue);
-                }
-            }
-        }
-    }
-
 }
Index: trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/ZScoreTargetNormalization.java
===================================================================
--- trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/ZScoreTargetNormalization.java	(revision 50)
+++ trunk/CrossPare/src/de/ugoe/cs/cpdp/dataprocessing/ZScoreTargetNormalization.java	(revision 51)
@@ -17,6 +17,4 @@
 import org.apache.commons.collections4.list.SetUniqueList;
 
-import weka.core.Attribute;
-import weka.core.Instance;
 import weka.core.Instances;
 
@@ -46,38 +44,5 @@
     @Override
     public void apply(Instances testdata, SetUniqueList<Instances> traindataSet) {
-        final Attribute classAttribute = testdata.classAttribute();
-
-        final double[] meanTest = new double[testdata.numAttributes()];
-        final double[] stddevTest = new double[testdata.numAttributes()];
-
-        // get means of testdata
-        for (int j = 0; j < testdata.numAttributes(); j++) {
-            if (testdata.attribute(j) != classAttribute) {
-                meanTest[j] = testdata.meanOrMode(j);
-                stddevTest[j] = Math.sqrt(testdata.variance(j));
-            }
-        }
-
-        // preprocess test data
-        for (int i = 0; i < testdata.numInstances(); i++) {
-            Instance instance = testdata.instance(i);
-            for (int j = 0; j < testdata.numAttributes(); j++) {
-                if (testdata.attribute(j) != classAttribute) {
-                    instance.setValue(j, instance.value(j) - meanTest[j] / stddevTest[j]);
-                }
-            }
-        }
-
-        // preprocess training data
-        for (Instances traindata : traindataSet) {
-            for (int i = 0; i < traindata.numInstances(); i++) {
-                Instance instance = traindata.instance(i);
-                for (int j = 0; j < testdata.numAttributes(); j++) {
-                    if (testdata.attribute(j) != classAttribute) {
-                        instance.setValue(j, instance.value(j) - meanTest[j] / stddevTest[j]);
-                    }
-                }
-            }
-        }
+        NormalizationUtil.zScoreTarget(testdata, traindataSet);
     }
 
@@ -88,36 +53,5 @@
     @Override
     public void apply(Instances testdata, Instances traindata) {
-        final Attribute classAttribute = testdata.classAttribute();
-
-        final double[] meanTest = new double[testdata.numAttributes()];
-        final double[] stddevTest = new double[testdata.numAttributes()];
-
-        // get means of testdata
-        for (int j = 0; j < testdata.numAttributes(); j++) {
-            if (testdata.attribute(j) != classAttribute) {
-                meanTest[j] = testdata.meanOrMode(j);
-                stddevTest[j] = Math.sqrt(testdata.variance(j));
-            }
-        }
-
-        // preprocess test data
-        for (int i = 0; i < testdata.numInstances(); i++) {
-            Instance instance = testdata.instance(i);
-            for (int j = 0; j < testdata.numAttributes(); j++) {
-                if (testdata.attribute(j) != classAttribute) {
-                    instance.setValue(j, instance.value(j) - meanTest[j] / stddevTest[j]);
-                }
-            }
-        }
-
-        // preprocess training data
-        for (int i = 0; i < traindata.numInstances(); i++) {
-            Instance instance = traindata.instance(i);
-            for (int j = 0; j < testdata.numAttributes(); j++) {
-                if (testdata.attribute(j) != classAttribute) {
-                    instance.setValue(j, instance.value(j) - meanTest[j] / stddevTest[j]);
-                }
-            }
-        }
+        NormalizationUtil.zScoreTarget(testdata, traindata);
     }
 }
