Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump NUnit from 3.14.0 to 4.0.1 #161

Merged
merged 5 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 18 additions & 23 deletions BadMedicine.Core/BadMedicine.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Title>HIC.BadMedicine</Title>
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/HicServices/BadMedicine</PackageProjectUrl>
<PackageTags>Test Data,Random,Synthetic Data,EHR,Electronic Health Record</PackageTags>
<Copyright>Copyright 2019</Copyright>
<PackageId>HIC.BadMedicine</PackageId>
<Authors>Health Informatics Centre - University of Dundee</Authors>
<TargetFramework>net7.0</TargetFramework>
<Title>HIC.BadMedicine</Title>
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/HicServices/BadMedicine</PackageProjectUrl>
<PackageTags>Test Data,Random,Synthetic Data,EHR,Electronic Health Record</PackageTags>
<Copyright>Copyright 2019</Copyright>
<PackageId>HIC.BadMedicine</PackageId>
<Authors>Health Informatics Centre - University of Dundee</Authors>
<TargetFramework>net8.0</TargetFramework>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<StartupObject></StartupObject>
<ApplicationIcon />
<OutputType>Library</OutputType>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<DebugType>embedded</DebugType>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<RootNamespace>BadMedicine</RootNamespace>
<AssemblyName>BadMedicine.Core</AssemblyName>
<Description>Library and CLI for randomly generating medical data like you might get out of an Electronic Health Records (EHR) system. It is intended for generating data for demos and testing ETL / cohort generation/ data management tools.
<LangVersion>latest</LangVersion>
<Description>
Library and CLI for randomly generating medical data like you might get out of an Electronic Health Records (EHR) system. It is intended for generating data for demos and testing ETL / cohort generation/ data management tools.

BadMedicine differs from other random data generators e.g. Mockaroo, SQL Data Generator etc in that data generated is based on (simple) models generated from live EHR datasets collected for over 30 years in Tayside and Fife (UK). This makes the data generated recognisable (codes used, frequency of codes etc) from a clinical perspective and representative of the problems (ontology mapping etc) that data analysts would encounter working with real medical data..</Description>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</PropertyGroup>
<PropertyGroup>
<LangVersion>9.0</LangVersion>
BadMedicine differs from other random data generators e.g. Mockaroo, SQL Data Generator etc in that data generated is based on (simple) models generated from live EHR datasets collected for over 30 years in Tayside and Fife (UK). This makes the data generated recognisable (codes used, frequency of codes etc) from a clinical perspective and representative of the problems (ontology mapping etc) that data analysts would encounter working with real medical data..
</Description>
<IsAotCompatible>true</IsAotCompatible>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Test|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -43,15 +39,14 @@ BadMedicine differs from other random data generators e.g. Mockaroo, SQL Data Ge
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\Datasets.doc.xml" Link="Datasets.doc.xml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Datasets\Aggregates.zip" />
<EmbeddedResource Include="Datasets\Maternity.csv" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="30.0.1" />
<PackageReference Include="Equ" Version="2.3.0" />
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
Expand Down
127 changes: 71 additions & 56 deletions BadMedicine.Core/BucketList.cs
Original file line number Diff line number Diff line change
@@ -1,81 +1,96 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace BadMedicine
namespace BadMedicine;

/// <summary>
/// Picks random object of Type T based on a specified probability for each element.
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class BucketList<T> : IEnumerable<(T item,int probability)>
{
private Lazy<int> _total;
private readonly List<(T item, int probability)> _list=[];

/// <summary>
/// Picks random object of Type T based on a specified probability for each element.
/// Construct an empty BucketList
/// </summary>
/// <typeparam name="T"></typeparam>
public class BucketList<T>
public BucketList()
{
_total = new Lazy<int>(GetTotal,LazyThreadSafetyMode.ExecutionAndPublication);
}

readonly List<T> _buckets = new List<T>();
readonly List<int> _probabilities = new List<int>();
private int GetTotal() => _list.Sum(static t => t.probability);

private int? _total = null;
/// <summary>
/// Returns a random bucket (based on the probability of each bucket)
/// </summary>
/// <returns></returns>
public T GetRandom(Random r)
{
var toPick = r.Next(0, _total.Value);

/// <summary>
/// Returns a random bucket (based on the probability of each bucket)
/// </summary>
/// <returns></returns>
public T GetRandom(Random r)
for (var i = 0; i < _list.Count; i++)
{
//cache the total
_total = _total??_probabilities.Sum();
toPick -= _list[i].probability;
if (toPick < 0)
return _list[i].item;
}

var toPick = r.Next(0, _total.Value);
throw new Exception("Could not GetRandom");
}

for (var i = 0; i < _probabilities.Count; i++)
{
toPick -= _probabilities[i];
if (toPick < 0)
return _buckets[i];
}

throw new Exception("Could not GetRandom");
}
/// <summary>
/// Returns a random bucket from the element indices provided (based on the probability of each bucket)
/// </summary>
/// <param name="usingOnlyIndices"></param>
/// <param name="r"></param>
/// <returns></returns>
public T GetRandom(IEnumerable<int> usingOnlyIndices, Random r)
{
var idx = usingOnlyIndices.ToList();

var total = idx.Sum(t => _list[t].probability);

/// <summary>
/// Returns a random bucket from the element indices provided (based on the probability of each bucket)
/// </summary>
/// <param name="usingOnlyIndices"></param>
/// <param name="r"></param>
/// <returns></returns>
public T GetRandom(IEnumerable<int> usingOnlyIndices, Random r)
{
var idx = usingOnlyIndices.ToList();
var toPick = r.Next(0, total);

var total = idx.Sum(t=>_probabilities[t]);
foreach (var i in idx)
{
toPick -= _list[i].probability;
if (toPick < 0)
return _list[i].item;
}

var toPick = r.Next(0, total);
throw new Exception("Could not GetRandom");
}

foreach (var i in idx)
{
toPick -= _probabilities[i];
if (toPick < 0)
return _buckets[i];
}

throw new Exception("Could not GetRandom");
}

