Skip to content

Commit

Permalink
MSS-58 Updated API to make it compatible with fo-dicom 4.0.3. Bumped …
Browse files Browse the repository at this point in the history
…version.
  • Loading branch information
tznind committed Oct 28, 2019
1 parent b704b09 commit 2220f15
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 59 deletions.
31 changes: 14 additions & 17 deletions BadMedicine.Dicom.Tests/DicomDataGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,20 @@ public void ExampleUsage()
var person = new Person(r);

//create a generator
var generator = new DicomDataGenerator(r,null,"CT");

//create a dataset in memory
DicomDataset dataset = generator.GenerateTestDataset(person);
using (var generator = new DicomDataGenerator(r, null, "CT"))
{
//create a dataset in memory
DicomDataset dataset = generator.GenerateTestDataset(person, r);

//values should match the patient details
Assert.AreEqual(person.CHI,dataset.GetValue<string>(DicomTag.PatientID,0));
Assert.GreaterOrEqual(dataset.GetValue<DateTime>(DicomTag.StudyDate,0),person.DateOfBirth);
//values should match the patient details
Assert.AreEqual(person.CHI,dataset.GetValue<string>(DicomTag.PatientID,0));
Assert.GreaterOrEqual(dataset.GetValue<DateTime>(DicomTag.StudyDate,0),person.DateOfBirth);

//should have a study description
Assert.IsNotNull(dataset.GetValue<string>(DicomTag.StudyDescription,0));
//should have a study description
Assert.IsNotNull(dataset.GetSingleValue<DateTime>(DicomTag.StudyTime).TimeOfDay);

generator.Dispose();
//should have a study description
Assert.IsNotNull(dataset.GetValue<string>(DicomTag.StudyDescription,0));
//should have a study description
Assert.IsNotNull(dataset.GetSingleValue<DateTime>(DicomTag.StudyTime).TimeOfDay);
}
}

[Test]
Expand All @@ -80,7 +79,7 @@ public void Test_CreatingInMemory_ModalityCT()
for(int i = 0 ; i < 100 ; i++)
{
//all should be CT because we said CT only
var ds = generator.GenerateTestDataset(person);
var ds = generator.GenerateTestDataset(person, r);
Assert.AreEqual("CT",ds.GetSingleValue<string>(DicomTag.Modality));
}

Expand All @@ -99,7 +98,7 @@ public void Test_CreatingInMemory_Modality_CTAndMR()
for(int i = 0 ; i < 100 ; i++)
{
//all should be CT because we said CT only
var ds = generator.GenerateTestDataset(person);
var ds = generator.GenerateTestDataset(person, r);
var modality = ds.GetSingleValue<string>(DicomTag.Modality);

Assert.IsTrue(modality == "CT" || modality == "MR","Unexpected modality {0}",modality);
Expand Down Expand Up @@ -155,8 +154,6 @@ public void Test_CsvOption()
}

}


}
}
}
4 changes: 2 additions & 2 deletions BadMedicine.Dicom/BadMedicine.Dicom.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="fo-dicom.NetCore" Version="4.0.1" />
<PackageReference Include="HIC.BadMedicine" Version="0.1.4" />
<PackageReference Include="fo-dicom.NetCore" Version="4.0.3" />
<PackageReference Include="HIC.BadMedicine" Version="0.1.5" />
<PackageReference Include="System.Drawing.Common" Version="4.5.1" />
</ItemGroup>

Expand Down
6 changes: 3 additions & 3 deletions BadMedicine.Dicom/BadMedicine.Dicom.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
<title>HIC.BadMedicine.Dicom</title>
<authors>Health Informatics Centre - University of Dundee</authors>
<owners>Health Informatics Centre - University of Dundee</owners>
<projectUrl>https://github.com/HicServices/BadMedicine</projectUrl>
<projectUrl>https://github.com/HicServices/BadMedicine.Dicom</projectUrl>
<license type="expression">GPL-3.0-or-later</license>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Generate large volumes of complex (in terms of tags) dicom images for integration/stress testing ETL and image management tools. BadMedicine.Dicom generates dicom images on demand based on an anonymous aggregate model of tag data found in scottish medical imaging with a small memory footprint.</description>
<copyright>Copyright 2019</copyright>
<tags>Dicom,Test Data,Random,Synthetic Data,Health</tags>
<dependencies>
<dependency id="MathNet.Numerics" version="4.7.0" exclude="Build,Analyzers" />
<dependency id="fo-dicom.NetCore" version="4.0.1" />
<dependency id="HIC.BadMedicine" version="0.1.4" />
<dependency id="fo-dicom.NetCore" version="4.0.3" />
<dependency id="HIC.BadMedicine" version="0.1.5" />
<dependency id="System.Drawing.Common" version="4.5.1" />
</dependencies>
</metadata>
Expand Down
26 changes: 17 additions & 9 deletions BadMedicine.Dicom/DicomDataGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,21 +152,21 @@ protected override string[] GetHeaders()
public DicomDataset[] GenerateStudyImages(Person p, out Study study)
{
//generate a study
study = new Study(this,p,GetRandomModality(),r);
study = new Study(this,p,GetRandomModality(r),r);

return study.SelectMany(series=>series).Select(image=>image).ToArray();
}

