Пример #1
0
        /// <summary>
        /// Fills this instance data members with the information read from <paramref name="inputMsExperiment"/>.
        /// </summary>
        /// <param name="inputMsExperiment">instance, the data source</param>
        /// <param name="wiffsample"> Wiff Sample</param>
        protected override void Initialize(MSExperiment inputMsExperiment, WiffSample wiffsample)
        {
            Cursor.Current = Cursors.WaitCursor;
            try
            {
                // set the status information
                AppContext.StatusInfo = "Getting wiff-data";

                // (1) Get Maldi Parameters
                string strMaldiParams = wiffsample.MaldiParametersString;

                // (2) get the number of mass MRM transitions
                this.massRanges = inputMsExperiment.Details.MassRangeInfo.Length;

                // (3) select 1. MRM trace
                XYData tic = inputMsExperiment.GetTotalIonChromatogram();

                // (4) Dimension the data arrray, the number "data points"
                this.numDataPoint = tic.NumDataPoints;

                // (5) Set up arrays for info
                this.rawData       = new float[this.massRanges, this.numDataPoint];
                this.timeData      = new float[this.numDataPoint];
                this.dwellTime     = new double[this.massRanges];
                this.massRangeName = new string[this.massRanges];
                this.massRangeMax  = new double[this.massRanges];
                this.massRangeMin  = new double[this.massRanges];
                this.meanValues    = new float[this.massRanges];
                this.medianValues  = new float[this.massRanges];

                // helper for mean and median
                var valuesForMedian = new List <float>();

                // (6) loop through the mass ranges
                for (int actMassRange = 0; actMassRange < this.massRanges; actMassRange++)
                {
                    // get mass range object
                    this.massRangeName[actMassRange] = inputMsExperiment.Details.MassRangeInfo[actMassRange].Name;

                    this.dwellTime[actMassRange] = inputMsExperiment.Details.MassRangeInfo[actMassRange].DwellTime;

                    // loop through the spectrum
                    this.massRangeMax[actMassRange] = double.MinValue;
                    this.massRangeMin[actMassRange] = double.MaxValue;
                    double meanSum = 0.0;
                    valuesForMedian.Clear();

                    // Extract xic Full Scan
                    var option = new ExtractedIonChromatogramSettings(actMassRange);
                    ExtractedIonChromatogram xic = inputMsExperiment.GetExtractedIonChromatogram(option);

                    // JP 23/11 I think there might be a better way to do this.
                    for (int actDataPoint = 0; actDataPoint < this.numDataPoint; actDataPoint++)
                    {
                        // get the actual value
                        double anaXValue = xic.GetActualXValues()[actDataPoint];
                        double anaYValue = xic.GetActualYValues()[actDataPoint];

                        if (anaYValue < this.massRangeMin[actMassRange])
                        {
                            this.massRangeMin[actMassRange] = anaYValue;
                        }

                        if (anaYValue > this.massRangeMax[actMassRange])
                        {
                            this.massRangeMax[actMassRange] = anaYValue;
                        }

                        // now get the actual data
                        this.rawData[actMassRange, actDataPoint] = (float)anaYValue;
                        this.timeData[actDataPoint] = (float)anaXValue * 60;

                        // mean and median calculation...sum up the value to calculate the mean
                        meanSum += anaYValue;

                        // fill an extra array to calculate the median
                        valuesForMedian.Add((float)anaYValue);
                    }

                    // calculate the mean
                    this.meanValues[actMassRange] = (float)(meanSum / this.numDataPoint);

                    // calculate the median
                    valuesForMedian.Sort();
                    this.medianValues[actMassRange] = ((valuesForMedian.Count % 2) == 0) ? (valuesForMedian[(valuesForMedian.Count / 2) - 1] + valuesForMedian[valuesForMedian.Count / 2]) / 2.0f : valuesForMedian[valuesForMedian.Count / 2];
                }

                // (7) time per point in sec
                this.timeinXDirection = (float)((tic.GetActualXValues()[this.numDataPoint - 1] - tic.GetActualXValues()[1]) * 60 / (this.numDataPoint - 2));

                // (8) Calculate distInXDirection: fetch the x1, x2, y1, y2, width and height from the WiffSample instance this experiment belongs to.
                double x1    = wiffsample.P1.X;
                double y2    = 82 - wiffsample.P1.Y;
                double x2    = wiffsample.P2.X;
                double width = wiffsample.Width;

                // (9) fetch the position data from the WiffSample instance this experiment belongs to.
                uint[,] posData = wiffsample.PositionData;
                long posDataLength = wiffsample.PositionDataLength;

                // try and find the first and last valid indices in the posData, where valid means a nonzero time value...
                long firstNonZeroTimeInPos = -1;
                for (long t = 0; t < posDataLength - 1; t++)
                {
                    if (posData[t, 0] > 0)
                    {
                        firstNonZeroTimeInPos = t + 1;
                        break; // ok, we're done...
                    }
                }

                long lastNonZeroTimeInPos = -1;
                for (long t = posDataLength - 1; t >= 0; t++)
                {
                    if (posData[t, 0] > 0)
                    {
                        lastNonZeroTimeInPos = t - 1;
                        break; // ok, we're done...
                    }
                }

                // (10) Make sure we have found valid values, bail out if not
                if (firstNonZeroTimeInPos < 0 || lastNonZeroTimeInPos < 0)
                {
                    // haven't found a valid posData triplet. All time values are zero or less...bail out
                    return;
                }

                // (11) Calculate distInYDirection
                this.distInYDirection = 0;
                for (long t = firstNonZeroTimeInPos; t < lastNonZeroTimeInPos; t++)
                {
                    if ((posData[t, 1] > ((x2 + x1) * 500)) & Equals(this.distInYDirection, 0.0))
                    {
                        this.distInYDirection = posData[t, 2];
                    }

                    if ((posData[t, 1] < ((x2 + x1) * 500)) & (this.distInYDirection > 0))
                    {
                        this.distInYDirection = (float)Math.Round((decimal)(posData[t, 2] - this.distInYDirection) / 500, (int)(1 - Math.Log10((posData[t, 2] - this.distInYDirection) / 500))) / 2;
                        break;
                    }
                }

                // (12) Calculate speed in x direction
                this.speedinXDirection = (float)Math.Round((posData[firstNonZeroTimeInPos + 2, 1] - posData[firstNonZeroTimeInPos + 1, 1]) / (decimal)(posData[firstNonZeroTimeInPos + 2, 0] - posData[firstNonZeroTimeInPos + 1, 0]) * 2, 0) / 2;

                // (13) distInXDirection
                this.distInXDirection = (float)(int)(this.speedinXDirection * this.timeinXDirection * 1000) / 1000;

                // (14) number of points in x
                this.numPointsOnXAxis = (int)(width / this.speedinXDirection / this.timeinXDirection);

                // (15) number of points in y
                // y2 from the wiff file is not the actual y2 from the stage - replace with value from path file...
                // JP added "82 -" so what we convert wiff format to analyse co-ordinate system
                var y1 = 82 - (double)Math.Round((decimal)posData[lastNonZeroTimeInPos, 2] / 1000, 2);

                // ...and this has an effect of the numPointsOnYAxis
                this.numPointsOnYAxis = (int)Math.Round((decimal)((y2 - y1) / this.distInYDirection) + 1);

                // (16) Calc Lines Breaks
                double syncTime1 = (float)posData[firstNonZeroTimeInPos, 0] / 1000;
                double syncTime2 = (float)posData[lastNonZeroTimeInPos, 0] / 1000;

                if (this.numPointsOnYAxis % 2 == 0)
                {
                    // even number of scanlines
                    this.lineBreak = ((syncTime2 - syncTime1)
                                      - ((x2 - ((float)posData[firstNonZeroTimeInPos, 1] / 1000)) / this.speedinXDirection)
                                      - (((this.numPointsOnYAxis - 2) * (x2 - x1)) / this.speedinXDirection)
                                      - ((x2 - ((float)posData[lastNonZeroTimeInPos, 1] / 1000)) / this.speedinXDirection))
                                     / (this.numPointsOnYAxis - 1);
                }
                else
                {
                    // odd number of scanlines
                    this.lineBreak = ((syncTime2 - syncTime1)
                                      - ((x2 - ((float)posData[firstNonZeroTimeInPos, 1] / 1000)) / this.speedinXDirection)
                                      - (((this.numPointsOnYAxis - 2) * (x2 - x1)) / this.speedinXDirection)
                                      - ((((float)posData[lastNonZeroTimeInPos, 1] / 1000) - x1) / this.speedinXDirection))
                                     / (this.numPointsOnYAxis - 1);
                }

                // (17) time offset
                this.timeOffset = ((float)posData[firstNonZeroTimeInPos, 0] / 1000) - ((((float)posData[firstNonZeroTimeInPos, 1] / 1000) - x1) / this.speedinXDirection);

                double dwellTimeSum = 0;

                AppContext.StatusInfo = string.Empty;

                // (18) Format Data
                for (int actMassRange = 0; actMassRange < this.massRanges; actMassRange++)
                {
                    // format the data into a rectangular, 2 dimensional array of floats that will represent the image data
                    var imageData = new float[this.numPointsOnXAxis][];
                    for (int i = 0; i < imageData.Length; i++)
                    {
                        imageData[i] = new float[this.numPointsOnYAxis];
                    }

                    dwellTimeSum -= this.dwellTime[actMassRange] / 1000 / 2;

                    double optTimeOffset = this.timeOffset;
                    double optLineBreak  = this.lineBreak;
                    if (AppContext.UseApproximation)
                    {
                        // Perform the optimization...
                        this.HeuristicOptimization(imageData, actMassRange, x2 - x1, dwellTimeSum, ref optLineBreak, ref optTimeOffset);
                    }

                    this.FormatImageSharp(imageData, actMassRange, x2 - x1, dwellTimeSum, optLineBreak, optTimeOffset);

                    dwellTimeSum -= this.dwellTime[actMassRange] / 1000 / 2;

                    // create the appropriate dataset and add it to the WiffFileContent object...
                    string   imgName = wiffsample.Name + " : " + this.massRangeName[actMassRange];
                    Document doc     = wiffsample.WiffFileContent.Document;

                    // create the meta information data structure and populate with relevant information...
                    var metaData = new ImageMetaData();
                    try
                    {
                        const float Epsilon = (float)1E-10;
                        metaData.Add("Sample Name", typeof(string), wiffsample.Name, false);
                        metaData.Add("Mass Range", typeof(string), this.massRangeName[actMassRange], false);
                        metaData.Add("X1 (mm)", typeof(string), (Math.Abs(x1 - (int)x1) < Epsilon) ? x1.ToString("0.0") : x1.ToString(CultureInfo.InvariantCulture), false);
                        metaData.Add("Y1 (mm)", typeof(string), (Math.Abs(y1 - (int)y1) < Epsilon) ? y1.ToString("0.0") : y1.ToString(CultureInfo.InvariantCulture), false);
                        metaData.Add("X2 (mm)", typeof(string), (Math.Abs(x2 - (int)x2) < Epsilon) ? x2.ToString("0.0") : x2.ToString(CultureInfo.InvariantCulture), false);
                        metaData.Add("Y2 (mm)", typeof(string), (Math.Abs(y2 - (int)y2) < Epsilon) ? y2.ToString("0.0") : y2.ToString(CultureInfo.InvariantCulture), false);
                        metaData.Add("Data Points in X", typeof(string), this.numPointsOnXAxis.ToString(CultureInfo.InvariantCulture), false);
                        metaData.Add("Data Points in Y", typeof(string), this.numPointsOnYAxis.ToString(CultureInfo.InvariantCulture), false);
                        metaData.Add("Point Width (mm)", typeof(string), Math.Round(this.distInXDirection, 2).ToString(CultureInfo.InvariantCulture), false);
                        metaData.Add("Point Height (mm)", typeof(string), Math.Round(this.distInYDirection, 2).ToString(CultureInfo.InvariantCulture), false);

                        // Add Maldi Parameters
                        string[] splitstring = strMaldiParams.Split(SepMaldiParams, StringSplitOptions.None);
                        metaData.Add("Laser Frequency (Hz)", typeof(string), splitstring[1], false);
                        metaData.Add("Laser Power (%)", typeof(string), splitstring[2], false);
                        metaData.Add("Ablation Mode", typeof(string), splitstring[3], false);
                        metaData.Add("Skimmer Voltage (V)", typeof(string), splitstring[4], false);
                        metaData.Add("Source Gas", typeof(string), splitstring[5], false);
                        metaData.Add("Raster Speed (mm/s)", typeof(string), splitstring[6], false);
                        metaData.Add("Line Direction", typeof(string), splitstring[7], false);
                        metaData.Add("Rastor Pitch ", typeof(string), splitstring[8], false);
                    }
                    catch (Exception e)
                    {
                        Util.ReportException(e);
                    }

                    // (19) Create new ImageData and add WiffContent to Wiffsample
                    wiffsample.WiffFileContent.Add(new ImageData(
                                                       doc,
                                                       imageData,
                                                       imgName,
                                                       metaData,
                                                       (float)this.massRangeMin[actMassRange],
                                                       (float)this.massRangeMax[actMassRange],
                                                       this.meanValues[actMassRange],
                                                       this.medianValues[actMassRange],
                                                       (float)this.distInXDirection,
                                                       (float)this.distInYDirection,
                                                       null,
                                                       Core.ExperimentType.MRM));
                }
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }
Пример #2
0
        /// <summary>
        /// This routine gets the full list of Image Data for an MS Scan
        /// It uses the GetExtractedIonChromatogram() method to extract the data
        /// Runs a little slow.. so using the PopulateListByScan() for now.
        /// </summary>
        private void PopulateListByMass()
        {
            AppContext.ProgressStart("Populating Imagelist...");

            try
            {
                // (1) Loop through all the masses in the MassRange - We will use size of the dataList to specify number of masses in the range
                foreach (float[][] specDataPoints in this.dataList)
                {
                    // (2) Use GetExtractedIonChromatogram to get a specified mass
                    int    currMassIndex  = this.dataList.IndexOf(specDataPoints);
                    double massSpecNumber = this.minMass + (currMassIndex * this.massStepSize);

                    // Use startmass = endmass to get the full data set for a specific mass
                    var option = new ExtractedIonChromatogramSettings(massSpecNumber, massSpecNumber);

                    // Use GetExtractedIonChromatogram to get a specified mass
                    ExtractedIonChromatogram xic = this.msexperiment.GetExtractedIonChromatogram(option);
                    var specRawData = new double[this.numDataPoints];

                    // (3) For each massSpectrum collate all the intensities for each X value
                    for (int actDataPoint = 0; actDataPoint < this.numDataPoints; actDataPoint++)
                    {
                        // GetActualYValues Gets the intensity
                        specRawData[actDataPoint] = xic.GetActualYValues()[actDataPoint];
                    }

                    // (4) Populate this.dataList.massSpecDataPoints
                    for (int pointOnYAxis = 0; pointOnYAxis < this.numPointsOnYAxis; pointOnYAxis++)
                    {
                        // currentLine is the offset to the start of the current line in the linear datastream (rawData)
                        var currentLine = (int)Math.Floor(Math.Abs(this.lineOffset + (((((this.x2 - this.x1) / this.speedinXDirection) / this.timeinXDirection) + this.lineBreak) * pointOnYAxis)));
                        for (int pointOnXAxis = 0; pointOnXAxis < this.numPointsOnXAxis; pointOnXAxis++)
                        {
                            int currentPoint;
                            if (pointOnYAxis % 2 == 0)
                            {
                                // even y: scan direction: -->
                                currentPoint = currentLine + pointOnXAxis;
                            }
                            else
                            {
                                // odd y:  scan direction: <--
                                currentPoint = currentLine + this.numPointsOnXAxis - 1 - pointOnXAxis;
                            }

                            if (currentPoint < this.numDataPoints)
                            {
                                this.dataList[currMassIndex][pointOnXAxis][this.numPointsOnYAxis - 1 - pointOnYAxis] = (float)specRawData[currentPoint];
                            }
                            else
                            {
                                this.dataList[currMassIndex][pointOnXAxis][this.numPointsOnYAxis - 1 - pointOnYAxis] = 0;
                            }
                        }
                    }

                    AppContext.ProgressSetValue((100.0 / this.massSpecDataPoints) * currMassIndex);
                }
            }
            finally
            {
                AppContext.ProgressClear();
            }
        }