Index: /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing.Views/3.4/HeuristicLab.DataPreprocessing.Views-3.4.csproj
===================================================================
--- /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing.Views/3.4/HeuristicLab.DataPreprocessing.Views-3.4.csproj	(revision 14520)
+++ /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing.Views/3.4/HeuristicLab.DataPreprocessing.Views-3.4.csproj	(revision 14521)
@@ -317,4 +317,9 @@
       <Name>HeuristicLab.DataPreprocessing-3.4</Name>
     </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="ScatterPlotSingleView.resx">
+      <DependentUpon>ScatterPlotSingleView.cs</DependentUpon>
+    </EmbeddedResource>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Index: /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing.Views/3.4/ScatterPlotSingleView.Designer.cs
===================================================================
--- /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing.Views/3.4/ScatterPlotSingleView.Designer.cs	(revision 14520)
+++ /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing.Views/3.4/ScatterPlotSingleView.Designer.cs	(revision 14521)
@@ -45,6 +45,8 @@
     /// </summary>
     private void InitializeComponent() {
+      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ScatterPlotSingleView));
       this.scatterPlotControl = new HeuristicLab.Analysis.Views.ScatterPlotControl();
       this.groupBox1 = new System.Windows.Forms.GroupBox();
+      this.useGradientCheckBox = new System.Windows.Forms.CheckBox();
       this.label3 = new System.Windows.Forms.Label();
       this.label2 = new System.Windows.Forms.Label();
@@ -59,4 +61,8 @@
       this.label4 = new System.Windows.Forms.Label();
       this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+      this.gradientPanel = new System.Windows.Forms.Panel();
+      this.gradientMinimumLabel = new System.Windows.Forms.Label();
+      this.gradientMaximumLabel = new System.Windows.Forms.Label();
+      this.gradientPictureBox = new System.Windows.Forms.PictureBox();
       this.groupBox1.SuspendLayout();
       this.regressionGroupBox.SuspendLayout();
@@ -66,17 +72,22 @@
       this.splitContainer1.Panel2.SuspendLayout();
       this.splitContainer1.SuspendLayout();
+      this.gradientPanel.SuspendLayout();
+      ((System.ComponentModel.ISupportInitialize)(this.gradientPictureBox)).BeginInit();
       this.SuspendLayout();
       // 
       // scatterPlotControl
       // 
+      this.scatterPlotControl.Caption = "View";
       this.scatterPlotControl.Content = null;
       this.scatterPlotControl.Dock = System.Windows.Forms.DockStyle.Fill;
       this.scatterPlotControl.Location = new System.Drawing.Point(0, 0);
       this.scatterPlotControl.Name = "scatterPlotControl";
-      this.scatterPlotControl.Size = new System.Drawing.Size(687, 517);
+      this.scatterPlotControl.ReadOnly = false;
+      this.scatterPlotControl.Size = new System.Drawing.Size(618, 517);
       this.scatterPlotControl.TabIndex = 0;
       // 
       // groupBox1
       // 
+      this.groupBox1.Controls.Add(this.useGradientCheckBox);
       this.groupBox1.Controls.Add(this.label3);
       this.groupBox1.Controls.Add(this.label2);
@@ -88,8 +99,19 @@
       this.groupBox1.Location = new System.Drawing.Point(0, 0);
       this.groupBox1.Name = "groupBox1";
-      this.groupBox1.Size = new System.Drawing.Size(172, 137);
+      this.groupBox1.Size = new System.Drawing.Size(172, 150);
       this.groupBox1.TabIndex = 1;
       this.groupBox1.TabStop = false;
       this.groupBox1.Text = "Variables";
