private static short AddMassError(ICollection <short> massErrors10X, double massError) { if (massErrors10X != null) { short massError10X = ChromPeak.To10x(massError); massErrors10X.Add(massError10X); return(massError10X); } return(0); }
private static void WriteMassErrors(Stream stream, IList <float> values) { PrimitiveArrays.Write(stream, values.Select(value => ChromPeak.To10x(value)).ToArray()); }
public TimeIntensities Interpolate(IList <float> timesNew, bool inferZeros) { if (timesNew.Count == 0) { return(this); } double intervalDelta = 0; if (timesNew.Count > 1) { intervalDelta = (timesNew[timesNew.Count - 1] - timesNew[0]) / (timesNew.Count - 1); } var timesMeasured = Times; var intensMeasured = Intensities; IList <float> massErrorsMeasured = MassErrors; var intensNew = new List <float>(); var massErrorsNew = massErrorsMeasured != null ? new List <float>() : null; int iTime = 0; double timeLast = timesNew[0]; double intenLast = 0; double massErrorLast = 0; if (!inferZeros && intensMeasured.Count != 0) { intenLast = intensMeasured[0]; if (massErrorsMeasured != null) { massErrorLast = massErrorsMeasured[0]; } } for (int i = 0; i < timesMeasured.Count && iTime < timesNew.Count; i++) { double intenNext; float time = timesMeasured[i]; float inten = intensMeasured[i]; double totalInten = inten; double massError = 0; if (massErrorsMeasured != null) { massError = massErrorsMeasured[i]; } // Continue enumerating points until one is encountered // that has a greater time value than the point being assigned. while (i < timesMeasured.Count - 1 && time < timesNew[iTime]) { i++; time = timesMeasured[i]; inten = intensMeasured[i]; if (massErrorsMeasured != null) { // Average the mass error in these points weigthed by intensity // into the next mass error value totalInten += inten; // TODO: Figure out whether this is an appropriate estimation method massError += (massErrorsMeasured[i] - massError) * inten / totalInten; } } if (i >= timesMeasured.Count) { break; } // If the next measured intensity is more than the new delta // away from the intensity being assigned, then interpolate // the next point toward zero, and set the last intensity to // zero. if (inferZeros && intenLast > 0 && timesNew[iTime] + intervalDelta < time) { intenNext = intenLast + (timesNew[iTime] - timeLast) * (0 - intenLast) / (timesNew[iTime] + intervalDelta - timeLast); intensNew.Add((float)intenNext); AddMassError(massErrorsNew, massError); timeLast = timesNew[iTime++]; intenLast = 0; } if (inferZeros) { // If the last intensity was zero, and the next measured time // is more than a delta away, assign zeros until within a // delta of the measured intensity. while (intenLast == 0 && iTime < timesNew.Count && timesNew[iTime] + intervalDelta < time) { intensNew.Add(0); AddMassError(massErrorsNew, massError); timeLast = timesNew[iTime++]; } } else { // Up to just before the current point, project the line from the // last point to the current point at each interval. while (iTime < timesNew.Count && timesNew[iTime] + intervalDelta < time) { intenNext = intenLast + (timesNew[iTime] - timeLast) * (inten - intenLast) / (time - timeLast); intensNew.Add((float)intenNext); AddMassError(massErrorsNew, massError); iTime++; } } if (iTime >= timesNew.Count) { break; } // Interpolate from the last intensity toward the measured // intenisty now within a delta of the point being assigned. if (time == timeLast) { intenNext = intenLast; } else { intenNext = intenLast + (timesNew[iTime] - timeLast) * (inten - intenLast) / (time - timeLast); } intensNew.Add((float)intenNext); massErrorLast = AddMassError(massErrorsNew, massError); iTime++; intenLast = inten; timeLast = time; } // Fill any unassigned intensities with zeros. while (intensNew.Count < timesNew.Count) { intensNew.Add(0); AddMassError(massErrorsNew, massErrorLast); } int[] scanIndexesNew = null; // Replicate scan ids to match new times. if (ScanIds != null) { scanIndexesNew = new int[timesNew.Count]; int rawIndex = 0; for (int i = 0; i < timesNew.Count; i++) { // Choose the RawScanId corresponding to the closest RawTime to the new time. float newTime = timesNew[i]; while (rawIndex < Times.Count && Times[rawIndex] <= newTime) { rawIndex++; } if (rawIndex >= Times.Count) { rawIndex--; } if (rawIndex > 0 && newTime - Times[rawIndex - 1] < Times[rawIndex] - newTime) { rawIndex--; } scanIndexesNew[i] = ScanIds[rawIndex]; } } IEnumerable <float> massErrorsNewTruncated = null; if (massErrorsNew != null) { // Round off all the mass errors, since that is what will be persisted in the .skyd file massErrorsNewTruncated = massErrorsNew.Select(error => ChromPeak.To10x(error) / 10f); } return(new TimeIntensities(timesNew, intensNew, massErrorsNewTruncated, scanIndexesNew)); }