// ReSharper restore UnusedMember.Local private bool CreateCache(ILoadMonitor loader, IProgressStatus status, int percent) { var sm = loader.StreamManager; BufferedStream stream = new BufferedStream(CreateStream(loader), 32 * 1024); int version = 1; string id = string.Empty, revision = string.Empty; int size = ReadSize(stream); int i; if (size == 0) { version = 2; size = ReadSize(stream); const int countLibHeader = 256 - 8; byte[] libHeader = new byte[countLibHeader]; if (stream.Read(libHeader, 0, libHeader.Length) != libHeader.Length) { throw new InvalidDataException(Resources.XHunterLibrary_CreateCache_Data_truncation_in_library_header_File_may_be_corrupted); } for (i = 0; i < libHeader.Length; i++) { if (libHeader[i] == 0) { break; } } string header = Encoding.UTF8.GetString(libHeader, 0, i); Match match = REGEX_HEADER.Match(header); if (match.Success) { version = int.Parse(match.Groups[1].Value); id = match.Groups[2].Value; revision = match.Groups[3].Value; } } var setLibKeys = new HashSet <LibKey>(size); var libraryEntries = new List <XHunterSpectrumInfo>(size); const int countHeader = ((int)SpectrumHeaders2.count) * sizeof(int); byte[] specHeader = new byte[1024]; byte[] specSequence = new byte[1024]; i = 0; while (stream.Read(specHeader, 0, countHeader) == countHeader) { int percentComplete = (i++ *percent / size); if (status.PercentComplete != percentComplete) { // Check for cancellation after each integer change in percent loaded. if (loader.IsCanceled) { loader.UpdateProgress(status.Cancel()); return(false); } // If not cancelled, update progress. loader.UpdateProgress(status = status.ChangePercentComplete(percentComplete)); } int charge = (version == 1 ? GetInt32(specHeader, ((int)SpectrumHeaders1.charge)) : GetInt32(specHeader, ((int)SpectrumHeaders2.charge))); float i2 = (version == 1 ? GetSingle(specHeader, ((int)SpectrumHeaders1.i2)) : GetSingle(specHeader, ((int)SpectrumHeaders2.i2))); int seqLength = (version == 1 ? GetInt32(specHeader, ((int)SpectrumHeaders1.seq_len)) : GetInt32(specHeader, ((int)SpectrumHeaders2.seq_len))); float expect = (version == 1 ? 0.001f : GetSingle(specHeader, (int)SpectrumHeaders2.expect)); // Read sequence information ReadComplete(stream, specSequence, seqLength); specSequence[seqLength] = 0; short numPeaks = (short)ReadSize(stream); // Save spectrum location long location = stream.Position; // Read over spectrum int countPeaks = (sizeof(byte) + sizeof(float)) * numPeaks; stream.Seek(countPeaks, SeekOrigin.Current); // Skip spectrum // Read modifications int numMods = ReadSize(stream); string modifiedSequence = Encoding.UTF8.GetString(specSequence, 0, seqLength); if (numMods > 0) { StringBuilder sb = new StringBuilder(); ReadComplete(stream, specHeader, (4 + sizeof(double)) * numMods); int iLast = 0; double modTotal = 0; for (int j = 0; j < numMods; j++) { int iPos = GetInt32(specHeader, j * 3); double mod = BitConverter.ToDouble(specHeader, (j * 3 + 1) * 4); // X! Hunter allows multiple modifications on the same // residue. So, they need to be totaled, and assigned to a // single residue to allow them to match Skyline modification // settings. if (iPos > iLast) { if (modTotal != 0) { sb.Append(SequenceMassCalc.GetModDiffDescription(modTotal)); } sb.Append(Encoding.UTF8.GetString(specSequence, iLast, iPos - iLast)); modTotal = 0; } modTotal += mod; iLast = iPos; } if (modTotal != 0) { sb.Append(SequenceMassCalc.GetModDiffDescription(modTotal)); } sb.Append(Encoding.UTF8.GetString(specSequence, iLast, seqLength - iLast)); modifiedSequence = sb.ToString(); } // Skip over homologs (list of protein IDs and start positions from a FASTA // file used to generate the library) int numHomologs = ReadSize(stream); for (int j = 0; j < numHomologs; j++) { stream.Seek(ReadSize(stream) + 4, SeekOrigin.Current); } // These libraries should not have duplicates, but just in case. // Apparently, GPM libraries do contain redundancies, as we found // when a revision lost this test. var key = new LibKey(modifiedSequence, charge); if (setLibKeys.Add(key)) { libraryEntries.Add(new XHunterSpectrumInfo(key, i2, expect, numPeaks, location)); } } libraryEntries = FilterInvalidLibraryEntries(ref status, libraryEntries); using (FileSaver fs = new FileSaver(CachePath, sm)) using (Stream outStream = sm.CreateStream(fs.SafeName, FileMode.Create, true)) { foreach (var info in libraryEntries) { info.Key.Write(outStream); PrimitiveArrays.WriteOneValue(outStream, info.Location); PrimitiveArrays.WriteOneValue(outStream, info.ProcessedIntensity); PrimitiveArrays.WriteOneValue(outStream, info.NumPeaks); PrimitiveArrays.WriteOneValue(outStream, info.Expect); } byte[] revisionBytes = Encoding.UTF8.GetBytes(revision); outStream.Write(revisionBytes, 0, revisionBytes.Length); byte[] idBytes = Encoding.UTF8.GetBytes(id); outStream.Write(idBytes, 0, idBytes.Length); outStream.Write(BitConverter.GetBytes(revisionBytes.Length), 0, sizeof(int)); outStream.Write(BitConverter.GetBytes(idBytes.Length), 0, sizeof(int)); outStream.Write(BitConverter.GetBytes(FORMAT_VERSION_CACHE), 0, sizeof(int)); outStream.Write(BitConverter.GetBytes(libraryEntries.Count), 0, sizeof(int)); outStream.Write(BitConverter.GetBytes((long)0), 0, sizeof(long)); sm.Finish(outStream); fs.Commit(); sm.SetCache(FilePath, CachePath); } loader.UpdateProgress(status.Complete()); return(true); }