+      // 
+      // useGradientCheckBox
+      // 
+      this.useGradientCheckBox.AutoSize = true;
+      this.useGradientCheckBox.Location = new System.Drawing.Point(51, 121);
+      this.useGradientCheckBox.Name = "useGradientCheckBox";
+      this.useGradientCheckBox.Size = new System.Drawing.Size(115, 17);
+      this.useGradientCheckBox.TabIndex = 4;
+      this.useGradientCheckBox.Text = "Use Color Gradient";
+      this.useGradientCheckBox.UseVisualStyleBackColor = true;
+      this.useGradientCheckBox.CheckedChanged += new System.EventHandler(this.useGradientCheckBox_CheckedChanged);
       // 
       // label3
@@ -122,5 +144,5 @@
       // comboBoxGroup
       // 
-      this.comboBoxGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+      this.comboBoxGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
             | System.Windows.Forms.AnchorStyles.Right)));
       this.comboBoxGroup.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
@@ -135,5 +157,5 @@
       // comboBoxYVariable
       // 
-      this.comboBoxYVariable.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+      this.comboBoxYVariable.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
             | System.Windows.Forms.AnchorStyles.Right)));
       this.comboBoxYVariable.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
@@ -148,5 +170,5 @@
       // comboBoxXVariable
       // 
-      this.comboBoxXVariable.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+      this.comboBoxXVariable.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
             | System.Windows.Forms.AnchorStyles.Right)));
       this.comboBoxXVariable.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
@@ -166,5 +188,5 @@
       this.regressionGroupBox.Controls.Add(this.label4);
       this.regressionGroupBox.Dock = System.Windows.Forms.DockStyle.Top;
-      this.regressionGroupBox.Location = new System.Drawing.Point(0, 137);
+      this.regressionGroupBox.Location = new System.Drawing.Point(0, 150);
       this.regressionGroupBox.Name = "regressionGroupBox";
       this.regressionGroupBox.Size = new System.Drawing.Size(172, 78);
@@ -175,5 +197,5 @@
       // regressionTypeComboBox
       // 
-      this.regressionTypeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+      this.regressionTypeComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
             | System.Windows.Forms.AnchorStyles.Right)));
       this.regressionTypeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
@@ -187,5 +209,5 @@
       // polynomialRegressionOrderNumericUpDown
       // 
-      this.polynomialRegressionOrderNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+      this.polynomialRegressionOrderNumericUpDown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
             | System.Windows.Forms.AnchorStyles.Right)));
       this.polynomialRegressionOrderNumericUpDown.Location = new System.Drawing.Point(51, 47);
@@ -244,7 +266,54 @@
       // 
       this.splitContainer1.Panel2.Controls.Add(this.scatterPlotControl);
+      this.splitContainer1.Panel2.Controls.Add(this.gradientPanel);
       this.splitContainer1.Size = new System.Drawing.Size(863, 517);
       this.splitContainer1.SplitterDistance = 172;
       this.splitContainer1.TabIndex = 5;
+      // 
+      // gradientPanel
+      // 
+      this.gradientPanel.Controls.Add(this.gradientPictureBox);
+      this.gradientPanel.Controls.Add(this.gradientMinimumLabel);
+      this.gradientPanel.Controls.Add(this.gradientMaximumLabel);
+      this.gradientPanel.Dock = System.Windows.Forms.DockStyle.Right;
+      this.gradientPanel.Location = new System.Drawing.Point(618, 0);
+      this.gradientPanel.Name = "gradientPanel";
+      this.gradientPanel.Size = new System.Drawing.Size(69, 517);
+      this.gradientPanel.TabIndex = 1;
+      // 
+      // gradientMinimumLabel
+      // 
+      this.gradientMinimumLabel.BackColor = System.Drawing.Color.Transparent;
+      this.gradientMinimumLabel.Dock = System.Windows.Forms.DockStyle.Bottom;
+      this.gradientMinimumLabel.Location = new System.Drawing.Point(0, 492);
+      this.gradientMinimumLabel.Name = "gradientMinimumLabel";
+      this.gradientMinimumLabel.Size = new System.Drawing.Size(69, 25);
+      this.gradientMinimumLabel.TabIndex = 18;
+      this.gradientMinimumLabel.Text = "0.0";
+      this.gradientMinimumLabel.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+      // 
+      // gradientMaximumLabel
+      // 
+      this.gradientMaximumLabel.BackColor = System.Drawing.Color.Transparent;
+      this.gradientMaximumLabel.Dock = System.Windows.Forms.DockStyle.Top;
+      this.gradientMaximumLabel.Location = new System.Drawing.Point(0, 0);
+      this.gradientMaximumLabel.Name = "gradientMaximumLabel";
+      this.gradientMaximumLabel.Size = new System.Drawing.Size(69, 25);
+      this.gradientMaximumLabel.TabIndex = 17;
+      this.gradientMaximumLabel.Text = "1.0";
+      this.gradientMaximumLabel.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
+      // 
+      // gradientPictureBox
+      // 
+      this.gradientPictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+            | System.Windows.Forms.AnchorStyles.Left)));
+      this.gradientPictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+      this.gradientPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("GradientPictureBox.Image")));
+      this.gradientPictureBox.Location = new System.Drawing.Point(17, 29);
+      this.gradientPictureBox.Name = "gradientPictureBox";
+      this.gradientPictureBox.Size = new System.Drawing.Size(35, 460);
+      this.gradientPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+      this.gradientPictureBox.TabIndex = 19;
+      this.gradientPictureBox.TabStop = false;
       // 
       // ScatterPlotSingleView
