Skip to content

Commit

Permalink
Rework rendering of Concatenated Indices
Browse files Browse the repository at this point in the history
Purpose of this was to get unit tests working. The most important work here was done in the gapsAndJoins class.
All unit tests for this class are now working.
  • Loading branch information
towsey committed Mar 19, 2019
1 parent 668e48b commit d690c35
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 76 deletions.
119 changes: 60 additions & 59 deletions src/AudioAnalysisTools/Indices/GapsAndJoins.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ public class GapsAndJoins
/// <summary>
/// Does several data integrity checks.
/// </summary>
/// <param name="summaryIndices">a dictionary of summary indices</param>
/// <param name="gapRendering">describes how recording gaps are to be rendered</param>
/// <returns>a list of erroneous segments</returns>
/// <param name="summaryIndices">a dictionary of summary indices.</param>
/// <param name="gapRendering">describes how recording gaps are to be rendered.</param>
/// <returns>a list of erroneous segments.</returns>
public static List<GapsAndJoins> DataIntegrityCheck(IEnumerable<SummaryIndexValues> summaryIndices, ConcatMode gapRendering)
{
// Integrity check 1: look for whether a recording minute exists
var errors = DataIntegrityCheckForNoRecording(summaryIndices, gapRendering);
var errors = DataIntegrityCheckRecordingGaps(summaryIndices, gapRendering);

// Integrity check 2: look for whether there is join between two recording files
errors.AddRange(DataIntegrityCheckForFileJoins(summaryIndices, gapRendering));
Expand All @@ -88,21 +88,21 @@ public static List<GapsAndJoins> DataIntegrityCheck(IEnumerable<SummaryIndexValu
/// <summary>
/// Does three data integrity checks.
/// </summary>
/// <param name="spectralIndices">a dictionary of spectral indices</param>
/// <param name="gapRendering">how to render the gap in image terms</param>
/// <returns>a list of erroneous segments</returns>
/// <param name="spectralIndices">a dictionary of spectral 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> DataIntegrityCheck(Dictionary<string, double[,]> spectralIndices, ConcatMode gapRendering)
{
var errors = DataIntegrityCheckSpectralIndices(spectralIndices, gapRendering);
return errors;
}

/// <summary>
/// Writes a list of erroneous segment properties to file
/// Writes a list of erroneous segment properties to file.
/// </summary>
/// <param name="errors">list of erroneous segments</param>
/// <param name="outputDirectory">directory in which json file to be written</param>
/// <param name="fileStem">name of json file</param>
/// <param name="errors">list of erroneous segments.</param>
/// <param name="outputDirectory">directory in which json file to be written.</param>
/// <param name="fileStem">name of json file.</param>
public static void WriteErrorsToFile(List<GapsAndJoins> errors, DirectoryInfo outputDirectory, string fileStem)
{
// write info to file
Expand All @@ -118,72 +118,79 @@ public static void WriteErrorsToFile(List<GapsAndJoins> errors, DirectoryInfo ou
}

/// <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.
/// 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> DataIntegrityCheckForNoRecording(IEnumerable<SummaryIndexValues> summaryIndices, ConcatMode gapRendering)
/// <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 joins = new List<GapsAndJoins>();
string previousFileName = summaryIndices.First<SummaryIndexValues>().FileName;
var gaps = new List<GapsAndJoins>();

// now loop through the rows/vectors of indices
// 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 (previousFileName == null)
//if (!isGap && (row.RankOrder == previousRank + 1))
//{
// previousFileName = row.FileName;
// //everything OK
// //continue;
//}

//if (row.FileName != previousFileName)
// if in gap and zeros continue then still in gap
//if (isGap && (row.RankOrder == 0 && previousRank == 0))
//{
// if (isValidBlock)
// {
// isValidBlock = false;
// fileJoin = new GapsAndJoins
// {
// StartPosition = index,
// GapDescription = gapDescriptionFileJoin,
// GapRendering = gapRendering,
// };
// }
// else
// {
// // come to end of a bad patch
// isValidBlock = true;
// fileJoin.EndPosition = index - 1;
// joins.Add(fileJoin);
// }
// //still in gap
// //continue;
//}

if (row.FileName != previousFileName)
//if (!isGap && (row.RankOrder == 0 && previousRank == 0))
if (!isGap && (row.FileName == missingRow))
{
var fileJoin = new GapsAndJoins
// create gap instance
isGap = true;
gap = new GapsAndJoins
{
StartPosition = index,
GapDescription = gapDescriptionFileJoin,
GapDescription = gapDescriptionMissingData,
GapRendering = gapRendering,
EndPosition = index, // this renders to one pixel width.
};
}

joins.Add(fileJoin);
previousFileName = row.FileName;
//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++;
}

// if not OK at end of the array, need to terminate the gap.
//if (!isValidBlock)
//{
// joins[joins.Count - 1].EndPosition = joins[joins.Count - 1].EndPosition;
//}
// 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 joins;
return gaps;
}

/// <summary>
Expand Down Expand Up @@ -245,12 +252,6 @@ public static List<GapsAndJoins> DataIntegrityCheckForFileJoins(IEnumerable<Summ
index++;
}

// if not OK at end of the array, need to terminate the gap.
//if (!isValidBlock)
//{
// joins[joins.Count - 1].EndPosition = joins[joins.Count - 1].EndPosition;
//}

return joins;
}

Expand Down Expand Up @@ -447,7 +448,7 @@ public static List<GapsAndJoins> DataIntegrityCheckSpectralIndices(
}

