diff --git a/BadDicom/BadDicom.csproj b/BadDicom/BadDicom.csproj index 5359127..ef72b3d 100644 --- a/BadDicom/BadDicom.csproj +++ b/BadDicom/BadDicom.csproj @@ -33,6 +33,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/BadDicom/Configuration/ExplicitUIDs.cs b/BadDicom/Configuration/ExplicitUIDs.cs index f118fc0..f4cb8db 100644 --- a/BadDicom/Configuration/ExplicitUIDs.cs +++ b/BadDicom/Configuration/ExplicitUIDs.cs @@ -51,7 +51,7 @@ public void Load() private static IEnumerable GetUIDsFrom(string? path) { if (string.IsNullOrWhiteSpace(path) || !File.Exists(path)) return Enumerable.Empty(); - + return File.ReadLines(path).Where(l => !string.IsNullOrWhiteSpace(l)); } } \ No newline at end of file diff --git a/BadDicom/Configuration/TargetDatabase.cs b/BadDicom/Configuration/TargetDatabase.cs index dc24c7c..51bd427 100644 --- a/BadDicom/Configuration/TargetDatabase.cs +++ b/BadDicom/Configuration/TargetDatabase.cs @@ -17,12 +17,12 @@ public class TargetDatabase /// The ConnectionString containing the server name, credentials and other parameters for the connection /// public string? ConnectionString { get; set; } - + /// /// The name of database /// public string? DatabaseName { get; set; } - + /// /// The filename of a YAML template file to be used for this database /// diff --git a/BadDicom/Program.cs b/BadDicom/Program.cs index ce11dea..592b677 100644 --- a/BadDicom/Program.cs +++ b/BadDicom/Program.cs @@ -81,7 +81,7 @@ private static void RunOptionsAndReturnExitCode(ProgramOptions opts) } catch (Exception e) { - + Console.WriteLine(e); _returnCode = 3; return; @@ -144,7 +144,7 @@ private static int RunDatabaseTarget(TargetDatabase configDatabase, ProgramOptio //if we are going into a database we definitely do not need pixels! opts.NoPixels = true; - + var swTotal = Stopwatch.StartNew(); const string neverDistinct = "SOPInstanceUID"; @@ -171,7 +171,7 @@ private static int RunDatabaseTarget(TargetDatabase configDatabase, ProgramOptio ImplementationManager.Load(); var server = new DiscoveredServer(configDatabase.ConnectionString, configDatabase.DatabaseType); - + try { server.TestConnection(); @@ -183,7 +183,7 @@ private static int RunDatabaseTarget(TargetDatabase configDatabase, ProgramOptio return -2; } - + var db = server.ExpectDatabase(configDatabase.DatabaseName); if (!db.Exists()) @@ -198,14 +198,14 @@ private static int RunDatabaseTarget(TargetDatabase configDatabase, ProgramOptio } var creator = new ImagingTableCreation(db.Server.GetQuerySyntaxHelper()); - + Console.WriteLine($"Image template contained schemas for {template.Tables.Count} tables. Looking for existing tables.."); - + //setting up bulk inserters var tables = new DiscoveredTable[template.Tables.Count]; var batches = new DataTable[batchSize][]; - for (var i = 0; i < batches.Length; i++) + for (var i = 0; i < batches.Length; i++) batches[i] = new DataTable[template.Tables.Count]; var uploaders= new IBulkCopy[batchSize][]; @@ -259,7 +259,7 @@ private static int RunDatabaseTarget(TargetDatabase configDatabase, ProgramOptio create = false; } } - + if(create) { Console.WriteLine($"About to create '{tbl.GetFullyQualifiedName()}'"); @@ -275,21 +275,21 @@ private static int RunDatabaseTarget(TargetDatabase configDatabase, ProgramOptio var dt = tbl.GetDataTable(); dt.Rows.Clear(); - batches[j][i] = dt; + batches[j][i] = dt; uploaders[j][i] = tbl.BeginBulkInsert(); } } var identifiers = GetPeople(opts, out var r); Parallel.For(0, batchSize, i => RunBatch(identifiers, opts, r, batches[i], uploaders[i])); - + swTotal.Stop(); for (var i = 0; i < tables.Length; i++) { if(pks[i] == null) continue; - + Console.WriteLine( $"{DateTime.Now} Making table '{tables[i]}' distinct (this may take a long time)"); var tbl = tables[i]; tbl.MakeDistinct(500000000); @@ -297,9 +297,9 @@ private static int RunDatabaseTarget(TargetDatabase configDatabase, ProgramOptio Console.WriteLine( $"{DateTime.Now} Creating primary key on '{tables[i]}' of '{pks[i]}'"); tbl.CreatePrimaryKey(500000000,tbl.DiscoverColumn(pks[i])); } - + Console.WriteLine("Final Row Counts:"); - + foreach (var t in tables) Console.WriteLine($"{t.GetFullyQualifiedName()}: {t.GetRowCount():0,0}"); @@ -322,14 +322,14 @@ private static void RunBatch(IPersonCollection identifiers, ProgramOptions opts, var p = identifiers.People[r.Next(identifiers.People.Length)]; var ds = dicomGenerator.GenerateStudyImages(p,out _); - + swGeneration.Stop(); foreach (var dataset in ds) { var rows = new DataRow[batches.Length]; - for (var j = 0; j < batches.Length; j++) + for (var j = 0; j < batches.Length; j++) rows[j] = batches[j].NewRow(); swReading.Start(); @@ -371,7 +371,7 @@ private static void RunBatch(IPersonCollection identifiers, ProgramOptions opts, batches[i].Dispose(); } } - + Console.WriteLine($"Total time Generating Dicoms:{swGeneration.Elapsed}"); Console.WriteLine($"Total time Reading Dicoms:{swReading.Elapsed}"); Console.WriteLine($"Total time Uploading Records:{swUploading.Elapsed}"); diff --git a/BadDicom/ProgramOptions.cs b/BadDicom/ProgramOptions.cs index 2ebd1d0..91bcb65 100644 --- a/BadDicom/ProgramOptions.cs +++ b/BadDicom/ProgramOptions.cs @@ -21,7 +21,7 @@ internal class ProgramOptions [Value(3, HelpText = "Comma separated list of modalities to generate from", Default = "CT")] public string Modalities { get; set; } = "CT"; - + [Option("NoPixels",HelpText= "Generate dicom files without pixel data (only tags). This results in much smaller file sizes")] public bool NoPixels{get;set;} @@ -42,13 +42,13 @@ public static IEnumerable Examples { get { - yield return + yield return new Example("Generate test data", new ProgramOptions { OutputDirectory = @"c:/temp" }); yield return new Example("Generate a custom amount of data", new ProgramOptions { OutputDirectory = @"c:/temp",NumberOfPatients = 5000, NumberOfStudies = 20000}); - + } } diff --git a/BadMedicine.Dicom.Tests/BadMedicine.Dicom.Tests.csproj b/BadMedicine.Dicom.Tests/BadMedicine.Dicom.Tests.csproj index e13b44c..438733c 100644 --- a/BadMedicine.Dicom.Tests/BadMedicine.Dicom.Tests.csproj +++ b/BadMedicine.Dicom.Tests/BadMedicine.Dicom.Tests.csproj @@ -15,7 +15,11 @@ - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/BadMedicine.Dicom.Tests/DicomDataGeneratorTests.cs b/BadMedicine.Dicom.Tests/DicomDataGeneratorTests.cs index ec871ac..6defb25 100644 --- a/BadMedicine.Dicom.Tests/DicomDataGeneratorTests.cs +++ b/BadMedicine.Dicom.Tests/DicomDataGeneratorTests.cs @@ -21,45 +21,50 @@ public void Test_CreatingOnDisk_OneFile() //generates a study but because of maximum images 1 we should only get 1 image being generated var studyUid = (string)generator.GenerateTestDataRow(person)[0]; - + //should be a directory named after the Study UID - Assert.IsTrue(Directory.Exists(Path.Combine(TestContext.CurrentContext.WorkDirectory, studyUid))); - + Assert.That(Directory.Exists(Path.Combine(TestContext.CurrentContext.WorkDirectory, studyUid))); + //should be a single file var f = new FileInfo(Directory.GetFiles(Path.Combine(TestContext.CurrentContext.WorkDirectory, studyUid)).Single()); - Assert.IsTrue(f.Exists); + Assert.That(f.Exists); var datasetCreated = DicomFile.Open(f.FullName); - - Assert.AreEqual(studyUid, - datasetCreated.Dataset.GetValues(DicomTag.StudyInstanceUID)[0].UID, - "UID in the dicom file generated did not match the one output into the CSV inventory file" - ); - Assert.IsNotEmpty(datasetCreated.Dataset.GetSingleValue(DicomTag.AccessionNumber)); + Assert.Multiple(() => + { + Assert.That(datasetCreated.Dataset.GetValues(DicomTag.StudyInstanceUID)[0].UID, Is.EqualTo(studyUid), + "UID in the dicom file generated did not match the one output into the CSV inventory file" + ); + + Assert.That(datasetCreated.Dataset.GetSingleValue(DicomTag.AccessionNumber), Is.Not.Empty); + }); } - + [Test] public void ExampleUsage() - { + { //create a test person var r = new Random(23); var person = new Person(r); - //create a generator + //create a generator using var generator = new DicomDataGenerator(r, null, "CT"); //create a dataset in memory var dataset = generator.GenerateTestDataset(person, r); - //values should match the patient details - Assert.AreEqual(person.CHI,dataset.GetValue(DicomTag.PatientID,0)); - Assert.GreaterOrEqual(dataset.GetValue(DicomTag.StudyDate,0),person.DateOfBirth); - - //should have a study description - Assert.IsNotNull(dataset.GetValue(DicomTag.StudyDescription,0)); - //should have a study description - Assert.IsNotNull(dataset.GetSingleValue(DicomTag.StudyTime).TimeOfDay); + Assert.Multiple(() => + { + //values should match the patient details + Assert.That(dataset.GetValue(DicomTag.PatientID, 0), Is.EqualTo(person.CHI)); + Assert.That(dataset.GetValue(DicomTag.StudyDate, 0), Is.GreaterThanOrEqualTo(person.DateOfBirth)); + + //should have a study description + Assert.That(dataset.GetValue(DicomTag.StudyDescription, 0), Is.Not.Null); + //should have a study time + Assert.That(dataset.Contains(DicomTag.StudyTime)); + }); } [Test] @@ -68,13 +73,13 @@ public void Test_CreatingInMemory_ModalityCT() var r = new Random(23); var person = new Person(r); using var generator = new DicomDataGenerator(r,new string(TestContext.CurrentContext.WorkDirectory),"CT") {NoPixels = true}; - + //generate 100 images for(var i = 0 ; i < 100 ; i++) { //all should be CT because we said CT only var ds = generator.GenerateTestDataset(person, r); - Assert.AreEqual("CT",ds.GetSingleValue(DicomTag.Modality)); + Assert.That(ds.GetSingleValue(DicomTag.Modality), Is.EqualTo("CT")); } } @@ -85,21 +90,27 @@ public void Test_Anonymise() var person = new Person(r); using var generator = new DicomDataGenerator(r,new string(TestContext.CurrentContext.WorkDirectory),"CT"); - + // without anonymisation (default) we get the normal patient ID var ds = generator.GenerateTestDataset(person, r); - - Assert.IsTrue(ds.Contains(DicomTag.PatientID)); - Assert.AreEqual(person.CHI,ds.GetValue(DicomTag.PatientID,0)); - + + Assert.Multiple(() => + { + Assert.That(ds.Contains(DicomTag.PatientID)); + Assert.That(ds.GetValue(DicomTag.PatientID, 0), Is.EqualTo(person.CHI)); + }); + // with anonymisation generator.Anonymise = true; - + var ds2 = generator.GenerateTestDataset(person, r); - // we get a blank patient ID - Assert.IsTrue(ds2.Contains(DicomTag.PatientID)); - Assert.AreEqual(string.Empty,ds2.GetString(DicomTag.PatientID)); + Assert.Multiple(() => + { + // we get a blank patient ID + Assert.That(ds2.Contains(DicomTag.PatientID)); + Assert.That(ds2.GetString(DicomTag.PatientID), Is.EqualTo(string.Empty)); + }); } [Test] public void Test_CreatingInMemory_Modality_CTAndMR() @@ -108,7 +119,7 @@ public void Test_CreatingInMemory_Modality_CTAndMR() var person = new Person(r); using var generator = new DicomDataGenerator(r,new string(TestContext.CurrentContext.WorkDirectory),"CT","MR"); - + //generate 100 images for(var i = 0 ; i < 100 ; i++) { @@ -116,7 +127,7 @@ public void Test_CreatingInMemory_Modality_CTAndMR() var ds = generator.GenerateTestDataset(person, r); var modality = ds.GetSingleValue(DicomTag.Modality); - Assert.IsTrue(modality is "CT" or "MR","Unexpected modality {0}",modality); + Assert.That(modality is "CT" or "MR","Unexpected modality {0}",modality); } } @@ -151,7 +162,7 @@ public void Test_CsvOption() } //3 csv files + index.csv (the default one - Assert.AreEqual(4,outputDir.GetFiles().Length); + Assert.That(outputDir.GetFiles(), Has.Length.EqualTo(4)); foreach (var f in outputDir.GetFiles()) { @@ -164,7 +175,7 @@ public void Test_CsvOption() //should be 1 row per image + 1 for header if(f.Name == DicomDataGenerator.ImageCsvFilename) - Assert.AreEqual(501,rowcount); + Assert.That(rowcount, Is.EqualTo(501)); } } } \ No newline at end of file diff --git a/BadMedicine.Dicom.Tests/PackageListIsCorrectTests.cs b/BadMedicine.Dicom.Tests/PackageListIsCorrectTests.cs index 51f2e57..88e4c7f 100644 --- a/BadMedicine.Dicom.Tests/PackageListIsCorrectTests.cs +++ b/BadMedicine.Dicom.Tests/PackageListIsCorrectTests.cs @@ -9,10 +9,10 @@ namespace BadMedicine.Dicom.Tests; /// -/// Tests to confirm that the dependencies in csproj files (NuGet packages) match those in the .nuspec files and that packages.md +/// Tests to confirm that the dependencies in csproj files (NuGet packages) match those in the .nuspec files and that packages.md /// lists the correct versions (in documentation) /// -public class PackageListIsCorrectTests +public sealed class PackageListIsCorrectTests { private static readonly EnumerationOptions EnumerationOptions = new() { RecurseSubdirectories = true,MatchCasing = MatchCasing.CaseInsensitive,IgnoreInaccessible = true}; @@ -36,17 +36,18 @@ public void TestPackagesDocumentCorrect(string rootPath=null) // Extract the named packages from PACKAGES.md var packagesMarkdown = File.ReadAllLines(GetPackagesMarkdown(root)) - .Select(line => RMarkdownEntry.Match(line)) - .Where(m=>m.Success) - .Select(m => m.Groups[1].Value) + .Select(static line => RMarkdownEntry.Match(line)) + .Where(static m=>m.Success) + .Select(static m => m.Groups[1].Value) .ToHashSet(StringComparer.InvariantCultureIgnoreCase); // Extract the named packages from csproj files, then subtract those listed in PACKAGES.md (should be empty) - var undocumentedPackages = GetCsprojFiles(root).Select(File.ReadAllText).SelectMany(s => RPackageRef.Matches(s)) - .Select(m=>m.Groups[1].Value).Except(packagesMarkdown).Select(BuildRecommendedMarkdownLine); + var undocumentedPackages = GetCsprojFiles(root).Select(File.ReadAllText) + .SelectMany(static s => RPackageRef.Matches(s)) + .Select(static m=>m.Groups[1].Value).Except(packagesMarkdown).Select(BuildRecommendedMarkdownLine); undocumented.AppendJoin(Environment.NewLine, undocumentedPackages); - Assert.IsEmpty(undocumented.ToString()); + Assert.That(undocumented.ToString(), Is.Empty); } /// @@ -54,7 +55,8 @@ public void TestPackagesDocumentCorrect(string rootPath=null) /// /// /// - private static object BuildRecommendedMarkdownLine(string package) => $"Package {package} is not documented in PACKAGES.md. Recommended line is:\r\n| {package} | [GitHub]() | LICENCE GOES HERE | |"; + private static object BuildRecommendedMarkdownLine(string package) => + $"Package {package} is not documented in PACKAGES.md. Recommended line is:\r\n| {package} | [GitHub]() | LICENCE GOES HERE | |"; /// /// Find the root of this repo, which is usually the directory containing the .sln file @@ -72,7 +74,7 @@ private static DirectoryInfo FindRoot(string path = null) var root = new DirectoryInfo(TestContext.CurrentContext.TestDirectory); while (!root.EnumerateFiles("*.sln", SearchOption.TopDirectoryOnly).Any() && root.Parent != null) root = root.Parent; - Assert.IsNotNull(root.Parent, "Could not find root of repository"); + Assert.That(root.Parent, Is.Not.Null, "Could not find root of repository"); return root; } @@ -83,7 +85,8 @@ private static DirectoryInfo FindRoot(string path = null) /// private static IEnumerable GetCsprojFiles(DirectoryInfo root) { - return root.EnumerateFiles("*.csproj", EnumerationOptions).Select(f => f.FullName).Where(f => !f.Contains("tests", StringComparison.InvariantCultureIgnoreCase)); + return root.EnumerateFiles("*.csproj", EnumerationOptions).Select(static f => f.FullName) + .Where(static f => !f.Contains("tests", StringComparison.InvariantCultureIgnoreCase)); } /// @@ -93,8 +96,9 @@ private static IEnumerable GetCsprojFiles(DirectoryInfo root) /// private static string GetPackagesMarkdown(DirectoryInfo root) { - var path = root.EnumerateFiles("packages.md", EnumerationOptions).Select(f => f.FullName).SingleOrDefault(); - Assert.IsNotNull(path, "Could not find packages.md"); + var path = root.EnumerateFiles("packages.md", EnumerationOptions).Select(static f => f.FullName) + .SingleOrDefault(); + Assert.That(path, Is.Not.Null, "Could not find packages.md"); return path; } diff --git a/BadMedicine.Dicom.Tests/StudyTests.cs b/BadMedicine.Dicom.Tests/StudyTests.cs index 3123975..63bc0c4 100644 --- a/BadMedicine.Dicom.Tests/StudyTests.cs +++ b/BadMedicine.Dicom.Tests/StudyTests.cs @@ -14,17 +14,20 @@ public void Test_CreatingNewStudy_HasSomeImages() using var generator = new DicomDataGenerator(r,null) {NoPixels = true}; var p = new Person(r); - + Study study = new(generator,p,new ModalityStats("MR",2,0,50,0,r),r); - Assert.AreEqual(2,study.Series.Count); - Assert.AreEqual(50,study.Series[0].Datasets.Count); + Assert.That(study.Series, Has.Count.EqualTo(2)); + Assert.That(study.Series[0].Datasets, Has.Count.EqualTo(50)); foreach(var ds in study.Series[0]) { - Assert.AreEqual("MR",ds.GetValues(DicomTag.Modality)[0]); - Assert.AreEqual(study.StudyTime,ds.GetSingleValue(DicomTag.StudyTime).TimeOfDay); + Assert.Multiple(() => + { + Assert.That(ds.GetValues(DicomTag.Modality)[0], Is.EqualTo("MR")); + Assert.That(ds.GetSingleValue(DicomTag.StudyTime).TimeOfDay, Is.EqualTo(study.StudyTime)); + }); } } @@ -43,12 +46,18 @@ public void Test_UsingExplicitUIDs() Study study = new(generator, p, new ModalityStats("MR", 2, 0, 50, 0, r), r); - Assert.AreEqual("999", study.StudyUID.UID); - Assert.AreEqual("888", study.Series[0].SeriesUID.UID); + Assert.Multiple(() => + { + Assert.That(study.StudyUID.UID, Is.EqualTo("999")); + Assert.That(study.Series[0].SeriesUID.UID, Is.EqualTo("888")); + }); var image1 = study.Series[0].Datasets[0]; - Assert.AreEqual("999", image1.GetSingleValue(DicomTag.StudyInstanceUID).UID); - Assert.AreEqual("888", image1.GetSingleValue(DicomTag.SeriesInstanceUID).UID); - Assert.AreEqual("777", image1.GetSingleValue(DicomTag.SOPInstanceUID).UID); + Assert.Multiple(() => + { + Assert.That(image1.GetSingleValue(DicomTag.StudyInstanceUID).UID, Is.EqualTo("999")); + Assert.That(image1.GetSingleValue(DicomTag.SeriesInstanceUID).UID, Is.EqualTo("888")); + Assert.That(image1.GetSingleValue(DicomTag.SOPInstanceUID).UID, Is.EqualTo("777")); + }); } } \ No newline at end of file diff --git a/BadMedicine.Dicom/BadMedicine.Dicom.csproj b/BadMedicine.Dicom/BadMedicine.Dicom.csproj index 6023a2f..80ac9e4 100644 --- a/BadMedicine.Dicom/BadMedicine.Dicom.csproj +++ b/BadMedicine.Dicom/BadMedicine.Dicom.csproj @@ -41,6 +41,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/BadMedicine.Dicom/DicomDataGenerator.cs b/BadMedicine.Dicom/DicomDataGenerator.cs index 7e9e3f2..aa1ac8e 100644 --- a/BadMedicine.Dicom/DicomDataGenerator.cs +++ b/BadMedicine.Dicom/DicomDataGenerator.cs @@ -50,7 +50,7 @@ public FileSystemLayout Layout{ get => _pathProvider.Layout; set => _pathProvider = new FileSystemLayoutProvider(value); } - + /// /// The maximum number of images to generate regardless of how many calls to , Defaults to int.MaxValue /// @@ -157,7 +157,7 @@ public DicomDataGenerator(Random r, string? outputDir, params string[] modalitie { DevNull = outputDir?.Equals("/dev/null", StringComparison.InvariantCulture)!=false; OutputDir = DevNull ? null : Directory.CreateDirectory(outputDir!); - + var stats = DicomDataGeneratorStats.GetInstance(); if(modalities.Length == 0) @@ -172,7 +172,7 @@ public DicomDataGenerator(Random r, string? outputDir, params string[] modalitie _modalities = modalities.Select(m=>stats.ModalityIndexes[m]).ToArray(); } } - + /// /// Creates a new dicom dataset /// @@ -242,7 +242,7 @@ protected override string[] GetHeaders() /// /// public DicomDataset[] GenerateStudyImages(Person p, out Study study) - { + { //generate a study study = new Study(this,p,GetRandomModality(r),r); @@ -276,14 +276,14 @@ private ModalityStats GetRandomModality(Random _r) public DicomDataset GenerateTestDataset(Person p,Series series) { var ds = new DicomDataset(); - + ds.AddOrUpdate(DicomTag.StudyInstanceUID,series.Study.StudyUID); ds.AddOrUpdate(DicomTag.SeriesInstanceUID,series.SeriesUID); var sopInstanceUID = UIDAllocator.GenerateSOPInstanceUID(); ds.AddOrUpdate(DicomTag.SOPInstanceUID,sopInstanceUID); ds.AddOrUpdate(DicomTag.SOPClassUID , DicomUID.SecondaryCaptureImageStorage); - + //patient details ds.AddOrUpdate(DicomTag.PatientID, p.CHI); ds.AddOrUpdate(DicomTag.PatientName, $"{p.Forename} {p.Surname}"); @@ -304,10 +304,10 @@ public DicomDataset GenerateTestDataset(Person p,Series series) ds.AddOrUpdate(new DicomDate(DicomTag.SeriesDate, series.SeriesDate)); ds.AddOrUpdate(new DicomTime(DicomTag.SeriesTime, DateTime.Today + series.SeriesTime)); - + ds.AddOrUpdate(DicomTag.Modality,series.Modality); ds.AddOrUpdate(DicomTag.AccessionNumber, series.Study.AccessionNumber?? ""); - + if(series.Study.StudyDescription != null) ds.AddOrUpdate(DicomTag.StudyDescription,series.Study.StudyDescription); @@ -322,7 +322,7 @@ public DicomDataset GenerateTestDataset(Person p,Series series) // Go back to the year the person was born in case of a leap year if (p.DateOfBirth.Date > series.SeriesDate.AddYears(-age)) age--; ds.AddOrUpdate(new DicomAgeString(DicomTag.PatientAge, $"{age:000}Y")); - + if(!NoPixels) PixelDrawer.DrawBlackBoxWithWhiteText(ds,500,500,sopInstanceUID.UID); @@ -379,7 +379,7 @@ private void InitialiseCSVOutput() _studyWriter = new CsvWriter(new StreamWriter(Path.Combine(OutputDir.FullName, StudyCsvFilename)),CultureInfo.CurrentCulture); _seriesWriter = new CsvWriter(new StreamWriter(Path.Combine(OutputDir.FullName, SeriesCsvFilename)),CultureInfo.CurrentCulture); _imageWriter = new CsvWriter(new StreamWriter(Path.Combine(OutputDir.FullName, ImageCsvFilename)),CultureInfo.CurrentCulture); - + // Write header WriteData(_studyWriter, StudyTags.Select(i => i.DictionaryEntry.Keyword)); WriteData(_seriesWriter, SeriesTags.Select(i => i.DictionaryEntry.Keyword)); @@ -390,7 +390,7 @@ private static void WriteData(CsvWriter sw, IEnumerable data) { foreach (var s in data) sw.WriteField(s); - + sw.NextRecord(); } diff --git a/BadMedicine.Dicom/ModalityStats.cs b/BadMedicine.Dicom/ModalityStats.cs index 49b730e..22de405 100644 --- a/BadMedicine.Dicom/ModalityStats.cs +++ b/BadMedicine.Dicom/ModalityStats.cs @@ -8,7 +8,7 @@ namespace BadMedicine.Dicom; /// public class ModalityStats { - + /// /// Which Modality this relates to, for example 'MR' /// @@ -42,8 +42,8 @@ public class ModalityStats /// /// The Normal distribution of the number of Images per Series for this Modality /// - public Normal ImagesPerSeriesNormal {get; private set; } - + public Normal ImagesPerSeriesNormal {get; private set; } + /// /// The Random pseudo-random number generator to be used /// diff --git a/BadMedicine.Dicom/PixelDrawer.cs b/BadMedicine.Dicom/PixelDrawer.cs index f8a3121..2975b53 100644 --- a/BadMedicine.Dicom/PixelDrawer.cs +++ b/BadMedicine.Dicom/PixelDrawer.cs @@ -26,7 +26,7 @@ internal static void DrawBlackBoxWithWhiteText(DicomDataset ds, int width, int h img.Mutate(x => x.Fill(Color.Black)); img.Mutate(x=>x.DrawText(msg,Font,Color.White,new PointF(width/2f,height/2f))); img.CopyPixelDataTo(buffer); - + ds.Add(DicomTag.PhotometricInterpretation, PhotometricInterpretation.Rgb.Value); ds.Add(DicomTag.Rows, (ushort)img.Height); ds.Add(DicomTag.Columns, (ushort)img.Width); diff --git a/BadMedicine.Dicom/Series.cs b/BadMedicine.Dicom/Series.cs index 51c811e..26a4310 100644 --- a/BadMedicine.Dicom/Series.cs +++ b/BadMedicine.Dicom/Series.cs @@ -17,7 +17,7 @@ public class Series : IEnumerable /// The unique identifier for this series /// public DicomUID SeriesUID {get; } - + /// /// The Dicom Study this series is a part of /// @@ -31,7 +31,7 @@ public class Series : IEnumerable public IReadOnlyList Datasets{get; } private readonly List _datasets = new(); - + /// /// Patient level information generated by BadMedicine.Dicom for whom /// the study exists. @@ -93,21 +93,21 @@ internal Series(Study study, Person person, string modality, string imageType, i Modality = modality; ImageType = imageType; NumberOfSeriesRelatedInstances = imageCount; - + //todo: for now just use the Study date, in theory secondary capture images could be generated later SeriesDate = study.StudyDate; SeriesTime = study.StudyTime; SeriesDescription = part?.SeriesDescription; BodyPartExamined = part?.BodyPartExamined; - + for (var i =0 ; i(_datasets); } - + /// /// Returns as IEnumerable /// diff --git a/BadMedicine.Dicom/Study.cs b/BadMedicine.Dicom/Study.cs index 41ecd9c..7165706 100644 --- a/BadMedicine.Dicom/Study.cs +++ b/BadMedicine.Dicom/Study.cs @@ -8,7 +8,7 @@ namespace BadMedicine.Dicom; /// /// Represents a whole DICOM Study (a collection of Series objects). /// Stores the DICOM tags that fit at the study/patient level hierarchy -/// (and are modelled by BadMedicine.Dicom). +/// (and are modelled by BadMedicine.Dicom). /// public class Study : IEnumerable { @@ -21,7 +21,7 @@ public class Study : IEnumerable /// The DicomDataGenerator which created this Study /// public DicomDataGenerator Parent; - + /// /// The DICOM UID of this Study /// @@ -87,7 +87,7 @@ public Study(DicomDataGenerator parent, Person person, ModalityStats modalitySta StudyTime = DicomDataGeneratorStats.Instance.GetRandomTimeOfDay(r); ///////////////////// Generate all the Series (will also generate images) ///////////////////// - + //have a random number of series (based on average and standard deviation for that modality) //but have at least 1 series! diff --git a/Packages.md b/Packages.md index d69b8c2..a451201 100644 --- a/Packages.md +++ b/Packages.md @@ -21,6 +21,7 @@ | Vecc.YamlDotNet.Analyzers.StaticGenerator | [GitHub](https://github.com/aaubry/YamlDotNet) | [MIT](https://opensource.org/licenses/MIT) |Extension to YamlDotNet for static processing| | CommandLineParser | [GitHub](https://github.com/commandlineparser/commandline) | [MIT](https://opensource.org/licenses/MIT) | Allows command line arguments for main client application and CLI executables | | [Nunit](https://nunit.org/) |[GitHub](https://github.com/nunit/nunit) | [MIT](https://opensource.org/licenses/MIT) | Unit testing | +| [NUnit.Analyzers](https://nunit.org/) |[GitHub](https://github.com/nunit/nunit.analyzers) | [MIT](https://opensource.org/licenses/MIT) | Unit testing support code | | NUnit3TestAdapter | [GitHub](https://github.com/nunit/nunit3-vs-adapter)| [MIT](https://opensource.org/licenses/MIT) | Run unit tests from within Visual Studio | | Microsoft.NET.Test.Sdk | [GitHub](https://github.com/microsoft/vstest/) | [MIT](https://opensource.org/licenses/MIT) | Run unit tests | | | NunitXml.TestLogger | [GitHub](https://github.com/spekt/nunit.testlogger) | [MIT](https://opensource.org/licenses/MIT) | Report test results in XML syntax | |