@@ -264,4 +333,6 @@
       ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
       this.splitContainer1.ResumeLayout(false);
+      this.gradientPanel.ResumeLayout(false);
+      ((System.ComponentModel.ISupportInitialize)(this.gradientPictureBox)).EndInit();
       this.ResumeLayout(false);
 
@@ -284,4 +355,9 @@
     private System.Windows.Forms.Label label4;
     private System.Windows.Forms.SplitContainer splitContainer1;
+    private System.Windows.Forms.CheckBox useGradientCheckBox;
+    private System.Windows.Forms.Panel gradientPanel;
+    private System.Windows.Forms.Label gradientMinimumLabel;
+    private System.Windows.Forms.Label gradientMaximumLabel;
+    protected System.Windows.Forms.PictureBox gradientPictureBox;
   }
 }
Index: /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing.Views/3.4/ScatterPlotSingleView.cs
===================================================================
--- /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing.Views/3.4/ScatterPlotSingleView.cs	(revision 14520)
+++ /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing.Views/3.4/ScatterPlotSingleView.cs	(revision 14521)
@@ -22,8 +22,11 @@
 using System;
 using System.Collections.Generic;
+using System.Drawing;
 using System.Linq;
 using HeuristicLab.Analysis;
+using HeuristicLab.Common;
 using HeuristicLab.Core.Views;
 using HeuristicLab.MainForm;
+using HeuristicLab.MainForm.WindowsForms;
 using RegressionType = HeuristicLab.Analysis.ScatterPlotDataRowVisualProperties.ScatterPlotDataRowRegressionType;
 
