示例#1
0
    public void Test_DifficultSet_Owen2013()
    {
        // This ion set came from https://www.nature.com/articles/nature12330

        var ionSet = new Ion[]
        {
            new Ion("K", 50, 3),
            new Ion("Gluconate", 50, 0),
            new Ion("Cs", 70, 0),
            new Ion("HSO3", 70, 0),
            new Ion("TEA (TetraethylAmmonium)", 10, 10),
            new Ion("Cl", 12, 131.6),
            new Ion("Mg", 5, 1.3),
            new Ion("HEPES", 10, 0),
            new Ion("EGTA(2-)", .3, 0),
            new Ion("Tris", 10, 0),
            new Ion("ATP (Adenosine 5'-Triphosphate)", 4, 0),
            new Ion("Na", 0.3, 139.25),
            new Ion("HCO3", 0, 26),
            new Ion("H2PO4", 0, 1.25),
            new Ion("Ca", 0, 2),
            new Ion("4-AP (4-aminopyridine)", 0, 5),
        };

        ionSet = IonLibrary.Lookup(ionSet);

        LjpResult ljp = LjpCalculator.SolvePhisThenCalculateLjp(ionSet, temperatureC: 33);

        Assert.That(ljp.LjpMillivolts, Is.EqualTo(15.1 - 3.3).Within(0.5));
    }
示例#2
0
    public void Test_Calculator_LimitIterations()
    {
        // This ion set in this order is known to be very difficult to solve

        Ion[] ions =
        {
            new Ion("Zn",  9, .0284),
            new Ion("K",   0,     3),
            new Ion("Cl", 18, 3.062),
            new Ion("Mg",  5,     3),
            new Ion("Ag",  1,     1),
        };

        ions = IonLibrary.Lookup(ions);

        LjpCalculator calcWithoutSorting = new(ions, autoSort : false);

        calcWithoutSorting.IterateRepeatedly(1.0, 123);
        Assert.That(calcWithoutSorting.Iterations, Is.EqualTo(123));

        LjpCalculator calcWithSorting = new(ions, autoSort : true);

        calcWithSorting.IterateRepeatedly(1.0, 123);
        Assert.That(calcWithSorting.Iterations, Is.LessThan(calcWithoutSorting.Iterations));
    }
示例#3
0
    public void Test_BadOrder_FixedByAutoSort002()
    {
        /* Known to crash due to poor ion order https://github.com/swharden/LJPcalc/issues/9 */
        // fixed by autoSort prior to calculation

        var ionSet = new Ion[] {
            new Ion("K", 145, 2.8),
            new Ion("Na", 13, 145),
            new Ion("Cl", 10, 148.8),
            new Ion("Gluconate", 145, 0),
            new Ion("Mg", 1, 2),
            new Ion("Ca", 0, 1),
            new Ion("HEPES", 5, 5),
        };

        ionSet = IonLibrary.Lookup(ionSet);

        // it does not solve in this order
        LjpResult result = LjpCalculator.SolvePhisThenCalculateLjp(ionSet, autoSort: false, maxIterations: 123);

        Assert.That(result.Iterations, Is.EqualTo(123));

        // but it does solve if allowed to auto-sort
        LjpResult result2 = LjpCalculator.SolvePhisThenCalculateLjp(ionSet, autoSort: true, maxIterations: 123);

        Assert.That(result2.LjpMillivolts, Is.EqualTo(16.3).Within(0.5));
    }
示例#4
0
    public void Test_BadOrder_FixedByAutoSort001()
    {
        /* Known to crash due to poor ion order https://github.com/swharden/LJPcalc/issues/9 */
        // fixed by autoSort prior to calculation

        var ionSet = new Ion[] {
            new Ion("Zn", 9, .0284),
            new Ion("K", 0, 3),
            new Ion("Cl", 18, 3.062),
            new Ion("Mg", 5, 3),
            new Ion("Ag", 1, 1),
        };

        ionSet = IonLibrary.Lookup(ionSet);

        // it does not solve in this order
        LjpResult result = LjpCalculator.SolvePhisThenCalculateLjp(ionSet, autoSort: false, maxIterations: 123);

        Assert.That(result.Iterations, Is.EqualTo(123));

        // but it does solve if allowed to auto-sort
        LjpResult result2 = LjpCalculator.SolvePhisThenCalculateLjp(ionSet, autoSort: true, maxIterations: 123);

        Assert.That(result2.LjpMillivolts, Is.EqualTo(-11.9).Within(0.5));
    }
