/// <summary> /// Base-Constructor. Performs the initalizations common to all experiments. /// </summary> /// <param name="wiffFile">A <see cref="FMANWiffFileClass"/> instance. The source from where to /// read the periods properties and data.</param> /// <param name="wiffPeriod">The <see cref="WiffPeriod"/> instance this experiment belongs to.</param> /// <param name="experimentIndex">The <b>zero-based</b> index of this experiment in the associated period.</param> public WiffExperiment(FMANWiffFileClass wiffFile, WiffPeriod wiffPeriod, int experimentIndex) { if (wiffFile == null) { throw new ArgumentNullException("wiffFile"); } if (wiffPeriod == null) { throw new ArgumentNullException("wiffPeriod"); } this.wiffPeriod = wiffPeriod; this.index = experimentIndex; Initialize(wiffFile); }
/// <summary> /// Constructor. Creates and initializes a WiffPeriod instance. /// </summary> /// <param name="wiffFile">A <see cref="FMANWiffFileClass"/> instance. The source from where to /// read the periods properties and data.</param> /// <param name="wiffSample">The <see cref="WiffSample"/> instance this period belongs to.</param> /// <param name="periodIndex">The <b>zero-based</b> index of this period in the associated sample.</param> public WiffPeriod(FMANWiffFileClass wiffFile, WiffSample wiffSample, int periodIndex) { if (wiffSample == null) { throw new ArgumentNullException("wiffSample"); } sample = wiffSample; if (periodIndex < 0) { throw new ArgumentOutOfRangeException("periodIndex"); } index = periodIndex; Initialize(wiffFile); }
/// <summary> /// Determines with what kind of experiment we're dealing with and instatiates /// an object of the accurate subclass derived from the abstract baseclass /// <see cref="WiffExperiment"/>. /// </summary> /// <param name="wiffFile">A <see cref="FMANWiffFileClass"/> instance. The source from where to /// read the experiments properties and data.</param> /// <param name="wiffPeriod">The <see cref="WiffPeriod"/> instance this the experiment belongs to.</param> /// <param name="experimentIndex">The <b>zero-based</b> index of the experiment in the associated period.</param> /// <returns>The newly created, <see cref="WiffExperiment"/> dirived object.</returns> public static WiffExperiment CreateWiffExperiment(FMANWiffFileClass wiffFile, WiffPeriod wiffPeriod, int experimentIndex) { Experiment experiment = (Experiment)wiffFile.GetExperimentObject(wiffPeriod.Sample.Index, wiffPeriod.Index, experimentIndex); // get scan type short scanType = experiment.ScanType; WiffExperiment theExperiment = null; switch (scanType) { case 0: // Q1 scan { theExperiment = new Q1ScanExperiment(wiffFile, wiffPeriod, experimentIndex); } break; case 1: // Q1 MI scan case 2: // Q3 scan case 3: // Q3 MI scan break; case 4: // MRM scan { theExperiment = new MRMScanExperiment(wiffFile, wiffPeriod, experimentIndex); } break; case 5: // precursor scan case 6: // product ion scan case 7: // neural loss scan break; default: { // TODO -- Check if this is really, really intended... theExperiment = new MRMScanExperiment(wiffFile, wiffPeriod, experimentIndex); } break; } return(theExperiment); }
/// <summary> /// Fills this instance data members with the information read from <paramref name="wiffFile"/>. /// </summary> /// <param name="wiffFile">A <see cref="FMANWiffFileClass"/> instance. The data source.</param> private void Initialize(FMANWiffFileClass wiffFile) { //get the number of cycles cycles = wiffFile.GetActualNumberOfCycles(sample.Index, index); // get the period object Period period = (Period)wiffFile.GetPeriodObject(sample.Index, index); // get the cycle time cycleTime = period.CycleTime; // get number of experiments int nrExperiments = wiffFile.GetNumberOfExperiments(sample.Index, index); // loop through the experiments; the index of the experiments is zero based!! for (int actExperiment = 0; actExperiment < nrExperiments; actExperiment++) { WiffExperiment experiment = WiffExperimentFactory.CreateWiffExperiment(wiffFile, this, actExperiment); experiments.Add(experiment); } }
/// <summary> /// Constructor /// </summary> /// <param name="wiffFile">A <see cref="FMANWiffFileClass"/> instance. The source from where to /// read the samples properties and data.</param> /// <param name="wiffFileContent">The <see cref="WiffFileContent"/> instance this sample belongs to.</param> /// <param name="sampleIndex">A <see cref="int"/> value specifying the <b>one-based</b>index of this sample in the <paramref name="wiffFile"/>.</param> /// <remarks>Please take note, that the the counting of samples in the wiff file start with 1( in contrary to most ather indexes).</remarks> public WiffSample(FMANWiffFileClass wiffFile, WiffFileContent wiffFileContent, int sampleIndex) { if (wiffFile == null) { throw new ArgumentNullException("wiffFile"); } if (wiffFileContent == null) { throw new ArgumentNullException("wiffFileContent"); } if (sampleIndex < 0) { throw new ArgumentOutOfRangeException("sampleIndex"); } index = sampleIndex; this.wiffFileContent = wiffFileContent; Initialize(wiffFile); }
/// <summary> /// Fills this instance data members with the information read from <paramref name="wiffFile"/>. /// </summary> /// <param name="wiffFile">A <see cref="FMANWiffFileClass"/> instance. The data source.</param> protected override void Initialize(FMANWiffFileClass wiffFile) { // get experiment object and the experiment parameters ITripleQuadMALDI experimentParams = (ITripleQuadMALDI)wiffFile.GetExperimentObject(WiffPeriod.Sample.Index, WiffPeriod.Index, Index); Experiment experiment = (Experiment)wiffFile.GetExperimentObject(WiffPeriod.Sample.Index, WiffPeriod.Index, Index); MassRange massRange = (MassRange)experiment.GetMassRange(0); minMass = massRange.QstartMass; // anaSpec.GetStartMass(); maxMass = massRange.QstopMass; // anaSpec.GetStopMass(); massStepSize = massRange.QstepMass; //anaSpec.StepSize; // get the number of MS data points massSpecDataPoints = (int)((maxMass - minMass) / massStepSize + 1); // select 1. data points FMANChromData chrom = new FMANChromData(); chrom.WiffFileName = wiffFile.GetWiffFileName(); chrom.SetToTIC(WiffPeriod.Sample.Index, WiffPeriod.Index, Index); // dimension the data arrray nrDataPoints = chrom.GetNumberOfDataPoints(); rawData = new float[nrDataPoints]; timeData = new float[nrDataPoints]; //loop through the mass ranges massRangeName = "TIC " + minMass.ToString() + " - " + maxMass.ToString(); double xValue = chrom.GetDataPointXValue(1); double yValue = chrom.GetDataPointYValue(1); massRangeMax = double.MinValue; massRangeMin = double.MaxValue; timeOffset = xValue * 1000; // helper for mean and median double meanSum = 0; List <float> valuesForMedian = new List <float>(); // read the data... for (int actDataPoint = 1; actDataPoint <= nrDataPoints; actDataPoint++) { // get the actual value... xValue = chrom.GetDataPointXValue(actDataPoint); yValue = chrom.GetDataPointYValue(actDataPoint); // and copy it to our local data structur rawData[actDataPoint - 1] = (float)yValue; timeData[actDataPoint - 1] = (float)xValue * 60; // keep track of the extrema if (yValue < massRangeMin) { massRangeMin = yValue; } if (yValue > massRangeMax) { massRangeMax = yValue; } // mean and median calculation... // sum up the value to calculate the mean meanSum += yValue; // fill an extra array to calculate the median valuesForMedian.Add((float)yValue); } // calculate the mean meanValue = (float)(meanSum / nrDataPoints); // calculate the median valuesForMedian.Sort(); medianValue = ((valuesForMedian.Count % 2) == 0) ? (float)(valuesForMedian[(valuesForMedian.Count / 2) - 1] + valuesForMedian[valuesForMedian.Count / 2]) / 2.0f : valuesForMedian[valuesForMedian.Count / 2]; #if (false) // analyze the timing values in timeData List <float> timeSpans = new List <float>(); for (int i = 1; i < timeData.Length; i++) { timeSpans.Add(timeData[i] - timeData[i - 1]); } float tMean = 0; float tMedian = 0; timeSpans.Sort(); foreach (float ts in timeSpans) { tMean += ts; } tMean = tMean / timeSpans.Count; tMedian = ((timeSpans.Count % 2) == 0) ? (float)(timeSpans[(timeSpans.Count / 2) - 1] + timeSpans[timeSpans.Count / 2]) / 2.0f : timeSpans[timeSpans.Count / 2]; #endif // fetch the x1, x2, y1, y2, width and height from the WiffSample instance this experiment belongs to. double x1 = WiffPeriod.Sample.P1.X; double y1 = WiffPeriod.Sample.P1.Y; double x2 = WiffPeriod.Sample.P2.X; double y2 = WiffPeriod.Sample.P2.Y; double width = WiffPeriod.Sample.Width; double height = WiffPeriod.Sample.Height; //get MALDI parmas and assign variables string strMALDIParams = experimentParams.TripleQuadMALDIParameters; // x speed in mm/s xSpeed = float.Parse(strMALDIParams.Split(sepMALDIParams, System.StringSplitOptions.None)[6]); //line distance in mm yDist = float.Parse(strMALDIParams.Split(sepMALDIParams, System.StringSplitOptions.None)[8]) / 1000; //time per point in s xTime = (float)((chrom.GetDataPointXValue(nrDataPoints) - chrom.GetDataPointXValue(2)) * 60 / (nrDataPoints - 2)); xDist = (float)(int)(xSpeed * xTime * 1000) / 1000; //number of poins in x xPoints = (int)((width) / xSpeed / xTime); // fetch the position data from the WiffSample instance this experiment belongs to. uint[,] posData = WiffPeriod.Sample.PositionData; long posDataLength = WiffPeriod.Sample.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; // ok, we're done... break; } } long lastNonZeroTimeInPos = -1; for (long t = posDataLength - 1; t >= 0; t++) { if (posData[t, 0] > 0) { lastNonZeroTimeInPos = t; // ok, we're done... break; } } if (firstNonZeroTimeInPos < 0 || lastNonZeroTimeInPos < 0) { // haven't found a valid posData triplet. All time values are zero or less... // bail out return; } // y2 from the wiff file is not the actual y2 from the stage - replace with value from path file... y2 = (double)Math.Round((decimal)posData[lastNonZeroTimeInPos, 2] / 1000, 2); // ...and this has an effect of the ypoints yPoints = (int)Math.Round((decimal)((y2 - y1) / yDist)) + 1; double timeSpanPos = posData[lastNonZeroTimeInPos, 0] / 1000.0 - posData[firstNonZeroTimeInPos, 0] / 1000.0; if (yPoints % 2 == 0) { // even number of scanlines lineBreak = (timeSpanPos - (x2 - (float)posData[firstNonZeroTimeInPos, 1] / 1000) / xSpeed - (yPoints - 2) * (width) / xSpeed - (x2 - (float)posData[lastNonZeroTimeInPos, 1] / 1000) / xSpeed) / (yPoints - 1); } else { // odd number of scanlines lineBreak = (timeSpanPos - (x2 - (float)posData[firstNonZeroTimeInPos, 1] / 1000) / xSpeed - (yPoints - 2) * (width) / xSpeed - ((float)posData[lastNonZeroTimeInPos, 1] / 1000 - x1) / xSpeed) / (yPoints - 1); } lineBreak = lineBreak / xTime; timeOffset = (float)posData[firstNonZeroTimeInPos, 0] / 1000 - (((float)posData[firstNonZeroTimeInPos, 1] / 1000 - x1) / xSpeed); lineOffset = (5 - (timeData[5] - timeOffset) / xTime) + 1; /////////////////////////////////////////////////////////////////////////////////////////////////////// // TIC throughout the total massrange... /////////////////////////////////////////////////////////////////////////////////////////////////////// // format the data into a rectangular, 2 dimensional array of floats that will represent the image data // AppContext.ProgressStart("formating image data..."); // prepare the data structure float[][] dataTIC; try { dataTIC = new float[xPoints][]; for (int i = 0; i < dataTIC.Length; i++) { dataTIC[i] = new float[yPoints]; } // copy the data from wiff file datastream to the rectangular array. Take account of the line offset and // the line break timings. for (int y = 0; y < yPoints; y++) { int currentPoint; // currentLine is the offset to the start of the current line in the linear datastream (rawData) int currentLine = (int)Math.Floor(Math.Abs(lineOffset + ((x2 - x1) / xSpeed / xTime + lineBreak) * y)); for (int x = 0; x < xPoints; x++) { if (y % 2 == 0) { // even y: scan direction: --> currentPoint = (int)(currentLine + x); } else { // odd y: scan direction: <-- currentPoint = (int)(currentLine + xPoints - 1 - x); } if (currentPoint < nrDataPoints) { dataTIC[x][y] = rawData[currentPoint]; } else { dataTIC[x][y] = 0; } } AppContext.ProgressSetValue(100.0 * y / yPoints); } } finally { AppContext.ProgressClear(); } // create the appropriate dataset and add it to the WiffFileContent object... string imgName = WiffPeriod.Sample.Name + " : " + massRangeName; Document doc = WiffPeriod.Sample.WiffFileContent.Document; //create the meta information data structure and populate with relevant information... ImageMetaData metaData = new ImageMetaData(); try { metaData.Add("Sample Name", typeof(string), WiffPeriod.Sample.Name, false); metaData.Add("Mass Range", typeof(string), massRangeName, false); string[] splitted = strMALDIParams.Split(sepMALDIParams, System.StringSplitOptions.None); metaData.Add("Laser Frequency (Hz)", typeof(string), splitted[1], false); metaData.Add("Laser Power (%)", typeof(string), splitted[2], false); metaData.Add("Ablation Mode", typeof(string), splitted[3], false); metaData.Add("Skimmer Voltage (V)", typeof(string), splitted[4], false); metaData.Add("Source Gas", typeof(string), splitted[5], false); metaData.Add("Raster Speed (mm/s)", typeof(string), splitted[6], false); metaData.Add("Raster Pitch", typeof(string), splitted[8], false); } catch (Exception e) { Util.ReportException(e); } ImageData imageTIC = new ImageData(doc, dataTIC, imgName, metaData, (float)massRangeMin, (float)massRangeMax, (float)meanValue, (float)medianValue, (float)xDist, (float)yDist, (float)minMass, (float)maxMass); /////////////////////////////////////////////////////////////////////////////////////////////////////// // Q1 spectrum scan... FMANSpecData spec = new FMANSpecData(); spec.WiffFileName = wiffFile.GetWiffFileName(); // prepare the data structure List <float[][]> dataList; List <ImageData> imageDataList; AppContext.ProgressStart("formating spectrum data..."); try { dataList = new List <float[][]>(); for (int i = 0; i < massSpecDataPoints; i++) { float[][] data = new float[xPoints][]; for (int j = 0; j < xPoints; j++) { data[j] = new float[yPoints]; } dataList.Add(data); } for (int y = 0; y < yPoints; y++) { int currentPoint; // currentLine is the offset to the start of the current line in the linear datastream (rawData) int currentLine = (int)Math.Floor(Math.Abs(lineOffset + ((x2 - x1) / xSpeed / xTime + lineBreak) * y)); for (int x = 0; x < xPoints; x++) { if (y % 2 == 0) { // even y: scan direction: --> currentPoint = (int)(currentLine + x); } else { // odd y: scan direction: <-- currentPoint = (int)(currentLine + xPoints - 1 - x); } if (currentPoint >= nrDataPoints) { continue; } float currentTime = (float)chrom.GetXValueInSec(currentPoint + 1); spec.SetSpectrum(WiffPeriod.Sample.Index, WiffPeriod.Index, Index, currentTime, currentTime); int specDataPoints = spec.GetNumberOfDataPoints(); for (int k = 1; k <= specDataPoints; k++) { int specIndex = (int)((spec.GetDataPointXValue(k) - minMass) / massStepSize + 0.4); dataList[specIndex][x][y] = (float)spec.GetDataPointYValue(k); } } AppContext.ProgressSetValue(100.0 * y / yPoints); } // create the list of imageData objects passed to the imageSpectrumData object on it's creation later on... imageDataList = new List <ImageData>(); for (int k = 0; k < massSpecDataPoints; k++) { float[][] specData = dataList[k]; float mass = (float)(minMass + (massStepSize * k)); imgName = WiffPeriod.Sample.Name + " : " + mass.ToString(); // TODO -- rethink if one should really calculate the mean, median, min, max etc. if the images aren't used for imaging but for export... float minInt = float.MaxValue; float maxInt = float.MinValue; float mean = 0; float median = 0; // helper for mean and median meanSum = 0; valuesForMedian.Clear(); { for (int x = 0; x < xPoints; x++) { for (int y = 0; y < yPoints; y++) { float value = specData[x][y]; // keep track of the extrema if (value < minInt) { minInt = value; } if (value > maxInt) { maxInt = value; } // mean and median calculation... // sum up the value to calculate the mean meanSum += value; // fill an extra array to calculate the median valuesForMedian.Add(value); } } } // calculate the mean mean = (float)(meanSum / (xPoints * yPoints)); // calculate the median valuesForMedian.Sort(); median = ((valuesForMedian.Count % 2) == 0) ? (float)(valuesForMedian[(valuesForMedian.Count / 2) - 1] + valuesForMedian[valuesForMedian.Count / 2]) / 2.0f : valuesForMedian[valuesForMedian.Count / 2]; // ok, now create the imageData and add to list... ImageData imageData = new ImageData(doc, specData, imgName, new ImageMetaData(), minInt, maxInt, mean, median, (float)xDist, (float)yDist, (float)0.0f, (float)mass); imageDataList.Add(imageData); } } finally { AppContext.ProgressClear(); } // now everything should be set to create the ImageSpectrumData object... imgName = WiffPeriod.Sample.Name + " SPECT " + minMass.ToString() + " - " + maxMass.ToString(); ImageSpectrumData imageSpectrum = new ImageSpectrumData(doc, imgName, new ImageMetaData(), imageDataList, (float)minMass, (float)maxMass, (float)massStepSize); imageSpectrum.ImageTIC = imageTIC; WiffPeriod.Sample.WiffFileContent.Add(imageSpectrum); #if (false) // TODO -- find out what to do with the 'globalMassMax' value float anaTime = (float)chrom.GetXValueInSec(nrDataPoints - 1); chrom.SetToBPC(WiffPeriod.Sample.Index, WiffPeriod.Index, Index, 0, anaTime, minMass, maxMass, 2 * massStepSize); double tempMass; chrom.GetYValueRange(out tempMass, out globalMassMax); chrom.SetToTIC(WiffPeriod.Sample.Index, WiffPeriod.Index, Index); #endif chrom.WiffFileName = ""; chrom = null; spec.WiffFileName = ""; spec = null; }
/// <summary> /// Constructor. Creates and initializes a Q1ScanExperiment instance. /// </summary> /// <param name="wiffFile">A <see cref="FMANWiffFileClass"/> instance. The source from where to /// read the periods properties and data.</param> /// <param name="wiffPeriod">The <see cref="WiffPeriod"/> instance this experiment belongs to.</param> /// <param name="experimentIndex">The <b>zero-based</b> index of this experiment in the associated period.</param> public Q1ScanExperiment(FMANWiffFileClass wiffFile, WiffPeriod wiffPeriod, int experimentIndex) : base(wiffFile, wiffPeriod, experimentIndex) { }
// Private Methods (1) /// <summary> /// Fills this instance data members with the information read from <paramref name="wiffFile"/>. /// </summary> /// <param name="wiffFile">A <see cref="FMANWiffFileClass"/> instance. The data source.</param> private void Initialize(FMANWiffFileClass wiffFile) { // retrieve this sample's name name = wiffFile.GetSampleName(index); // get the position information for the selected sample // the position data exists in a seperate file ( one per sample ) // and is read from that file 'manually' AppContext.ProgressStart("reading path file"); try { string pathFile = wiffFileContent.FileName + " (" + index.ToString() + ").path"; FileStream positionStream = new FileStream(@pathFile, FileMode.Open, FileAccess.Read); // calculate the count of position entries positionDataLength = positionStream.Length / 12; // 12 Byte per position entry // the array to hold the position information positionData = new uint[positionDataLength, 3]; BinaryReader positionReader = new BinaryReader(positionStream); for (long i = 0; i < positionDataLength; i++) { positionData[i, 0] = positionReader.ReadUInt32(); positionData[i, 1] = positionReader.ReadUInt32(); positionData[i, 2] = positionReader.ReadUInt32(); if ((i % (positionDataLength / 100.0)) == 0) // hundred progress ticks { AppContext.ProgressSetValue(100.0 * i / positionDataLength); } } positionReader.Close(); positionStream.Close(); } finally { AppContext.ProgressClear(); } #if (false) string csvPosFile = wiffFileContent.FileName + " (" + index.ToString() + ").path" + ".csv"; using (FileStream csvPosStream = new FileStream(@csvPosFile, FileMode.Create, FileAccess.Write)) { using (StreamWriter sw = new StreamWriter(csvPosStream)) { for (long i = 0; i < positionDataLength; i++) { sw.Write(positionData[i, 0]); sw.Write(','); sw.Write(positionData[i, 1]); sw.Write(','); sw.Write(positionData[i, 2]); sw.WriteLine(); } } } #endif // get user data of the selected sample string userData = wiffFile.GetUserData(index); if (!string.IsNullOrEmpty(userData)) { //width in mm x2 = float.Parse(userData.Split(',')[2]); x1 = float.Parse(userData.Split(',')[0]); width = x2 - x1; //height in mm y2 = float.Parse(userData.Split(',')[3]); y1 = float.Parse(userData.Split(',')[1]); height = y2 - y1; } // get the number of periods int nrPeriods = wiffFile.GetActualNumberOfPeriods(index); // loop through the periods; the index of the periods is zero based!! for (int actPeriod = 0; actPeriod < nrPeriods; actPeriod++) { WiffPeriod period = new WiffPeriod(wiffFile, this, actPeriod); periods.Add(period); } }
/// <summary> /// Fills this instance data members with the information read from <paramref name="wiffFile"/>. /// </summary> /// <param name="wiffFile">A <see cref="FMANWiffFileClass"/> instance. The data source.</param> protected abstract void Initialize(FMANWiffFileClass wiffFile);
/// <summary> /// Load the wiff file's content. /// </summary> /// <returns>A <see cref="bool"/> value indicating the success of the loading.</returns> public bool LoadContent() { #if (COPY_LOCAL) string tempFile = ""; #endif bool result = false; FMANWiffFileControlClass wiffFileControl = null; FMANWiffFileClass wiffFile = null; try { string fileToOpen = fileName; #if (COPY_LOCAL) // if file is not local, copy it to the users tempdir string uncName = Util.PathToUnc(fileName); if (!string.IsNullOrEmpty(uncName)) { string tempDir = Path.GetTempPath(); string file = Path.GetFileName(uncName); tempFile = Path.Combine(tempDir, file); fileToOpen = tempFile; File.Copy(fileName, fileToOpen, true); // and the scan file if (File.Exists(fileName + ".scan")) { File.Copy(fileName + ".scan", fileToOpen + ".scan", true); } } #endif wiffFileControl = new FMANWiffFileControlClass(); // get wiff file object from given file wiffFile = (FMANWiffFileClass)wiffFileControl.GetWiffFileObject(fileToOpen, 1); // get number of samples int nrSamples = wiffFile.GetActualNumberOfSamples(); #if (false) // let the user select one sample to be processed string[] sampleNames = new string[nrSamples]; // the index for the samples in the wiff file is based 1 !! int actSample; for (actSample = 1; actSample <= nrSamples; actSample++) { sampleNames[actSample - 1] = wiffFile.GetSampleName(actSample); } if (nrSamples > 1) { // get the sample which is actually to be used... SelectSampleDlg selectSample = new SelectSampleDlg(sampleNames); selectSample.Owner = AppContext.MainWindow; selectSample.ShowDialog(); if (selectSample.DialogResult == true) { actSample = selectSample.SelectedSampleIndex; } else if (selectSample.DialogResult == false) { return(false); } } else { // just one sample in wiff file actSample = 1; } // create and add the singular sample to this objects list of samples... WiffSample sample = new WiffSample(wiffFile, actSample); samples.Add(sample); #else // create sample objects for all the samples present in the wiff file // the index for the samples in the wiff file is based 1 !! for (int actSample = 1; actSample <= nrSamples; actSample++) { // create and add the sample to this objects list of samples... WiffSample sample = new WiffSample(wiffFile, this, actSample); samples.Add(sample); } #endif result = true; } catch (Exception e) { Util.ReportException(e); result = false; } finally { try { if (wiffFile != null) { wiffFile.CloseWiffFile(); wiffFile = null; } wiffFileControl = null; #if (COPY_LOCAL) if (!string.IsNullOrEmpty(tempFile) && File.Exists(tempFile)) { File.Delete(tempFile); if (File.Exists(tempFile + ".scan")) { File.Delete(tempFile + ".scan"); } } #endif } catch (Exception) { } } return(result); }
/// <summary> /// Fills this instance data members with the information read from <paramref name="wiffFile"/>. /// </summary> /// <param name="wiffFile">A <see cref="FMANWiffFileClass"/> instance. The data source.</param> protected override void Initialize(FMANWiffFileClass wiffFile) { // set the status information AppContext.StatusInfo = "Getting wiff-data"; // get the experiment parameters and the experiment object ITripleQuadMALDI experimentParams = (ITripleQuadMALDI)wiffFile.GetExperimentObject(WiffPeriod.Sample.Index, WiffPeriod.Index, Index); Experiment experiment = (Experiment)wiffFile.GetExperimentObject(WiffPeriod.Sample.Index, WiffPeriod.Index, Index); // get the number of mass MRM transitions massRanges = experiment.MassRangesCount; // select 1. MRM trace FMANChromData anaChrom = new FMANChromData(); anaChrom.WiffFileName = wiffFile.GetWiffFileName(); anaChrom.SetToXICZeroWidth(WiffPeriod.Sample.Index, WiffPeriod.Index, Index, 0); // dimension the data arrray, the number "data points" nrDataPoints = anaChrom.GetNumberOfDataPoints(); rawData = new float[massRanges, nrDataPoints]; timeData = new float[nrDataPoints]; dwellTime = new double[massRanges]; massRangeName = new string[massRanges]; massRangeMax = new double[massRanges]; massRangeMin = new double[massRanges]; meanValues = new float[massRanges]; medianValues = new float[massRanges]; // helper for mean and median double meanSum = 0; List <float> valuesForMedian = new List <float>(); // loop through the mass ranges double[] startMass = new double[massRanges]; double[] stopMass = new double[massRanges]; double[] stepMass = new double[massRanges]; for (int actMassRange = 0; actMassRange < massRanges; actMassRange++) { // get mass range object MassRange anaMassRange = (MassRange)experiment.GetMassRange(actMassRange); startMass[actMassRange] = anaMassRange.QstartMass; stopMass[actMassRange] = anaMassRange.QstopMass; stepMass[actMassRange] = anaMassRange.QstepMass; massRangeName[actMassRange] = Math.Round(startMass[actMassRange], 2).ToString() + " > " + Math.Round(stepMass[actMassRange], 2).ToString(); dwellTime[actMassRange] = anaMassRange.DwellTime; // select MRM trace anaChrom.SetToXICZeroWidth(WiffPeriod.Sample.Index, WiffPeriod.Index, Index, (short)actMassRange); // loop throug the spectrum massRangeMax[actMassRange] = double.MinValue; massRangeMin[actMassRange] = double.MaxValue; meanSum = 0.0; valuesForMedian.Clear(); for (int actDataPoint = 1; actDataPoint <= nrDataPoints; actDataPoint++) { // get the actual value double anaXValue = anaChrom.GetDataPointXValue(actDataPoint); double anaYValue = anaChrom.GetDataPointYValue(actDataPoint); if (anaYValue < massRangeMin[actMassRange]) { massRangeMin[actMassRange] = anaYValue; } if (anaYValue > massRangeMax[actMassRange]) { massRangeMax[actMassRange] = anaYValue; } // now get the actual data rawData[actMassRange, actDataPoint - 1] = (float)anaYValue; timeData[actDataPoint - 1] = (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 meanValues[actMassRange] = (float)(meanSum / nrDataPoints); // calculate the median valuesForMedian.Sort(); medianValues[actMassRange] = ((valuesForMedian.Count % 2) == 0) ? (float)(valuesForMedian[(valuesForMedian.Count / 2) - 1] + valuesForMedian[valuesForMedian.Count / 2]) / 2.0f : valuesForMedian[valuesForMedian.Count / 2]; } // get MALDI parmas and assign variables string strMALDIParams = experimentParams.TripleQuadMALDIParameters; // x speed in mm/s xSpeed = float.Parse(strMALDIParams.Split(sepMALDIParams, System.StringSplitOptions.None)[6]); //line distance in mm yDist = float.Parse(strMALDIParams.Split(sepMALDIParams, System.StringSplitOptions.None)[8]) / 1000; //time per point in s xTime = (float)((anaChrom.GetDataPointXValue(nrDataPoints) - anaChrom.GetDataPointXValue(2)) * 60 / (nrDataPoints - 2)); xDist = (float)(int)(xSpeed * xTime * 1000) / 1000; anaChrom.SetToTIC(WiffPeriod.Sample.Index, WiffPeriod.Index, Index); // fetch the x1, x2, y1, y2, width and height from the WiffSample instance this experiment belongs to. double x1 = WiffPeriod.Sample.P1.X; double y1 = WiffPeriod.Sample.P1.Y; double x2 = WiffPeriod.Sample.P2.X; double y2 = WiffPeriod.Sample.P2.Y; double width = WiffPeriod.Sample.Width; double height = WiffPeriod.Sample.Height; //number of poins in x xPoints = (int)((width) / xSpeed / xTime); //number of points in y yPoints = (int)((height) / yDist + 0.5) + 1; // lineOffset = 1; // fetch the position data from the WiffSample instance this experiment belongs to. uint[,] posData = WiffPeriod.Sample.PositionData; long posDataLength = WiffPeriod.Sample.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; // ok, we're done... break; } } long lastNonZeroTimeInPos = -1; for (long t = posDataLength - 1; t >= 0; t++) { if (posData[t, 0] > 0) { lastNonZeroTimeInPos = t - 1; // ok, we're done... break; } } if (firstNonZeroTimeInPos < 0 || lastNonZeroTimeInPos < 0) { // haven't found a valid posData triplet. All time values are zero or less... // bail out return; } // y2 from the wiff file is not the actual y2 from the stage - replace with value from path file... y2 = (double)Math.Round((decimal)posData[lastNonZeroTimeInPos, 2] / 1000, 2); // ...and this has an effect of the ypoints yPoints = (int)Math.Round((decimal)((y2 - y1) / yDist)) + 1; #if (false) // experimental method to format the ms-data to the x,y suitable for an image representation // fet two time stamps from the start and end of chrom file double tFirstMSDataPoint = anaChrom.GetDataPointXValue(10) * 60 * 1000; double tLastMSDataPoint = anaChrom.GetDataPointXValue(nrDataPoints - 10) * 60 * 1000; int positionMarker = 1; // get the corresponding position from the path file for (int i = 0; posData[i, 0] < tFirstMSDataPoint; i++) { positionMarker = i; } double xFirstMSDataPoint = ((tFirstMSDataPoint - posData[positionMarker, 0]) / (posData[positionMarker + 1, 0] - posData[positionMarker, 0]) * (int)(posData[positionMarker + 1, 1] - posData[positionMarker, 1]) + posData[positionMarker, 1]) / 1000; double yFirstMSDataPoint = (double)Math.Round((decimal)posData[positionMarker, 2] / 1000, 2); for (int i = 0; posData[i, 0] < tLastMSDataPoint; i++) { positionMarker = i; } double xLastMSDataPoint = ((tLastMSDataPoint - posData[positionMarker, 0]) / (posData[positionMarker + 1, 0] - posData[positionMarker, 0]) * (int)(posData[positionMarker + 1, 1] - posData[positionMarker, 1]) + posData[positionMarker, 1]) / 1000; double yLastMSDataPoint = (double)Math.Round((decimal)posData[positionMarker, 2] / 1000, 2); lineOffset = 10 - (xFirstMSDataPoint - x1) / xDist; if (yPoints % 2 == 0) { // even number of scanlines lineBreak = (((nrDataPoints - 10 - 10) - (x2 - (float)xFirstMSDataPoint) / xDist - (yPoints - 2) * (x2 - x1) / xDist - (x2 - (float)xLastMSDataPoint) / xDist)) / (yPoints - 1); } else { // odd number of scanlines lineBreak = (((nrDataPoints - 10 - 10) - (x2 - (float)xFirstMSDataPoint) / xDist - (yPoints - 2) * (x2 - x1) / xDist - ((float)xLastMSDataPoint - x1) / xDist)) / (yPoints - 1); } //timeOffset = (float)posData[5, 0] / 1000 - (((float)posData[5, 1] / 1000 - x1) / xSpeed); for (int actMassRange = 0; actMassRange < massRanges; actMassRange++) { /////////////////////////////////////////////////////////////////////////////////////////////////////// // format the data into a rectangular, 2 dimensional array of floats that will represent the image data // // prepare the data structure float[][] imageData = new float[xPoints][]; for (int i = 0; i < imageData.Length; i++) { imageData[i] = new float[yPoints]; } // copy the data from wiff file datastream to the rectangular array. Take account of the line offset and // the line break timings. for (int y = 0; y < yPoints; y++) { int currentPoint; // currentLine is the offset to the start of the current line in the linear datastream (rawData) int currentLine = (int)Math.Floor(lineOffset + ((x2 - x1) / xDist + lineBreak) * y); for (int x = 0; x < xPoints; x++) { if (y % 2 == 0) { // even y: scan direction: --> currentPoint = (int)(currentLine + x); } else { // odd y: scan direction: <-- currentPoint = (int)(currentLine + xPoints - 1 - x); } if (currentPoint < nrDataPoints) { imageData[x][y] = rawData[actMassRange, currentPoint]; } else { imageData[x][y] = 0; } } } lineOffset += ((double)dwellTime[actMassRange] + 5) / 1000 * xSpeed / xDist; #endif double timeSpanPos = posData[lastNonZeroTimeInPos, 0] / 1000.0 - posData[firstNonZeroTimeInPos, 0] / 1000.0; double syncTime1 = (float)posData[firstNonZeroTimeInPos, 0] / 1000; double syncTime2 = (float)posData[lastNonZeroTimeInPos, 0] / 1000; if (yPoints % 2 == 0) { // even number of scanlines lineBreak = ((syncTime2 - syncTime1) - (x2 - (float)posData[firstNonZeroTimeInPos, 1] / 1000) / xSpeed - (yPoints - 2) * (x2 - x1) / xSpeed - (x2 - (float)posData[lastNonZeroTimeInPos, 1] / 1000) / xSpeed) / (yPoints - 1); //timeOffset = (float)posData[posDataLength - 1, 0] / 1000 + (((float)posData[posDataLength - 1, 1] / 1000 - x1) / xSpeed) - (float)timeData[nrDataPoints - 1] + (float)timeData[0] - 2*xTime; //testing new method } else { // odd number of scanlines lineBreak = ((syncTime2 - syncTime1) - (x2 - (float)posData[firstNonZeroTimeInPos, 1] / 1000) / xSpeed - (yPoints - 2) * (x2 - x1) / xSpeed - ((float)posData[lastNonZeroTimeInPos, 1] / 1000 - x1) / xSpeed) / (yPoints - 1); //timeOffset = (float)posData[posDataLength - 1, 0] / 1000 + ((x2 - (float)posData[posDataLength - 1, 1] / 1000) / xSpeed) - (float)timeData[nrDataPoints - 1] + (float)timeData[0] - xTime;//testing new method } // MSt lineBreak = lineBreak / xTime; timeOffset = (float)posData[firstNonZeroTimeInPos, 0] / 1000 - (((float)posData[firstNonZeroTimeInPos, 1] / 1000 - x1) / xSpeed); // original method of calculation //MSt lineOffset = (timeData[0]-timeOffset) * xSpeed / xDist + .5; double dwellTimeSum = 0; // reset the status information AppContext.StatusInfo = ""; for (int actMassRange = 0; actMassRange < massRanges; actMassRange++) { /////////////////////////////////////////////////////////////////////////////////////////////////////// // format the data into a rectangular, 2 dimensional array of floats that will represent the image data // // prepare the data structure float[][] imageData = new float[xPoints][]; for (int i = 0; i < imageData.Length; i++) { imageData[i] = new float[yPoints]; } dwellTimeSum -= (dwellTime[actMassRange] / 1000 / 2); double optTimeOffset = timeOffset; double optLineBreak = lineBreak; if (AppContext.UseApproximation) { // Perform the optimization... HeuristicOptimization(imageData, actMassRange, (x2 - x1), dwellTimeSum, ref optLineBreak, ref optTimeOffset); } FormatImageFuzzy(imageData, actMassRange, (x2 - x1), dwellTimeSum, optLineBreak, optTimeOffset); dwellTimeSum -= (dwellTime[actMassRange] / 1000 / 2); // create the appropriate dataset and add it to the WiffFileContent object... string imgName = WiffPeriod.Sample.Name + " : " + massRangeName[actMassRange]; Document doc = WiffPeriod.Sample.WiffFileContent.Document; //create the meta information data structure and populate with relevant information... ImageMetaData metaData = new ImageMetaData(); try { metaData.Add("Sample Name", typeof(string), WiffPeriod.Sample.Name, false); metaData.Add("Mass Range", typeof(string), massRangeName[actMassRange], false); metaData.Add("X1 (mm)", typeof(string), x1.ToString(), false); metaData.Add("X2 (mm)", typeof(string), x2.ToString(), false); metaData.Add("Y1 (mm)", typeof(string), y1.ToString(), false); metaData.Add("Y2 (mm)", typeof(string), y2.ToString(), false); metaData.Add("Data Points in X", typeof(string), xPoints.ToString(), false); metaData.Add("Data Points in Y", typeof(string), yPoints.ToString(), false); metaData.Add("Point Width (mm)", typeof(string), xDist.ToString(), false); metaData.Add("Point Height (mm)", typeof(string), yDist.ToString(), false); string[] splitted = strMALDIParams.Split(sepMALDIParams, System.StringSplitOptions.None); metaData.Add("Laser Frequency (Hz)", typeof(string), splitted[1], false); metaData.Add("Laser Power (%)", typeof(string), splitted[2], false); metaData.Add("Ablation Mode", typeof(string), splitted[3], false); metaData.Add("Skimmer Voltage (V)", typeof(string), splitted[4], false); metaData.Add("Source Gas", typeof(string), splitted[5], false); metaData.Add("Raster Speed (mm/s)", typeof(string), splitted[6], false); metaData.Add("Line Distance (µm)", typeof(string), splitted[8], false); } catch (Exception e) { Util.ReportException(e); } WiffPeriod.Sample.WiffFileContent.Add(new ImageData(doc, imageData, imgName, metaData, (float)massRangeMin[actMassRange], (float)massRangeMax[actMassRange], (float)meanValues[actMassRange], (float)medianValues[actMassRange], (float)xDist, (float)yDist, (float)startMass[actMassRange], (float)stepMass[actMassRange])); } anaChrom.WiffFileName = ""; anaChrom = null; }