/// <summary>
/// This method draws the error segments in in hierarchical order, highest level errors first.
/// This method draws the error segments in hierarchical order, highest level errors first.
/// This way error due to missing recording is drawn last and overwrites other casading errors due to missing recording.
/// </summary>
/// <param name="bmp">The chromeless spectrogram to have segments drawn on it.</param>
Expand Down
18 changes: 9 additions & 9 deletions src/AudioAnalysisTools/Indices/IndexDisplay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public static Bitmap DrawImageOfSummaryIndices(
continue;
}

string name = ip.Name;
//string name = ip.Name;
double[] array = dictionaryOfSummaryIndices[key];
scaleLength = array.Length;
Image bitmap = ip.GetPlotImage(array, errors);
Expand All @@ -144,25 +144,25 @@ public static Bitmap DrawImageOfSummaryIndices(
.Where(b => b != null).ToList();

//set up the composite image parameters
int X_offset = 2;
int graphWidth = X_offset + scaleLength;
int imageWidth = X_offset + scaleLength + TrackEndPanelWidth;
TimeSpan scaleDuration = TimeSpan.FromMinutes(scaleLength);
int imageHt = trackHeight * (listOfBitmaps.Count + 4); //+3 for title and top and bottom time tracks
int x_offset = 2;
int graphWidth = x_offset + scaleLength;
int imageWidth = x_offset + scaleLength + TrackEndPanelWidth;
//TimeSpan scaleDuration = TimeSpan.FromMinutes(scaleLength);
//int imageHt = trackHeight * (listOfBitmaps.Count + 4); //+3 for title and top and bottom time tracks
Bitmap titleBmp = ImageTrack.DrawTitleTrack(imageWidth, trackHeight, titleText);

//Bitmap time1Bmp = ImageTrack.DrawTimeTrack(scaleDuration, TimeSpan.Zero, DrawSummaryIndices.TimeScale, graphWidth, TrackHeight, "Time (hours)");
TimeSpan xAxisPixelDuration = indexCalculationDuration;
TimeSpan fullDuration = TimeSpan.FromTicks(xAxisPixelDuration.Ticks * graphWidth);
Bitmap timeBmp1 = ImageTrack.DrawTimeRelativeTrack(fullDuration, graphWidth, trackHeight);
Bitmap timeBmp2 = timeBmp1;
Bitmap suntrack = null;
//Bitmap suntrack = null;
DateTimeOffset? dateTimeOffset = recordingStartDate;
if (dateTimeOffset.HasValue)
{
// draw extra time scale with absolute start time. AND THEN Do SOMETHING WITH IT.
timeBmp2 = ImageTrack.DrawTimeTrack(fullDuration, dateTimeOffset, graphWidth, trackHeight);
suntrack = SunAndMoon.AddSunTrackToImage(scaleLength, dateTimeOffset, sunriseDataFile);
//suntrack = SunAndMoon.AddSunTrackToImage(scaleLength, dateTimeOffset, sunriseDataFile);
}

//draw the composite bitmap
Expand All @@ -175,7 +175,7 @@ public static Bitmap DrawImageOfSummaryIndices(
}

imageList.Add(timeBmp2);
imageList.Add(suntrack);
//imageList.Add(suntrack);
Bitmap compositeBmp = (Bitmap)ImageTools.CombineImagesVertically(imageList);
return compositeBmp;
}
Expand Down
4 changes: 2 additions & 2 deletions src/AudioAnalysisTools/Indices/IndexProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,8 @@ public Image GetPlotImage(double[] array, List<GapsAndJoins> errors = null)
int trackHeight = IndexDisplay.DefaultTrackHeight;
Color[] grayScale = ImageTools.GrayScale();

Bitmap bmp = new Bitmap(trackWidth, trackHeight);
Graphics g = Graphics.FromImage(bmp);
var bmp = new Bitmap(trackWidth, trackHeight);
var g = Graphics.FromImage(bmp);
g.Clear(grayScale[240]);

// for pixels in the line
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@ namespace Acoustics.Test.AnalysisPrograms.Concatenation
using System.IO;
using System.IO.Compression;
using System.Linq;

using Acoustics.Shared;
using global::AnalysisPrograms;

using global::AudioAnalysisTools.Indices;
using global::AudioAnalysisTools.LongDurationSpectrograms;
using global::TowseyLibrary;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestHelpers;
using TowseyLibrary;

/// <summary>
/// Test methods for the various Frequency Scales
Expand Down Expand Up @@ -341,7 +338,7 @@ public void SampledDataConcatModeTests(ConcatMode gapRendering, int[] expectedWi
var actualImage = ImageTools.ReadImage2Bitmap(imagePath);
Assert.That.ImageIsSize(expectedWidth, 632, actualImage);

// target region for each image: 40,254, 20,20
// target region for each image: 40, 254, 20,20
switch (gapRendering)
{
case ConcatMode.TimedGaps:
Expand All @@ -355,7 +352,7 @@ public void SampledDataConcatModeTests(ConcatMode gapRendering, int[] expectedWi
case ConcatMode.NoGaps:
// There should basically be no pattern here
var histogram = ImageTools.GetColorHistogramNormalized(
actualImage,
actualImage,
new Rectangle(40, 254, 20, 20));

// should not have empty space
Expand Down
2 changes: 1 addition & 1 deletion tests/Acoustics.Test/InfiniteTextStreamTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void Generate()
}
}

var work = Task.Run(Generate, token);
var work = Task.Run((Action)Generate, token);

Assert.IsFalse(work.IsCompleted);
source.CancelAfter(this.timeout);
Expand Down

0 comments on commit d690c35

Please sign in to comment.