@@ -33,4 +36,6 @@
   [Content(typeof(SingleScatterPlotContent), true)]
   public partial class ScatterPlotSingleView : ItemView {
+
+    private readonly string NoGroupItem = "-";
 
     public new SingleScatterPlotContent Content {
@@ -55,10 +60,10 @@
       comboBoxXVariable.Items.AddRange(variables.ToArray());
       comboBoxYVariable.Items.AddRange(variables.ToArray());
-      comboBoxGroup.Items.Add("-");
+      comboBoxGroup.Items.Add(NoGroupItem);
       for (int i = 0; i < Content.PreprocessingData.Columns; ++i) {
         if (Content.PreprocessingData.VariableHasType<double>(i)) {
-          double distinctValueCount = Content.PreprocessingData.GetValues<double>(i).GroupBy(x => x).Count();
-          if (distinctValueCount <= 20)
-            comboBoxGroup.Items.Add(Content.PreprocessingData.GetVariableName(i));
+          //double distinctValueCount = Content.PreprocessingData.GetValues<double>(i).GroupBy(x => x).Count();
+          //if (distinctValueCount <= 20)
+          comboBoxGroup.Items.Add(Content.PreprocessingData.GetVariableName(i));
         }
       }
@@ -86,4 +91,10 @@
     }
 
+    protected override void SetEnabledStateOfControls() {
+      base.SetEnabledStateOfControls();
+      useGradientCheckBox.Enabled = (string)comboBoxGroup.SelectedItem != NoGroupItem;
+      gradientPanel.Visible = useGradientCheckBox.Enabled && useGradientCheckBox.Checked; ;
+    }
+
     private void UpdateScatterPlot() {
       if (comboBoxXVariable.SelectedItem != null && comboBoxYVariable.SelectedItem != null && comboBoxGroup.SelectedItem != null) {
@@ -91,13 +102,28 @@
         var yVariable = (string)comboBoxYVariable.SelectedItem;
         var groupVariable = (string)comboBoxGroup.SelectedItem;
+
+        bool groupingActive = useGradientCheckBox.Checked && groupVariable != NoGroupItem;
+        double min = 0, max = 1;
+        if (groupingActive) {
+          var groupValues = Content.PreprocessingData.GetValues<double>(Content.PreprocessingData.GetColumnIndex(groupVariable))
+            .Distinct().OrderBy(x => x).ToList();
+          min = groupValues.First();
+          max = groupValues.Last();
+        }
         ScatterPlot scatterPlot = Content.CreateScatterPlot(xVariable, yVariable, groupVariable);
+        var rows = scatterPlot.Rows.ToList();
+        scatterPlot.Rows.Clear();
         var regressionType = (RegressionType)regressionTypeComboBox.SelectedValue;
         int order = (int)polynomialRegressionOrderNumericUpDown.Value;
-        foreach (var row in scatterPlot.Rows) {
+        foreach (var row in rows) {
           row.VisualProperties.PointSize = 6;
           row.VisualProperties.IsRegressionVisibleInLegend = false;
           row.VisualProperties.RegressionType = regressionType;
           row.VisualProperties.PolynomialRegressionOrder = order;
-        }
+          row.VisualProperties.IsVisibleInLegend = !useGradientCheckBox.Checked;
+          if (groupingActive)
+            row.VisualProperties.Color = GetColor(double.Parse(row.Name), min, max);
+        }
+        scatterPlot.Rows.AddRange(rows);
         var vp = scatterPlot.VisualProperties;
         vp.Title = string.Empty;
@@ -106,4 +132,9 @@
 
         scatterPlotControl.Content = scatterPlot;
+
+        if (groupingActive) {
+          gradientMinimumLabel.Text = min.ToString("G5");
+          gradientMaximumLabel.Text = max.ToString("G5");
+        }
 
         //save selected x and y variable in content
@@ -152,4 +183,6 @@
 
     private void comboBoxGroup_SelectedIndexChanged(object sender, EventArgs e) {
+      useGradientCheckBox.Enabled = (string)comboBoxGroup.SelectedItem != NoGroupItem;
+      gradientPanel.Visible = useGradientCheckBox.Enabled && useGradientCheckBox.Checked;
       UpdateScatterPlot();
     }
@@ -159,4 +192,5 @@
       var regressionType = (RegressionType)regressionTypeComboBox.SelectedValue;
       polynomialRegressionOrderNumericUpDown.Enabled = regressionType == RegressionType.Polynomial;
+
       UpdateRegressionLine();
     }
@@ -170,11 +204,68 @@
       int order = (int)polynomialRegressionOrderNumericUpDown.Value;
 
-      foreach (var row in scatterPlotControl.Content.Rows) {
+      var rows = scatterPlotControl.Content.Rows.ToList();
+      scatterPlotControl.Content.Rows.Clear();
+      foreach (var row in rows) {
         row.VisualProperties.IsRegressionVisibleInLegend = false;
         row.VisualProperties.RegressionType = regressionType;
         row.VisualProperties.PolynomialRegressionOrder = order;
       }
+      scatterPlotControl.Content.Rows.AddRange(rows);
     }
     #endregion
+
+    private void useGradientCheckBox_CheckedChanged(object sender, EventArgs e) {
+      gradientPanel.Visible = useGradientCheckBox.Enabled && useGradientCheckBox.Checked;
+
+      // remove rows and re-add them later to avoid firing visual property changd events
+      var rows = scatterPlotControl.Content.Rows.ToDictionary(r => r.Name, r => r);
+      scatterPlotControl.Content.Rows.Clear();
+
+      if (useGradientCheckBox.Checked) {
+        var groupVariable = (string)comboBoxGroup.SelectedItem;
+        if (groupVariable == NoGroupItem) return;
+
+        var groupValues = Content.PreprocessingData.GetValues<double>(Content.PreprocessingData.GetColumnIndex(groupVariable))
+          .Distinct().OrderBy(x => x).ToList();
+        double min = groupValues.First(), max = groupValues.Last();
+        foreach (var group in groupValues) {
+          ScatterPlotDataRow row;
+          if (rows.TryGetValue(group.ToString("R"), out row)) {
+            row.VisualProperties.Color = GetColor(group, min, max);
+            row.VisualProperties.IsVisibleInLegend = false;
+          }
+        }
+        gradientMinimumLabel.Text = min.ToString("G5");
+        gradientMaximumLabel.Text = max.ToString("G5");
+      } else {
+        foreach (var row in rows.Values) {
+          row.VisualProperties.Color = Color.Empty;
+          row.VisualProperties.IsVisibleInLegend = true;
+        }
+      }
+      scatterPlotControl.Content.Rows.AddRange(rows.Values);
+    }
+
+    private static Color GetColor(double value, double min, double max) {
+      if (double.IsNaN(value)) {
+        return Color.DarkGray;
+      }
+      var colors = ColorGradient.Colors;
+      int index = (int)((colors.Count - 1) * (value - min) / (max - min));
+      if (index >= colors.Count) index = colors.Count - 1;
+      if (index < 0) index = 0;
+      return colors[index];
+    }
+
+    private void BatchRowUpdate(Action<ScatterPlotDataRow> rowAction) {
+      var scatterPlot = scatterPlotControl.Content;
+      var rows = scatterPlot.Rows.ToList();
+      // remove rows and re-add them later to avoid firing visual property changd events
+      scatterPlot.Rows.Clear();
+      foreach (var row in rows) {
+        rowAction(row);
+      }
+      scatterPlot.Rows.AddRange(rows);
+    }
   }
 }