public DicomDataset GenerateTestDataset(Person p)
public DicomDataset GenerateTestDataset(Person p,Random r)
{
//get a random modality
var modality = GetRandomModality();
var modality = GetRandomModality(r);
return GenerateTestDataset(p,new Study(this,p,modality,r).Series[0]);
}

private ModalityStats GetRandomModality()
private ModalityStats GetRandomModality(Random r)
{
return DicomDataGeneratorStats.GetInstance(r).ModalityFrequency.GetRandom(_modalities);
return DicomDataGeneratorStats.GetInstance(r).ModalityFrequency.GetRandom(_modalities,r);
}

/// <summary>
Expand All @@ -189,8 +189,16 @@ public DicomDataset GenerateTestDataset(Person p,Series series)
ds.AddOrUpdate(DicomTag.PatientID, p.CHI);
ds.AddOrUpdate(DicomTag.PatientName, p.Forename + " " + p.Surname);
ds.AddOrUpdate(DicomTag.PatientBirthDate, p.DateOfBirth);
ds.AddOrUpdate(DicomTag.PatientAddress,p.Address.Line1 + " " + p.Address.Line2 + " " + p.Address.Line3 + " " + p.Address.Line4 + " " + p.Address.Postcode.Value);

if (p.Address != null)
{
string s = p.Address.Line1 + " " + p.Address.Line2 + " " + p.Address.Line3 + " " + p.Address.Line4 +
" " + p.Address.Postcode.Value;

ds.AddOrUpdate(DicomTag.PatientAddress,
s.Substring(0,Math.Min(s.Length,64)) //LO only allows 64 characters
);
}

ds.AddOrUpdate(new DicomDate(DicomTag.StudyDate, series.Study.StudyDate));
ds.AddOrUpdate(new DicomTime(DicomTag.StudyTime, DateTime.Today + series.Study.StudyTime));
Expand Down Expand Up @@ -235,11 +243,11 @@ public DicomDataset GenerateTestDataset(Person p,Series series)
ds.AddOrUpdate(DicomTag.AcquisitionNumber, "0");
ds.AddOrUpdate(DicomTag.AcquisitionDate, series.SeriesDate);
ds.AddOrUpdate(new DicomTime(DicomTag.AcquisitionTime, DateTime.Today + series.SeriesTime));
ds.AddOrUpdate(DicomTag.ImagePositionPatient, "0");
ds.AddOrUpdate(DicomTag.PixelSpacing, "0");
ds.AddOrUpdate(DicomTag.ImagePositionPatient, "0","0","0");
ds.AddOrUpdate(new DicomDecimalString(DicomTag.PixelSpacing,"0.3","0.25"));
ds.AddOrUpdate(DicomTag.FieldOfViewDimensions, "0");
ds.AddOrUpdate(DicomTag.FieldOfViewDimensionsInFloat, "0");
ds.AddOrUpdate(DicomTag.TransferSyntaxUID, "0");
//ds.AddOrUpdate(DicomTag.TransferSyntaxUID, "1.2.840.10008.1.2"); this seems to break saving of files lets not set it
ds.AddOrUpdate(DicomTag.LossyImageCompression, "00");
ds.AddOrUpdate(DicomTag.LossyImageCompressionMethod, "ISO_10918_1");
ds.AddOrUpdate(DicomTag.LossyImageCompressionRatio, "1");
Expand Down
22 changes: 11 additions & 11 deletions BadMedicine.Dicom/DicomDataGeneratorStats.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ internal class DicomDataGeneratorStats

private DicomDataGeneratorStats(Random r)
{
InitializeTagValuesByModalityAndTag(r);
InitializeTagValuesByModalityAndTag();
InitializeModalityFrequency(r);
InitializeImageType(r);
InitializeImageType();

InitializeHourOfDay(r);
}
Expand All @@ -42,7 +42,7 @@ private void InitializeHourOfDay(Random r)
//Provenance:
//select DATEPART(HOUR,StudyTime),work.dbo.get_aggregate_value(count(*)) from CT_Godarts_StudyTable group by DATEPART(HOUR,StudyTime)

HourOfDay = new BucketList<int>(r);
HourOfDay = new BucketList<int>();