/// <summary>
/// Adds a new bucket to the list which will be returned using the total <paramref name="probability"/> ratio (relative
/// to the other buckets).
/// </summary>
/// <param name="probability"></param>
/// <param name="toAdd"></param>
public void Add(int probability, T toAdd)
{
_list.Add((toAdd,probability));
if (_total.IsValueCreated)
_total = new Lazy<int>(GetTotal, LazyThreadSafetyMode.ExecutionAndPublication);
}

/// <inheritdoc/>
public IEnumerator<(T item, int probability)> GetEnumerator()
{
return ((IEnumerable<(T item, int probability)>)_list).GetEnumerator();
}

/// <summary>
/// Adds a new bucket to the list which will be returned using the total <paramref name="probability"/> ratio (relative
/// to the other buckets).
/// </summary>
/// <param name="probability"></param>
/// <param name="toAdd"></param>
public void Add(int probability, T toAdd)
{
_probabilities.Add(probability);
_buckets.Add(toAdd);
_total = null;
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_list).GetEnumerator();
}
}
}
41 changes: 17 additions & 24 deletions BadMedicine.Core/Datasets/Appointment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,25 @@

using System;

namespace BadMedicine.Datasets
namespace BadMedicine.Datasets;

/// <summary>
/// Data class describing an appointment including a guid identifier
/// </summary>
/// <remarks>
/// Creates a new randomly generated appointment within the lifetime of the <paramref name="testPerson"/>
/// </remarks>
/// <param name="testPerson"></param>
/// <param name="r"></param>
public sealed class Appointment(Person testPerson, Random r)
{
/// <summary>
/// Data class describing an appointment including a guid identifier
/// Globally unique identifier for this appointment
/// </summary>
public class Appointment
{
/// <summary>
/// Globally unique identifier for this appointment
/// </summary>
public string Identifier { get; set; }

/// <summary>
/// Random date within the lifetime of the <see cref="Person"/> used for construction
/// </summary>
public DateTime StartDate { get; set; }
public string Identifier { get; set; } = $"APPT_{Guid.NewGuid()}";

/// <summary>
/// Creates a new randomly generated appointment within the lifetime of the <paramref name="testPerson"/>
/// </summary>
/// <param name="testPerson"></param>
/// <param name="r"></param>
public Appointment(Person testPerson, Random r)
{
Identifier = $"APPT_{Guid.NewGuid()}";
StartDate = testPerson.GetRandomDateDuringLifetime(r);
}
}
/// <summary>
/// Random date within the lifetime of the <see cref="Person"/> used for construction
/// </summary>
public DateTime StartDate { get; set; } = testPerson.GetRandomDateDuringLifetime(r);
}
62 changes: 27 additions & 35 deletions BadMedicine.Core/Datasets/Biochemistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,17 @@
// You should have received a copy of the GNU General Public License along with RDMP. If not, see <https://www.gnu.org/licenses/>.

using System;
using System.IO;

namespace BadMedicine.Datasets
namespace BadMedicine.Datasets;

/// <include file='../../Datasets.doc.xml' path='Datasets/Biochemistry'/>
/// <inheritdoc/>
public sealed class Biochemistry(Random rand) : DataGenerator(rand)
{
/// <include file='../../Datasets.doc.xml' path='Datasets/Biochemistry'/>
public class Biochemistry: DataGenerator
{
/// <inheritdoc/>
public Biochemistry(Random rand) : base(rand)
{
}

/// <inheritdoc/>
public override object[] GenerateTestDataRow(Person p)
{
/// <inheritdoc/>
public override object[] GenerateTestDataRow(Person p)
{
var results = new object[13];

var randomSample = new BiochemistryRecord(r);
Expand All @@ -42,26 +38,22 @@ public override object[] GenerateTestDataRow(Person p)

}

/// <inheritdoc/>
protected override string[] GetHeaders()
{
return new string[]
{
"chi", //0
"Healthboard", //1
"SampleDate", //2
"SampleType", //3
"TestCode", //4
"Result", //5
"Labnumber", //6
"QuantityUnit", //7
"ReadCodeValue", //8
"ArithmeticComparator", //9
"Interpretation", //10
"RangeHighValue", //11
"RangeLowValue", //12

};
}
}
}
/// <inheritdoc/>
protected override string[] GetHeaders() =>
[
"chi", //0
"Healthboard", //1
"SampleDate", //2
"SampleType", //3
"TestCode", //4
"Result", //5
"Labnumber", //6
"QuantityUnit", //7
"ReadCodeValue", //8
"ArithmeticComparator", //9
"Interpretation", //10
"RangeHighValue", //11
"RangeLowValue" //12

];
}
Loading