Index: /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing/3.4/Content/ScatterPlotContent.cs
===================================================================
--- /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing/3.4/Content/ScatterPlotContent.cs	(revision 14520)
+++ /branches/DataPreprocessing Enhancements/HeuristicLab.DataPreprocessing/3.4/Content/ScatterPlotContent.cs	(revision 14521)
@@ -72,8 +72,12 @@
       } else {
         var groupValues = PreprocessingData.GetValues<double>(PreprocessingData.GetColumnIndex(variableNameGroup));
-        var data = points.Zip(groupValues, (p, g) => new { p, g });
-        foreach (var groupValue in groupValues.Distinct()) {
+        var data = points.Zip(groupValues, (p, g) => new { p, g })
+          .Where(x => !double.IsNaN(x.p.X) && !double.IsNaN(x.p.Y) && !double.IsNaN(x.g) && !double.IsInfinity(x.p.X) && !double.IsInfinity(x.p.Y) && !double.IsInfinity(x.g))
+          .ToList();
+
+        foreach (var groupValue in groupValues.Distinct().OrderBy(g => g)) {
           var values = data.Where(x => x.g == groupValue).Select(v => v.p);
           var row = new ScatterPlotDataRow(string.Format("{0} ({1})", variableNameGroup, groupValue), "", values) {
+            Name = groupValue.ToString("R"),
             VisualProperties = { PointSize = 6 }
           };