HourOfDay.Add(1,1);
HourOfDay.Add(4,1);
Expand Down Expand Up @@ -73,7 +73,7 @@ private void InitializeHourOfDay(Random r)
/// <returns></returns>
public TimeSpan GetRandomTimeOfDay(Random r)
{
var ts = new TimeSpan(0,HourOfDay.GetRandom(),r.Next(60),r.Next(60),0);
var ts = new TimeSpan(0,HourOfDay.GetRandom(r),r.Next(60),r.Next(60),0);

ts = ts.Subtract(new TimeSpan(ts.Days,0,0,0));

Expand All @@ -83,9 +83,9 @@ public TimeSpan GetRandomTimeOfDay(Random r)
return ts;
}

public string GetRandomImageType()
public string GetRandomImageType(Random r)
{
return ImageType.GetRandom();
return ImageType.GetRandom(r);
}

/// <summary>
Expand All @@ -109,7 +109,7 @@ private void InitializeModalityFrequency(Random r)

DicomDataGenerator.EmbeddedCsvToDataTable(typeof(DicomDataGenerator), "DicomDataGeneratorModalities.csv",dt);

ModalityFrequency = new BucketList<ModalityStats>(r);
ModalityFrequency = new BucketList<ModalityStats>();

int idx=0;
foreach(DataRow dr in dt.Rows)
Expand All @@ -130,7 +130,7 @@ private void InitializeModalityFrequency(Random r)

}

private void InitializeTagValuesByModalityAndTag(Random r)
private void InitializeTagValuesByModalityAndTag()
{
DataTable dt = new DataTable();
dt.Columns.Add("Frequency", typeof(int));
Expand All @@ -146,16 +146,16 @@ private void InitializeTagValuesByModalityAndTag(Random r)
TagValuesByModalityAndTag.Add(modality,new Dictionary<DicomTag, BucketList<string>>());

if(!TagValuesByModalityAndTag[modality].ContainsKey(tag))
TagValuesByModalityAndTag[modality].Add(tag,new BucketList<string>(r));
TagValuesByModalityAndTag[modality].Add(tag,new BucketList<string>());

int frequency = (int) dr["Frequency"];
TagValuesByModalityAndTag[modality][tag].Add(frequency,(string)dr["Value"]);
}
}