示例#5
0
    public void Test_Calculator_ManualIterations()
    {
        // This ion set in this order is known to be very difficult to solve

        Ion[] ions =
        {
            new Ion("Zn",  9, .0284),
            new Ion("K",   0,     3),
            new Ion("Cl", 18, 3.062),
            new Ion("Mg",  5,     3),
            new Ion("Ag",  1,     1),
        };

        ions = IonLibrary.Lookup(ions);

        LjpCalculator calc  = new(ions);
        double        error = double.PositiveInfinity;

        for (int i = 0; i < 100; i++)
        {
            calc.Iterate();
            if (calc.BestSolution.MaxAbsoluteError < error)
            {
                error = calc.BestSolution.MaxAbsoluteError;
                Console.WriteLine(calc);
            }
        }

        Console.WriteLine(calc.GetBestLjpResult());
    }
示例#6
0
    public void Test_KnownIonSets_LjpWithinExpectedRange()
    {
        IKnownIonSet[] knowSets = Core.KnownIonSets.KnownSets.GetAll();
        Assert.That(knowSets, Is.Not.Null);
        Assert.That(knowSets, Is.Not.Empty);

        Parallel.ForEach(knowSets, (knownSet) =>
        {
            Ion[] ions       = IonLibrary.Lookup(knownSet.Ions);
            LjpResult result = LjpCalculator.SolvePhisThenCalculateLjp(ions, knownSet.Temperature_C);
            Assert.That(result.LjpMillivolts, Is.EqualTo(knownSet.Ljp_mV).Within(knownSet.Accuracy_mV), knownSet.Name);
        });
    }
示例#7
0
    public void Test_LjpCalculationMatches_ExampleFromSourceCode()
    {
        /* From JLJP: https://github.com/swharden/JLJP/blob/2.0.0/src/Example.java */

        Ion Zn = new Ion("Zn", MolsPerCubicMeter(9), MolsPerCubicMeter(0.0284));
        Ion K  = new Ion("K", MolsPerCubicMeter(0), MolsPerCubicMeter(3));
        Ion Cl = new Ion("Cl", MolsPerCubicMeter(18), MolsPerCubicMeter(3.0568));

        var ionSet = new Ion[] { Zn, K, Cl };

        ionSet = IonLibrary.Lookup(ionSet);

        LjpResult ljp = LjpCalculator.SolvePhisThenCalculateLjp(ionSet, autoSort: false);

        Assert.That(ljp.LjpMillivolts, Is.EqualTo(-20.79558643).Within(1e-6));
    }
示例#8
0
    public void Test_LjpCalculationMatches_Harper004()
    {
        // ion set from Harper (1985) Table I
        // https://pubs.acs.org/doi/pdf/10.1021/j100255a022

        var ionSet = new Ion[]
        {
            new Ion("Zn", .4, .0186),
            new Ion("SO4", .4, .0186),
        };

        ionSet = IonLibrary.Lookup(ionSet);

        LjpResult ljp = LjpCalculator.SolvePhisThenCalculateLjp(ionSet);

        Assert.That(ljp.LjpMillivolts, Is.EqualTo(-8.1).Within(0.5));
    }
示例#9
0
    public void Test_LjpCalculationMatches_ExampleFromScreenshot()
    {
        /* Test came from screenshot on original JLJP website */

        var ionSet = new Ion[]
        {
            new Ion("Zn", 9, 0.0284),
            new Ion("K", 0, 3),
            new Ion("Cl", 18, 3.0568)
        };

        ionSet = IonLibrary.Lookup(ionSet);

        LjpResult ljp = LjpCalculator.SolvePhisThenCalculateLjp(ionSet, autoSort: false);

        Assert.That(ljp.LjpMillivolts, Is.EqualTo(-20.79558643).Within(1e-6));
    }
