lv_study.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. import 'package:fis_measure/configs/cardiac.dart';
  2. import 'package:fis_measure/configs/patient.dart';
  3. import 'package:fis_measure/interfaces/enums/calcuator.dart';
  4. import 'package:fis_measure/interfaces/enums/species.dart';
  5. import 'package:fis_measure/interfaces/process/calculators/values.dart';
  6. import 'package:fis_measure/interfaces/process/items/terms.dart';
  7. import 'package:fis_measure/process/items/top_item.dart';
  8. import 'package:fis_measure/process/primitives/combos/lv_study.dart';
  9. import 'package:fis_measure/process/primitives/straightline.dart';
  10. import 'package:flutter/foundation.dart';
  11. import 'package:vid/us/vid_us_unit.dart';
  12. import 'calculator.dart';
  13. import 'formulas/cardiac.dart';
  14. class LvStudySimpleCal extends LvStudyCalculatorBase<LvStudy> {
  15. late final StraightLine kidLVIDd;
  16. late final StraightLine kidLVIDs;
  17. LvStudySimpleCal(super.ref) {
  18. kidLVIDd = ref.findChildByName("L1") as StraightLine;
  19. kidLVIDs = ref.findChildByName("L2") as StraightLine;
  20. }
  21. @override
  22. void calculate() {
  23. if (ref.feature == null) return;
  24. final feature = ref.feature!;
  25. restoreVals();
  26. v.lvidd = pickChildFloatValue(kidLVIDd);
  27. v.lvids = pickChildFloatValue(kidLVIDs);
  28. for (var output in ref.meta.outputs) {
  29. switch (output.name) {
  30. case MeasureTerms.LvStudySimple:
  31. feature.updateStringValue(output, "");
  32. break;
  33. case MeasureTerms.LVEDV:
  34. updateLVEDV();
  35. break;
  36. case MeasureTerms.LVESV:
  37. updateLVESV();
  38. break;
  39. case MeasureTerms.SV:
  40. updateSV();
  41. break;
  42. case MeasureTerms.EF:
  43. updateEF();
  44. break;
  45. case MeasureTerms.FS:
  46. updatePercentFS();
  47. break;
  48. }
  49. }
  50. }
  51. }
  52. class LvStudyDistanceGroupCal extends LvStudyCalculatorBase<LvStudy> {
  53. late final StraightLine kidIVSd;
  54. late final StraightLine kidLVIDd;
  55. late final StraightLine kidLVPWd;
  56. late final StraightLine kidIVSs;
  57. late final StraightLine kidLVIDs;
  58. late final StraightLine kidLVPWs;
  59. LvStudyDistanceGroupCal(super.ref) {
  60. kidIVSd = ref.findChildByName(MeasureTerms.IVSd) as StraightLine;
  61. kidLVIDd = ref.findChildByName(MeasureTerms.LVIDd) as StraightLine;
  62. kidLVPWd = ref.findChildByName(MeasureTerms.LVPWd) as StraightLine;
  63. kidIVSs = ref.findChildByName(MeasureTerms.IVSs) as StraightLine;
  64. kidLVIDs = ref.findChildByName(MeasureTerms.LVIDs) as StraightLine;
  65. kidLVPWs = ref.findChildByName(MeasureTerms.LVPWs) as StraightLine;
  66. }
  67. @override
  68. void calculate() {
  69. if (ref.feature == null) return;
  70. final feature = ref.feature!;
  71. final viewport = feature.hostVisualArea!.viewport!;
  72. VidUsUnit yUnit = viewport.yUnit;
  73. v = _ValTemp();
  74. FloatValue? ivsd = pickChildToFloatValue(kidIVSd);
  75. FloatValue? lvidd = pickChildToFloatValue(kidLVIDd);
  76. FloatValue? lvpwd = pickChildToFloatValue(kidLVPWd);
  77. FloatValue? ivss = pickChildToFloatValue(kidIVSs);
  78. FloatValue? lvids = pickChildToFloatValue(kidLVIDs);
  79. FloatValue? lvpws = pickChildToFloatValue(kidLVPWs);
  80. v.ivsd = updateCalculateValue(ivsd, yUnit);
  81. v.ivss = updateCalculateValue(ivss, yUnit);
  82. v.lvidd = updateCalculateValue(lvidd, yUnit);
  83. v.lvids = updateCalculateValue(lvids, yUnit);
  84. v.lvpwd = updateCalculateValue(lvpwd, yUnit);
  85. v.lvpws = updateCalculateValue(lvpws, yUnit);
  86. for (var output in ref.meta.outputs) {
  87. switch (output.name) {
  88. case MeasureTerms.LvStudy:
  89. feature.updateStringValue(output, "");
  90. break;
  91. case MeasureTerms.LVEDV:
  92. updateLVEDV();
  93. break;
  94. case MeasureTerms.LVESV:
  95. updateLVESV();
  96. break;
  97. case MeasureTerms.LVdMass:
  98. updateLVdMass();
  99. break;
  100. case MeasureTerms.PercentIVS:
  101. updatePercentIVS();
  102. break;
  103. case MeasureTerms.SV:
  104. updateSV();
  105. break;
  106. case MeasureTerms.EF:
  107. updateEF();
  108. break;
  109. case MeasureTerms.FS:
  110. updatePercentFS();
  111. break;
  112. case MeasureTerms.PercentLVPW:
  113. updatePercentLVPW();
  114. break;
  115. case MeasureTerms.CO:
  116. updateCO();
  117. break;
  118. case MeasureTerms.CI:
  119. updateCI();
  120. break;
  121. case MeasureTerms.SI:
  122. updateSI();
  123. break;
  124. }
  125. }
  126. }
  127. double? updateCalculateValue(FloatValue? floatValue, VidUsUnit unit) {
  128. if (floatValue != null) {
  129. if (floatValue.unit == unit) {
  130. return floatValue.value;
  131. } else {
  132. if (floatValue.unit == VidUsUnit.mm &&
  133. floatValue.unit == VidUsUnit.cm) {
  134. return floatValue.value == null ? null : floatValue.value! * 10;
  135. } else if (floatValue.unit == VidUsUnit.cm &&
  136. floatValue.unit == VidUsUnit.mm) {
  137. return floatValue.value == null ? null : floatValue.value! / 10;
  138. }
  139. }
  140. }
  141. return null;
  142. }
  143. }
  144. class LvStudyCalculatorBase<T extends TopMeasureItem>
  145. extends Calculator<T, double> {
  146. LvStudyCalculatorBase(super.ref);
  147. @protected
  148. late _ValTemp v;
  149. @override
  150. void calculate() {
  151. // TODO: implement calculate
  152. }
  153. void restoreVals() {
  154. v = _ValTemp();
  155. }
  156. @protected
  157. void updateLVEDV() {
  158. if (v.lvidd == null) {
  159. return;
  160. }
  161. final lvidd = v.lvidd!;
  162. double value = 0;
  163. if (GlobalCardiacConfigs.EDVFormulaMode ==
  164. CardiacEDVFormulaMode.teichholz) {
  165. value = CardiacFormulas.edvTeichholz(lvidd);
  166. } else if (GlobalCardiacConfigs.EDVFormulaMode ==
  167. CardiacEDVFormulaMode.cube) {
  168. value = CardiacFormulas.edvCube(lvidd);
  169. }
  170. updateFloatValueByName(MeasureTerms.LVEDV, value, unit: VidUsUnit.ml);
  171. v.lvedv = value;
  172. }
  173. @protected
  174. void updateLVESV() {
  175. if (v.lvids == null) {
  176. return;
  177. }
  178. final lvids = v.lvids!;
  179. double value = 0;
  180. if (GlobalCardiacConfigs.EDVFormulaMode ==
  181. CardiacEDVFormulaMode.teichholz) {
  182. value = CardiacFormulas.esvTeichholz(lvids);
  183. } else if (GlobalCardiacConfigs.EDVFormulaMode ==
  184. CardiacEDVFormulaMode.cube) {
  185. value = CardiacFormulas.esvCube(lvids);
  186. }
  187. updateFloatValueByName(MeasureTerms.LVESV, value, unit: VidUsUnit.ml);
  188. v.lvesv = value;
  189. }
  190. @protected
  191. void updateLVdMass() {
  192. if (v.ivsd == null || v.lvidd == null || v.lvpwd == null) {
  193. return;
  194. }
  195. double value = CardiacFormulas.lvdMass(v.ivsd!, v.lvidd!, v.lvpwd!);
  196. updateFloatValueByName(MeasureTerms.LVdMass, value, unit: VidUsUnit.g);
  197. }
  198. @protected
  199. void updatePercentIVS() {
  200. if (v.ivsd == null || v.ivss == null) {
  201. return;
  202. }
  203. double value = CardiacFormulas.ivsPercent(v.ivss!, v.ivsd!);
  204. updateFloatValueByName(MeasureTerms.PercentIVS, value);
  205. }
  206. @protected
  207. void updateSV() {
  208. if (v.lvedv == null || v.lvesv == null) {
  209. return;
  210. }
  211. final edv = v.lvedv!;
  212. final esv = v.lvesv!;
  213. double value = CardiacFormulas.sv(edv, esv);
  214. updateFloatValueByName(MeasureTerms.SV, value, unit: VidUsUnit.ml);
  215. v.sv = value;
  216. }
  217. @protected
  218. void updateEF() {
  219. if (v.lvedv == null || v.lvesv == null) {
  220. return;
  221. }
  222. final edv = v.lvedv!;
  223. final esv = v.lvesv!;
  224. double value = CardiacFormulas.ef(edv, esv);
  225. updateFloatValueByName(MeasureTerms.EF, value, unit: VidUsUnit.percent);
  226. }
  227. @protected
  228. void updatePercentFS() {
  229. if (v.lvidd == null || v.lvids == null) {
  230. return;
  231. }
  232. final lvidd = v.lvidd!;
  233. final lvids = v.lvids!;
  234. double value = CardiacFormulas.fsPercent(lvidd, lvids);
  235. updateFloatValueByName(MeasureTerms.FS, value);
  236. }
  237. @protected
  238. void updatePercentLVPW() {
  239. if (v.lvpws == null || v.lvpwd == null) {
  240. return;
  241. }
  242. final lvpws = v.lvpws!;
  243. final lvpwd = v.lvpwd!;
  244. double value = CardiacFormulas.lvpwPercent(lvpws, lvpwd);
  245. updateFloatValueByName(MeasureTerms.PercentLVPW, value);
  246. }
  247. @protected
  248. void updateCO() {
  249. if (v.sv == null || v.hr == null) {
  250. return;
  251. }
  252. double value = CardiacFormulas.co(v.sv!, hr: v.hr!);
  253. updateFloatValueByName(MeasureTerms.CO, value, unit: VidUsUnit.Lmin);
  254. }
  255. @protected
  256. void updateCI() {
  257. if (v.sv == null || v.hr == null) {
  258. return;
  259. }
  260. if (GlobalPatientConfig.bsa == 0) {
  261. return;
  262. }
  263. double value = CardiacFormulas.ci(
  264. v.sv!,
  265. hr: v.hr!,
  266. bsa: GlobalPatientConfig.bsa,
  267. );
  268. updateFloatValueByName(MeasureTerms.CI, value, unit: VidUsUnit.Lminm2);
  269. }
  270. @protected
  271. void updateLVEDVI() {
  272. if (v.lvedv == null) {
  273. return;
  274. }
  275. if (GlobalPatientConfig.bsa == 0) {
  276. return;
  277. }
  278. final value = CardiacFormulas.lvevi(v.lvedv!, GlobalPatientConfig.bsa);
  279. updateFloatValueByName(MeasureTerms.LVEDVI, value, unit: VidUsUnit.mlm2);
  280. }
  281. @protected
  282. void updateLVESVI() {
  283. if (v.lvesv == null) {
  284. return;
  285. }
  286. if (GlobalPatientConfig.bsa == 0) {
  287. return;
  288. }
  289. final value = CardiacFormulas.lvevi(v.lvesv!, GlobalPatientConfig.bsa);
  290. updateFloatValueByName(MeasureTerms.LVESVI, value, unit: VidUsUnit.mlm2);
  291. }
  292. @protected
  293. void updateSI() {
  294. if (v.sv == null) {
  295. return;
  296. }
  297. if (GlobalPatientConfig.bsa == 0) {
  298. return;
  299. }
  300. double value = CardiacFormulas.si(v.sv!, GlobalPatientConfig.bsa);
  301. updateFloatValueByName(MeasureTerms.SI, value, unit: VidUsUnit.mlm2);
  302. }
  303. @protected
  304. void updateFloatValueByName(
  305. String name,
  306. double value, {
  307. VidUsUnit? unit,
  308. }) {
  309. ref.measuredFeatures;
  310. final feature = ref.feature!;
  311. final outputMeta = ref.meta.outputs.firstWhere((x) => x.name == name);
  312. outputMeta.unit = updateUnitBySpeciesType(unit ?? outputMeta.unit, name);
  313. feature.updateFloatValue(outputMeta, value, outputMeta.unit);
  314. }
  315. VidUsUnit updateUnitBySpeciesType(VidUsUnit unit, String name) {
  316. if (GlobalPatientConfig.speciesType != SpeciesType.mouse) {
  317. return unit;
  318. }
  319. switch (name) {
  320. case MeasureTerms.LVEDV:
  321. return VidUsUnit.mil;
  322. case MeasureTerms.LVESV:
  323. return VidUsUnit.mil;
  324. case MeasureTerms.LVEDVI:
  325. return VidUsUnit.mil;
  326. case MeasureTerms.LVESVI:
  327. return VidUsUnit.mil;
  328. case MeasureTerms.SI:
  329. return VidUsUnit.mlm2;
  330. case MeasureTerms.CO:
  331. return VidUsUnit.mlmin;
  332. case MeasureTerms.CI:
  333. return VidUsUnit.mlmincm2;
  334. case MeasureTerms.LVdMass:
  335. return VidUsUnit.mg;
  336. case MeasureTerms.FS:
  337. return VidUsUnit.percent;
  338. case MeasureTerms.EF:
  339. return VidUsUnit.percent;
  340. case MeasureTerms.PercentLVPW:
  341. return VidUsUnit.percent;
  342. case MeasureTerms.SV:
  343. return VidUsUnit.mil;
  344. case MeasureTerms.SV_Card:
  345. return VidUsUnit.mlmin;
  346. case MeasureTerms.SV_Diam:
  347. return VidUsUnit.cm;
  348. case MeasureTerms.SV_Trace:
  349. return VidUsUnit.cm;
  350. case MeasureTerms.IVSd:
  351. return VidUsUnit.mm;
  352. case MeasureTerms.LVIDd:
  353. return VidUsUnit.mm;
  354. case MeasureTerms.LVPWd:
  355. return VidUsUnit.mm;
  356. case MeasureTerms.IVSs:
  357. return VidUsUnit.mg;
  358. case MeasureTerms.LVIDs:
  359. return VidUsUnit.mm;
  360. case MeasureTerms.LVPWs:
  361. return VidUsUnit.mm;
  362. case MeasureTerms.CO_2D:
  363. return VidUsUnit.mlmin;
  364. case MeasureTerms.CO_M: // 脉动心输出量
  365. return VidUsUnit.mlmin;
  366. case MeasureTerms.CO_P: // 脉动心输出量
  367. return VidUsUnit.mlmin;
  368. default:
  369. return unit;
  370. }
  371. }
  372. }
  373. class _ValTemp {
  374. double? ivsd;
  375. double? lvidd;
  376. double? lvpwd;
  377. double? ivss;
  378. double? lvids;
  379. double? lvpws;
  380. double? lvedv;
  381. double? lvesv;
  382. double? sv;
  383. int? hr = GlobalPatientConfig.hr; // TODO: from vid ext
  384. }