private void InitializeImageType(Random r)
private void InitializeImageType()
{
ImageType = new BucketList<string>(r);
ImageType = new BucketList<string>();

ImageType.Add(96,"ORIGINAL\\PRIMARY\\AXIAL");
ImageType.Add(1,"ORIGINAL\\PRIMARY\\LOCALIZER");
Expand Down
6 changes: 3 additions & 3 deletions BadMedicine.Dicom/Study.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public Study(DicomDataGenerator parent, Person person, ModalityStats modalitySta

//if it's a study level one record it here
if(dict.Key == DicomTag.StudyDescription)
StudyDescription = dict.Value.GetRandom();
StudyDescription = dict.Value.GetRandom(r);
}

AccessionNumber = stats.GetRandomAccessionNumber(r);
Expand All @@ -58,7 +58,7 @@ public Study(DicomDataGenerator parent, Person person, ModalityStats modalitySta
if(modalityStats.Modality == "CT")
{
// Set ImageType
imageType = stats.GetRandomImageType();
imageType = stats.GetRandomImageType(r);
if(imageType == "ORIGINAL\\PRIMARY\\AXIAL")
{
NumberOfStudyRelatedInstances = Math.Max(1,(int)modalityStats.SeriesPerStudyNormal.Sample());
Expand All @@ -67,7 +67,7 @@ public Study(DicomDataGenerator parent, Person person, ModalityStats modalitySta
}
else
{
imageType = "UNKNOWN";
imageType = "ORIGINAL\\PRIMARY";
NumberOfStudyRelatedInstances = Math.Max(1,(int)modalityStats.SeriesPerStudyNormal.Sample());
imageCount = Math.Max(1,(int)modalityStats.ImagesPerSeriesNormal.Sample());
}
Expand Down
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

...
## [0.0.4] - 2019-10-28

## Changed

- Updated dependencies to latest fo Dicom library 4.0.3

## Fixed

- Fixed dodgy tags in test data generated which results in broken images with fo Dicom 4.0.3

## [0.0.3] - 2019-10-28

### Added

- Added Csv mode where by dicom tags are output in full to series/study/instance level CSV files

## [0.0.2] - 2019-07-16

Expand All @@ -24,6 +39,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support for PatientAge, Modality, Address, UIDs, StudyDate/Time
- Support for pixel data / NoPixels flag

[Unreleased]: https://github.com/HicServices/BadMedicine.Dicom/compare/5517d7e29aaf3742e91b86288b85f692a063dba4...develop
[Unreleased]: https://github.com/HicServices/BadMedicine.Dicom/compare/v0.0.4...develop
[0.0.4]: https://github.com/HicServices/BadMedicine.Dicom/compare/v0.0.3...v0.0.4
[0.0.3]: https://github.com/HicServices/BadMedicine.Dicom/compare/5517d7e29aaf3742e91b86288b85f692a063dba4...v0.0.3
[0.0.2]: https://github.com/HicServices/BadMedicine.Dicom/compare/v0.0.1...5517d7e29aaf3742e91b86288b85f692a063dba4
[0.0.1]: https://github.com/HicServices/BadMedicine.Dicom/compare/bdea963df0337e47434c3e72bde7a16a111b99a8...v0.0.1
4 changes: 2 additions & 2 deletions Packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

| Package | Source Code | Version | License | Purpose | Additional Risk Assessment |
| ------- | ------------| --------| ------- | ------- | -------------------------- |
| HIC.BadMedicine | [GitHub](https://github.com/HicServices/BadMedicine) | [0.1.4](https://www.nuget.org/packages/HIC.BadMedicine/0.1.4) | [GPL 3.0](https://www.gnu.org/licenses/gpl-3.0.html) | Handles generating baseline random data (patient date of birth, CHI numberts etc)| |
| fo-dicom.NetCore | [GitHub](https://github.com/fo-dicom/fo-dicom) |[4.0.1](https://www.nuget.org/packages/fo-dicom.NetCore/4.0.1)|[MS-PL](https://opensource.org/licenses/MS-PL) | Handles reading/writing dicom tags from dicom datasets | |
| HIC.BadMedicine | [GitHub](https://github.com/HicServices/BadMedicine) | [0.1.5](https://www.nuget.org/packages/HIC.BadMedicine/0.1.5) | [GPL 3.0](https://www.gnu.org/licenses/gpl-3.0.html) | Handles generating baseline random data (patient date of birth, CHI numberts etc)| |
| fo-dicom.NetCore | [GitHub](https://github.com/fo-dicom/fo-dicom) |[4.0.3](https://www.nuget.org/packages/fo-dicom.NetCore/4.0.3)|[MS-PL](https://opensource.org/licenses/MS-PL) | Handles reading/writing dicom tags from dicom datasets | |
| YamlDotNet | [GitHub](https://github.com/aaubry/YamlDotNet) | [6.0.0](https://www.nuget.org/packages/YamlDotNet/6.0.0) | [MIT](https://opensource.org/licenses/MIT) |Loading configuration files|
| [Nunit](https://nunit.org/) |[GitHub](https://github.com/nunit/nunit) | [3.11.0](https://www.nuget.org/packages/NUnit/3.11.0) | [MIT](https://opensource.org/licenses/MIT) | Unit testing |
| NUnit3TestAdapter | [GitHub](https://github.com/nunit/nunit3-vs-adapter)| [3.13.0](https://www.nuget.org/packages/NUnit3TestAdapter/3.13.0) | [MIT](https://opensource.org/licenses/MIT) | Run unit tests from within Visual Studio |
Expand Down
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,18 @@ var r = new Random(23);
var person = new Person(r);

//create a generator
var generator = new DicomDataGenerator(r,null,"CT");

//create a dataset in memory
DicomDataset dataset = generator.GenerateTestDataset(person);

//values should match the patient details
Assert.AreEqual(person.CHI,dataset.GetValue<string>(DicomTag.PatientID,0));
Assert.GreaterOrEqual(dataset.GetValue<DateTime>(DicomTag.StudyDate,0),person.DateOfBirth);
using (var generator = new DicomDataGenerator(r, null, "CT"))
{
//create a dataset in memory
DicomDataset dataset = generator.GenerateTestDataset(person, r);

//values should match the patient details
Assert.AreEqual(person.CHI,dataset.GetValue<string>(DicomTag.PatientID,0));
Assert.GreaterOrEqual(dataset.GetValue<DateTime>(DicomTag.StudyDate,0),person.DateOfBirth);

//should have a study description
Assert.IsNotNull(dataset.GetValue<string>(DicomTag.StudyDescription,0));
}
```

## Building
Expand Down
6 changes: 3 additions & 3 deletions SharedAssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
[assembly: AssemblyCulture("")]

// These should be replaced with correct values by the release process
[assembly: AssemblyVersion("0.0.3")]
[assembly: AssemblyFileVersion("0.0.3")]
[assembly: AssemblyInformationalVersion("0.0.3")]
[assembly: AssemblyVersion("0.0.4")]
[assembly: AssemblyFileVersion("0.0.4")]
[assembly: AssemblyInformationalVersion("0.0.4")]

0 comments on commit 2220f15

Please sign in to comment.