|
@@ -1,20 +1,84 @@
|
|
|
import 'dart:math' as math;
|
|
|
|
|
|
-import 'package:fis_common/logger/logger.dart';
|
|
|
import 'package:fis_measure/configs/cardiac.dart';
|
|
|
+import 'package:fis_measure/configs/patient.dart';
|
|
|
+import 'package:fis_measure/interfaces/enums/species.dart';
|
|
|
+import 'package:fis_measure/process/calcuators/formulas/general.dart';
|
|
|
import 'package:fis_measure/utils/number.dart';
|
|
|
|
|
|
-import 'general.dart';
|
|
|
-
|
|
|
class CardiacFormulas {
|
|
|
- CardiacFormulas._();
|
|
|
+ static final ICardiacFormulaStrategy _singleton =
|
|
|
+ GlobalPatientConfig.speciesType != SpeciesType.general
|
|
|
+ ? BaseCardiacFormulas()
|
|
|
+ : MouseCardiacFormulas();
|
|
|
+
|
|
|
+ static double teiIndex(double co, double et) => _singleton.teiIndex(co, et);
|
|
|
+ static double ef(double edv, double esv) => _singleton.ef(edv, esv);
|
|
|
+ static double edvTeichholz(double lvidd) => _singleton.edvTeichholz(lvidd);
|
|
|
+ static double edvCube(double lvidd) => _singleton.edvCube(lvidd);
|
|
|
+ static double esvTeichholz(double lvids) => _singleton.esvTeichholz(lvids);
|
|
|
+ static double esvCube(double lvids) => _singleton.esvCube(lvids);
|
|
|
+ static double sv(double edv, double esv) => _singleton.sv(edv, esv);
|
|
|
+ static double co(double sv, {required int hr}) => _singleton.co(sv, hr: hr);
|
|
|
+ static double ci(double sv, {required int hr, required double bsa}) =>
|
|
|
+ _singleton.ci(sv, hr: hr, bsa: bsa);
|
|
|
+ static double lvdMass(double ivsd, double lvidd, double lvpwd) =>
|
|
|
+ _singleton.lvdMass(ivsd, lvidd, lvpwd);
|
|
|
+ static double lvdMassAL(
|
|
|
+ double lvadSaxEpi, double lvadSaxEndo, double lvldApical) =>
|
|
|
+ _singleton.lvdMassAL(lvadSaxEpi, lvadSaxEndo, lvldApical);
|
|
|
+ static double lvdMassIndex(double lvdmass, double bsa) =>
|
|
|
+ _singleton.lvdMassIndex(lvdmass, bsa);
|
|
|
+ static double fsPercent(double lvidd, double lvids) =>
|
|
|
+ _singleton.fsPercent(lvidd, lvids);
|
|
|
+ static double ivsPercent(double ivss, double ivsd) =>
|
|
|
+ _singleton.ivsPercent(ivss, ivsd);
|
|
|
+ static double lvpwPercent(double lvpws, double lvpwd) =>
|
|
|
+ _singleton.lvpwPercent(lvpws, lvpwd);
|
|
|
+ static double mamPercent(double mapse, double lvidd, double lvids) =>
|
|
|
+ _singleton.mamPercent(mapse, lvidd, lvids);
|
|
|
+ static double si(double sv, double bsa) => _singleton.si(sv, bsa);
|
|
|
+ static double flowAreaByVTI(double otDiam, double otvti, double vti) =>
|
|
|
+ _singleton.flowAreaByVTI(otDiam, otvti, vti);
|
|
|
+ static double dviByVTI(double otvti, double vti) =>
|
|
|
+ _singleton.dviByVTI(otvti, vti);
|
|
|
+ static double avaIndex(double avaByVTI, double bsa) =>
|
|
|
+ _singleton.avaIndex(avaByVTI, bsa);
|
|
|
+
|
|
|
+ CardiacFormulas._internal(); // 私有构造函数
|
|
|
+}
|
|
|
|
|
|
+abstract class ICardiacFormulaStrategy {
|
|
|
+ double teiIndex(double co, double et);
|
|
|
+ double ef(double edv, double esv);
|
|
|
+ double edvTeichholz(double lvidd);
|
|
|
+ double edvCube(double lvidd);
|
|
|
+ double esvTeichholz(double lvids);
|
|
|
+ double esvCube(double lvids);
|
|
|
+ double sv(double edv, double esv);
|
|
|
+ double co(double sv, {required int hr});
|
|
|
+ double ci(double sv, {required int hr, required double bsa});
|
|
|
+ double lvdMass(double ivsd, double lvidd, double lvpwd);
|
|
|
+ double lvdMassAL(double lvadSaxEpi, double lvadSaxEndo, double lvldApical);
|
|
|
+ double lvdMassIndex(double lvdmass, double bsa);
|
|
|
+ double fsPercent(double lvidd, double lvids);
|
|
|
+ double ivsPercent(double ivss, double ivsd);
|
|
|
+ double lvpwPercent(double lvpws, double lvpwd);
|
|
|
+ double mamPercent(double mapse, double lvidd, double lvids);
|
|
|
+ double si(double sv, double bsa);
|
|
|
+ double flowAreaByVTI(double otDiam, double otvti, double vti);
|
|
|
+ double dviByVTI(double otvti, double vti);
|
|
|
+ double avaIndex(double avaByVTI, double bsa);
|
|
|
+}
|
|
|
+
|
|
|
+class BaseCardiacFormulas implements ICardiacFormulaStrategy {
|
|
|
/// IMP
|
|
|
///
|
|
|
/// Formula: `(CO-ET)/ET`
|
|
|
///
|
|
|
/// Result Unit: `None`
|
|
|
- static double teiIndex(double co, double et) {
|
|
|
+ @override
|
|
|
+ double teiIndex(double co, double et) {
|
|
|
double imp = 0.0;
|
|
|
if (et != 0.0) {
|
|
|
imp = (((co).abs() - (et).abs()) / et).abs();
|
|
@@ -30,7 +94,8 @@ class CardiacFormulas {
|
|
|
/// [esv] Unit: `cm³`
|
|
|
///
|
|
|
/// Result Unit: `None`
|
|
|
- static double ef(double edv, double esv) {
|
|
|
+ @override
|
|
|
+ double ef(double edv, double esv) {
|
|
|
// 这行判断暂时注释掉是为了使实际表现与旧版一致
|
|
|
// if (edv < esv) {
|
|
|
// return double.nan;
|
|
@@ -45,7 +110,8 @@ class CardiacFormulas {
|
|
|
/// [lvidd] Unit: `cm`
|
|
|
///
|
|
|
/// Result Unit: `cm³`
|
|
|
- static double edvTeichholz(double lvidd) {
|
|
|
+ @override
|
|
|
+ double edvTeichholz(double lvidd) {
|
|
|
double edv = double.nan;
|
|
|
if (!NumUtil.almostEquals(lvidd, 0)) {
|
|
|
edv = 7.0 * math.pow(lvidd, 3) / (2.4 + lvidd);
|
|
@@ -60,7 +126,8 @@ class CardiacFormulas {
|
|
|
/// [lvidd] Unit: `cm`
|
|
|
///
|
|
|
/// Result Unit: `cm³`
|
|
|
- static double edvCube(double lvidd) {
|
|
|
+ @override
|
|
|
+ double edvCube(double lvidd) {
|
|
|
double edv = double.nan;
|
|
|
if (!NumUtil.almostEquals(lvidd, 0)) {
|
|
|
edv = math.pow(lvidd, 3).toDouble();
|
|
@@ -75,7 +142,8 @@ class CardiacFormulas {
|
|
|
/// [lvids] Unit: `cm`
|
|
|
///
|
|
|
/// Result Unit: `cm³`
|
|
|
- static double esvTeichholz(double lvids) {
|
|
|
+ @override
|
|
|
+ double esvTeichholz(double lvids) {
|
|
|
// 计算公式相同,入参不同
|
|
|
return edvTeichholz(lvids);
|
|
|
}
|
|
@@ -87,18 +155,21 @@ class CardiacFormulas {
|
|
|
/// [lvids] Unit: `cm`
|
|
|
///
|
|
|
/// Result Unit: `cm³`
|
|
|
- static double esvCube(double lvids) {
|
|
|
+ @override
|
|
|
+ double esvCube(double lvids) {
|
|
|
// 计算公式相同,入参不同
|
|
|
return edvCube(lvids);
|
|
|
}
|
|
|
|
|
|
/// SV
|
|
|
- static double sv(double edv, double esv) {
|
|
|
+ @override
|
|
|
+ double sv(double edv, double esv) {
|
|
|
return edv - esv;
|
|
|
}
|
|
|
|
|
|
/// CO
|
|
|
- static double co(
|
|
|
+ @override
|
|
|
+ double co(
|
|
|
double sv, {
|
|
|
required int hr,
|
|
|
}) {
|
|
@@ -106,7 +177,8 @@ class CardiacFormulas {
|
|
|
}
|
|
|
|
|
|
/// CI
|
|
|
- static double ci(
|
|
|
+ @override
|
|
|
+ double ci(
|
|
|
double sv, {
|
|
|
required int hr,
|
|
|
required double bsa,
|
|
@@ -115,7 +187,8 @@ class CardiacFormulas {
|
|
|
}
|
|
|
|
|
|
/// LVdMass
|
|
|
- static double lvdMass(double ivsd, double lvidd, double lvpwd) {
|
|
|
+ @override
|
|
|
+ double lvdMass(double ivsd, double lvidd, double lvpwd) {
|
|
|
const density = GlobalCardiacConfigs.density;
|
|
|
const correctionFactor = GlobalCardiacConfigs.correctionFactor;
|
|
|
double part1 = math.pow(ivsd + lvidd + lvpwd, 3).toDouble();
|
|
@@ -125,7 +198,8 @@ class CardiacFormulas {
|
|
|
}
|
|
|
|
|
|
/// LVd Mass AL
|
|
|
- static double lvdMassAL(
|
|
|
+ @override
|
|
|
+ double lvdMassAL(
|
|
|
double lvadSaxEpi,
|
|
|
double lvadSaxEndo,
|
|
|
double lvldApical,
|
|
@@ -141,27 +215,32 @@ class CardiacFormulas {
|
|
|
}
|
|
|
|
|
|
/// LVd Mass Index
|
|
|
- static double lvdMassIndex(double lvdmass, double bsa) {
|
|
|
+ @override
|
|
|
+ double lvdMassIndex(double lvdmass, double bsa) {
|
|
|
return lvdmass / bsa * 1000;
|
|
|
}
|
|
|
|
|
|
/// %FS
|
|
|
- static double fsPercent(double lvidd, double lvids) {
|
|
|
+ @override
|
|
|
+ double fsPercent(double lvidd, double lvids) {
|
|
|
return ((lvidd - lvids) / lvidd) * 100;
|
|
|
}
|
|
|
|
|
|
/// %IVS
|
|
|
- static double ivsPercent(double ivss, double ivsd) {
|
|
|
+ @override
|
|
|
+ double ivsPercent(double ivss, double ivsd) {
|
|
|
return ((ivss - ivsd) / ivsd) * 100;
|
|
|
}
|
|
|
|
|
|
/// %LVPW
|
|
|
- static double lvpwPercent(double lvpws, double lvpwd) {
|
|
|
+ @override
|
|
|
+ double lvpwPercent(double lvpws, double lvpwd) {
|
|
|
return ((lvpws - lvpwd) / lvpwd) * 100;
|
|
|
}
|
|
|
|
|
|
/// MAM%
|
|
|
- static double mamPercent(double mapse, double lvidd, double lvids) {
|
|
|
+ @override
|
|
|
+ double mamPercent(double mapse, double lvidd, double lvids) {
|
|
|
return mapse / (lvidd - lvids + mapse) * 100;
|
|
|
}
|
|
|
|
|
@@ -174,7 +253,8 @@ class CardiacFormulas {
|
|
|
/// [bsa] m²
|
|
|
///
|
|
|
/// return `cm³/m²`
|
|
|
- static double si(double sv, double bsa) {
|
|
|
+ @override
|
|
|
+ double si(double sv, double bsa) {
|
|
|
double si = sv / bsa;
|
|
|
return si;
|
|
|
}
|
|
@@ -189,7 +269,8 @@ class CardiacFormulas {
|
|
|
/// <param name="otvti">cm</param>
|
|
|
/// <param name="vti">cm</param>
|
|
|
/// <returns>cm^2</returns>
|
|
|
- static double flowAreaByVTI(double otDiam, double otvti, double vti) {
|
|
|
+ @override
|
|
|
+ double flowAreaByVTI(double otDiam, double otvti, double vti) {
|
|
|
double sv = 0.25 * math.pi * math.pow(otDiam, 2) * otvti / vti;
|
|
|
return sv;
|
|
|
}
|
|
@@ -197,7 +278,8 @@ class CardiacFormulas {
|
|
|
/// <param name="otvti">cm</param>
|
|
|
/// <param name="vti">cm</param>
|
|
|
/// <returns>Unit None</returns>
|
|
|
- static double dviByVTI(double otvti, double vti) {
|
|
|
+ @override
|
|
|
+ double dviByVTI(double otvti, double vti) {
|
|
|
double dvi = double.nan;
|
|
|
if (!GeneralFormulas.doubleAlmostEquals(vti, 0)) {
|
|
|
dvi = otvti / vti;
|
|
@@ -211,7 +293,8 @@ class CardiacFormulas {
|
|
|
/// <param name="avaByVTI">cm2</param>
|
|
|
/// <param name="bsa">m2</param>
|
|
|
/// <returns>cm2/m2</returns>
|
|
|
- static double avaIndex(double avaByVTI, double bsa) {
|
|
|
+ @override
|
|
|
+ double avaIndex(double avaByVTI, double bsa) {
|
|
|
double index = double.nan;
|
|
|
if (!GeneralFormulas.doubleAlmostEquals(bsa, 0)) {
|
|
|
index = avaByVTI / bsa;
|
|
@@ -219,3 +302,39 @@ class CardiacFormulas {
|
|
|
return index;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+class MouseCardiacFormulas extends BaseCardiacFormulas {
|
|
|
+ MouseCardiacFormulas() : super();
|
|
|
+
|
|
|
+ @override
|
|
|
+ double teiIndex(double co, double et) {
|
|
|
+ double imp = 0.0;
|
|
|
+ if (et != 0.0) {
|
|
|
+ imp = (((co).abs() - (et).abs()) / et).abs();
|
|
|
+ }
|
|
|
+ return imp;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// SV
|
|
|
+ @override
|
|
|
+ double sv(double edv, double esv) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// EF
|
|
|
+ /// Formula: `(EDV - ESV )/EDV`
|
|
|
+ ///
|
|
|
+ /// [edv] Unit: `cm³`
|
|
|
+ ///
|
|
|
+ /// [esv] Unit: `cm³`
|
|
|
+ ///
|
|
|
+ /// Result Unit: `None`
|
|
|
+ @override
|
|
|
+ double ef(double edv, double esv) {
|
|
|
+ // 这行判断暂时注释掉是为了使实际表现与旧版一致
|
|
|
+ // if (edv < esv) {
|
|
|
+ // return double.nan;
|
|
|
+ // }
|
|
|
+ return 0.5;
|
|
|
+ }
|
|
|
+}
|