static void ProcessClusterHierarchy(OverlapRemovalCluster root, ClusterDelegate worker) { var stack = new Stack<ClusterItem>(); stack.Push(new ClusterItem(root)); while (stack.Count > 0) { // Keep the cluster on the stack until we're done with its children. var item = stack.Peek(); int prevStackCount = stack.Count; if (!item.ChildrenHaveBeenPushed) { item.ChildrenHaveBeenPushed = true; foreach (var childCluster in item.Cluster.Clusters) { stack.Push(new ClusterItem(childCluster)); } if (stack.Count > prevStackCount) { continue; } } // endif !node.ChildrenHaveBeenPushed // No children to push so pop and process this cluster. Debug.Assert(stack.Peek() == item, "stack.Peek() should be 'item'"); stack.Pop(); worker(item.Cluster); } }
public int Carve() { int filesRestored = 0; RootDirectory r; ClusterDelegate getClusterNo = delegate(int sector) { return(((sector - DataRegion_start_sector) / SectorsPerCluster) + Constants.START_CLUSTER); }; List <RootDirectory> root_entries = new List <RootDirectory>(); uint start_cluster_for_file = Constants.NULLED, fileSize = Constants.NULLED, start_sector_for_file = Constants.NULLED; bool foundHeader = false; /* * Read all root directory entries */ for (int j = 0; j < RootDirectory_size; j++) { byte[][] RootDirectoryEntries = split(getSector(j + RootDirectory_start_sector), Constants.RD_ENTRY_LENGTH); for (int i = 0; i < RootDirectoryEntries.Length; i++) { if (!RootDirectoryEntries[i].All(singlByte => singlByte == 0)) { root_entries.Add(new RootDirectory(RootDirectoryEntries[i])); } } } /* * This for-loop reads each cluster in the data region and * changes the FAT region (as necessary). */ for (int sector = DataRegion_start_sector; sector < data.Length / BytesPerSector && sector < ushort.MaxValue; sector++) { /* * Prepare yourself for unneccessary unit and int casts * and cluster and sector conversions. */ int type = HeaderChecker.checkClusterForFooterAndHeader(getSector(sector), ref fileSize, ref fileSize); switch (type) { case (int)headerFooter.GIFHeader: case (int)headerFooter.JPGHeader: case (int)headerFooter.PNGHeader: if (foundHeader) { throw new Exception(); } else { foundHeader = true; } start_sector_for_file = (uint)sector; break; case (int)headerFooter.BMPHeader: if (foundHeader) { throw new Exception(); } start_cluster_for_file = (uint)getClusterNo(sector); if (changeFATTable(start_cluster_for_file, (uint)(Math.Ceiling((double)fileSize / bytesPerCluster)))) { r = new RootDirectory(); r.FileName = (++filesRestored).ToString(); r.FileExtension = HeaderChecker.getExtension(type); r.byteSize = fileSize; r.start_cluster = (ushort)start_cluster_for_file; root_entries.Add(r); } break; case (int)headerFooter.GIFFooter: case (int)headerFooter.JPGFooter: case (int)headerFooter.PNGFooter: if (!foundHeader) { throw new Exception(); } else { foundHeader = false; } int aa2 = getClusterNo(sector); uint file_cluster_length = (uint)(getClusterNo(sector) - getClusterNo((int)start_sector_for_file)) + 1; /* * Oh my god, what have I created. */ if (changeFATTable((uint)getClusterNo((int)start_sector_for_file), file_cluster_length)) { r = new RootDirectory(); r.FileName = (++filesRestored).ToString(); r.FileExtension = HeaderChecker.getExtension(type); int lastSectorLength = RemoveTrailingZeros(getSector(sector)).Length; r.byteSize = (uint)(lastSectorLength + ((sector - start_sector_for_file) * BytesPerSector)); r.start_cluster = (ushort)getClusterNo((int)start_sector_for_file); root_entries.Add(r); } break; case (int)headerFooter.Invalid: break; default: throw new Exception(); } } if (filesRestored != 0) { //Code for reading the current root directories can also be placed here. /* * Get the Root directory data in terms of sector byte data */ int clustersToReserve = (int)(Math.Floor(((double)root_entries.Count * Constants.RD_ENTRY_LENGTH) / BytesPerSector)); List <byte[]> dataToWrite = new List <byte[]>(); foreach (RootDirectory rr in root_entries) { dataToWrite.Add(rr.ByteData); } int k = 0; foreach (byte[] b in dataToWrite) { foreach (byte bb in b) { data[RootDirectory_start_sector * BytesPerSector + k++] = bb; } } } return(filesRestored); }
/// <summary> /// Calculate metric for a single cluser of sequences (all stored sequences), /// and write metric data to file/s if required. /// </summary> public void ProcessSequences() { bool isGood = true; if (allSequences != null && allSequences.Count > 0 && !isComplete) // do the following only if there are sequences to be processed { clusterCount++; ClusterMetric metric = new ClusterMetric(expectedPloidy, numSamples); // Initialise metric output file/s InitMetricOutputFiles(); // Initialise bam output file/s InitBamOutputFiles(); // Perform core metric calculations on cluster sequences metric.Calculate(allSequences); isGood = GoodOrBad(metric); // Get haplotype information if(haplotypingEnabled && expectedPloidy == 2) { GetHaplotypeInfo(ref metric, ref isGood); } if(isGood) { ++goodCount; } Console.WriteLine(metric.ToString() + "\t" + (isGood ? Properties.Resources.GOOD_CLUSTER : Properties.Resources.BAD_CLUSTER)); // Get statistics from the metric for this new cluster CreateSummaryArrays(metric, isGood); SetOverviewStats(metric, isGood); // Output sequences to metric file/s and/or filtered bam file WriteToMetricOutputFiles(metric, isGood); AddToOutputBamQueueOrDispose(metric, isGood); // If the bam file is not currently being written to, and there are sequences in the queue ready to be // written, launch a new thread to perform the writing to file if (writeToFilteredBam && canWriteToBam && bamOutputQueue.Count > 0) { canWriteToBam = false; ClusterDelegate runner = new ClusterDelegate(WriteToBam); runner.BeginInvoke(null, null); } } // Now that all processing has been performed for the current cluster, if the handler has been // aborted, perform any final file outputs if(aborted) { SetComplete(false); } }