/// <summary> /// Cuts out gap portion of a spectrogram image. /// </summary> public static Image <Rgb24> RemoveGapPatch(Image <Rgb24> source, GapsAndJoins error) { int ht = source.Height; int width = source.Width; int gapStart = error.StartPosition; int gapEnd = error.EndPosition; int gapWidth = error.EndPosition - error.StartPosition + 1; // create new image Image <Rgb24> newBmp = new Image <Rgb24>(width - gapWidth, ht); newBmp.Mutate(g => { Rectangle srcRect = new Rectangle(0, 0, gapStart, ht); g.DrawImage(source.Clone(x => x.Crop(srcRect)), new Point(0, 0), 1); // copy image after the gap srcRect = new Rectangle(gapEnd + 1, 0, width, ht); g.DrawImage(source.CropIntersection(srcRect), new Point(gapStart, 0), 1); // draw separator at the join g.DrawLine(new Pen(Color.LightGray, 1), gapStart - 1, 0, gapStart, 15); g.DrawLine(new Pen(Color.LightGray, 1), gapStart, 0, gapStart, 15); }); return(newBmp); }
/// <summary> /// This method reads through a SUMMARY index array to check for file joins. /// </summary> /// <param name="summaryIndices">array of summary indices.</param> /// <param name="gapRendering">how to render the gap in image terms.</param> /// <returns>a list of erroneous segments.</returns> public static List <GapsAndJoins> DataIntegrityCheckForFileJoins(IEnumerable <SummaryIndexValues> summaryIndices, ConcatMode gapRendering) { // init list of gaps and joins var joins = new List <GapsAndJoins>(); string previousFileName = summaryIndices.First <SummaryIndexValues>().FileName; // now loop through the rows/vectors of indices int index = 0; foreach (var row in summaryIndices) { if (row.FileName != previousFileName) { var fileJoin = new GapsAndJoins { StartPosition = index, GapDescription = gapDescriptionFileJoin, GapRendering = gapRendering, EndPosition = index, // this renders to one pixel width. }; joins.Add(fileJoin); previousFileName = row.FileName; } index++; } return(joins); }
/// <summary> /// Cuts out gap portion of a spectrogram image /// </summary> public static Image RemoveGapPatch(Image source, GapsAndJoins error) { int ht = source.Height; int width = source.Width; int gapStart = error.StartPosition; int gapEnd = error.EndPosition; int gapWidth = error.EndPosition - error.StartPosition + 1; // create new image Bitmap newBmp = new Bitmap(width - gapWidth, ht); using (Graphics g = Graphics.FromImage(newBmp)) { Rectangle srcRect = new Rectangle(0, 0, gapStart, ht); g.DrawImage(source, 0, 0, srcRect, GraphicsUnit.Pixel); // copy image after the gap srcRect = new Rectangle(gapEnd + 1, 0, width, ht); g.DrawImage(source, gapStart, 0, srcRect, GraphicsUnit.Pixel); // draw separator at the join g.DrawLine(new Pen(Color.LightGray), gapStart - 1, 0, gapStart, 15); g.DrawLine(new Pen(Color.LightGray), gapStart, 0, gapStart, 15); } return(newBmp); }
/// <summary> /// This method reads through a SUMMARY index array to check for file joins. /// </summary> /// <param name="summaryIndices">array of summary indices</param> /// <param name="gapRendering">how to render the gap in image terms</param> /// <returns>a list of erroneous segments</returns> public static List <GapsAndJoins> DataIntegrityCheckForFileJoins(IEnumerable <SummaryIndexValues> summaryIndices, ConcatMode gapRendering) { // init list of gaps and joins var gaps = new List <GapsAndJoins>(); bool isValidBlock = true; string previousFileName = null; GapsAndJoins gap = null; // now loop through the rows/vectors of indices int index = 0; foreach (var row in summaryIndices) { if (previousFileName == null) { previousFileName = row.FileName; } if (row.FileName != previousFileName) { if (isValidBlock) { isValidBlock = false; gap = new GapsAndJoins { StartPosition = index, GapDescription = gapDescriptionFileJoin, GapRendering = gapRendering, }; } else { // come to end of a bad patch isValidBlock = true; gap.EndPosition = index - 1; gaps.Add(gap); } } previousFileName = row.FileName; index++; } // if not OK at end of the array, need to terminate the gap. if (!isValidBlock) { gaps[gaps.Count - 1].EndPosition = gaps[gaps.Count - 1].EndPosition; } return(gaps); }
/// <summary> /// This method reads through a ZeroIndex SUMMARY array. /// It reads the ZeroSignal array to make sure there was actually a signal to analyse. /// If this occurs an error is flagged. /// TODO: should do a unit test. Argument should be an a array of zeros with two insertions of short runs of ones. /// // One of the runs should terminate the array. e.g. 000000000000000000000000000000001111110000000000000000000000001111111111111. /// </summary> /// <param name="summaryIndices">array of summary indices</param> /// <returns>a list of erroneous segments</returns> public static List <GapsAndJoins> DataIntegrityCheckForZeroSignal(IEnumerable <SummaryIndexValues> summaryIndices) { const double tolerance = 0.0001; // init list of errors var errors = new List <GapsAndJoins>(); bool allOk = true; var error = new GapsAndJoins(); int index = 0; foreach (var row in summaryIndices) { // if (zeroSignal index > 0), i.e. if signal == zero if (Math.Abs(row.ZeroSignal) > tolerance) { if (allOk) { allOk = false; error = new GapsAndJoins { StartPosition = index, GapDescription = gapDescriptionZeroSignal, GapRendering = ConcatMode.TimedGaps, // all zero signal errors must be drawn as timed gaps }; } } else if (!allOk && Math.Abs(row.ZeroSignal) < tolerance) { // come to end of a bad patch allOk = true; error.EndPosition = index - 1; errors.Add(error); } index++; } // if not OK at end of the array, need to close the error. if (!allOk) { error.EndPosition = index - 1; errors.Add(error); } return(errors); }
/// <summary> /// This method reads through a SUMMARY index array to make sure there was actually a signal to analyse. /// If this occurs an gap/join event is flagged. /// </summary> /// <param name="summaryIndices">array of summary indices</param> /// <param name="gapRendering">how to render the gap in image terms</param> /// <returns>a list of erroneous segments</returns> public static List <GapsAndJoins> DataIntegrityCheckForNoRecording(IEnumerable <SummaryIndexValues> summaryIndices, ConcatMode gapRendering) { // init list of gaps and joins var gaps = new List <GapsAndJoins>(); bool isValidBlock = true; GapsAndJoins gap = null; // now loop through the rows/vectors of indices int index = 0; foreach (var row in summaryIndices) { // if this row is missing signal if (row.FileName == IndexMatrices.MissingRowString) { if (isValidBlock) { isValidBlock = false; gap = new GapsAndJoins { StartPosition = index, GapDescription = gapDescriptionMissingData, GapRendering = gapRendering, }; } } else if (!isValidBlock && row.FileName != IndexMatrices.MissingRowString) { // come to end of a bad patch isValidBlock = true; gap.EndPosition = index - 1; gaps.Add(gap); } index++; } // if not OK at end of the array, need to terminate the gap. if (!isValidBlock) { gaps[gaps.Count - 1].EndPosition = index - 1; } return(gaps); }
/// <summary> /// Draws an echo patch into a spectrogram image. /// </summary> public static Image <Rgb24> DrawEchoPatch(Image <Rgb24> source, GapsAndJoins error) { int ht = source.Height; int gapStart = error.StartPosition; int gapEnd = error.EndPosition; source.Mutate(g => { // get copy of the last spectrum before the gap. Rectangle srcRect = new Rectangle(gapStart - 1, 0, 1, ht); // plus one to gap end to draw the last column rather than leave it black for (int i = gapStart; i < gapEnd + 1; i++) { g.DrawImage(source.Clone(x => x.Crop(srcRect)), new Point(i, 0), 1); } //g.DrawLine(new Pen(Color.LightGray, 1), gapStart, 0, gapStart, ht); g.DrawLine(new Pen(Color.LightGray, 1), gapEnd, 0, gapEnd, 15); }); return(source); }
/// <summary> /// Draws an echo patch into a spectrogram image /// </summary> public static Image DrawEchoPatch(Image source, GapsAndJoins error) { int ht = source.Height; int gapStart = error.StartPosition; int gapEnd = error.EndPosition; using (var g = Graphics.FromImage(source)) { // get copy of the last spectrum before the gap. Rectangle srcRect = new Rectangle(gapStart - 1, 0, 1, ht); // plus one to gap end to draw the last column rather than leave it black for (int i = gapStart; i < gapEnd + 1; i++) { g.DrawImage(source, i, 0, srcRect, GraphicsUnit.Pixel); } //g.DrawLine(new Pen(Color.LightGray), gapStart, 0, gapStart, ht); g.DrawLine(new Pen(Color.LightGray), gapEnd, 0, gapEnd, 15); } return(source); }
/// <summary> /// This method reads through a SUMMARY index array looking for gaps in the recording. /// I initilly tried to detect these when the RankOrder index takes consecutive zero values. /// However this does not work with recordings sampled one minute in N minutes. /// So reverted to detecting the mising data flag which is when row.FileName == missingRow. /// If this occurs a gap event is flagged. /// </summary> /// <param name="summaryIndices">array of summary indices.</param> /// <param name="gapRendering">how to render the gap in image terms.</param> /// <returns>a list of erroneous segments.</returns> public static List <GapsAndJoins> DataIntegrityCheckRecordingGaps(IEnumerable <SummaryIndexValues> summaryIndices, ConcatMode gapRendering) { // init list of gaps and joins var gaps = new List <GapsAndJoins>(); // initialise starting conditions for loop string missingRow = IndexMatrices.MissingRowString; //int previousRank = -1; GapsAndJoins gap = null; bool isGap = false; int index = 0; // now loop through the rows/vectors of indices foreach (var row in summaryIndices) { //if (!isGap && (row.RankOrder == previousRank + 1)) //{ // //everything OK // //continue; //} // if in gap and zeros continue then still in gap //if (isGap && (row.RankOrder == 0 && previousRank == 0)) //{ // //still in gap // //continue; //} //if (!isGap && (row.RankOrder == 0 && previousRank == 0)) if (!isGap && (row.FileName == missingRow)) { // create gap instance isGap = true; gap = new GapsAndJoins { StartPosition = index, GapDescription = gapDescriptionMissingData, GapRendering = gapRendering, }; } //if (isGap && (row.RankOrder == 1 && previousRank == 0)) if (isGap && (row.FileName != missingRow)) { // come to end of a gap isGap = false; gap.EndPosition = index - 1; gaps.Add(gap); } //previousRank = row.RankOrder; index++; } // reached end of array // if still have gap at end of the array, need to terminate it. if (isGap) { //gaps[gaps.Count - 1].EndPosition = index - 1; gap.EndPosition = summaryIndices.Count() - 1; gaps.Add(gap); } return(gaps); }