simpson.dart 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. // ignore_for_file: non_constant_identifier_names
  2. import 'package:fis_measure/configs/patient.dart';
  3. import 'package:fis_measure/interfaces/process/calculators/values.dart';
  4. import 'package:fis_measure/interfaces/process/items/item_metas.dart';
  5. import 'package:fis_measure/interfaces/process/items/terms.dart';
  6. import 'package:fis_measure/process/calcuators/unit_formulas/base/utils.dart';
  7. import 'package:fis_measure/process/calcuators/unit_formulas/index.dart';
  8. import 'package:fis_measure/process/items/item_feature.dart';
  9. import 'package:fis_measure/process/items/top_item.dart';
  10. import 'package:fis_measure/process/primitives/combos/simpson.dart';
  11. import 'package:fis_measure/process/primitives/multi_method/multi_simpson_path.dart';
  12. import 'package:fis_measure/process/primitives/simpson_path.dart';
  13. import 'package:vid/us/vid_us_unit.dart';
  14. import 'calculator.dart';
  15. import 'formulas/cardiac.dart';
  16. import 'lv_study.dart';
  17. import 'dart:math' as math;
  18. class LvSimpsonCal extends LvStudyCalculatorBase<LvStudySimpson> {
  19. LvSimpsonCal(super.ref) {
  20. //
  21. }
  22. @override
  23. void calculate() {
  24. if (ref.feature == null) return;
  25. final feature = ref.feature!;
  26. restoreVals();
  27. feature.updateStringValue(
  28. ItemOutputMeta(
  29. ref.meta.description, ref.meta.description, VidUsUnit.None),
  30. "",
  31. );
  32. for (var childItem in ref.childItems) {
  33. _clacChildItem(childItem as MultiSimpsonPath);
  34. }
  35. for (var output in ref.meta.outputs) {
  36. switch (output.name) {
  37. case MeasureTerms.LVEDV:
  38. updateLVEDV();
  39. break;
  40. case MeasureTerms.LVESV:
  41. updateLVESV();
  42. break;
  43. case MeasureTerms.SV:
  44. updateSV();
  45. break;
  46. case MeasureTerms.EF:
  47. updateEF();
  48. break;
  49. case MeasureTerms.FS:
  50. updatePercentFS();
  51. break;
  52. case MeasureTerms.SI:
  53. updateSI();
  54. break;
  55. case MeasureTerms.LVEDVI:
  56. updateLVEDVI();
  57. break;
  58. case MeasureTerms.LVESVI:
  59. updateLVESVI();
  60. break;
  61. }
  62. }
  63. // _updateA2cGroup();
  64. // _updateA4cGroup();
  65. }
  66. @override
  67. void updateLVEDV() {
  68. final value = _clacLvedvNew(ref.a2cLvedv, ref.a4cLvedv);
  69. if (value != null) {
  70. updateFloatValueByName(MeasureTerms.LVEDV, value, unit: VidUsUnit.cm3);
  71. v.lvedv = value;
  72. }
  73. }
  74. @override
  75. void updateLVESV() {
  76. final value = _clacLvedvNew(ref.a2cLvesv, ref.a4cLvesv);
  77. if (value != null) {
  78. updateFloatValueByName(MeasureTerms.LVESV, value, unit: VidUsUnit.cm3);
  79. v.lvesv = value;
  80. }
  81. }
  82. double? _clacLvedv(MultiSimpsonPath path1, MultiSimpsonPath path2) {
  83. final feature1 = findChildFeature(path1);
  84. final feature2 = findChildFeature(path2);
  85. if (feature1 == null || feature2 == null) {
  86. return null;
  87. }
  88. feature1 as SimpsonPathFeature;
  89. feature2 as SimpsonPathFeature;
  90. final distance1 = feature1.centerLineLength;
  91. final distance2 = feature2.centerLineLength;
  92. int index = 0;
  93. List<double> aDiameters =
  94. List.generate(SimpsonPath.splitterCount, (index) => 0);
  95. index = 0;
  96. feature1.horizontalSplitterLegths.forEach((key, value) {
  97. aDiameters[index++] = value;
  98. });
  99. List<double> bDiameters =
  100. List.generate(SimpsonPath.splitterCount, (index) => 0);
  101. index = 0;
  102. feature2.horizontalSplitterLegths.forEach((key, value) {
  103. bDiameters[index++] = value;
  104. });
  105. final longDiameter = (distance1 + distance2) / 2.0;
  106. final lvesv = CardiacFormulas.lvSimsonVolume(
  107. longDiameter,
  108. aDiameters,
  109. bDiameters,
  110. SimpsonPath.splitterCount,
  111. );
  112. return lvesv;
  113. }
  114. double? _clacLvedvNew(MultiSimpsonPath path1, MultiSimpsonPath path2) {
  115. final feature1 = findChildFeature(path1);
  116. final feature2 = findChildFeature(path2);
  117. if (feature1 == null || feature2 == null) {
  118. return null;
  119. }
  120. feature1 as SimpsonPathFeature;
  121. feature2 as SimpsonPathFeature;
  122. final distance1 = feature1.centerLineLength;
  123. final distance2 = feature2.centerLineLength;
  124. int index = 0;
  125. List<double> aDiameters =
  126. List.generate(SimpsonPath.splitterCount, (index) => 0);
  127. index = 0;
  128. feature1.horizontalSplitterLegths.forEach((key, value) {
  129. aDiameters[index++] = value;
  130. });
  131. List<double> bDiameters =
  132. List.generate(SimpsonPath.splitterCount, (index) => 0);
  133. index = 0;
  134. feature2.horizontalSplitterLegths.forEach((key, value) {
  135. bDiameters[index++] = value;
  136. });
  137. double sum = 0;
  138. for (var i = 0; i < SimpsonPath.splitterCount; i++) {
  139. sum += aDiameters[i] * bDiameters[i];
  140. }
  141. final maxL = math.max(distance1, distance2);
  142. final value = maxL * 3.1415926 / (4 * 20) * sum;
  143. return value;
  144. }
  145. void _clacChildItem(MultiSimpsonPath childItem) {
  146. final feature = findChildFeature(childItem);
  147. if (feature == null) {
  148. return;
  149. }
  150. feature as SimpsonPathFeature;
  151. // final outputs = childItem.meta.outputs;
  152. // TODO:
  153. final itemName = childItem.meta.description.split(' ').first;
  154. final outputs = [
  155. ItemOutputMeta("Area", "$itemName LVAs", VidUsUnit.mm2),
  156. ItemOutputMeta("L", "$itemName LVLs", VidUsUnit.mm),
  157. ];
  158. for (var output in outputs) {
  159. switch (output.name) {
  160. case "Area":
  161. feature.updateFloatValue(output, feature.area, VidUsUnit.cm2);
  162. break;
  163. case "L":
  164. feature.updateFloatValue(
  165. output, feature.centerLineLength, VidUsUnit.cm);
  166. break;
  167. default:
  168. }
  169. }
  170. }
  171. void _updateA2cGroup() {
  172. _updateLVEDV_A2C();
  173. _updateLVESV_A2C();
  174. }
  175. void _updateA4cGroup() {
  176. _updateLVEDV_A2C();
  177. _updateLVESV_A2C();
  178. }
  179. void _updateLVEDV_A2C() {
  180. final feature = findChildFeature(ref.a2cLvedv);
  181. if (feature == null) {
  182. return;
  183. }
  184. feature as SimpsonPathFeature;
  185. final value = _SimpsonFormulas.lvedv(
  186. feature.area,
  187. feature.centerLineLength,
  188. );
  189. ref.feature!.updateFloatValue(
  190. ItemOutputMeta("LVEDV(A2C Simp)", "LVEDV(A2C Simp)", VidUsUnit.ml),
  191. value,
  192. VidUsUnit.ml,
  193. );
  194. }
  195. void _updateLVESV_A2C() {
  196. final feature = findChildFeature(ref.a2cLvesv);
  197. if (feature == null) {
  198. return;
  199. }
  200. feature as SimpsonPathFeature;
  201. final value = _SimpsonFormulas.lvedv(
  202. feature.area,
  203. feature.centerLineLength,
  204. );
  205. ref.feature!.updateFloatValue(
  206. ItemOutputMeta("LVESV(A2C Simp)", "LVESV(A2C Simp)", VidUsUnit.ml),
  207. value,
  208. VidUsUnit.ml,
  209. );
  210. }
  211. void _updateLVEDV_A4C() {}
  212. void _updateLVESV_A4C() {}
  213. }
  214. class LvSingleSimpsonCal extends LvStudyCalculatorBase<LvStudySingleSimpson> {
  215. LvSingleSimpsonCal(super.ref) {
  216. //
  217. }
  218. @override
  219. void calculate() {
  220. if (ref.feature == null) return;
  221. final feature = ref.feature!;
  222. restoreVals();
  223. feature.updateStringValue(
  224. ItemOutputMeta(
  225. ref.meta.description, ref.meta.description, VidUsUnit.None),
  226. "",
  227. );
  228. _clacChildItem(ref.lvedv);
  229. for (var output in ref.meta.outputs) {
  230. switch (output.name) {
  231. case MeasureTerms.LVEDV:
  232. updateLVEDV();
  233. break;
  234. case MeasureTerms.LVESV:
  235. updateLVESV();
  236. break;
  237. case MeasureTerms.SV:
  238. updateSV();
  239. break;
  240. case MeasureTerms.EF:
  241. updateEF();
  242. break;
  243. case MeasureTerms.SI:
  244. updateSI();
  245. break;
  246. case MeasureTerms.LVEDVI:
  247. updateLVEDVI();
  248. break;
  249. case MeasureTerms.LVESVI:
  250. updateLVESVI();
  251. break;
  252. }
  253. }
  254. /**
  255. *
  256. <OutPut Id="LVEDV" IsEnabled="False" CalculationIDs="LVEDV(BP Simp)"/>
  257. <OutPut Id="LVESV" IsEnabled="False" CalculationIDs="LVESV(BP Simp)"/>
  258. <OutPut Id="SV" IsEnabled="False" CalculationIDs="SV(Mod Simp)"/>
  259. <OutPut Id="EF" IsEnabled="False" CalculationIDs="EF(Mod Simp)"/>
  260. <OutPut Id="SI" IsEnabled="False" CalculationIDs="SI(Mod Simp)"/>
  261. <OutPut Id="LVEDVI" IsEnabled="False" CalculationIDs="LVEDVI(Mod Simp)"/>
  262. <OutPut Id="LVESVI" IsEnabled="False" CalculationIDs="LVESVI(Mod Simp)"/>
  263. <OutPut Id="CO" IsEnabled="False" CalculationIDs="CO(Mod Simp)"/>
  264. <OutPut Id="CI" IsEnabled="False" CalculationIDs="CI(Mod Simp)"/>
  265. */
  266. }
  267. @override
  268. void updateLVEDV() {
  269. final value = _calcLvedvNew(ref.lvedv);
  270. if (value != null) {
  271. updateFloatValueByName(MeasureTerms.LVEDV, value, unit: VidUsUnit.cm3);
  272. v.lvedv = value;
  273. }
  274. }
  275. @override
  276. void updateLVESV() {
  277. final value = _calcLvedvNew(ref.lvesv);
  278. if (value != null) {
  279. updateFloatValueByName(MeasureTerms.LVESV, value, unit: VidUsUnit.cm3);
  280. v.lvesv = value;
  281. }
  282. }
  283. double? _calcLvedv(MultiSimpsonPath item) {
  284. if (item.feature == null) {
  285. return null;
  286. }
  287. final feature = item.feature!;
  288. double longDiameter = roundDouble(feature.centerLineLength);
  289. int index = 0;
  290. List<double> bDiameters =
  291. List.generate(SimpsonPath.splitterCount, (index) => 0);
  292. feature.horizontalSplitterLegths.forEach((key, value) {
  293. bDiameters[index++] = value;
  294. });
  295. return CardiacFormulas.lvSimsonVolume(
  296. longDiameter,
  297. bDiameters,
  298. bDiameters,
  299. SimpsonPath.splitterCount,
  300. );
  301. }
  302. double? _calcLvedvNew(MultiSimpsonPath item) {
  303. final feature = findChildFeature(item);
  304. if (feature == null) {
  305. return null;
  306. }
  307. feature as SimpsonPathFeature;
  308. double longDiameter = roundDouble(feature.centerLineLength);
  309. int index = 0;
  310. List<double> bDiameters =
  311. List.generate(SimpsonPath.splitterCount, (index) => 0);
  312. feature.horizontalSplitterLegths.forEach((key, value) {
  313. bDiameters[index++] = value;
  314. });
  315. double sum = 0;
  316. for (var i = 0; i < SimpsonPath.splitterCount; i++) {
  317. sum += math.pow(bDiameters[i], 2).toDouble();
  318. }
  319. var value = longDiameter * 3.1415926 / (4 * 20) * sum;
  320. return value;
  321. return CardiacFormulas.lvSimsonVolume(
  322. longDiameter,
  323. bDiameters,
  324. bDiameters,
  325. SimpsonPath.splitterCount,
  326. );
  327. }
  328. void _clacChildItem(MultiSimpsonPath childItem) {
  329. final feature = findChildFeature(childItem);
  330. if (feature == null) {
  331. return;
  332. }
  333. feature as SimpsonPathFeature;
  334. // final outputs = childItem.meta.outputs;
  335. // TODO:
  336. final itemName = childItem.meta.description.split(' ').first;
  337. final outputs = [
  338. ItemOutputMeta("Area", "$itemName LVAs", VidUsUnit.mm2),
  339. ItemOutputMeta("L", "$itemName LVLs", VidUsUnit.mm),
  340. ];
  341. for (var output in outputs) {
  342. switch (output.name) {
  343. case "Area":
  344. feature.updateFloatValue(output, feature.area, VidUsUnit.cm2);
  345. break;
  346. case "L":
  347. feature.updateFloatValue(
  348. output, feature.centerLineLength, VidUsUnit.cm);
  349. break;
  350. default:
  351. }
  352. }
  353. }
  354. }
  355. abstract class _SimpsonFormulas {
  356. static double lvedv(double area, double distance) {
  357. final value = 0.85 * math.pow(area, 2) / distance;
  358. return value;
  359. }
  360. }
  361. class LvSimpsonCalNew extends LvSimpsonCalBase<LvStudySimpson> {
  362. LvSimpsonCalNew(super.ref) {
  363. //
  364. }
  365. @override
  366. void calculate() {
  367. super.calculate();
  368. if (ref.feature == null) return;
  369. final feature = ref.feature!;
  370. feature.updateStringValue(
  371. ItemOutputMeta(
  372. ref.meta.description, ref.meta.description, VidUsUnit.None),
  373. "",
  374. );
  375. for (var childItem in ref.childItems) {
  376. clacChildItem(childItem as MultiSimpsonPath);
  377. }
  378. calcCouple();
  379. calcA2c(ref.a2cLvedv, ref.a2cLvesv);
  380. calcA2c(ref.a4cLvedv, ref.a4cLvesv);
  381. doOutput();
  382. }
  383. void calcCouple() {
  384. final featureA2cD = findChildFeature(ref.a2cLvedv);
  385. final featureA2cS = findChildFeature(ref.a2cLvesv);
  386. final featureA4cD = findChildFeature(ref.a4cLvedv);
  387. final featureA4cS = findChildFeature(ref.a4cLvesv);
  388. UnitFloatValue? edv;
  389. UnitFloatValue? esv;
  390. if (featureA2cD != null && featureA4cD != null) {
  391. edv = coupleLVEDV(
  392. featureA4cD as SimpsonPathFeature,
  393. featureA2cD as SimpsonPathFeature,
  394. );
  395. }
  396. if (featureA2cS != null && featureA4cS != null) {
  397. esv = coupleLVEDV(
  398. featureA4cS as SimpsonPathFeature,
  399. featureA2cS as SimpsonPathFeature,
  400. );
  401. }
  402. v.coupleEDV = edv;
  403. v.coupleESV = esv;
  404. if (edv != null && esv != null) {
  405. v.coupleSV = calcSv(edv, esv);
  406. v.coupleEF = calcEf(edv, esv);
  407. v.coupleCO = calcCo(edv, esv);
  408. }
  409. }
  410. }
  411. class LvSingleSimpsonCalNew extends LvSimpsonCalBase<LvStudySingleSimpson> {
  412. LvSingleSimpsonCalNew(super.ref) {
  413. //
  414. }
  415. @override
  416. void calculate() {
  417. super.calculate();
  418. if (ref.feature == null) return;
  419. final feature = ref.feature!;
  420. feature.updateStringValue(
  421. ItemOutputMeta(
  422. ref.meta.description, ref.meta.description, VidUsUnit.None),
  423. "",
  424. );
  425. for (var childItem in ref.childItems) {
  426. clacChildItem(childItem as MultiSimpsonPath);
  427. }
  428. if (ref.meta.description.toLowerCase().contains("a2c")) {
  429. calcA2c(ref.lvedv, ref.lvesv);
  430. }
  431. if (ref.meta.description.toLowerCase().contains("a4c")) {
  432. calcA4c(ref.lvedv, ref.lvesv);
  433. }
  434. doOutput();
  435. }
  436. }
  437. abstract class LvSimpsonCalBase<T extends TopMeasureItem>
  438. extends Calculator<T, double> {
  439. LvSimpsonCalBase(super.ref);
  440. _SimpsonValues v = _SimpsonValues();
  441. @override
  442. void calculate() {
  443. v = _SimpsonValues();
  444. }
  445. void doOutput() {
  446. final feature = ref.feature!;
  447. for (var output in ref.meta.outputs) {
  448. switch (output.name) {
  449. // Couple
  450. case MeasureTerms.LVEDV:
  451. _outputVal(feature, output, v.coupleEDV);
  452. break;
  453. case MeasureTerms.LVESV:
  454. _outputVal(feature, output, v.coupleESV);
  455. break;
  456. case MeasureTerms.SV:
  457. _outputVal(feature, output, v.coupleSV);
  458. break;
  459. case MeasureTerms.EF:
  460. _outputVal(feature, output, v.coupleEF);
  461. break;
  462. case MeasureTerms.CO:
  463. _outputVal(feature, output, v.coupleCO);
  464. break;
  465. // A2C
  466. case "A2C LVEDV":
  467. _outputVal(feature, output, v.a2cEDV);
  468. break;
  469. case "A2C LVESV":
  470. _outputVal(feature, output, v.a2cESV);
  471. break;
  472. case "A2C SV":
  473. _outputVal(feature, output, v.a2cSV);
  474. break;
  475. case "A2C EF":
  476. _outputVal(feature, output, v.a2cEF);
  477. break;
  478. case "A2C CO":
  479. _outputVal(feature, output, v.a2cCO);
  480. break;
  481. // A4C
  482. case "A4C LVEDV":
  483. _outputVal(feature, output, v.a4cEDV);
  484. break;
  485. case "A4C LVESV":
  486. _outputVal(feature, output, v.a4cESV);
  487. break;
  488. case "A4C SV":
  489. _outputVal(feature, output, v.a4cSV);
  490. break;
  491. case "A4C EF":
  492. _outputVal(feature, output, v.a4cEF);
  493. break;
  494. case "A4C CO":
  495. _outputVal(feature, output, v.a4cCO);
  496. break;
  497. default:
  498. }
  499. }
  500. }
  501. void _outputVal(
  502. MeasureItemFeature feature,
  503. ItemOutputMeta output,
  504. UnitFloatValue? val,
  505. ) {
  506. if (val != null) {
  507. feature.updateFloatValue(output, val.value, val.unit);
  508. }
  509. }
  510. void calcA2c(MultiSimpsonPath itemD, MultiSimpsonPath itemS) {
  511. final featureD = findChildFeature(itemD);
  512. final featureS = findChildFeature(itemS);
  513. UnitFloatValue? edv;
  514. UnitFloatValue? esv;
  515. if (featureD != null) {
  516. edv = singleLVEDV(featureD as SimpsonPathFeature);
  517. }
  518. if (featureS != null) {
  519. esv = singleLVEDV(featureS as SimpsonPathFeature);
  520. }
  521. v.a2cEDV = edv;
  522. v.a2cESV = esv;
  523. if (edv != null && esv != null) {
  524. v.a2cSV = calcSv(edv, esv);
  525. v.a2cEF = calcEf(edv, esv);
  526. v.a2cCO = calcCo(edv, esv);
  527. }
  528. }
  529. void calcA4c(MultiSimpsonPath itemD, MultiSimpsonPath itemS) {
  530. final featureD = findChildFeature(itemD);
  531. final featureS = findChildFeature(itemS);
  532. UnitFloatValue? edv;
  533. UnitFloatValue? esv;
  534. if (featureD != null) {
  535. edv = singleLVEDV(featureD as SimpsonPathFeature);
  536. }
  537. if (featureS != null) {
  538. esv = singleLVEDV(featureS as SimpsonPathFeature);
  539. }
  540. v.a4cEDV = edv;
  541. v.a4cESV = esv;
  542. if (edv != null && esv != null) {
  543. v.a4cSV = calcSv(edv, esv);
  544. v.a4cEF = calcEf(edv, esv);
  545. v.a4cCO = calcCo(edv, esv);
  546. }
  547. }
  548. UnitFloatValue? coupleLVEDV(
  549. SimpsonPathFeature featureA,
  550. SimpsonPathFeature featureB,
  551. ) {
  552. // max([A4C LVEDV Simpson|L"cm;2D"],[A2C LVEDV Simpson|L"cm;2D"]) *3.1415926/(4*20) * Sum(2D1*4D1 + 2D2*4D2 + ... + 2D20*4D20)
  553. double lA = roundDouble(featureA.centerLineLength);
  554. double lB = roundDouble(featureB.centerLineLength);
  555. double lMax = math.max(lA, lB);
  556. final splitterALengths = featureA.horizontalSplitterLegths.values.toList();
  557. final splitterBLengths = featureB.horizontalSplitterLegths.values.toList();
  558. if (splitterALengths.length < SimpsonPath.splitterCount ||
  559. splitterBLengths.length < SimpsonPath.splitterCount) {
  560. return null;
  561. }
  562. double sum = 0;
  563. for (var i = 0; i < SimpsonPath.splitterCount; i++) {
  564. final dA = roundDouble(splitterALengths[i]);
  565. final dB = roundDouble(splitterBLengths[i]);
  566. sum += dA * dB;
  567. }
  568. var value = lMax * 3.1415926 / (4 * 20) * sum;
  569. value = value * 4;
  570. return UnitFloatValue(value, VidUsUnit.ml);
  571. }
  572. UnitFloatValue? singleLVEDV(SimpsonPathFeature feature) {
  573. // [A2C LVEDV Simpson|L"cm;2D"]*3.1415926/(4*20)* Sum(pow(D1,2),pow(D2,2),...,pow(D20,2))
  574. double l = roundDouble(feature.centerLineLength);
  575. final splitterLengths = feature.horizontalSplitterLegths.values.toList();
  576. if (splitterLengths.length < SimpsonPath.splitterCount) {
  577. return null;
  578. }
  579. double sum = 0;
  580. for (var i = 0; i < SimpsonPath.splitterCount; i++) {
  581. final d = math.pow(splitterLengths[i], 2).toDouble();
  582. sum += roundDouble(d);
  583. }
  584. var value = l * 3.1415926 / (4 * 20) * sum;
  585. return UnitFloatValue(value, VidUsUnit.ml);
  586. }
  587. UnitFloatValue calcSv(UnitFloatValue lvedv, UnitFloatValue lvesv) {
  588. // [LVEDV(A2C Simp)"ml;"]-[LVESV(A2C Simp)"ml;"]
  589. final value = lvedv.convert(VidUsUnit.ml) - lvesv.convert(VidUsUnit.ml);
  590. return UnitFloatValue(value, VidUsUnit.ml);
  591. }
  592. UnitFloatValue calcEf(UnitFloatValue lvedv, UnitFloatValue lvesv) {
  593. // ([LVEDV(A2C Simp)"ml;"]-[LVESV(A2C Simp)"ml;"])/[LVEDV(A2C Simp)"ml;"]*100
  594. final value = UnitFormulas.cardiac.ef(lvedv, lvesv);
  595. return value;
  596. }
  597. UnitFloatValue? calcCo(UnitFloatValue lvedv, UnitFloatValue lvesv) {
  598. // ([LVEDV(A2C Simp)"ml;"]-[LVESV(A2C Simp)"ml;"])*{[HR|HR"HR;M"]}/1000
  599. // ([LVEDV(A2C Simp)"ml;"]-[LVESV(A2C Simp)"ml;"])*{[HR|HR"HR;M"],[HR"HR;PatientInfo"]}/1000
  600. final hr = GlobalPatientConfig.hr;
  601. if (hr == null) {
  602. return null;
  603. }
  604. final edv = lvedv.convert(VidUsUnit.ml);
  605. final esv = lvesv.convert(VidUsUnit.ml);
  606. final value = (edv - esv) * hr / 1000;
  607. return UnitFloatValue(value, VidUsUnit.Lmin);
  608. }
  609. void clacChildItem(MultiSimpsonPath childItem) {
  610. final feature = findChildFeature(childItem);
  611. if (feature == null) {
  612. return;
  613. }
  614. feature as SimpsonPathFeature;
  615. // final outputs = childItem.meta.outputs;
  616. // TODO:
  617. final itemName = childItem.meta.name.split(' ').first;
  618. final isD = itemName.toLowerCase().contains("edv");
  619. final sideTag = isD ? "d" : "s";
  620. final outputs = [
  621. ItemOutputMeta("Area", "$itemName LVA$sideTag", VidUsUnit.mm2),
  622. ItemOutputMeta("L", "$itemName LVL$sideTag", VidUsUnit.mm),
  623. ];
  624. for (var output in outputs) {
  625. switch (output.name) {
  626. case "Area":
  627. feature.updateFloatValue(output, feature.area, VidUsUnit.cm2);
  628. break;
  629. case "L":
  630. feature.updateFloatValue(
  631. output, feature.centerLineLength, VidUsUnit.cm);
  632. break;
  633. default:
  634. }
  635. }
  636. }
  637. }
  638. class _SimpsonValues {
  639. UnitFloatValue? a2cEDV;
  640. UnitFloatValue? a2cESV;
  641. UnitFloatValue? a2cSV;
  642. UnitFloatValue? a2cEF;
  643. UnitFloatValue? a2cCO;
  644. UnitFloatValue? a4cEDV;
  645. UnitFloatValue? a4cESV;
  646. UnitFloatValue? a4cSV;
  647. UnitFloatValue? a4cEF;
  648. UnitFloatValue? a4cCO;
  649. UnitFloatValue? coupleEDV;
  650. UnitFloatValue? coupleESV;
  651. UnitFloatValue? coupleSV;
  652. UnitFloatValue? coupleEF;
  653. UnitFloatValue? coupleCO;
  654. }