private void PlotNonlinearity(Nonlinearity nonlinearity, string distributionName, Color color, double lineThickness)
        {
            if (nonlinearity == null)
                return;

            var curve = nonlinearity.FiringRateCurve;

            // Prepare data in arrays.
            var x = new double[curve.GetLength(0)];
            var y = new double[curve.GetLength(0)];

            for (var index = 0; index < curve.GetLength(0); index++)
            {
                x[index] = curve[index, 0];
                y[index] = curve[index, 1];
            }

            // Add data sources.
            var yDataSource = new EnumerableDataSource<double>(y);
            yDataSource.SetYMapping(Y => Y);
            yDataSource.AddMapping(ShapeElementPointMarker.ToolTipTextProperty, Y => string.Format("Normal Value \n\n{0}", Y));

            var xDataSource = new EnumerableDataSource<double>(x);
            xDataSource.SetXMapping(X => X);

            var compositeDataSource = new CompositeDataSource(xDataSource, yDataSource);

            // MatchValuePlotter.Viewport.Restrictions.Add(new PhysicalProportionsRestriction { ProportionRatio = 500000 });
            var graph = ChartPlotter.AddLineGraph(compositeDataSource, color, lineThickness, distributionName);

            // Cache for later usage (e.g. change visibility).
            if (graph != null)
                _histogramGraphs.Add(graph);
        }
        private void GetSTAResponseHistogramPlotData(out Histogram rawStimuliSTAResponseHistogram, out double[] rawStimuliSTAMatchValues, out Histogram spikeTriggeredStimuliSTAResponseDiagram, out double[] spikeTriggeredStimuliSTAMatchValues, out Nonlinearity nonlinearity, bool recalcData = true)
        {
            rawStimuliSTAResponseHistogram = null;
            rawStimuliSTAMatchValues = null;
            spikeTriggeredStimuliSTAResponseDiagram = null;
            spikeTriggeredStimuliSTAMatchValues = null;
            nonlinearity = null;

            if (_spikes == null)
                return;

            // caching
            if (!recalcData)
            {
                rawStimuliSTAResponseHistogram = _rawStimuliSTAResponseHistogram;
                spikeTriggeredStimuliSTAResponseDiagram = _spikeTriggeredStimuliSTAResponseDiagram;
                nonlinearity = _nonlinearity;

                return;
            }

            var spikes = new List<double[][]>();

            if (Cell1CheckBox.IsChecked != null && Cell1CheckBox.IsChecked.Value)
                spikes.Add(_spikes[0]);

            if (Cell2CheckBox.IsChecked != null && Cell2CheckBox.IsChecked.Value)
                spikes.Add(_spikes[1]);

            if (Cell3CheckBox.IsChecked != null && Cell3CheckBox.IsChecked.Value)
                spikes.Add(_spikes[2]);

            if (Cell4CheckBox.IsChecked != null && Cell4CheckBox.IsChecked.Value)
                spikes.Add(_spikes[3]);

            if (spikes.Count == 0)
                return;

            int offset;
            if (!int.TryParse(OffsetTextbox.Text, out offset))
                offset = 13;

            int maxTime;
            if (!int.TryParse(TimeTextbox.Text, out maxTime))
                maxTime = 13;

            var rawStimuliHistogramBuckets = MatchValuesForRawStimuliBucketsUpDown.Value != null ? MatchValuesForRawStimuliBucketsUpDown.Value.Value : 200;
            var spikeTriggeredStimuliHistogramBuckets = MatchValuesForSpikeTriggeredStimuliBucketsUpDown.Value != null ? MatchValuesForSpikeTriggeredStimuliBucketsUpDown.Value.Value : 200;
            double[,] smoothKernel = null;
            bool useDynamicDivisorForEdges = false;

            GetSmoothKernel(out smoothKernel, out useDynamicDivisorForEdges);

            SpikeTriggeredAnalysis.CalculateSTAResponseHistogram(_stimuli, spikes.ToArray(), false, offset, maxTime, smoothKernel, useDynamicDivisorForEdges, rawStimuliHistogramBuckets, out rawStimuliSTAMatchValues, out rawStimuliSTAResponseHistogram);
            SpikeTriggeredAnalysis.CalculateSTAResponseHistogram(_stimuli, spikes.ToArray(), true, offset, maxTime, smoothKernel, useDynamicDivisorForEdges, spikeTriggeredStimuliHistogramBuckets, out spikeTriggeredStimuliSTAMatchValues, out spikeTriggeredStimuliSTAResponseDiagram);

            _rawStimuliSTAResponseHistogram = rawStimuliSTAResponseHistogram;
            _rawStimuliSTAMatchValues = rawStimuliSTAMatchValues;

            _spikeTriggeredStimuliSTAResponseDiagram = spikeTriggeredStimuliSTAResponseDiagram;
            _spikeTriggeredStimuliSTAMatchValues = spikeTriggeredStimuliSTAMatchValues;

            var frequencyRawStimuli = new NormalDistribution(rawStimuliSTAMatchValues.Average(), Math.Variance(rawStimuliSTAMatchValues), 10, rawStimuliSTAResponseHistogram.LowerBound, rawStimuliSTAResponseHistogram.UpperBound);
            var frequencySpikeTriggeredStimuli = new NormalDistribution(spikeTriggeredStimuliSTAMatchValues.Average(), Math.Variance(spikeTriggeredStimuliSTAMatchValues), 10, spikeTriggeredStimuliSTAResponseDiagram.LowerBound, spikeTriggeredStimuliSTAResponseDiagram.UpperBound);

            nonlinearity =
                // caching
                _nonlinearity = new Nonlinearity(frequencyRawStimuli, frequencySpikeTriggeredStimuli, 100);
        }