chore: deploy initial code base
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
using Strata.RxNorm.Biz.RxNorm;
|
||||
|
||||
namespace Strata.RxNorm.Biz.Test.Unit.RxNorm
|
||||
{
|
||||
public class FlattenConso
|
||||
{
|
||||
public string RRxcui1 { get; set; }
|
||||
public string RRxcui2 { get; set; }
|
||||
public string Rxcui1 { get; set; }
|
||||
public string Sab1 { get; set; }
|
||||
public string Tty1 { get; set; }
|
||||
public string Str1 { get; set; }
|
||||
public string Rxcui2 { get; set; }
|
||||
public string Sab2 { get; set; }
|
||||
public string Tty2 { get; set; }
|
||||
public string Str2 { get; set; }
|
||||
public string Sab3 { get; set; }
|
||||
public string Tty3 { get; set; }
|
||||
public string Str3 { get; set; }
|
||||
public string SatStype { get; set; }
|
||||
public string SatAtn { get; set; }
|
||||
public string SatSab { get; set; }
|
||||
public string SatAtv { get; set; }
|
||||
public RxnRelation RxnRelation { get; set; }
|
||||
public RxnConcept[] conso { get; set; }
|
||||
public RxnAttribute sat { get; set; }
|
||||
|
||||
public FlattenConso(RxnRelation rel, RxnConcept conso1, RxnConcept conso2, RxnConcept conso3, RxnAttribute sat)
|
||||
{
|
||||
RxnRelation = rel;
|
||||
conso = new[] { conso1, conso2, conso3 };
|
||||
this.sat = sat;
|
||||
RRxcui1 = rel.Rxcui1;
|
||||
RRxcui2 = rel.Rxcui2;
|
||||
Rxcui1 = conso1.Rxcui;
|
||||
Sab1 = conso1.Sab;
|
||||
Tty1 = conso1.Tty;
|
||||
Str1 = conso1.Str;
|
||||
Rxcui2 = conso2?.Rxcui;
|
||||
Sab2 = conso2?.Sab ?? "";
|
||||
Tty2 = conso2?.Tty ?? "";
|
||||
Str2 = conso2?.Str ?? "";
|
||||
Sab3 = conso3?.Sab ?? "";
|
||||
Tty3 = conso3?.Tty ?? "";
|
||||
Str3 = conso3?.Str ?? "";
|
||||
SatStype = sat?.Stype;
|
||||
SatAtn = sat?.Atn;
|
||||
SatSab = sat?.Sab;
|
||||
SatAtv = sat?.Atv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
using EFCore.BulkExtensions;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Moq;
|
||||
using Npgsql;
|
||||
using NUnit.Framework;
|
||||
using Strata.CoreLib.Claims;
|
||||
using Strata.RxNorm.Biz.DbContexts;
|
||||
using Strata.RxNorm.Biz.Notification;
|
||||
using Strata.RxNorm.Biz.Pharmacy;
|
||||
using Strata.RxNorm.Biz.RxNorm;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.RxNorm.Biz.Test.Unit.RxNorm;
|
||||
|
||||
[TestFixture]
|
||||
internal class RxNormServiceTests
|
||||
{
|
||||
private RxNormDbContext _dbContext;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var builder = new NpgsqlConnectionStringBuilder()
|
||||
{
|
||||
Database = "rxnorm",
|
||||
Host = "localhost",
|
||||
Port = 5555,
|
||||
Username = "postgres",
|
||||
Password = "postgres",
|
||||
WriteBufferSize = 1024 * 1024 * 16
|
||||
};
|
||||
|
||||
var options = new DbContextOptionsBuilder<RxNormDbContext>()
|
||||
.UseNpgsql(builder.ToString())
|
||||
.UseSnakeCaseNamingConvention()
|
||||
.Options;
|
||||
|
||||
_dbContext = new RxNormDbContext(options);
|
||||
}
|
||||
|
||||
[Explicit("Make sure local database is up before running tests")]
|
||||
[TestCase("RXNSAT1A.RRF", TypeArgs = [typeof(RxnAttribute)], TestName = "RxnAttribute Small 50MB")]
|
||||
[TestCase("RXNSAT.RRF", TypeArgs = [typeof(RxnAttribute)], TestName = "RxnAttribute Big 250MB")]
|
||||
[TestCase("RXNCONSO.RRF", TypeArgs = [typeof(RxnConcept)], TestName = "RxnConcept 30MB")]
|
||||
[TestCase("RXNREL1A.RRF", TypeArgs = [typeof(RxnRelation)], TestName = "RxnRelation 50MB")]
|
||||
public async Task SeedTableTests<TEntity>(string fileName) where TEntity : class
|
||||
{
|
||||
var pharmacyUpdateService = Mock.Of<IPharmacyUpdateService>();
|
||||
Mock.Get(pharmacyUpdateService)
|
||||
.Setup(p => p.RunPharmacyUpdateClientJob(It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync("Success");
|
||||
var rxNormService = new RxNormService(_dbContext, pharmacyUpdateService, NullLogger<RxNormService>.Instance, Mock.Of<IHubContext<NotificationHub, INotificationHub>>(), new StubClaimsPrincipalAccessor(username: "user"));
|
||||
|
||||
const string testFileDirectory = "../../../Rrf_Files";
|
||||
var fullFilePath = Path.Combine(testFileDirectory, fileName);
|
||||
await using var fileStream = File.OpenRead(fullFilePath);
|
||||
|
||||
var fileSizeInMb = Math.Round(fileStream.Length / 1024.0 / 1024.0, 1);
|
||||
TestContext.WriteLine($"{fileName} is {fileSizeInMb} MB");
|
||||
|
||||
await _dbContext.TruncateAsync<TEntity>(cancellationToken: TestContext.CurrentContext.CancellationToken);
|
||||
var rowCount = await _dbContext.Set<TEntity>().CountAsync(TestContext.CurrentContext.CancellationToken);
|
||||
// make sure we start with clean slate
|
||||
Assert.That(rowCount, Is.Zero);
|
||||
|
||||
await rxNormService.SeedTable<TEntity>(fileStream, TestContext.CurrentContext.CancellationToken);
|
||||
|
||||
// assert that SOME rows were added
|
||||
rowCount = await _dbContext.Set<TEntity>().CountAsync(TestContext.CurrentContext.CancellationToken);
|
||||
Assert.That(rowCount, Is.GreaterThan(0));
|
||||
}
|
||||
}
|
||||
|
||||
public class StubClaimsPrincipalAccessor : IClaimsPrincipalAccessor
|
||||
{
|
||||
private readonly ClaimsPrincipal _principal;
|
||||
|
||||
/// <summary>
|
||||
/// Will always return the given <see cref="ClaimsPrincipal"/>
|
||||
/// </summary>
|
||||
public StubClaimsPrincipalAccessor(ClaimsPrincipal principal)
|
||||
{
|
||||
_principal = principal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ClaimsPrincipal"/> with the given strata specific claims values
|
||||
/// and will always return that principal
|
||||
/// </summary>
|
||||
public StubClaimsPrincipalAccessor(
|
||||
Guid? databaseGuid = null,
|
||||
int? strataId = null,
|
||||
string username = null,
|
||||
Guid? userGuid = null,
|
||||
IEnumerable<KeyValuePair<string, string>> additionalClaims = null)
|
||||
{
|
||||
var claims = new List<Claim>();
|
||||
if (databaseGuid.HasValue)
|
||||
{
|
||||
claims.Add(new Claim(StrataClaims.DatabaseGuid, databaseGuid.ToString()));
|
||||
}
|
||||
|
||||
if (strataId.HasValue)
|
||||
{
|
||||
claims.Add(new Claim(StrataClaims.StrataId, strataId.ToString()));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(username))
|
||||
{
|
||||
claims.Add(new Claim(StrataClaims.Username, username));
|
||||
}
|
||||
|
||||
if (userGuid.HasValue)
|
||||
{
|
||||
claims.Add(new Claim(StrataClaims.UserGuid, userGuid.ToString()));
|
||||
}
|
||||
|
||||
if (additionalClaims != null)
|
||||
{
|
||||
foreach (var (key, value) in additionalClaims)
|
||||
{
|
||||
claims.Add(new Claim(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
var claimsIdentity = new ClaimsIdentity(claims, "IntegrationTest");
|
||||
_principal = new ClaimsPrincipal(claimsIdentity);
|
||||
}
|
||||
|
||||
public ClaimsPrincipal GetCurrentClaimsPrincipal()
|
||||
{
|
||||
return _principal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using Strata.RxNorm.Biz.RxNorm;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Strata.RxNorm.Biz.Test.Unit.RxNorm
|
||||
{
|
||||
public class RxnComponent
|
||||
{
|
||||
[Key]
|
||||
public int Key { get; set; }
|
||||
public int AltKey { get; set; }
|
||||
public string Rxcui { get; set; }
|
||||
public string Rxcui2 { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Attribute { get; set; }
|
||||
|
||||
public RxnComponent()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public RxnComponent(RxnConcept concept, RxnAttribute attribute)
|
||||
{
|
||||
Key = int.TryParse(concept.Rxcui, out var cui) ? cui : 0;
|
||||
AltKey = int.TryParse(attribute.Rxcui, out var cui2) ? cui2 : 0;
|
||||
Rxcui = concept.Rxcui;
|
||||
Rxcui2 = attribute.Rxcui;
|
||||
Description = concept.Str;
|
||||
Attribute = attribute.Atv;
|
||||
}
|
||||
|
||||
public RxnComponent(RxnConcept concept, RxnConcept concept2)
|
||||
{
|
||||
Key = int.TryParse(concept.Rxcui, out var cui) ? cui : 0;
|
||||
AltKey = int.TryParse(concept2.Rxcui, out var cui2) ? cui2 : 0;
|
||||
Rxcui = concept.Rxcui;
|
||||
Rxcui2 = concept2.Rxcui;
|
||||
Description = concept.Str;
|
||||
Attribute = concept2.Str;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Strata.RxNorm.Biz.Test.Unit.RxNorm
|
||||
{
|
||||
public class RxnComponentIngredient
|
||||
{
|
||||
[Key]
|
||||
public int Key { get; set; }
|
||||
public string ComponentRxcui { get; set; }
|
||||
public string ComponentDescription { get; set; }
|
||||
public string IngredientRxcui { get; set; }
|
||||
public string IngredientDescription { get; set; }
|
||||
public string Strength { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Strata.RxNorm.Biz.Test.Unit.RxNorm
|
||||
{
|
||||
public class RxnGenericComponent
|
||||
{
|
||||
[Key]
|
||||
public int Key { get; set; }
|
||||
public string GenericRxcui { get; set; }
|
||||
public string GenericDescription { get; set; }
|
||||
public string ComponentRxcui { get; set; }
|
||||
public string ComponentDescription { get; set; }
|
||||
public string Strength { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Strata.RxNorm.Biz.RxNorm;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Strata.RxNorm.Biz.Test.Unit.RxNorm
|
||||
{
|
||||
public class Rxndata
|
||||
{
|
||||
[Key]
|
||||
public int Key { get; set; }
|
||||
public string Rxcui { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
||||
public Rxndata() { }
|
||||
|
||||
public Rxndata(RxnAttribute sat)
|
||||
{
|
||||
Key = int.TryParse(sat.Rxcui, out var cui) ? cui : 0;
|
||||
Rxcui = sat.Rxcui;
|
||||
Description = sat.Atv;
|
||||
}
|
||||
|
||||
public Rxndata(RxnConcept conso)
|
||||
{
|
||||
Key = int.TryParse(conso.Rxcui, out var cui) ? cui : 0;
|
||||
Rxcui = conso.Rxcui;
|
||||
Description = conso.Str;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+402
@@ -0,0 +1,402 @@
|
||||
[
|
||||
{
|
||||
Code: 1000086,
|
||||
Description: Lastacaft
|
||||
},
|
||||
{
|
||||
Code: 1000108,
|
||||
Description: Xeomin
|
||||
},
|
||||
{
|
||||
Code: 1001473,
|
||||
Description: Ecpirin
|
||||
},
|
||||
{
|
||||
Code: 1001585,
|
||||
Description: TachoSil
|
||||
},
|
||||
{
|
||||
Code: 1001715,
|
||||
Description: Zencia Wash
|
||||
},
|
||||
{
|
||||
Code: 1005925,
|
||||
Description: Ella
|
||||
},
|
||||
{
|
||||
Code: 1006555,
|
||||
Description: Clinpro 5000
|
||||
},
|
||||
{
|
||||
Code: 1009213,
|
||||
Description: Veletri
|
||||
},
|
||||
{
|
||||
Code: 1010729,
|
||||
Description: PureLax
|
||||
},
|
||||
{
|
||||
Code: 1011084,
|
||||
Description: Gas-X Prevention
|
||||
},
|
||||
{
|
||||
Code: 1011654,
|
||||
Description: Krystexxa
|
||||
},
|
||||
{
|
||||
Code: 1011859,
|
||||
Description: LMX
|
||||
},
|
||||
{
|
||||
Code: 1011867,
|
||||
Description: Thrive
|
||||
},
|
||||
{
|
||||
Code: 1012324,
|
||||
Description: Ana-Lex
|
||||
},
|
||||
{
|
||||
Code: 1012397,
|
||||
Description: Marcaine
|
||||
},
|
||||
{
|
||||
Code: 1012462,
|
||||
Description: Revonto
|
||||
},
|
||||
{
|
||||
Code: 1012591,
|
||||
Description: Regenecare
|
||||
},
|
||||
{
|
||||
Code: 1012782,
|
||||
Description: Carbocaine with NeoCobefrin
|
||||
},
|
||||
{
|
||||
Code: 1012896,
|
||||
Description: Gilenya
|
||||
},
|
||||
{
|
||||
Code: 101306,
|
||||
Description: Herceptin
|
||||
},
|
||||
{
|
||||
Code: 1013633,
|
||||
Description: Calcitrene
|
||||
},
|
||||
{
|
||||
Code: 1013644,
|
||||
Description: Cidaflex
|
||||
},
|
||||
{
|
||||
Code: 1013931,
|
||||
Description: Kapvay
|
||||
},
|
||||
{
|
||||
Code: 1014134,
|
||||
Description: SaltAire
|
||||
},
|
||||
{
|
||||
Code: 1014606,
|
||||
Description: Fisherman's Friend
|
||||
},
|
||||
{
|
||||
Code: 1014651,
|
||||
Description: Wal-Act
|
||||
},
|
||||
{
|
||||
Code: 1014655,
|
||||
Description: Wal-itin D
|
||||
},
|
||||
{
|
||||
Code: 1020036,
|
||||
Description: Sorilux
|
||||
},
|
||||
{
|
||||
Code: 1020123,
|
||||
Description: Loradamed
|
||||
},
|
||||
{
|
||||
Code: 1037027,
|
||||
Description: Doctor's Choice
|
||||
},
|
||||
{
|
||||
Code: 1037031,
|
||||
Description: Kid's Choice
|
||||
},
|
||||
{
|
||||
Code: 1037046,
|
||||
Description: Pradaxa
|
||||
},
|
||||
{
|
||||
Code: 1037229,
|
||||
Description: Hyophen
|
||||
},
|
||||
{
|
||||
Code: 1037297,
|
||||
Description: Phosphasal
|
||||
},
|
||||
{
|
||||
Code: 1038807,
|
||||
Description: Iferex
|
||||
},
|
||||
{
|
||||
Code: 1038905,
|
||||
Description: Listerine
|
||||
},
|
||||
{
|
||||
Code: 1038918,
|
||||
Description: Lantiseptic
|
||||
},
|
||||
{
|
||||
Code: 1039035,
|
||||
Description: Lantiseptic Multi-Purpose
|
||||
},
|
||||
{
|
||||
Code: 1039066,
|
||||
Description: Soothe & Cool Powder
|
||||
},
|
||||
{
|
||||
Code: 1039169,
|
||||
Description: Lanacane
|
||||
},
|
||||
{
|
||||
Code: 1039252,
|
||||
Description: Cepacol Sore Throat Plus Cough
|
||||
},
|
||||
{
|
||||
Code: 1039270,
|
||||
Description: Scalpicin Itch Relief
|
||||
},
|
||||
{
|
||||
Code: 1039350,
|
||||
Description: Vagisil Satin
|
||||
},
|
||||
{
|
||||
Code: 1039537,
|
||||
Description: Ting AF
|
||||
},
|
||||
{
|
||||
Code: 1039547,
|
||||
Description: Vagisil Wipes
|
||||
},
|
||||
{
|
||||
Code: 1039670,
|
||||
Description: Sucrets Original
|
||||
},
|
||||
{
|
||||
Code: 1039802,
|
||||
Description: Ustell
|
||||
},
|
||||
{
|
||||
Code: 1039916,
|
||||
Description: Soothe Lubricant Eye Drops
|
||||
},
|
||||
{
|
||||
Code: 1040009,
|
||||
Description: Teflaro
|
||||
},
|
||||
{
|
||||
Code: 1040019,
|
||||
Description: Acthar
|
||||
},
|
||||
{
|
||||
Code: 1040032,
|
||||
Description: Latuda
|
||||
},
|
||||
{
|
||||
Code: 1040055,
|
||||
Description: Nuedexta
|
||||
},
|
||||
{
|
||||
Code: 1041509,
|
||||
Description: Ala-Hist IR
|
||||
},
|
||||
{
|
||||
Code: 1041513,
|
||||
Description: Aloe Vesta Skin Conditioner
|
||||
},
|
||||
{
|
||||
Code: 1041527,
|
||||
Description: Ofirmev
|
||||
},
|
||||
{
|
||||
Code: 1041531,
|
||||
Description: Dendracin Neurodendraxcin
|
||||
},
|
||||
{
|
||||
Code: 1042664,
|
||||
Description: MenthoLatum
|
||||
},
|
||||
{
|
||||
Code: 1043071,
|
||||
Description: Beta-HC
|
||||
},
|
||||
{
|
||||
Code: 1043225,
|
||||
Description: Perform
|
||||
},
|
||||
{
|
||||
Code: 1043229,
|
||||
Description: Biofreeze
|
||||
},
|
||||
{
|
||||
Code: 1043241,
|
||||
Description: Head & Shoulders
|
||||
},
|
||||
{
|
||||
Code: 1043620,
|
||||
Description: Listerine Antiseptic
|
||||
},
|
||||
{
|
||||
Code: 1044439,
|
||||
Description: Luden's Drops
|
||||
},
|
||||
{
|
||||
Code: 1044588,
|
||||
Description: Egrifta
|
||||
},
|
||||
{
|
||||
Code: 1044929,
|
||||
Description: NeutrapHor
|
||||
},
|
||||
{
|
||||
Code: 1044933,
|
||||
Description: Cool bottoms
|
||||
},
|
||||
{
|
||||
Code: 1045457,
|
||||
Description: Halaven
|
||||
},
|
||||
{
|
||||
Code: 1045538,
|
||||
Description: Chloraseptic Sore Throat + Cough
|
||||
},
|
||||
{
|
||||
Code: 1045617,
|
||||
Description: Fungicure Solution
|
||||
},
|
||||
{
|
||||
Code: 1046235,
|
||||
Description: Cosamin
|
||||
},
|
||||
{
|
||||
Code: 1046239,
|
||||
Description: Schiff
|
||||
},
|
||||
{
|
||||
Code: 1046278,
|
||||
Description: Psoriasin Wash
|
||||
},
|
||||
{
|
||||
Code: 1046284,
|
||||
Description: MiniDrops
|
||||
},
|
||||
{
|
||||
Code: 1046399,
|
||||
Description: Xgeva
|
||||
},
|
||||
{
|
||||
Code: 1047139,
|
||||
Description: Axiron
|
||||
},
|
||||
{
|
||||
Code: 1047432,
|
||||
Description: Gablofen
|
||||
},
|
||||
{
|
||||
Code: 1047505,
|
||||
Description: Moxeza
|
||||
},
|
||||
{
|
||||
Code: 1047876,
|
||||
Description: Gly-Oxide
|
||||
},
|
||||
{
|
||||
Code: 1049420,
|
||||
Description: GentleLax
|
||||
},
|
||||
{
|
||||
Code: 1050088,
|
||||
Description: Boroleum
|
||||
},
|
||||
{
|
||||
Code: 1050312,
|
||||
Description: Nexiclon
|
||||
},
|
||||
{
|
||||
Code: 1051071,
|
||||
Description: Fortesta
|
||||
},
|
||||
{
|
||||
Code: 1052413,
|
||||
Description: Pamprin Max Formula
|
||||
},
|
||||
{
|
||||
Code: 1052436,
|
||||
Description: Pamprin Multi-Symptom
|
||||
},
|
||||
{
|
||||
Code: 1052442,
|
||||
Description: Pamprin Cramp Formula
|
||||
},
|
||||
{
|
||||
Code: 1052463,
|
||||
Description: Percogesic ReformuLated Jan 2011
|
||||
},
|
||||
{
|
||||
Code: 1052617,
|
||||
Description: Anbesol Cold Sore Therapy
|
||||
},
|
||||
{
|
||||
Code: 1052638,
|
||||
Description: Premsyn PMS
|
||||
},
|
||||
{
|
||||
Code: 1052951,
|
||||
Description: Aquaphor
|
||||
},
|
||||
{
|
||||
Code: 1052997,
|
||||
Description: Critic-Aid Clear Moisture
|
||||
},
|
||||
{
|
||||
Code: 1053139,
|
||||
Description: Wal-Dryl
|
||||
},
|
||||
{
|
||||
Code: 1053143,
|
||||
Description: Stye
|
||||
},
|
||||
{
|
||||
Code: 1053155,
|
||||
Description: Baza-Protect
|
||||
},
|
||||
{
|
||||
Code: 1053197,
|
||||
Description: Baza Cleanse and Protect
|
||||
},
|
||||
{
|
||||
Code: 1053324,
|
||||
Description: Stanback Headache Powder ReformuLated Jan 2011
|
||||
},
|
||||
{
|
||||
Code: 1053336,
|
||||
Description: Tanac Liquid
|
||||
},
|
||||
{
|
||||
Code: 1053648,
|
||||
Description: Abstral
|
||||
},
|
||||
{
|
||||
Code: 1053856,
|
||||
Description: Carb-O-Lac
|
||||
},
|
||||
{
|
||||
Code: 10601,
|
||||
Description: Timoptic
|
||||
},
|
||||
{
|
||||
Code: 1085416,
|
||||
Description: Active Q
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,824 @@
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal;
|
||||
using Strata.RxNorm.Biz.RxNorm;
|
||||
using Strata.RxNorm.Biz.RxNorm.Dimensions;
|
||||
using Strata.RxNorm.Biz.Test.Unit.Extensions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
using VerifyTests;
|
||||
|
||||
namespace Strata.RxNorm.Biz.Test.Unit.RxNorm
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestRxNormBase
|
||||
{
|
||||
public VerifySettings VerifySetting { get; set; }
|
||||
|
||||
public List<RxnRelation> RxnRelations { get; set; }
|
||||
public List<RxnConcept> RxnConcepts { get; set; }
|
||||
public List<RxnAttribute> RxnAttributes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <seealso cref="RxnConcept"/>
|
||||
/// </summary>
|
||||
/// <remarks>TTY == "BN"</remarks>
|
||||
public IQueryable<Rxndata> BrandNames { get; set; }
|
||||
/// <summary>
|
||||
/// <seealso cref="RxnConcept"/>
|
||||
/// </summary>
|
||||
/// <remarks>TTY == "DF"</remarks>
|
||||
public IQueryable<Rxndata> DoseForms { get; set; }
|
||||
/// <summary>
|
||||
/// <seealso cref="RxnConcept"/>
|
||||
/// </summary>
|
||||
/// <remarks>TTY == "DFG"</remarks>
|
||||
public IQueryable<Rxndata> DoseFormGroups { get; set; }
|
||||
/// <summary>
|
||||
/// <seealso cref="RxnConcept"/>
|
||||
/// </summary>
|
||||
/// <remarks>TTY == "SCD"</remarks>
|
||||
public IQueryable<Rxndata> GenericDrugs { get; set; }
|
||||
/// <summary>
|
||||
/// <seealso cref="RxnConcept"/>
|
||||
/// </summary>
|
||||
/// <remarks>TTY == "SCD"</remarks>
|
||||
public IQueryable<Rxndata> SemanticBrandDrugs { get; set; }
|
||||
/// <summary>
|
||||
/// <seealso cref="RxnAttribute"/>
|
||||
/// </summary>
|
||||
/// <remarks>Atn == "NDC"</remarks>
|
||||
public IQueryable<Rxndata> Ndcs { get; set; }
|
||||
|
||||
/// <summary>Generic Drugs</summary>
|
||||
/// <remarks><see cref="RxnConcept"/> where Tty == "SCD"</remarks>
|
||||
protected IEnumerable<RxnConcept> rxngenericdrugs => RxnConcepts.Where(r => r.Tty == "SCD");
|
||||
/// <summary>RxnConcept where Tty == "DF"</summary>
|
||||
protected IEnumerable<RxnConcept> rxndoseforms => RxnConcepts.Where(r => r.Tty == "DF");
|
||||
/// <summary>RxnConcept where Tty == "DFG"</summary>
|
||||
protected IEnumerable<RxnConcept> rxndoseformgroups => RxnConcepts.Where(r => r.Tty == "DFG");
|
||||
/// <summary>RxnConcept where Tty == "SCDC"</summary>
|
||||
protected IEnumerable<RxnConcept> rxncomponents => RxnConcepts.Where(r => r.Tty == "SCDC");
|
||||
/// <summary>RxnConcept where Tty == "IN"</summary>
|
||||
protected IEnumerable<RxnConcept> rxningredients => RxnConcepts.Where(r => r.Tty == "IN");
|
||||
/// <summary>Brand Name</summary>
|
||||
/// <remarks>RxnConcept where Tty == "BN"</remarks>
|
||||
protected IEnumerable<RxnConcept> rxnbrandnames => RxnConcepts.Where(r => r.Tty == "BN");
|
||||
|
||||
protected IEnumerable<RxnAttribute> rxnstrengths => RxnAttributes.Where(s => s.Atn == "RXN_STRENGTH");
|
||||
|
||||
protected IEnumerable<RxnComponent> RxnComponents
|
||||
=> from d in RxnConcepts.Where(r => r.Tty == "SCDC")
|
||||
join s in RxnAttributes.Where(s => s.Atn == "RXN_STRENGTH") on d.Rxcui equals s.Rxcui
|
||||
select new RxnComponent(d, s);
|
||||
|
||||
protected IEnumerable<RxnComponentIngredient> RxnComponentIngredients
|
||||
=> from r in RxnRelations
|
||||
join s in RxnAttributes.Where(s => s.Atn == "RXN_STRENGTH") on r.Rxcui1 equals s.Rxcui
|
||||
join d in RxnConcepts.Where(r => r.Tty == "SCDC") on r.Rxcui1 equals d.Rxcui
|
||||
into rd
|
||||
from rdx in rd.DefaultIfEmpty()
|
||||
join i in RxnConcepts.Where(r => r.Tty == "IN") on r.Rxcui2 equals i.Rxcui
|
||||
into ri
|
||||
from rix in ri.DefaultIfEmpty()
|
||||
select new RxnComponentIngredient
|
||||
{
|
||||
Key = int.TryParse(r.Rxcui1, out var cui) ? cui : 0,
|
||||
ComponentRxcui = r.Rxcui1,
|
||||
IngredientRxcui = r.Rxcui2,
|
||||
ComponentDescription = rdx?.Str ?? "--",
|
||||
IngredientDescription = rix?.Str ?? "--",
|
||||
Strength = s.Atv
|
||||
};
|
||||
|
||||
/// <summary>SemanticBrandedDrugs, Tty == "SCD" && Tty == "SCDC"</summary>
|
||||
protected IEnumerable<RxnGenericComponent> RxnGenericComponents
|
||||
=> from r in RxnRelations
|
||||
join g in RxnConcepts.Where(r => r.Tty == "SCD") on r.Rxcui1 equals g.Rxcui
|
||||
join c in RxnConcepts.Where(r => r.Tty == "SCDC") on r.Rxcui2 equals c.Rxcui
|
||||
select new RxnGenericComponent
|
||||
{
|
||||
Key = int.TryParse(r.Rxcui1, out var cui) ? cui : 0,
|
||||
GenericRxcui = r.Rxcui1,
|
||||
GenericDescription = g.Str,
|
||||
ComponentRxcui = r.Rxcui2,
|
||||
ComponentDescription = c.Str
|
||||
};
|
||||
|
||||
/// <summary>SemanticBrandedDrugs, Tty == "SBD" && Tty == "SCD"</summary>
|
||||
protected IEnumerable<FlattenConso> RxnSemanticBrandedDrugs
|
||||
=> from r in RxnRelations
|
||||
join bd in RxnConcepts.Where(r => r.Tty == "SBD") on r.Rxcui1 equals bd.Rxcui
|
||||
join gd in RxnConcepts.Where(r => r.Tty == "SCD") on r.Rxcui2 equals gd.Rxcui
|
||||
orderby bd.Str
|
||||
select new FlattenConso(r, bd, gd, null, null);
|
||||
|
||||
/// <summary>BrandedDrugs, Tty == "SBD" && Tty == "BN"</summary>
|
||||
protected IEnumerable<FlattenConso> BrandedDrugNames
|
||||
=> from r in RxnRelations
|
||||
join bd in RxnConcepts.Where(r => r.Tty == "SBD") on r.Rxcui1 equals bd.Rxcui
|
||||
join bn in RxnConcepts.Where(r => r.Tty == "BN") on r.Rxcui2 equals bn.Rxcui
|
||||
orderby bn.Str
|
||||
select new FlattenConso(r, bn, bd, null, null);
|
||||
|
||||
protected IEnumerable<FlattenConso> BrandedDrugGenericDrugNames
|
||||
=> from r in RxnRelations
|
||||
join bd in BrandedDrugNames on r.Rxcui1 equals bd.RRxcui1
|
||||
join gd in RxnConcepts.Where(r => r.Tty == "SCD") on r.Rxcui2 equals gd.Rxcui
|
||||
orderby bd.Str1
|
||||
select new FlattenConso(r, bd.conso[0], bd.conso[1], gd, null);
|
||||
|
||||
|
||||
[OneTimeSetUp]
|
||||
public async Task SetUpFixture()
|
||||
{
|
||||
VerifySetting = TestExtensions.TestSettings();
|
||||
|
||||
RxnConcepts = "RXNCONSO.RRF".LoadRxnConcepts().ToList();
|
||||
RxnRelations = "RXNREL1A.RRF".LoadRxnRelations()
|
||||
.Union("RXNREL1B.RRF".LoadRxnRelations())
|
||||
.Union("RXNREL2A.RRF".LoadRxnRelations())
|
||||
.Union("RXNREL2B.RRF".LoadRxnRelations())
|
||||
.ToList();
|
||||
RxnAttributes = "RXNSAT1A.RRF".LoadRxnAttributes()
|
||||
.Union("RXNSAT1B.RRF".LoadRxnAttributes())
|
||||
.Union("RXNSAT2A.RRF".LoadRxnAttributes())
|
||||
.Union("RXNSAT2B.RRF".LoadRxnAttributes())
|
||||
.Union("RXNSAT3A.RRF".LoadRxnAttributes())
|
||||
.Union("RXNSAT3B.RRF".LoadRxnAttributes()).ToList();
|
||||
|
||||
BrandNames = QueryRxnConcept("BN");
|
||||
DoseFormGroups = QueryRxnConcept("DFG");
|
||||
DoseForms = QueryRxnConcept("DF");
|
||||
SemanticBrandDrugs = QueryRxnConcept("SCD");
|
||||
|
||||
Ndcs = QueryRxnAttribute("NDC");
|
||||
}
|
||||
|
||||
public IQueryable<Rxndata> QueryRxnConcept(string tty)
|
||||
=> (from c in RxnConcepts
|
||||
where c.Tty == tty
|
||||
orderby c.Str
|
||||
select new Rxndata(c)).AsQueryable();
|
||||
|
||||
public IQueryable<Rxndata> QueryRxnAttribute(string atn)
|
||||
=> (from c in RxnAttributes
|
||||
where c.Atn == atn
|
||||
orderby c.Atv
|
||||
select new Rxndata(c)).AsQueryable();
|
||||
|
||||
[TestCase("66490069110")]
|
||||
public async Task TestNdc(string ndc)
|
||||
{
|
||||
var Relations = (from a in Ndcs.Where(n => n.Description == ndc)
|
||||
//RxnAttributes.Where(ra => ra.Atn == "NDC" && ra.Atv == ndc)
|
||||
join r in RxnRelations on a.Rxcui equals r.Rxcui2
|
||||
join b in RxnConcepts on r.Rxcui1 equals b.Rxcui
|
||||
select b);
|
||||
await Verifier.Verify(Relations, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(RxnConceptsTestCases))]
|
||||
public async Task TestDimRxNormConcepts(int take, int skip, string tty)
|
||||
{
|
||||
IEnumerable<IRxNormConcept> concepts;
|
||||
switch (tty)
|
||||
{
|
||||
case "BN":
|
||||
concepts = RxnConcepts
|
||||
.Where(c => c.Tty == tty)
|
||||
.Select(x => new DimBrandName(x))
|
||||
.OrderBy(x => x.Code).Skip(skip).Take(take);
|
||||
break;
|
||||
case "DF":
|
||||
concepts = RxnConcepts
|
||||
.Where(c => c.Tty == tty)
|
||||
.Select(x => new DimDoseForm(x))
|
||||
.OrderBy(x => x.Code).Skip(skip).Take(take);
|
||||
break;
|
||||
case "SBD":
|
||||
concepts = RxnConcepts
|
||||
.Where(c => c.Tty == tty)
|
||||
.Select(x => new DimBrandedDrug(x))
|
||||
.OrderBy(x => x.Code).Skip(skip).Take(take);
|
||||
break;
|
||||
case "SCD":
|
||||
concepts = RxnConcepts
|
||||
.Where(c => c.Tty == tty)
|
||||
.Select(x => new DimSemanticDrug(x))
|
||||
.OrderBy(x => x.Code).Skip(skip).Take(take);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
await Verifier.Verify(concepts, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCase(100, 0)]
|
||||
public async Task TestFactNdc(int take, int skip)
|
||||
{
|
||||
var attributes = RxnAttributes
|
||||
.Where(a => a.Atn == "NDC")
|
||||
.Select(a => new FactNdc { Ndc = a.Atv })
|
||||
.OrderBy(a => a.Ndc)
|
||||
.Skip(skip).Take(take);
|
||||
await Verifier.Verify(attributes, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public async Task TestAdvil()
|
||||
{
|
||||
var dimBrandNames = RxnConcepts.Where(c => c.Tty == "BN").Select(x => new DimBrandName(x));
|
||||
var brandNames = dimBrandNames.Where(c => c.Description.Contains("Advil", System.StringComparison.CurrentCultureIgnoreCase));
|
||||
await Verifier.Verify(brandNames, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public async Task TestIbuprofen()
|
||||
{
|
||||
var dimBrandNames = RxnConcepts.Where(c => c.Tty == "IN").Select(x => new DimBrandName(x));
|
||||
var brandNames = dimBrandNames.Where(c => c.Description.Contains("Ibuprofen", System.StringComparison.CurrentCultureIgnoreCase));
|
||||
await Verifier.Verify(brandNames, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public async Task TestIbuprofenIngredients()
|
||||
{
|
||||
var ibuprofen = RxnConcepts
|
||||
.Where(c => c.Tty == "IN" && c.Str.Contains("Ibuprofen", System.StringComparison.CurrentCultureIgnoreCase))
|
||||
.ToList();
|
||||
var rxcuis = ibuprofen.Select(x => x.Rxcui);
|
||||
var brandNames = RxnConcepts.Where(c => c.Tty == "BN").ToList()
|
||||
.Join(RxnRelations.Where(r => rxcuis.Contains(r.Rxcui2)),
|
||||
b => b.Rxcui, r => r.Rxcui1, (b, r) => new { b, r })
|
||||
.Join(ibuprofen,
|
||||
r => r.r.Rxcui2, c => c.Rxcui, (r, b) => new DimBrandName(r.b))
|
||||
.OrderBy(b => b.Description);
|
||||
await Verifier.Verify(brandNames, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCase(100, 0)]
|
||||
public async Task TestBrandNames(int take, int skip)
|
||||
{
|
||||
var dimBrandNames = RxnConcepts.Where(c => c.Tty == "BN").Select(x => new DimBrandName(x));
|
||||
var brandNames = BrandNames.Skip(skip).Take(take).ToList();
|
||||
await Verifier.Verify(brandNames, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(RxnConceptsTestCases))]
|
||||
public async Task TestRxcuiCode(int take, int skip, string tty)
|
||||
{
|
||||
if (take > 0)
|
||||
{
|
||||
var rxnConcepts = RxnConcepts
|
||||
.Where(c => (c.Tty == tty || string.IsNullOrEmpty(tty)) && c.Code != c.Rxcui)
|
||||
.Skip(skip).Take(take).ToList();
|
||||
await Verifier.Verify(rxnConcepts, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
return;
|
||||
}
|
||||
var concepts = RxnConcepts
|
||||
.Where(c => c.Code != c.Rxcui)
|
||||
.GroupBy(c => c.Tty, (TTY, concepts) => new ConceptGroup
|
||||
{
|
||||
Tty = TTY,
|
||||
Concepts = concepts.Select(c => new ConceptDump(c))
|
||||
.OrderBy(c => c.Code)
|
||||
.ThenBy(c => c.Rxcui)
|
||||
});
|
||||
await Verifier.Verify(concepts, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
internal class ConceptGroup
|
||||
{
|
||||
public string Tty { get; set; }
|
||||
public IEnumerable<ConceptDump> Concepts { get; set; }
|
||||
}
|
||||
|
||||
internal class ConceptDump
|
||||
{
|
||||
public string Rxcui { get; set; }
|
||||
public string Code { get; set; }
|
||||
public ConceptDump(RxnConcept concept)
|
||||
{
|
||||
Rxcui = concept.Rxcui;
|
||||
Code = concept.Code;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> RxnConceptsTestCases()
|
||||
{
|
||||
yield return new TestCaseData(0, 0, "")
|
||||
.SetName("{m} Generic");
|
||||
yield return new TestCaseData(100, 0, "BN")
|
||||
.SetName("{m} " + nameof(DimBrandName));
|
||||
yield return new TestCaseData(100, 0, "DF")
|
||||
.SetName("{m} " + nameof(DimDoseForm));
|
||||
yield return new TestCaseData(100, 0, "SBD")
|
||||
.SetName("{m} " + nameof(DimBrandedDrug));
|
||||
yield return new TestCaseData(100, 0, "SCD")
|
||||
.SetName("{m} " + nameof(DimSemanticDrug));
|
||||
}
|
||||
|
||||
[TestCase(100, 0)]
|
||||
public async Task TestNdcs(int take, int skip)
|
||||
{
|
||||
var ndcs = Ndcs.Skip(skip).Take(take).ToList();
|
||||
await Verifier.Verify(ndcs, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public async Task TestConceptTypes()
|
||||
{
|
||||
var conceptTypes = RxnConcepts
|
||||
.GroupBy(c => c.Tty, (Tty, d) => new { Tty, Count = d.Count() })
|
||||
.OrderBy(c => c.Tty).ToList();
|
||||
await Verifier.Verify(conceptTypes, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
/// <summary>
|
||||
/// Populate the rxngenericdrugs table:
|
||||
/// - Extract Generic Drug Descriptions
|
||||
/// -- Identify all Semantic Clinical Drug Terms in the concepts table by looking for TTY(Term Type) SCD
|
||||
/// -- Extract these rows, interpreting Rxcui as GenericRxcui and Description as GenericDrugDescription
|
||||
/// - Extract Dose Forms
|
||||
/// -- Identify all Dose Form Terms in the concepts table by looking for TTY(Tevarrm Type) DF
|
||||
/// -- Extract these rows, interpreting Rxcui as DoseFormRxcui and Description as DoseFormDescription
|
||||
/// - Complete Generic Drugs table by adding dose form
|
||||
/// -- Limit CUI Relations table to rows where Rxcui1 has type SCD and Rxcui2 has type DF
|
||||
/// -- Extract these rows, intepreting Rxcui1 as GenericRxcui and Rxcui2 as DoseFormRxcui
|
||||
/// -- Join the above to Generic Drug Descriptions, keeping GenericRxcui, GenericDrugDescription, and DoseFormRxcui
|
||||
/// </summary>
|
||||
public async Task Populate_the_rxngenericdrugs_table()
|
||||
{
|
||||
var genericDrugDescriptions = rxngenericdrugs.Select(r => new Rxndata(r)).OrderBy(r => r.Description);
|
||||
|
||||
var doseForms = rxndoseforms.Select(r => new Rxndata(r)).OrderBy(r => r.Description);
|
||||
|
||||
var genericDrugs =
|
||||
from r in RxnRelations
|
||||
join gd in rxngenericdrugs on r.Rxcui1 equals gd.Rxcui
|
||||
join df in rxndoseforms on r.Rxcui2 equals df.Rxcui
|
||||
select new
|
||||
{
|
||||
GenericRxcui = gd.Rxcui,
|
||||
GernericDrugDescription = gd.Str,
|
||||
DoseFormRxcui = df.Rxcui,
|
||||
DoseForm = df.Str
|
||||
};
|
||||
|
||||
await Verifier.Verify(genericDrugDescriptions.ToList(), VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName(nameof(genericDrugDescriptions)));
|
||||
await Verifier.Verify(doseForms.ToList(), VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName(nameof(doseForms)));
|
||||
await Verifier.Verify(genericDrugs.ToList(), VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName(nameof(genericDrugs)));
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
/// <summary>
|
||||
/// Populate Components and Ingredients
|
||||
/// - Populate Ingredients Table
|
||||
/// -- Identify all <c>RxnConcept</c>s with TTY(Term Type) IN
|
||||
/// -- Extract these rows, interpreting Rxcui as IngredientRxcui and Description as IngredientDescription
|
||||
/// - Populate Components Table
|
||||
/// -- Get Component Descriptions
|
||||
/// --- Identify all concepts with TTY(Term Type) SCDC(Semantic Clinical Drug Component)
|
||||
/// --- Extract these rows, interpreting Rxcui as ComponentRxcui and Description as ComponentDescription
|
||||
/// -- Get Component Strengths
|
||||
/// --- Identify all attribute rows the Rxcui has TTY SCDC and where Atn(Attribute Name) is RXN_STRENGTH
|
||||
/// --- Extract these rows, interpreting Rxcui as ComponentRxcui and Atv(Attribute Value) as Strength
|
||||
/// -- Get Component Ingredients
|
||||
/// --- Identify all rows in cui_Relations where Rxcui1 has TTY SCDC and Rxcui2 has TTY IN
|
||||
/// --- Extract these rows, interpreting Rxcui1 as ComponentRxcui and Rxcui2 as IngredientRxcui
|
||||
/// -- Complete Components Table
|
||||
/// --- Every ComponentRxcui should have one ComponentDescription, one Strength, and one IngredientRxcui.
|
||||
/// --- The table should have these four columns
|
||||
/// </summary>
|
||||
public async Task Populate_Components_and_Ingrediaents()
|
||||
{
|
||||
var ingredients = rxningredients.Select(r => new Rxndata(r)).OrderBy(r => r.Description);
|
||||
|
||||
var componentDescriptions = rxncomponents.Select(r => new Rxndata(r)).OrderBy(r => r.Description);
|
||||
|
||||
var strengths = rxnstrengths.Select(r => new Rxndata(r)).OrderBy(r => r.Description);
|
||||
|
||||
var componentStrengths =
|
||||
from r in RxnRelations
|
||||
join c in rxncomponents on r.Rxcui1 equals c.Rxcui
|
||||
join s in rxnstrengths on r.Rxcui2 equals s.Rxcui
|
||||
select new RxnComponent(c, s);
|
||||
|
||||
var componentIngredients =
|
||||
from r in RxnRelations
|
||||
join c in rxncomponents on r.Rxcui1 equals c.Rxcui
|
||||
join s in rxningredients on r.Rxcui2 equals s.Rxcui
|
||||
select new RxnComponent(c, s);
|
||||
|
||||
var components =
|
||||
from c in componentDescriptions
|
||||
join s in componentStrengths on c.Key equals s.Key into cs
|
||||
from csx in cs.DefaultIfEmpty()
|
||||
join i in componentIngredients on c.Key equals i.Key into ci
|
||||
from cix in ci.DefaultIfEmpty()
|
||||
orderby (cix?.Rxcui2 == null ? 1 : 0), csx?.Attribute
|
||||
select new
|
||||
{
|
||||
c.Key,
|
||||
ComponentRxcui = c?.Rxcui,
|
||||
ComponentDescription = c?.Description,
|
||||
IngredientRxcui = cix?.Rxcui2,
|
||||
Strength = csx?.Attribute
|
||||
};
|
||||
|
||||
await Verifier.Verify(ingredients, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName(nameof(ingredients)));
|
||||
await Verifier.Verify(componentDescriptions, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName(nameof(componentDescriptions)));
|
||||
await Verifier.Verify(componentStrengths, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName(nameof(componentStrengths)));
|
||||
await Verifier.Verify(componentIngredients, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName(nameof(componentIngredients)));
|
||||
await Verifier.Verify(components, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName(nameof(components)));
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
/// <summary>
|
||||
/// Populate Generic Drug Components Table
|
||||
/// - Limit CUI Relations to rows where Rxcui1 has TTY SCD and Rxcui2 has TTY SCDC
|
||||
/// - Extract these rows, interpreting Rxcui1 as GenericRxcui and Rxcui2 as ComponentRxcui
|
||||
/// </summary>
|
||||
public async Task Populate_Generic_Drug_Components_Table()
|
||||
{
|
||||
var genericDrugDescriptions = rxngenericdrugs.Select(r => new Rxndata(r)).OrderBy(r => r.Description).ToList();
|
||||
|
||||
var doseForms = rxndoseforms.Select(r => new Rxndata(r)).OrderBy(r => r.Description).ToList();
|
||||
|
||||
var genericDrugs =
|
||||
from r in RxnRelations
|
||||
join gd in rxngenericdrugs on r.Rxcui1 equals gd.Rxcui
|
||||
join df in rxndoseforms on r.Rxcui2 equals df.Rxcui
|
||||
select new RxnComponent(gd, df);
|
||||
|
||||
var ingredients = rxningredients.Select(r => new Rxndata(r)).OrderBy(r => r.Description).ToList();
|
||||
|
||||
var componentDescriptions = rxncomponents.Select(r => new Rxndata(r)).OrderBy(r => r.Description).ToList();
|
||||
|
||||
var strengths = rxnstrengths.Select(r => new Rxndata(r)).OrderBy(r => r.Description).ToList();
|
||||
|
||||
var componentStrengths =
|
||||
from s in rxnstrengths
|
||||
join c in rxncomponents on s.Rxcui equals c.Rxcui
|
||||
select new RxnComponent(c, s);
|
||||
|
||||
var componentIngredients =
|
||||
from r in RxnRelations
|
||||
join c in rxncomponents on r.Rxcui1 equals c.Rxcui
|
||||
join i in rxningredients on r.Rxcui2 equals i.Rxcui
|
||||
select new RxnComponent(c, i);
|
||||
|
||||
var components =
|
||||
from c in componentDescriptions
|
||||
join s in componentStrengths on c.Key equals s.Key into cs
|
||||
from csx in cs.DefaultIfEmpty()
|
||||
join i in componentIngredients on c.Key equals i.Key into ci
|
||||
from cix in ci.DefaultIfEmpty()
|
||||
select new { c, csx, cix };
|
||||
|
||||
var genericComponents =
|
||||
from r in RxnRelations
|
||||
join g in genericDrugs on r.Rxcui1 equals g.Rxcui
|
||||
join c in components on r.Rxcui2 equals c.c.Rxcui
|
||||
select new
|
||||
{
|
||||
ComponentRxcui = r.Rxcui2,
|
||||
GenericRxcui = r.Rxcui1
|
||||
};
|
||||
|
||||
await Verifier.Verify(genericComponents, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
/// <summary>
|
||||
/// Populate Branded Drug Tables
|
||||
/// - Populate Brand Names
|
||||
/// -- Limit concepts to terms with TTY(Term Type) BN(Brand Name)
|
||||
/// -- Extract these rows, interpreting Rxcui as BrandNameRxcui and Description as BrandName
|
||||
/// - Populate Branded Drugs
|
||||
/// -- Get Branded Drug Descriptions
|
||||
/// --- Limit concepts to terms with TTY(Term Type) SBD(Semantic Branded Drug)
|
||||
/// --- Extract these rows, interpreting Rxcui as BrandedDrugRxcui and Description as BrandedDrugDescription
|
||||
/// -- Get Branded Drug Generic Drugs
|
||||
/// --- Limit CUI Relations to rows where Rxcui1 has TTY SBD and Rxcui2 has TTY SCD
|
||||
/// --- Extract these rows, interpreting Rxcui1 as BrandedDrugRxcui and Rxcui2 as GenericRxcui
|
||||
/// -- Get Branded Drug Brand Names
|
||||
/// --- Limit CUI Relations to rows where Rxcui has TTY SBD and Rxcui2 as TTY BN
|
||||
/// --- Extract these rows, interpreting Rxcui1 as BrandedDrugRxcui and Rxcui2 as BrandNameRxcui
|
||||
/// -- Get Branded Drug Dose Forms
|
||||
/// --- Join Branded Drug Generic Drugs to Generic Drugs on GenericRxcui
|
||||
/// --- Get DoseFormRxcui for each BrandedDrugRxcui
|
||||
/// -- Combine Information to get columns
|
||||
/// --- BrandedDrugRxcui
|
||||
/// --- BrandedDrugDescription
|
||||
/// --- GenericRxcui
|
||||
/// --- GenericDrugDescription
|
||||
/// --- BrandNameRxcui
|
||||
/// --- DoseFormRxcui
|
||||
/// </summary>
|
||||
public async Task Populate_Branded_Drug_Tables()
|
||||
{
|
||||
var Bn = (from c in RxnConcepts where c.Tty == "BN" select new { BrandName = c.Str, BrandNameRxcui = c.Rxcui });
|
||||
var Bdd = (from c in RxnConcepts where c.Tty == "SBD" select new { BrandedDrugName = c.Str, BrandedDrugRxcui = c.Rxcui });
|
||||
var BdGd = (from r in RxnRelations
|
||||
join c1 in RxnConcepts.Where(c => c.Tty == "SBD") on r.Rxcui1 equals c1.Rxcui
|
||||
join c2 in RxnConcepts.Where(c => c.Tty == "SCD") on r.Rxcui2 equals c2.Rxcui
|
||||
select new
|
||||
{
|
||||
BrandedDrugRxcui = r.Rxcui1,
|
||||
BrandedDrugName = c1.Str,
|
||||
GenericRxcui = r.Rxcui2,
|
||||
GenericDrugName = c2.Str
|
||||
});
|
||||
|
||||
var Gdd = (from c in RxnConcepts where c.Tty == "SCD" select new { GenericDrugName = c.Str, GenericRxcui = c.Rxcui });
|
||||
var Df = (from c in RxnConcepts where c.Tty == "DF" select new { DoseFormDescription = c.Str, DoseFormRxcui = c.Rxcui });
|
||||
var Gd = (from r in RxnRelations
|
||||
join gd in Gdd on r.Rxcui1 equals gd.GenericRxcui
|
||||
join df in Df on r.Rxcui2 equals df.DoseFormRxcui
|
||||
select new
|
||||
{
|
||||
gd.GenericRxcui,
|
||||
gd.GenericDrugName,
|
||||
df.DoseFormRxcui,
|
||||
DoseForm = df.DoseFormDescription
|
||||
});
|
||||
|
||||
var BdBn = (from r in RxnRelations
|
||||
join c1 in RxnConcepts.Where(c => c.Tty == "SBD") on r.Rxcui1 equals c1.Rxcui
|
||||
join c2 in RxnConcepts.Where(c => c.Tty == "BN") on r.Rxcui2 equals c2.Rxcui
|
||||
select new
|
||||
{
|
||||
BrandedDrugRxcui = r.Rxcui1,
|
||||
BrandedDrugName = c1.Str,
|
||||
BrandNameRxcui = r.Rxcui2,
|
||||
BrandName = c2.Str
|
||||
});
|
||||
|
||||
var BrandedDrugDoseForms = (
|
||||
from bdgd in BdGd
|
||||
join bn in BdBn on bdgd.BrandedDrugRxcui equals bn.BrandedDrugRxcui into bnj
|
||||
from bnji in bnj.DefaultIfEmpty()
|
||||
join g in Gd on bdgd.GenericRxcui equals g.GenericRxcui into gj
|
||||
from gji in gj.DefaultIfEmpty()
|
||||
join n in Ndcs on bdgd.BrandedDrugRxcui equals n.Rxcui into nj
|
||||
from nji in nj.DefaultIfEmpty()
|
||||
//where bnji == null
|
||||
orderby bnji?.BrandName, bdgd.BrandedDrugName, gji?.DoseForm
|
||||
select new
|
||||
{
|
||||
Ndc = nji?.Description,
|
||||
BrandName = bnji?.BrandName ?? "Generic",
|
||||
bdgd.BrandedDrugName,
|
||||
gji?.GenericDrugName,
|
||||
gji?.DoseForm,
|
||||
bnji?.BrandNameRxcui,
|
||||
bdgd.BrandedDrugRxcui,
|
||||
gji?.GenericRxcui,
|
||||
gji?.DoseFormRxcui,
|
||||
//Strength = s.Description
|
||||
});
|
||||
|
||||
await Verifier.Verify(BrandedDrugDoseForms, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCase(10, 0)]
|
||||
public async Task PublishFactRxNorm(int take, int skip)
|
||||
{
|
||||
var ndcDoseForms =
|
||||
from rel in RxnRelations
|
||||
join ndc in RxnAttributes.Where(a => a.Atn == "NDC") on rel.Rxcui1 equals ndc.Rxcui
|
||||
join df in RxnConcepts.Where(c => c.Tty == "DF") on rel.Rxcui2 equals df.Rxcui
|
||||
select new
|
||||
{
|
||||
NDC = ndc.Atv,
|
||||
NdcCode = ndc.Code,
|
||||
DoseForm = df.Str,
|
||||
DoseFormCode = df.Code,
|
||||
NdcRxcui = rel.Rxcui1,
|
||||
DoseFormRxcui = rel.Rxcui2,
|
||||
rel.Rel
|
||||
};
|
||||
|
||||
var SemanticClinicalDrugName =
|
||||
from r in RxnRelations
|
||||
join c1 in RxnConcepts.Where(c => c.Tty == "SCD") on r.Rxcui1 equals c1.Rxcui
|
||||
join c2 in RxnConcepts.Where(c => c.Tty == "SBD") on r.Rxcui2 equals c2.Rxcui
|
||||
select new
|
||||
{
|
||||
SemanticClinicalDrugRxcui = r.Rxcui1,
|
||||
SemanticClinicalDrugName = c1.Str,
|
||||
SemanticClinicalDrugCode = c1.Code,
|
||||
SemanticClinicalNameRxcui = r.Rxcui2,
|
||||
SemanticClinicalName = c2.Str,
|
||||
SemanticClinicalCode = c2.Code
|
||||
};
|
||||
|
||||
var SemanticBrandBrandName =
|
||||
from r in RxnRelations
|
||||
join c1 in RxnConcepts.Where(c => c.Tty == "SBD") on r.Rxcui1 equals c1.Rxcui
|
||||
join c2 in RxnConcepts.Where(c => c.Tty == "BN") on r.Rxcui2 equals c2.Rxcui
|
||||
select new
|
||||
{
|
||||
BrandedDrugRxcui = r.Rxcui1,
|
||||
BrandedDrugName = c1.Str,
|
||||
BrandedDrugCode = c1.Code,
|
||||
BrandNameRxcui = r.Rxcui2,
|
||||
BrandName = c2.Str,
|
||||
BrandCode = c2.Code
|
||||
};
|
||||
|
||||
var ndcDoseFormBrands =
|
||||
from rel in RxnRelations
|
||||
join ndc in ndcDoseForms on rel.Rxcui1 equals ndc.NdcRxcui
|
||||
join b in RxnConcepts.Where(c => c.Tty == "BN") on rel.Rxcui2 equals b.Rxcui into ndcb
|
||||
from ndcj in ndcb.DefaultIfEmpty()
|
||||
join sbd in SemanticBrandBrandName on rel.Rxcui2 equals sbd.BrandedDrugRxcui into sbds
|
||||
from sbdj in sbds.DefaultIfEmpty()
|
||||
select new
|
||||
{
|
||||
ndc.NDC,
|
||||
ndc.NdcCode,
|
||||
ndc.DoseForm,
|
||||
ndc.DoseFormCode,
|
||||
Brand = ndcj?.Str ?? "Not Specified",
|
||||
BrandCode = ndcj?.Code ?? "Not Specified",
|
||||
ndc.NdcRxcui,
|
||||
ndc.DoseFormRxcui,
|
||||
BrandRxcui = ndcj?.Rxcui ?? "",
|
||||
};
|
||||
|
||||
var ndcDFBSBD =
|
||||
from rel in RxnRelations
|
||||
join ndc in ndcDoseFormBrands on rel.Rxcui1 equals ndc.NdcRxcui
|
||||
join sbd in SemanticBrandBrandName on rel.Rxcui2 equals sbd.BrandedDrugRxcui into ndcs
|
||||
from ndcj in ndcs.DefaultIfEmpty()
|
||||
select new
|
||||
{
|
||||
ndc.NDC,
|
||||
ndc.NdcCode,
|
||||
ndc.DoseForm,
|
||||
ndc.DoseFormCode,
|
||||
ndc.Brand,
|
||||
ndc.BrandCode,
|
||||
SemanticBrand = ndcj?.BrandedDrugName ?? "Not Specified",
|
||||
SemanticBrandCode = ndcj?.BrandedDrugCode ?? "Not Specified",
|
||||
SemanticBrandName = ndcj?.BrandName ?? "Not Specified",
|
||||
SemanticBrandNameCode = ndcj?.BrandCode ?? "Not Specified",
|
||||
ndc.NdcRxcui,
|
||||
ndc.DoseFormRxcui,
|
||||
ndc.BrandRxcui,
|
||||
SemanticBrandRxcui = ndcj?.BrandedDrugRxcui ?? "",
|
||||
SemanticBrandNameRxcui = ndcj?.BrandNameRxcui ?? "",
|
||||
};
|
||||
|
||||
var ndcDFBSBDSCD =
|
||||
from rel in RxnRelations
|
||||
join ndc in ndcDFBSBD on rel.Rxcui1 equals ndc.NdcRxcui
|
||||
join sbd in SemanticClinicalDrugName on rel.Rxcui2 equals sbd.SemanticClinicalDrugRxcui
|
||||
select new
|
||||
{
|
||||
ndc.NDC,
|
||||
ndc.NdcCode,
|
||||
ndc.DoseForm,
|
||||
ndc.DoseFormCode,
|
||||
ndc.Brand,
|
||||
ndc.BrandCode,
|
||||
ndc.SemanticBrand,
|
||||
ndc.SemanticBrandCode,
|
||||
ndc.SemanticBrandName,
|
||||
ndc.SemanticBrandNameCode,
|
||||
SemanticClinicalBrand = sbd.SemanticClinicalDrugName,
|
||||
SemanticClinicalBrandCode = sbd.SemanticClinicalDrugCode,
|
||||
SemanticClinicalBrandName = sbd.SemanticClinicalName,
|
||||
SemanticClinicalBrandNameCode = sbd.SemanticClinicalCode,
|
||||
ndc.NdcRxcui,
|
||||
ndc.DoseFormRxcui,
|
||||
ndc.BrandRxcui,
|
||||
ndc.SemanticBrandRxcui,
|
||||
ndc.SemanticBrandNameRxcui,
|
||||
SemanticClinicalBrandRxcui = sbd.SemanticClinicalDrugRxcui,
|
||||
SemanticClinicalBrandNameRxcui = sbd.SemanticClinicalNameRxcui,
|
||||
};
|
||||
|
||||
await Verifier.Verify(ndcDFBSBDSCD
|
||||
.Where(b => b.Brand != "Not Specified" && b.SemanticBrand != "Not Specified")
|
||||
.OrderBy(b => b.NDC)
|
||||
.ThenBy(b => b.DoseFormCode)
|
||||
.ThenBy(b => b.BrandCode)
|
||||
.Distinct()
|
||||
.Skip(skip).Take(take), VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext?.TestName());
|
||||
}
|
||||
|
||||
internal class CheckForDuplicate
|
||||
{
|
||||
public string Code { get; set; }
|
||||
public IEnumerable<string> Names { get; set; }
|
||||
|
||||
public CheckForDuplicate(string code, IEnumerable<string> names)
|
||||
{
|
||||
Code = code;
|
||||
Names = names;
|
||||
}
|
||||
}
|
||||
|
||||
internal class DuplicateCheck
|
||||
{
|
||||
public IEnumerable<CheckForDuplicate> Duplicates { get; set; }
|
||||
public int DuplicateCount { get; set; }
|
||||
|
||||
public DuplicateCheck(IEnumerable<CheckForDuplicate> items)
|
||||
{
|
||||
DuplicateCount = items.Count(x => x.Names.Count() > 1);
|
||||
Duplicates = items.Where(x => x.Names.Count() > 1);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public async Task CheckForDuplicateBrands()
|
||||
{
|
||||
var items = RxnConcepts.Where(b => b.Tty == "BN")
|
||||
.GroupBy(b => b.Code, (Code, d) => new CheckForDuplicate(Code, d.Select(n => n.Str)))
|
||||
.OrderBy(x => x.Code)
|
||||
.ToList();
|
||||
var check = new DuplicateCheck(items);
|
||||
await Verifier.Verify(check, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext?.TestName());
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public async Task CheckForDuplicateDoseForms()
|
||||
{
|
||||
var items = RxnConcepts.Where(b => b.Tty == "DF")
|
||||
.GroupBy(b => b.Code, (Code, d) => new CheckForDuplicate(Code, d.Select(n => n.Str)))
|
||||
.OrderBy(x => x.Code)
|
||||
.ToList();
|
||||
var check = new DuplicateCheck(items);
|
||||
await Verifier.Verify(check, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext?.TestName());
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public async Task CheckForDuplicateSemanticClinicalDrugs()
|
||||
{
|
||||
var items = RxnConcepts.Where(b => b.Tty == "SCD")
|
||||
.GroupBy(b => b.Code, (Code, d) => new CheckForDuplicate(Code, d.Select(n => n.Str)))
|
||||
.OrderBy(x => x.Code)
|
||||
.ToList();
|
||||
var check = new DuplicateCheck(items);
|
||||
await Verifier.Verify(check, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext?.TestName());
|
||||
}
|
||||
|
||||
[TestCase()]
|
||||
public async Task CheckForDuplicateSemanticBrandedDrugs()
|
||||
{
|
||||
var items = RxnConcepts.Where(b => b.Tty == "SBD")
|
||||
.GroupBy(b => b.Code, (Code, d) => new CheckForDuplicate(Code, d.Select(n => n.Str)))
|
||||
.OrderBy(x => x.Code)
|
||||
.ToList();
|
||||
var check = new DuplicateCheck(items);
|
||||
await Verifier.Verify(check, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext?.TestName());
|
||||
}
|
||||
|
||||
[TestCase(100, 0)]
|
||||
public async Task CheckForDuplicateNDCs(int take, int skip)
|
||||
{
|
||||
var items = RxnAttributes.Where(b => b.Atn == "NDC")
|
||||
.GroupBy(b => b.Code, (Code, d) => new CheckForDuplicate(Code, d.Select(n => n.Atv)))
|
||||
.OrderBy(x => x.Code)
|
||||
.Skip(skip).Take(take)
|
||||
.ToList();
|
||||
var check = new DuplicateCheck(items);
|
||||
await Verifier.Verify(check, VerifySetting)
|
||||
.UseFileName(TestContext.CurrentContext?.TestName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user