Exemple #1
0
        void view_variable_full()
        {
            IMatrixProvider im = DataSet.ForMatrixProviders(this._core).ShowList(this, null);

            if (im == null)
            {
                return;
            }

            Vector peak = this.PickVariable(im.Provide);

            if (peak != null)
            {
                StringBuilder sb = new StringBuilder();

                for (int i = 0; i < peak.Observations.Length; i++)
                {
                    ObservationInfo obs = peak.Observations[i];
                    sb.AppendLine(obs.Time + obs.Group.DisplayShortName + obs.Rep + " = " + peak.Values[i]);
                }

                FrmInputMultiLine.ShowFixed(this, "View full variable", peak.ToString(), "Full variable information", sb.ToString());
            }
        }
Exemple #2
0
        /// <summary>
        /// Does Arian's PCA-ANOVA idea.
        /// </summary>
        public double PcaAnova(IntensityMatrix source, Peak peak, Core core, List <GroupInfo> types, List <int> replicates)
        {
            Range times = GetOverlappingTimeRange(core, source, types);

            // Create a matrix thusly:
            // Control Replicate 1: <day1> <day2> <day3> ...
            // Control Replicate 2: <day1> <day2> <day3> ...
            // Control Replicate 3: <day1> <day2> <day3> ...
            // Drought Replicate 1: <day1> <day2> <day3> ...
            // Drought Replicate 2: <day1> <day2> <day3> ...
            // ...

            // Create and clear the matrix
            int rowCount = types.Count * replicates.Count;
            int colCount = times.Count;

            double[,] matrix = new double[rowCount, colCount];

            for (int r = 0; r < rowCount; r++)
            {
                for (int c = 0; c < colCount; c++)
                {
                    matrix[r, c] = double.NaN;
                }
            }

            // Create the group vector
            double[] groups = new double[rowCount];

            for (int r = 0; r < rowCount; r++)
            {
                groups[r] = types[r / replicates.Count].Order;
            }

            IReadOnlyList <double> raw = source.Find(peak).Values;  // TODO: Dirty

            // Fill out the values we know
            for (int i = 0; i < core.Observations.Count; i++)
            {
                ObservationInfo o         = core.Observations[i];
                int             typeIndex = types.IndexOf(o.Group);
                int             repIndex  = replicates.IndexOf(o.Rep);

                if (times.Contains(o.Time) && typeIndex != -1 && repIndex != -1)
                {
                    int timeIndex = o.Time - times.Min;

                    int row = typeIndex * replicates.Count + repIndex;
                    UiControls.Assert(double.IsNaN(matrix[row, timeIndex]), "Duplicate day/time/rep observations in dataset are not allowed.");
                    matrix[row, timeIndex] = raw[i];
                }
            }

            // Guess missing values
            for (int r = 0; r < rowCount; r++)
            {
                for (int c = 0; c < colCount; c++)
                {
                    if (double.IsNaN(matrix[r, c]))
                    {
                        // Missing values - average other values for this point
                        int repIndex  = r % replicates.Count;
                        int typeStart = r - repIndex;

                        double total = 0;
                        int    count = 0;

                        for (int rep = 0; rep < replicates.Count; rep++)
                        {
                            int newRow = typeStart + rep;

                            if (!double.IsNaN(matrix[newRow, c]))
                            {
                                total += matrix[newRow, c];
                                count += 1;
                            }
                        }

                        matrix[r, c] = total / count;
                    }
                }
            }

            // Now do that R stuff...

            var rMatrix = _r.CreateNumericMatrix(matrix);
            var rVector = _r.CreateNumericVector(groups);

            _r.SetSymbol("a", rMatrix);
            _r.SetSymbol("g", rVector);

            //R.Evaluate("write.csv(a, file = \"E:/MJR/Project/05. PEAS/AbstressData/Leaf/Positive/CCor/LP1131.cs.csv\")");

            try
            {
                double result = _r.Evaluate(
                    @"p = prcomp(a)
f = data.frame(y = p$x[,1], group = factor(g))
fit = lm(y ~ group, f)
an = anova(fit)
pval = an$""Pr(>F)""[1]").AsNumeric()[0];

                return(result);
            }
            catch (Exception ex)
            {
                throw new Exception("Something went wrong calculating PCA-ANOVA statistics. See inner exception for details. (Note that this error can occur if only 1 replicate is specified and PCA-ANOVA is calculated with missing values - make sure the replicates are specified correctly.)", ex);
            }
        }
Exemple #3
0
        /// <summary>
        /// Plots a line of conditions on the graph
        /// </summary>
        /// <param name="peak">Peak to plot</param>
        /// <param name="seriesNames">Names of existing series</param>
        /// <param name="intensities">Intensity values (y)</param>
        /// <param name="seriesName">Name of this series</param>
        /// <param name="xInfo">Info for x position of intentises (in same order as intensities)</param>
        /// <param name="line">Line or dots/</param>
        /// <param name="bold">Bold line?</param>
        /// <param name="isConditions">Order by conditions or obervations</param>
        private void AddToPlot(
            MCharting.Plot plot,
            Peak peak,
            Dictionary <string, MCharting.Series> seriesNames,
            Vector intensities,
            string seriesName,
            StylisedPeakOptions o,
            EPlot draw,
            Dictionary <GroupInfoBase, MCharting.Series> groupLegends,
            MCharting.Series legend)
        {
            // Iterate whatever it is we're iterating
            for (int i = 0; i < intensities.Observations.Length; ++i)
            {
                // Get the values
                ObservationInfo obs = intensities.Observations[i];

                // Name the series
                if (draw.HasFlag(EPlot.ByBatch))
                {
                    if (!o.ViewBatches.Contains(obs.Batch))
                    {
                        continue;
                    }
                }
                else
                {
                    if (!o.ViewGroups.Contains(obs.Group))
                    {
                        continue;
                    }
                }

                bool          colorByBatch = draw.HasFlag(EPlot.ByBatch);
                GroupInfoBase seriesUsing  = colorByBatch ? (GroupInfoBase)obs.Batch : (GroupInfoBase)obs.Group;

                string           name = seriesName + " for " + seriesUsing.DisplayName;
                MCharting.Series series;

                // Create the series (if required)
                if (!seriesNames.ContainsKey(name))
                {
                    series = plot.Series.Add(name);
                    series.Style.StrictOrder = SeriesStyle.EOrder.X;
                    series.ApplicableLegends.Add(groupLegends[seriesUsing]);
                    series.ApplicableLegends.Add(legend);
                    seriesNames.Add(name, series);
                    series.Tag = peak;

                    Color colour = (draw.HasFlag(EPlot.DrawBold) || draw.HasFlag(EPlot.ByBatch) || !o.ShowTrend) ? seriesUsing.Colour : seriesUsing.ColourLight;

                    if (draw.HasFlag(EPlot.DrawLine))
                    {
                        series.Style.DrawLines       = new Pen(colour);
                        series.Style.DrawLines.Width = draw.HasFlag(EPlot.DrawBold) ? this._core.Options.LineWidth * 4 : this._core.Options.LineWidth;
                    }
                    else
                    {
                        UiControls.CreateIcon(series, seriesUsing);
                    }
                }
                else
                {
                    series = seriesNames[name];
                }

                // Get the X position
                double xPos;

                if (draw.HasFlag(EPlot.ByBatch))
                {
                    xPos = obs.Order;

                    if (o.ConditionsSideBySide)
                    {
                        xPos += this.GetBatchOffset(o.ViewBatches, obs.Batch);
                    }
                }
                else
                {
                    xPos = obs.Time;

                    if (o.ConditionsSideBySide)
                    {
                        xPos += this.GetTypeOffset(o.ViewGroups, obs.Group);
                    }
                }

                // Get the Y position
                double yPos = intensities.Values[i];

                if (double.IsNaN(yPos) || double.IsInfinity(yPos))
                {
                    yPos = 0;
                }

                // Create the point
                MCharting.DataPoint cdp = new MCharting.DataPoint(xPos, yPos);
                IntensityInfo       tag = new IntensityInfo(obs.Time, obs.Rep, obs.Group, yPos);
                cdp.Tag = tag;
                series.Points.Add(cdp);
            }
        }
Exemple #4
0
        private void AddUpperAndLowerShade(
            MCharting.Plot plot,
            StylisedPeakOptions o,
            Dictionary <string, MCharting.Series> seriesNames,
            Peak peak,
            Vector min,
            Vector max,
            Dictionary <GroupInfoBase, MCharting.Series> groupLegends)
        {
            MCharting.Series legendEntry = new MCharting.Series();
            legendEntry.Name             = "Range";
            legendEntry.Style.DrawVBands = new SolidBrush(Color.Gray);
            plot.LegendEntries.Add(legendEntry);

            // Iterate the conditions
            for (int i = 0; i < min.Observations.Length; i++)
            {
                ObservationInfo obs = min.Observations[i];

                Debug.Assert(max.Observations[i] == min.Observations[i], "Expected max and min trends to match sequences.");

                if (o.ViewGroups.Contains(obs.Group))
                {
                    // Name the series
                    string           name = "Range for " + obs.Group.DisplayName;
                    MCharting.Series series;

                    // Create the series (if required)
                    if (!seriesNames.ContainsKey(name))
                    {
                        series = plot.Series.Add(name);
                        series.Style.StrictOrder = SeriesStyle.EOrder.X;
                        Color c = obs.Group.ColourLight;
                        c          = Color.FromArgb(0x80, c.R, c.G, c.B);
                        series.Tag = peak;
                        series.Style.DrawVBands = obs.Group.CreateBrush(c);
                        series.ApplicableLegends.Add(groupLegends[obs.Group]);
                        series.ApplicableLegends.Add(legendEntry);
                        seriesNames.Add(name, series);
                    }
                    else
                    {
                        series = seriesNames[name];
                    }

                    // Get the X coordinate
                    int typeOffset = this.GetTypeOffset(o.ViewGroups, obs.Group);

                    double xVal = obs.Time;

                    if (o.ConditionsSideBySide)
                    {
                        xVal += typeOffset;
                    }

                    // Get the Y coordinates
                    double yMin = min.Values[i];
                    double yMax = max.Values[i];

                    if (double.IsNaN(yMin) || double.IsInfinity(yMin))
                    {
                        yMin = 0;
                    }

                    if (double.IsNaN(yMax) || double.IsInfinity(yMax))
                    {
                        yMax = 0;
                    }

                    // Create the point
                    IntensityInfo       info1 = new IntensityInfo(obs.Time, null, obs.Group, yMin);
                    IntensityInfo       info2 = new IntensityInfo(obs.Time, null, obs.Group, yMax);
                    MCharting.DataPoint cdp   = new MCharting.DataPoint(xVal, new[] { yMin, yMax });
                    cdp.Tag = new[] { info1, info2 };
                    series.Points.Add(cdp);
                }
            }
        }
Exemple #5
0
        private void _btnMarkAsOutlier_Click(object sender, EventArgs e)
        {
            object          item            = this._chart.SelectedItem.DataPoint.Tag;
            ObservationInfo observationInfo = item as ObservationInfo;
            Peak            peak            = item as Peak;

            bool safeToReplace = false;

            if (peak != null)
            {
                List <PeakFilter.Condition> filters = new List <PeakFilter.Condition>(this._peakFilter.Conditions.Cast <PeakFilter.Condition>());
                bool needsNewFilter = true;

                foreach (PeakFilter.Condition filter in filters)
                {
                    PeakFilter.ConditionPeak klalkq = filter as PeakFilter.ConditionPeak;

                    if (klalkq != null &&
                        klalkq.CombiningOperator == Filter.ELogicOperator.And &&
                        klalkq.Negate == false &&
                        klalkq.PeaksOp == Filter.EElementOperator.IsNot)
                    {
                        needsNewFilter = false;

                        List <Peak> strong;

                        if (!klalkq.Peaks.TryGetStrong(out strong))
                        {
                            FrmMsgBox.ShowError(this, "Couldn't modify current filter because it contains expired data.");
                            return;
                        }

                        filters.Remove(klalkq);
                        filters.Add(new PeakFilter.ConditionPeak(Filter.ELogicOperator.And, false, strong.ConcatSingle(peak), Filter.EElementOperator.IsNot));
                        safeToReplace = filters.Count == 1;
                        break;
                    }
                }

                if (needsNewFilter)
                {
                    filters.Add(new PeakFilter.ConditionPeak(Filter.ELogicOperator.And, false, new[] { peak }, Filter.EElementOperator.IsNot));
                }

                PeakFilter newFilter = new PeakFilter(null, null, filters);

                if (safeToReplace)
                {
                    this._core.SetPeakFilters(this._core.PeakFilters.ReplaceSingle(this._peakFilter, newFilter).ToArray());
                }
                else
                {
                    this._core.SetPeakFilters(this._core.PeakFilters.ConcatSingle(newFilter).ToArray());
                }

                this._peakFilter = newFilter;

                this.UpdateScores();
                return;
            }

            if (observationInfo == null)
            {
                bool needsNewFilter2 = true;

                List <ObsFilter.Condition> filters2 = new List <ObsFilter.Condition>(this._obsFilter.Conditions.Cast <ObsFilter.Condition>());

                foreach (ObsFilter.ConditionObservation fikaklq in filters2)
                {
                    ObsFilter.ConditionObservation qkklqq = fikaklq as ObsFilter.ConditionObservation;

                    if (qkklqq != null &&
                        qkklqq.CombiningOperator == Filter.ELogicOperator.And &&
                        qkklqq.Negate == false &&
                        qkklqq.Operator == Filter.EElementOperator.IsNot)
                    {
                        needsNewFilter2 = false;

                        filters2.Remove(qkklqq);
                        filters2.Add(new ObsFilter.ConditionObservation(Filter.ELogicOperator.And, false, Filter.EElementOperator.IsNot, qkklqq.Possibilities.ConcatSingle(observationInfo)));
                        safeToReplace = filters2.Count == 1;
                        break;
                    }
                }

                if (needsNewFilter2)
                {
                    filters2.Add(new ObsFilter.ConditionObservation(Filter.ELogicOperator.And, false, Filter.EElementOperator.IsNot, new[] { observationInfo }));
                }

                ObsFilter obsFilter = new ObsFilter(null, null, filters2);

                if (safeToReplace)
                {
                    this._core.SetObsFilters(this._core.ObsFilters.ReplaceSingle(this._obsFilter, obsFilter).ToArray());
                }
                else
                {
                    this._core.SetObsFilters(this._core.ObsFilters.ConcatSingle(obsFilter).ToArray());
                }

                this._obsFilter = obsFilter;

                this.UpdateScores();
            }
        }
        /// <summary>
        /// Actual plotting.
        /// </summary>
        public void Plot(StylisedCluster stylisedCluster)
        {
            Debug.WriteLine("ClusterPlot: " + stylisedCluster);

            // Reset the chart
            bool    isPreview = stylisedCluster != null && stylisedCluster.IsPreview;
            Cluster p         = stylisedCluster != null ? stylisedCluster.Cluster : null;
            Plot    plot      = this.PrepareNewPlot(!isPreview, (stylisedCluster != null) ? stylisedCluster.Cluster : null, p?.Assignments.Vectors.FirstOrDefault()?.Source);

            // Set the selected cluster
            Dictionary <Peak, LineInfo> colours = stylisedCluster != null ? stylisedCluster.Colours : null;

            this.SelectedCluster = stylisedCluster;

            if (stylisedCluster != null)
            {
                this.SetCaption(stylisedCluster.CaptionFormat, stylisedCluster.ActualElement, stylisedCluster.WhatIsHighlighted);
            }
            else
            {
                this.SetCaption("No plot displayed.");
            }

            Core core = this._core;
            CoreColourSettings colourSettings = core.Options.Colours;

            // If there is nothing to plot then exit
            if (p == null)
            {
                this.CompleteNewPlot(plot);
                return;
            }

            // Sort the variables exemplars top-most
            List <Assignment> toPlot = new List <Assignment>(p.Assignments.List);

            // Too much to plot
            while (toPlot.Count > core.Options.MaxPlotVariables)
            {
                //toPlot = toPlot.OrderBy(z => z.Peak.Index).ToList();
                toPlot.RemoveRange(core.Options.MaxPlotVariables, toPlot.Count - core.Options.MaxPlotVariables);
            }

            int numClusterCentres            = 0;
            HashSet <GroupInfo> groupsInPlot = p.Assignments.Vectors.First().ColHeaders.Unique(z => z.Observation.Group);

            if (!this._core.Options.DisplayAllGroupsInClusterPlot)
            {
                groupsInPlot.RemoveWhere(z => !this._core.Options.ViewTypes.Contains(z));
            }

            GroupInfo[] groupOrder = groupsInPlot.OrderBy(GroupInfoBase.GroupOrderBy).ToArray();

            MCharting.Series legendEntry = new MCharting.Series();
            legendEntry.Name            = "Input vector";
            legendEntry.Style.DrawLines = new Pen(Color.Black, this._core.Options.LineWidth * 2);
            plot.LegendEntries.Add(legendEntry);

            // --- LEGEND ---
            var groupLegends = this.DrawLegend(plot, groupOrder);

            HashSet <MCharting.Series> toBringToFront = new HashSet <MCharting.Series>();

            // --- PLOT CLUSTER ASSIGNMENTS ---
            // Iterate variables in cluster
            for (int assignmentIndex = 0; assignmentIndex < toPlot.Count; assignmentIndex++)
            {
                Assignment assignment = toPlot[assignmentIndex];
                Vector     vec        = assignment.Vector;
                Peak       peak       = vec.Peak;
                Dictionary <GroupInfo, MCharting.Series> vecSeries  = new Dictionary <GroupInfo, MCharting.Series>();
                Dictionary <GroupInfo, MCharting.Series> vec2Series = new Dictionary <GroupInfo, MCharting.Series>();
                MCharting.DataPoint lastPoint  = null;
                MCharting.Series    lastSeries = null;

                ///////////////////
                // PLOT THE POINT
                // Okay! Now plot the values pertinent to this peak & type
                for (int i = 0; i < vec.Count; ++i)
                {
                    // Peak, by observation
                    ObservationInfo obs   = vec.Observations[i];
                    GroupInfo       group = obs.Group;

                    if (!groupOrder.Contains(group))
                    {
                        continue;
                    }

                    MCharting.Series series = this.GetOrCreateSeries(plot, vecSeries, group, vec, stylisedCluster, groupLegends, legendEntry, toBringToFront, false);

                    // When the series changes we create an intermediate series to join the two together
                    //MCharting.Series seriesb = null;

                    //if (series != lastSeries && lastSeries != null)
                    //{
                    //    seriesb = GetOrCreateSeries(plot, vec2Series, group, vec, stylisedCluster, groupLegends, legendEntry, toBringToFront, true);
                    //}

                    lastSeries = series;

                    int typeOffset = this.GetTypeOffset(groupOrder, group);

                    int    x = typeOffset + obs.Time;
                    double v = vec.Values[i];
                    MCharting.DataPoint dataPoint = new MCharting.DataPoint(x, v);
                    dataPoint.Tag = new IntensityInfo(obs.Time, obs.Rep, obs.Group, v);
                    series.Points.Add(dataPoint);

                    //if (seriesb != null)
                    //{
                    //    seriesb.Points.Add(lastPoint);
                    //    seriesb.Points.Add(dataPoint);
                    //}

                    lastPoint = dataPoint;
                }
            }

            // --- PLOT CLUSTER CENTRES ---
            if (!isPreview && core.Options.ShowCentres && p.Centres.Count != 0 && p.Centres.Count < 100)
            {
                MCharting.Series legendEntry2 = new MCharting.Series();
                legendEntry2.Name                      = (p.Centres.Count == 1) ? "Cluster centre" : "Cluster centres";
                legendEntry2.Style.DrawLines           = new Pen(colourSettings.ClusterCentre, this._core.Options.LineWidth * 2);
                legendEntry2.Style.DrawLines.DashStyle = DashStyle.Dash;
                legendEntry2.Style.DrawPoints          = new SolidBrush(colourSettings.ClusterCentre);
                legendEntry2.Style.DrawPointsSize      = 8; // MarkerStyle.Diamond;
                plot.LegendEntries.Add(legendEntry2);

                var templateAssignment = p.Assignments.List.First();

                foreach (double[] centre in p.Centres)
                {
                    MCharting.Series series = new MCharting.Series();
                    series.Style.StrictOrder = SeriesStyle.EOrder.X;
                    series.ApplicableLegends.Add(legendEntry2);
                    plot.Series.Add(series);
                    series.Name                      = "Cluster centre #" + (++numClusterCentres);
                    series.Style.DrawLines           = new Pen(colourSettings.ClusterCentre, this._core.Options.LineWidth * 2);
                    series.Style.DrawLines.DashStyle = DashStyle.Dash;
                    series.Style.DrawPoints          = new SolidBrush(colourSettings.ClusterCentre);
                    series.Style.DrawPointsSize      = 8; // MarkerStyle.Diamond;

                    IEnumerable <int> order = templateAssignment.Vector.Observations.WhichOrder(ObservationInfo.GroupTimeReplicateDisplayOrder);

                    foreach (int index in order)
                    {
                        // Centre, by observation
                        ObservationInfo cond = templateAssignment.Vector.Observations[index];

                        if (!groupOrder.Contains(cond.Group))
                        {
                            continue;
                        }

                        double dp = centre[index];
                        int    x  = this.GetTypeOffset(groupOrder, cond.Group) + cond.Time;
                        MCharting.DataPoint cdp = new MCharting.DataPoint(x, dp);
                        cdp.Tag = new IntensityInfo(cond.Time, cond.Rep, cond.Group, dp);
                        series.Points.Add(cdp);
                    }
                }
            }

            // Bring highlighted series to the front
            foreach (MCharting.Series series in toBringToFront)
            {
                plot.Series.Remove(series);
                plot.Series.Add(series);
            }

            // --- LABELS ---
            this.DrawLabels(plot, true, groupOrder, true);

            // --- COMPLETE ---
            this.CompleteNewPlot(plot);
        }
Exemple #7
0
        /// <summary>
        /// Executes the correction for a set of raw values (in core.observation order).
        /// </summary>
        public double[] Calculate(Core core, IReadOnlyList <double> raw)
        {
            double[] result;

            if (!this.Args.IsUsingTrend)
            {
                var args = base.Args as ArgsCorrection;
                var algo = base.Args.GetAlgorithmOrThrow() as CorrectionBase;

                result = algo.Calculate(raw, args);
            }
            else
            {
                var args = base.Args;
                var algo = base.Args.GetAlgorithmOrThrow() as TrendBase;

                IReadOnlyList <ObservationInfo> trendOrder;
                double[] trend = this.ExtractTrend(core, raw, out trendOrder);
                IReadOnlyList <ObservationInfo> resultOrder = core.Observations;
                result = new double[raw.Count];

                switch (args.Mode)
                {
                case ECorrectionMode.Batch:
                {
                    // We know that the trend order for batch correction (above) is the core order
                    // so we can save time by not converting the indices
                    switch (args.Method)
                    {
                    case ECorrectionMethod.Divide:
                        for (int i = 0; i < trend.Length; i++)
                        {
                            result[i] = raw[i] / trend[i];
                        }
                        break;

                    case ECorrectionMethod.Subtract:
                        for (int i = 0; i < raw.Count; i++)
                        {
                            result[i] = raw[i] - trend[i];
                        }
                        break;

                    default:
                        throw new SwitchException(args.Method);
                    }
                }
                break;

                case ECorrectionMode.Control:
                {
                    // Here the trend will only represent the control group
                    for (int i = 0; i < raw.Count; i++)
                    {
                        ObservationInfo obs = resultOrder[i];

                        int j = trendOrder.FirstIndexWhere(z => z.Time == obs.Time);         // TODO: Awful linear search

                        if (j == -1)
                        {
                            // TODO: Time point for control outside range for observation
                            // This should be handled by truncation of the range and removal of QCs, for now let it pass
                            // throw new InvalidOperationException("The observation " + obs + " needs to be corrected using the corrected data for the same timepoint, but t = " + obs.Time + " cannot be found in the generated trend: " + StringHelper.ArrayToString(trendOrder.OrderBy(z => z.Time)) + "\r\nYou may need to truncate datapoints outside this range prior to correction.");
                            continue;
                        }

                        switch (args.Method)
                        {
                        case ECorrectionMethod.Divide:
                            result[i] = raw[i] / trend[j];
                            break;

                        case ECorrectionMethod.Subtract:
                            result[i] = raw[i] - trend[j];
                            break;

                        default:
                            throw new SwitchException(args.Method);
                        }
                    }
                }
                break;

                default:
                    throw new SwitchException(args.Mode);
                }
            }

            return(result);
        }