示例#10
0
    public void Test_IonSet_TextExport()
    {
        IKnownIonSet knownSet = new Owen2013();

        Ion[]  ions1        = IonLibrary.Lookup(knownSet.Ions);
        double temperature1 = knownSet.Temperature_C;

        string text1 = IonSet.ToText(ions1, temperature1);

        Console.WriteLine(text1);

        (Ion[] ions2, double temperature2) = IonSet.FromText(text1);
        string text2 = IonSet.ToText(ions2, temperature2);

        Assert.That(temperature1, Is.EqualTo(temperature2));
        Assert.That(text1, Is.EqualTo(text2));
    }
示例#11
0
    public void Test_LjpCalculationMatches_NgAndBarry001()
    {
        /* LJP for this test came from Ng and Barry (1994) Table 2 */

        // 50 mM NaCl : 50 mM KCl
        var ionSet = new Ion[]
        {
            new Ion("Na", 50, 0),
            new Ion("K", 0, 50),
            new Ion("Cl", 50, 50)
        };

        ionSet = IonLibrary.Lookup(ionSet);

        LjpResult ljp = LjpCalculator.SolvePhisThenCalculateLjp(ionSet);

        Assert.That(ljp.LjpMillivolts, Is.EqualTo(-4.3).Within(0.5));
    }
示例#12
0
    public void Test_LjpCalculationMatches_NgAndBarry005()
    {
        /* LJP for this test came from Ng and Barry (1994) Table 2 */

        // 100 CaCl2 : 100 MgCl2
        // Ca (100), Cl (200) : Mg (100) Cl (200)
        var ionSet = new Ion[]
        {
            new Ion("Ca", 100, 0),
            new Ion("Mg", 0, 100),
            new Ion("Cl", 200, 200)
        };

        ionSet = IonLibrary.Lookup(ionSet);

        LjpResult ljp = LjpCalculator.SolvePhisThenCalculateLjp(ionSet);

        Assert.That(ljp.LjpMillivolts, Is.EqualTo(+0.6).Within(0.5));
    }
示例#13
0
    public void Test_LjpCalculationMatches_JPWin002()
    {
        // ion set shown in JPCalcWin manual (page 10)
        // https://tinyurl.com/wk7otn7

        var ionSet = new Ion[]
        {
            new Ion("Cs", 145, 0),
            new Ion("Na", 0, 145),
            new Ion("F", 125, 0),
            new Ion("Cl", 20, 145)
        };

        ionSet = IonLibrary.Lookup(ionSet);

        LjpResult ljp = LjpCalculator.SolvePhisThenCalculateLjp(ionSet);

        Assert.That(ljp.LjpMillivolts, Is.EqualTo(+8.71).Within(0.5));
    }
示例#14
0
    public void Test_LjpCalculationMatches_NgAndBarry006()
    {
        /* LJP for this test came from Ng and Barry (1994) Table 2 */

        // 100 KCl + 2 CaCl2 : 100 LiCl + 2 CaCl2
        // K (100), Cl (104), Ca (2) : Li (100), Cl (104), Ca (2)
        var ionSet = new Ion[]
        {
            new Ion("Ca", 2, 2),
            new Ion("K", 100, 0),
            new Ion("Li", 0, 100),
            new Ion("Cl", 104, 104)
        };

        ionSet = IonLibrary.Lookup(ionSet);

        LjpResult ljp = LjpCalculator.SolvePhisThenCalculateLjp(ionSet);

        Assert.That(ljp.LjpMillivolts, Is.EqualTo(+6.4).Within(0.5));
    }
示例#15
0
    public void Test_Calculator_ManualIterationsOwen()
    {
        Core.KnownIonSets.Owen2013 set = new();
        Ion[] ions = IonLibrary.Lookup(set.Ions);

        LjpCalculator calc  = new(ions);
        double        error = double.PositiveInfinity;

        while (error > .01)
        {
            calc.Iterate();
            if (calc.BestSolution.MaxAbsoluteError < error)
            {
                error = calc.BestSolution.MaxAbsoluteError;
                Console.WriteLine(calc);
            }
        }

        Console.WriteLine(calc.GetBestLjpResult());
    }
