/* LabItem.cs * part of zaaReloaded2 * * Copyright 2015 Daniel Kraus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Globalization; using System.Text.RegularExpressions; using zaaReloaded2.LabModel; namespace zaaReloaded2.Importer.ZaaImporter { /// /// Represents a single laboratory item (e.g., sodium or creatinine). /// public class LaurisItem : LabItem { #region Properties /// /// The original Lauris string from which this lab item was created. /// public string LaurisText { get; private set; } /// /// The original name of this item as known by Lauris /// public string OriginalName { get; private set; } #endregion #region Constructors /// /// Creates an empty LabItem object. /// public LaurisItem() : base() { } public LaurisItem(string laurisString) : this() { LaurisText = laurisString; ParseLauris(); DetectMaterial(); } /// /// Creates a LabItem object from a given Lauris output, using /// a too look up additional /// properties (canonical name, material type, whether or not /// to always print the reference interval). /// /// Lauris output to parse. /// ParameterDictionary that is used /// to look up the canonical name, material type, and whether or /// not to always print the reference interval public LaurisItem(string laurisString, Dictionaries.ParameterDictionary parameterDictionary, Dictionaries.UnitDictionary unitDictionary) : this(laurisString) { if (parameterDictionary != null) { Name = parameterDictionary.GetCanonicalName(OriginalName); AlwaysPrintLimits = parameterDictionary.GetForceReferenceDisplay(Name); } if (unitDictionary != null) { Unit = unitDictionary.TranslateLaurisUnit(Unit); } } #endregion #region Private methods /// /// Parses the original Lauris string contained in /// . /// void ParseLauris() { // Examples of Lauris output strings: // "Natrium: 139 [135 - 145] mmol/l" // "HDL - Cholesterin: 45 [>= 35] mg/dl" // "GOT (ASAT): 303.0 [<= 50] U/l; " // "Niedermol. Heparin (Anti-Xa): 0.99 U/ml;" // "HBs-Antigen: neg. ;" // "Erythrozyten (U): + [negativ]" Match match; Regex numericalRegex = new Regex( @"(?[^:]+):\s*(?[\d.]+)\s*(?\[[^\]]+])?\s*(?[^;]+)?"); Regex categoricalRegex = new Regex( @"(?[^:]+):\s*(?[^[;]+)\s*(\[(?[^\]]+)])?"); if (numericalRegex.IsMatch(LaurisText)) { match = numericalRegex.Match(LaurisText); ParseLimits(match); } else { match = categoricalRegex.Match(LaurisText); Normal = match.Groups["normal"].Value.Trim(); } if (match != null) { OriginalName = match.Groups["name"].Value.Trim(); Name = OriginalName; Value = match.Groups["value"].Value.Trim(); Unit = match.Groups["unit"].Value.Trim(); } } /// /// Parses a string containing value limits. The string must be like /// "[3.5 - 5]", "[>= 50]", or "[<= 100]". /// /// Match object that should contain a group "limits". void ParseLimits(Match match) { if (match.Groups["limits"].Success) { Regex limitRegex = new Regex(@"\[(?[\d.]+)?\s*(?\S+)\s*(?[\d.]+)?]"); Match limitMatch = limitRegex.Match(match.Groups["limits"].Value); if (limitMatch.Groups["limit1"].Success && limitMatch.Groups["limit2"].Success) { // Use InvariantCulture because Lauris always outputs dots as decimal separator LowerLimit = Double.Parse(limitMatch.Groups["limit1"].Value, CultureInfo.InvariantCulture); UpperLimit = Double.Parse(limitMatch.Groups["limit2"].Value, CultureInfo.InvariantCulture); } else { switch (limitMatch.Groups["operator"].Value.Trim()) { case "<=": UpperLimit = Double.Parse(limitMatch.Groups["limit2"].Value, CultureInfo.InvariantCulture); break; case ">=": LowerLimit = Double.Parse(limitMatch.Groups["limit2"].Value, CultureInfo.InvariantCulture); break; default: throw new InvalidOperationException( String.Format("Unknown operator in {0}", match.Groups["limits"].Value)); } } } } /// /// Analyses the Lauris name for a material abbreviation. /// If the parameter does not refer to blood (serum, whole /// blood, etc.), Lauris appends an abbreviation in parentheses /// to the parameter name. /// /// /// Gesamt-Eiweiss (SU), Albumin (SU)/die, Gesamt-Eiweiss (PU) /// void DetectMaterial() { // The material is encoded in the original name of the item // that was produced by Lauris (eg. "Natrium (PU)" for spot // urine). Match m = _materialRegex.Match(OriginalName); if (m.Success) { switch (m.Groups["material"].Value.ToUpper()) { case "SU": Material = LabModel.Material.SU; break; case "PU": Material = LabModel.Material.U; break; } } } #endregion #region Fields static readonly Regex _materialRegex = new Regex(@"\((?(SU|PU))\)"); #endregion } }