Index: /branches/2904_CalculateImpacts/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs
===================================================================
--- /branches/2904_CalculateImpacts/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs	(revision 15814)
+++ /branches/2904_CalculateImpacts/3.4/Implementation/Regression/RegressionSolutionVariableImpactsCalculator.cs	(revision 15815)
@@ -56,16 +56,20 @@
     private const string DataPartitionParameterName = "DataPartition";
 
-    public IFixedValueParameter<EnumValue<ReplacementMethodEnum>> ReplacementParameter {
+    public IFixedValueParameter<EnumValue<ReplacementMethodEnum>> ReplacementParameter
+    {
       get { return (IFixedValueParameter<EnumValue<ReplacementMethodEnum>>)Parameters[ReplacementParameterName]; }
     }
-    public IFixedValueParameter<EnumValue<DataPartitionEnum>> DataPartitionParameter {
+    public IFixedValueParameter<EnumValue<DataPartitionEnum>> DataPartitionParameter
+    {
       get { return (IFixedValueParameter<EnumValue<DataPartitionEnum>>)Parameters[DataPartitionParameterName]; }
     }
 
-    public ReplacementMethodEnum ReplacementMethod {
+    public ReplacementMethodEnum ReplacementMethod
+    {
       get { return ReplacementParameter.Value.Value; }
       set { ReplacementParameter.Value.Value = value; }
     }
-    public DataPartitionEnum DataPartition {
+    public DataPartitionEnum DataPartition
+    {
       get { return DataPartitionParameter.Value.Value; }
       set { DataPartitionParameter.Value.Value = value; }
@@ -92,4 +96,101 @@
     }
 
+    private static void PrepareData(DataPartitionEnum partition,
+      IRegressionSolution solution,
+      out IEnumerable<int> rows,
+      out IEnumerable<double> targetValues,
+      out double originalR2) {
+      OnlineCalculatorError error;
+
+      switch (partition) {
+        case DataPartitionEnum.All:
+          rows = solution.ProblemData.AllIndices;
+          targetValues = solution.ProblemData.TargetVariableValues.ToList();
+          originalR2 = OnlinePearsonsRCalculator.Calculate(solution.ProblemData.TargetVariableValues, solution.EstimatedValues, out error);
+          if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during R² calculation.");
+          originalR2 = originalR2 * originalR2;
+          break;
+        case DataPartitionEnum.Training:
+          rows = solution.ProblemData.TrainingIndices;
+          targetValues = solution.ProblemData.TargetVariableTrainingValues.ToList();
+          originalR2 = solution.TrainingRSquared;
+          break;
+        case DataPartitionEnum.Test:
+          rows = solution.ProblemData.TestIndices;
+          targetValues = solution.ProblemData.TargetVariableTestValues.ToList();
+          originalR2 = solution.TestRSquared;
+          break;
+        default: throw new ArgumentException(string.Format("DataPartition {0} cannot be handled.", partition));
+      }
+    }
+
+    private static double CalculateImpactForDouble(string variableName,
+      IRegressionSolution solution,
+      ModifiableDataset modifiableDataset,
+      IEnumerable<int> rows,
+      IEnumerable<double> targetValues,
+      double originalR2,
+      ReplacementMethodEnum replacementMethod) {
+      OnlineCalculatorError error;
+      var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, variableName, modifiableDataset, rows, replacementMethod);
+      var newR2 = OnlinePearsonsRCalculator.Calculate(targetValues, newEstimates, out error);
+      if (error != OnlineCalculatorError.None) { throw new InvalidOperationException("Error during R² calculation with replaced inputs."); }
+      return originalR2 - (newR2 * newR2);
+    }
+
+    private static double CalculateImpactForString(string variableName,
+      IRegressionSolution solution,
+      ModifiableDataset modifiableDataset,
+      IEnumerable<int> rows,
+      IEnumerable<double> targetValues,
+      double originalR2,
+      FactorReplacementMethodEnum factorReplacementMethod) {
+
+      OnlineCalculatorError error;
+      if (factorReplacementMethod == FactorReplacementMethodEnum.Best) {
+        // try replacing with all possible values and find the best replacement value
+        var smallestImpact = double.PositiveInfinity;
+        foreach (var repl in solution.ProblemData.Dataset.GetStringValues(variableName, rows).Distinct()) {
+          var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, variableName, modifiableDataset, rows, Enumerable.Repeat(repl, solution.ProblemData.Dataset.Rows));
+          var newR2 = OnlinePearsonsRCalculator.Calculate(targetValues, newEstimates, out error);
+          if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during R² calculation with replaced inputs.");
+
+          var curImpact = originalR2 - (newR2 * newR2);
+          if (curImpact < smallestImpact) smallestImpact = curImpact;
+        }
+        return smallestImpact;
+      } else {
+        // for replacement methods shuffle and mode
+        // calculate impacts for factor variables
+        var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, variableName, modifiableDataset, rows, factorReplacementMethod);
+        var newR2 = OnlinePearsonsRCalculator.Calculate(targetValues, newEstimates, out error);
+        if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during R² calculation with replaced inputs.");
+
+        return originalR2 - (newR2 * newR2);
+      }
+    }
+    public static double CalculateImpact(string variableName,
+      IRegressionSolution solution,
+      DataPartitionEnum data = DataPartitionEnum.Training,
+      ReplacementMethodEnum replacementMethod = ReplacementMethodEnum.Median,
+      FactorReplacementMethodEnum factorReplacementMethod = FactorReplacementMethodEnum.Best,
+      IEnumerable<int> rows = null,
+      IEnumerable<double> targetValues = null,
+    double originalR2 = -1) {
+
+      double impact = 0;
+      var modifiableDataset = ((Dataset)solution.ProblemData.Dataset).ToModifiable();
+
+      // calculate impacts for double variables
+      if (solution.ProblemData.Dataset.VariableHasType<double>(variableName)) {
+        impact = CalculateImpactForDouble(variableName, solution, modifiableDataset, rows, targetValues, originalR2, replacementMethod);
+      } else if (solution.ProblemData.Dataset.VariableHasType<string>(variableName)) {
+        impact = CalculateImpactForString(variableName, solution, modifiableDataset, rows, targetValues, originalR2, factorReplacementMethod);
+      } else {
+        throw new NotSupportedException("Variable not supported");
+      }
+      return impact;
+    }
+
     public static IEnumerable<Tuple<string, double>> CalculateImpacts(
       IRegressionSolution solution,
@@ -99,44 +200,18 @@
       Func<double, string, bool> progressCallback = null) {
 
-      var problemData = solution.ProblemData;
-      var dataset = problemData.Dataset;
-
       IEnumerable<int> rows;
       IEnumerable<double> targetValues;
       double originalR2 = -1;
 
-      OnlineCalculatorError error;
-
-      switch (data) {
-        case DataPartitionEnum.All:
-          rows = solution.ProblemData.AllIndices;
-          targetValues = problemData.TargetVariableValues.ToList();
-          originalR2 = OnlinePearsonsRCalculator.Calculate(problemData.TargetVariableValues, solution.EstimatedValues, out error);
-          if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during R² calculation.");
-          originalR2 = originalR2 * originalR2;
-          break;
-        case DataPartitionEnum.Training:
-          rows = problemData.TrainingIndices;
-          targetValues = problemData.TargetVariableTrainingValues.ToList();
-          originalR2 = solution.TrainingRSquared;
-          break;
-        case DataPartitionEnum.Test:
-          rows = problemData.TestIndices;
-          targetValues = problemData.TargetVariableTestValues.ToList();
-          originalR2 = solution.TestRSquared;
-          break;
-        default: throw new ArgumentException(string.Format("DataPartition {0} cannot be handled.", data));
-      }
+      PrepareData(data, solution, out rows, out targetValues, out originalR2);
 
       var impacts = new Dictionary<string, double>();
-      var modifiableDataset = ((Dataset)dataset).ToModifiable();
-
-      var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(solution.Model.VariablesUsedForPrediction));
-      var allowedInputVariables = dataset.VariableNames.Where(v => inputvariables.Contains(v)).ToList();
+      var inputvariables = new HashSet<string>(solution.ProblemData.AllowedInputVariables.Union(solution.Model.VariablesUsedForPrediction));
+      var allowedInputVariables = solution.ProblemData.Dataset.VariableNames.Where(v => inputvariables.Contains(v)).ToList();
 
       int curIdx = 0;
-      int count = allowedInputVariables.Where(problemData.Dataset.VariableHasType<double>).Count();
+      int count = allowedInputVariables.Where(solution.ProblemData.Dataset.VariableHasType<double>).Count();
       // calculate impacts for double variables
-      foreach (var inputVariable in allowedInputVariables.Where(problemData.Dataset.VariableHasType<double>)) {
+      foreach (var inputVariable in allowedInputVariables) {
         //Report the current progress in percent. If the callback returns true, it means the execution shall be stopped
         if (progressCallback != null) {
@@ -144,48 +219,9 @@
           if (progressCallback((double)curIdx / count, string.Format("Calculating impact for variable {0} ({1} of {2})", inputVariable, curIdx, count))) { return null; }
         }
-        var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, inputVariable, modifiableDataset, rows, replacementMethod);
-        var newR2 = OnlinePearsonsRCalculator.Calculate(targetValues, newEstimates, out error);
-        if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during R² calculation with replaced inputs.");
-
-        newR2 = newR2 * newR2;
-        var impact = originalR2 - newR2;
-        impacts[inputVariable] = impact;
-      }
-
-      // calculate impacts for string variables
-      foreach (var inputVariable in allowedInputVariables.Where(problemData.Dataset.VariableHasType<string>)) {
-        if (factorReplacementMethod == FactorReplacementMethodEnum.Best) {
-          // try replacing with all possible values and find the best replacement value
-          var smallestImpact = double.PositiveInfinity;
-          foreach (var repl in problemData.Dataset.GetStringValues(inputVariable, rows).Distinct()) {
-            var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, inputVariable, modifiableDataset, rows,
-              Enumerable.Repeat(repl, dataset.Rows));
-            var newR2 = OnlinePearsonsRCalculator.Calculate(targetValues, newEstimates, out error);
-            if (error != OnlineCalculatorError.None)
-              throw new InvalidOperationException("Error during R² calculation with replaced inputs.");
-
-            newR2 = newR2 * newR2;
-            var impact = originalR2 - newR2;
-            if (impact < smallestImpact) smallestImpact = impact;
-          }
-          impacts[inputVariable] = smallestImpact;
-        } else {
-          // for replacement methods shuffle and mode
-          // calculate impacts for factor variables
-
-          var newEstimates = EvaluateModelWithReplacedVariable(solution.Model, inputVariable, modifiableDataset, rows,
-            factorReplacementMethod);
-          var newR2 = OnlinePearsonsRCalculator.Calculate(targetValues, newEstimates, out error);
-          if (error != OnlineCalculatorError.None)
-            throw new InvalidOperationException("Error during R² calculation with replaced inputs.");
-
-          newR2 = newR2 * newR2;
-          var impact = originalR2 - newR2;
-          impacts[inputVariable] = impact;
-        }
-      } // foreach
+        impacts[inputVariable] = CalculateImpact(inputVariable, solution, data, replacementMethod, factorReplacementMethod, rows, targetValues, originalR2);
+      }
+
       return impacts.OrderByDescending(i => i.Value).Select(i => Tuple.Create(i.Key, i.Value));
     }
-
 
     private static IEnumerable<double> EvaluateModelWithReplacedVariable(IRegressionModel model, string variable, ModifiableDataset dataset, IEnumerable<int> rows, ReplacementMethodEnum replacement = ReplacementMethodEnum.Median) {