示例#16
0
    public void Test_BadOrder_SecondFromLastSameConc()
    {
        // second to last ion cannot have same concentration on both sides
        var ionSet = new Ion[]
        {
            new Ion("Zn", 2, 2),
            new Ion("K", 3, 3),  // after sorting this is last (biggest absolute CL)
            new Ion("Mg", 2, 2),
            new Ion("Cl", 4, 0), // after sorting this is second to last (largest difference between C0 and CL)
        };

        ionSet = IonLibrary.Lookup(ionSet);

        Assert.Throws <InvalidOperationException>(() => LjpCalculator.SolvePhisThenCalculateLjp(ionSet, autoSort: false));

        LjpResult ljp = LjpCalculator.SolvePhisThenCalculateLjp(ionSet, autoSort: true);

        string ionOrder = string.Join(", ", ljp.Ions.Select(x => x.Name));

        Assert.That(ionOrder, Is.EqualTo("Zn, Mg, Cl, K"));
    }
示例#17
0
    public void Test_Lookup_KnownIon()
    {
        Ion ion = IonLibrary.Lookup("glutamate");

        Assert.That(ion.Charge, Is.EqualTo(-1));
    }
示例#18
0
    public void Test_CompareValues_ToJLJP()
    {
        // ion charges and mus came from the JLJP project source code
        // https://github.com/swharden/JLJP/blob/b585ab99d78f39960f85b17988374f3445b7dadb/src/Ion.java#L29-L125

        List <ionJLJP> ionsFromJLJP = new()
        {
            new ionJLJP()
            {
                name = "Ag", charge = 1, mu = 401656000000
            },
            new ionJLJP()
            {
                name = "Al", charge = 3, mu = 131939000000
            },
            new ionJLJP()
            {
                name = "Au(CN)2", charge = -1, mu = 324439000000
            },
            new ionJLJP()
            {
                name = "Au(CN)4", charge = -1, mu = 233596000000
            },
            new ionJLJP()
            {
                name = "Ba", charge = 2, mu = 206343000000
            },
            new ionJLJP()
            {
                name = "B(C6H5)4", charge = -1, mu = 136265000000
            },
            new ionJLJP()
            {
                name = "Be", charge = 2, mu = 145998000000
            },
            new ionJLJP()
            {
                name = "Br3", charge = -1, mu = 279018000000
            },
            new ionJLJP()
            {
                name = "Br", charge = -1, mu = 506774000000
            },
            new ionJLJP()
            {
                name = "BrO3", charge = -1, mu = 361425000000
            },
            new ionJLJP()
            {
                name = "Ca", charge = 2, mu = 192944000000
            },
            new ionJLJP()
            {
                name = "Cd", charge = 2, mu = 175197000000
            },
            new ionJLJP()
            {
                name = "Ce", charge = 3, mu = 150972000000
            },
            new ionJLJP()
            {
                name = "Cl", charge = -1, mu = 495159000000
            },
            new ionJLJP()
            {
                name = "ClO2", charge = -1, mu = 337417000000
            },
            new ionJLJP()
            {
                name = "ClO3", charge = -1, mu = 419176000000
            },
            new ionJLJP()
            {
                name = "ClO4", charge = -1, mu = 436695000000
            },
            new ionJLJP()
            {
                name = "CN", charge = -1, mu = 506125000000
            },
            new ionJLJP()
            {
                name = "CNO", charge = -1, mu = 419176000000
            },
            new ionJLJP()
            {
                name = "CO3", charge = -2, mu = 224836000000
            },
            new ionJLJP()
            {
                name = "Co", charge = 2, mu = 178442000000
            },
            new ionJLJP()
            {
                name = "Co(CN)6", charge = -3, mu = 213914000000
            },
            new ionJLJP()
            {
                name = "Co(NH3)6", charge = 3, mu = 220402000000
            },
            new ionJLJP()
            {
                name = "Cr", charge = 3, mu = 144916000000
            },
            new ionJLJP()
            {
                name = "CrO4", charge = -2, mu = 275773000000
            },
            new ionJLJP()
            {
                name = "Cs", charge = 1, mu = 500934000000
            },
            new ionJLJP()
            {
                name = "Cu", charge = 2, mu = 173900000000
            },
            //new JljpIon() { name = "D", charge = 1, mu = 1621550000000 }, // REF DOESNT HAV 25C
            new ionJLJP()
            {
                name = "Dy", charge = 3, mu = 141888000000
            },
            new ionJLJP()
            {
                name = "Er", charge = 3, mu = 142537000000
            },
            new ionJLJP()
            {
                name = "Eu", charge = 3, mu = 146647000000
            },
            new ionJLJP()
            {
                name = "F", charge = -1, mu = 359479000000
            },
            new ionJLJP()
            {
                name = "FeII", charge = 2, mu = 175197000000
            },
            new ionJLJP()
            {
                name = "FeIII", charge = 3, mu = 147079000000
            },
            new ionJLJP()
            {
                name = "Fe(CN)6 III", charge = -3, mu = 218240000000
            },
            new ionJLJP()
            {
                name = "Fe(CN)6 IIII", charge = -4, mu = 179091000000
            },
            new ionJLJP()
            {
                name = "Gd", charge = 3, mu = 145565000000
            },
            new ionJLJP()
            {
                name = "H2AsO4", charge = -1, mu = 220619000000
            },
            // new ionJLJP() { name = "H2PO2", charge = -1, mu = 298484000000 },
            // new JljpIon() { name = "H2PO4", charge = -1, mu = 233596000000 }, // INACCURATE?
            new ionJLJP()
            {
                name = "H2SbO4", charge = -1, mu = 201152000000
            },
            new ionJLJP()
            {
                name = "H", charge = 1, mu = 2268800000000
            },
            new ionJLJP()
            {
                name = "HCO3", charge = -1, mu = 288751000000
            },
            new ionJLJP()
            {
                name = "HF2", charge = -1, mu = 486659000000
            },
            //new JljpIon() { name = "Hg", charge = 2, mu = 222565000000 }, // INACCURATE?
            new ionJLJP()
            {
                name = "Ho", charge = 3, mu = 143402000000
            },
            //new JljpIon() { name = "HPO4", charge = -2, mu = 184930000000 }, // INACCURATE?
            new ionJLJP()
            {
                name = "HS", charge = -1, mu = 421771000000
            },
            //new JljpIon() { name = "HSO3", charge = -1, mu = 376350000000 }, // INACCURATE?
            //new JljpIon() { name = "HSO4", charge = -1, mu = 337417000000 }, // INACCURATE?
            new ionJLJP()
            {
                name = "I", charge = -1, mu = 498339000000
            },
            new ionJLJP()
            {
                name = "IO3", charge = -1, mu = 262796000000
            },
            new ionJLJP()
            {
                name = "IO4", charge = -1, mu = 353639000000
            },
            new ionJLJP()
            {
                name = "K", charge = 1, mu = 476796000000
            },
            new ionJLJP()
            {
                name = "La", charge = 3, mu = 150756000000
            },
            new ionJLJP()
            {
                name = "Li", charge = 1, mu = 250857000000
            },
            new ionJLJP()
            {
                name = "Mg", charge = 2, mu = 171953000000
            },
            new ionJLJP()
            {
                name = "Mn", charge = 2, mu = 173575000000
            },
            new ionJLJP()
            {
                name = "MnO4", charge = -1, mu = 397763000000
            },
            new ionJLJP()
            {
                name = "MoO4", charge = -2, mu = 241707000000
            },
            new ionJLJP()
            {
                name = "N2H5", charge = 1, mu = 382838000000
            },
            new ionJLJP()
            {
                name = "N3", charge = -1, mu = 447726000000
            },
            new ionJLJP()
            {
                name = "Na", charge = 1, mu = 324958000000
            },
            new ionJLJP()
            {
                name = "N(CN)2", charge = -1, mu = 353639000000
            },
            new ionJLJP()
            {
                name = "Nd", charge = 3, mu = 150107000000
            },
            new ionJLJP()
            {
                name = "NH2SO3", charge = -1, mu = 313408000000
            },
            new ionJLJP()
            {
                name = "NH4", charge = 1, mu = 476926000000
            },
            new ionJLJP()
            {
                name = "Ni", charge = 2, mu = 160922000000
            },
            new ionJLJP()
            {
                name = "NO2", charge = -1, mu = 465895000000
            },
            new ionJLJP()
            {
                name = "NO3", charge = -1, mu = 463429000000
            },
            new ionJLJP()
            {
                name = "OCN (cyanate)", charge = -1, mu = 419176000000
            },
            //new ionJLJP() { name = "OD", charge = -1, mu = 772166000000 },
            new ionJLJP()
            {
                name = "OH", charge = -1, mu = 1284780000000
            },
            new ionJLJP()
            {
                name = "Pb", charge = 2, mu = 230352000000
            },
            new ionJLJP()
            {
                name = "PF6", charge = -1, mu = 369212000000
            },
            new ionJLJP()
            {
                name = "PO3F", charge = -2, mu = 205370000000
            },
            //new JljpIon() { name = "PO4", charge = -3, mu = 200720000000 }, // INACCURATE?
            new ionJLJP()
            {
                name = "Pr", charge = 3, mu = 150324000000
            },
            new ionJLJP()
            {
                name = "Ra", charge = 2, mu = 216725000000
            },
            new ionJLJP()
            {
                name = "Rb", charge = 1, mu = 504828000000
            },
            new ionJLJP()
            {
                name = "ReO4", charge = -1, mu = 356234000000
            },
            //new ionJLJP() { name = "Sb(OH)6", charge = -1, mu = 206992000000 },
            new ionJLJP()
            {
                name = "Sc", charge = 3, mu = 139942000000
            },
            //new ionJLJP() { name = "SCN (thiocyanate)", charge = -1, mu = 428260000000 },
            new ionJLJP()
            {
                name = "SeCN", charge = -1, mu = 419825000000
            },
            new ionJLJP()
            {
                name = "SeO4", charge = -2, mu = 245601000000
            },
            new ionJLJP()
            {
                name = "Sm", charge = 3, mu = 148161000000
            },
            //new JljpIon() { name = "SO3", charge = -2, mu = 233596000000 }, // INACCURATE?
            new ionJLJP()
            {
                name = "SO4", charge = -2, mu = 259551000000
            },
            new ionJLJP()
            {
                name = "Sr", charge = 2, mu = 192717000000
            },
            new ionJLJP()
            {
                name = "Tl", charge = 1, mu = 484712000000
            },
            new ionJLJP()
            {
                name = "Tm", charge = 3, mu = 141456000000
            },
            new ionJLJP()
            {
                name = "UO2", charge = 2, mu = 103821000000
            },
            new ionJLJP()
            {
                name = "WO4", charge = -2, mu = 223863000000
            },
            new ionJLJP()
            {
                name = "Yb", charge = 3, mu = 141888000000
            },
            new ionJLJP()
            {
                name = "Y", charge = 3, mu = 134102000000
            },
            new ionJLJP()
            {
                name = "Zn", charge = 2, mu = 171304000000
            }
        };

        string[] libraryIonNames = IonLibrary.KnownIons.Select(x => x.Name).ToArray();

        foreach (ionJLJP ionFromJLJP in ionsFromJLJP)
        {
            Ion ionFromThisLibrary = IonLibrary.Lookup(ionFromJLJP.name);

            Assert.That(ionFromThisLibrary.Charge, Is.EqualTo(ionFromJLJP.charge), ionFromThisLibrary.Name);
            Assert.That(ionFromThisLibrary.Mu * 1e-4, Is.EqualTo(ionFromJLJP.mu).Within(10).Percent);
        }
    }
}
示例#19
0
    public void Test_Lookup_FailsWithoutCrashing()
    {
        Ion ion = IonLibrary.Lookup("adfasdfasdfasdf");

        Assert.That(ion.Charge, Is.EqualTo(0));
    }
示例#20
0
    public void Test_Lookup_ByDescription()
    {
        Ion ion = IonLibrary.Lookup("Glutamate");

        Assert.That(ion.Charge, Is.EqualTo(-1));
    }
示例#21
0
    public void Test_Lookup_IsCaseInsensitive()
    {
        Ion ion = IonLibrary.Lookup("gLuTaMaTe");

        Assert.That(ion.Charge, Is.EqualTo(-1));
    }