lv_study.dart 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  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. import 'unit_formulas/index.dart';
  15. class LvStudySimpleCal extends LvStudyCalculatorBase<LvStudy> {
  16. late final StraightLine kidLVIDd;
  17. late final StraightLine kidLVIDs;
  18. LvStudySimpleCal(super.ref) {
  19. kidLVIDd = ref.findChildByName("L1") as StraightLine;
  20. kidLVIDs = ref.findChildByName("L2") as StraightLine;
  21. }
  22. @override
  23. void calculate() {
  24. if (ref.feature == null) return;
  25. final feature = ref.feature!;
  26. restoreVals();
  27. uv.lvidd = pickChildToFloatValue(kidLVIDd)?.toUnitFloatValue();
  28. uv.lvids = pickChildToFloatValue(kidLVIDs)?.toUnitFloatValue();
  29. for (var output in ref.meta.outputs) {
  30. switch (output.name) {
  31. case MeasureTerms.LvStudySimple:
  32. feature.updateStringValue(output, "");
  33. break;
  34. case MeasureTerms.LVEDV:
  35. updateLVEDV();
  36. break;
  37. case MeasureTerms.LVESV:
  38. updateLVESV();
  39. break;
  40. case MeasureTerms.SV:
  41. updateSV();
  42. break;
  43. case MeasureTerms.EF:
  44. updateEF();
  45. break;
  46. case MeasureTerms.FS:
  47. updatePercentFS();
  48. break;
  49. case MeasureTerms.LVIDdIndex:
  50. updateLVIDdIndex();
  51. break;
  52. case MeasureTerms.LVIDsIndex:
  53. updateLVIDsIndex();
  54. break;
  55. case MeasureTerms.LVIDdN:
  56. updateLVIDdN();
  57. break;
  58. case MeasureTerms.LVIDsN:
  59. updateLVIDsN();
  60. break;
  61. }
  62. }
  63. }
  64. }
  65. class LvStudyDistanceGroupCal extends LvStudyCalculatorBase<LvStudy> {
  66. late final StraightLine kidIVSd;
  67. late final StraightLine kidLVIDd;
  68. late final StraightLine kidLVPWd;
  69. late final StraightLine kidIVSs;
  70. late final StraightLine kidLVIDs;
  71. late final StraightLine kidLVPWs;
  72. LvStudyDistanceGroupCal(super.ref) {
  73. kidIVSd = ref.findChildByName(MeasureTerms.IVSd) as StraightLine;
  74. kidLVIDd = ref.findChildByName(MeasureTerms.LVIDd) as StraightLine;
  75. kidLVPWd = ref.findChildByName(MeasureTerms.LVPWd) as StraightLine;
  76. kidIVSs = ref.findChildByName(MeasureTerms.IVSs) as StraightLine;
  77. kidLVIDs = ref.findChildByName(MeasureTerms.LVIDs) as StraightLine;
  78. kidLVPWs = ref.findChildByName(MeasureTerms.LVPWs) as StraightLine;
  79. }
  80. @override
  81. void calculate() {
  82. if (ref.feature == null) return;
  83. final feature = ref.feature!;
  84. final viewport = feature.hostVisualArea!.viewport!;
  85. VidUsUnit yUnit = viewport.yUnit;
  86. restoreVals();
  87. FloatValue? ivsd = pickChildToFloatValue(kidIVSd);
  88. FloatValue? lvidd = pickChildToFloatValue(kidLVIDd);
  89. FloatValue? lvpwd = pickChildToFloatValue(kidLVPWd);
  90. FloatValue? ivss = pickChildToFloatValue(kidIVSs);
  91. FloatValue? lvids = pickChildToFloatValue(kidLVIDs);
  92. FloatValue? lvpws = pickChildToFloatValue(kidLVPWs);
  93. uv.ivsd = ivsd?.toUnitFloatValue();
  94. uv.ivss = ivss?.toUnitFloatValue();
  95. uv.lvidd = lvidd?.toUnitFloatValue();
  96. uv.lvids = lvids?.toUnitFloatValue();
  97. uv.lvpwd = lvpwd?.toUnitFloatValue();
  98. uv.lvpws = lvpws?.toUnitFloatValue();
  99. for (var output in ref.meta.outputs) {
  100. switch (output.name) {
  101. case MeasureTerms.LvStudy:
  102. feature.updateStringValue(output, "");
  103. break;
  104. case MeasureTerms.LVEDV:
  105. updateLVEDV();
  106. break;
  107. case MeasureTerms.LVESV:
  108. updateLVESV();
  109. break;
  110. case MeasureTerms.LVdMass:
  111. updateLVdMass();
  112. break;
  113. case MeasureTerms.PercentIVS:
  114. updatePercentIVS();
  115. break;
  116. case MeasureTerms.SV:
  117. updateSV();
  118. break;
  119. case MeasureTerms.EF:
  120. updateEF();
  121. break;
  122. case MeasureTerms.FS:
  123. updatePercentFS();
  124. break;
  125. case MeasureTerms.PercentLVPW:
  126. updatePercentLVPW();
  127. break;
  128. case MeasureTerms.CO:
  129. updateCO();
  130. break;
  131. case MeasureTerms.CI:
  132. updateCI();
  133. break;
  134. case MeasureTerms.SI:
  135. updateSI();
  136. break;
  137. case MeasureTerms.LVIDdIndex:
  138. updateLVIDdIndex();
  139. break;
  140. case MeasureTerms.LVIDsIndex:
  141. updateLVIDsIndex();
  142. break;
  143. case MeasureTerms.LVIDdN:
  144. updateLVIDdN();
  145. break;
  146. case MeasureTerms.LVIDsN:
  147. updateLVIDsN();
  148. break;
  149. }
  150. }
  151. }
  152. double? updateCalculateValue(FloatValue? floatValue, VidUsUnit unit) {
  153. if (floatValue != null) {
  154. if (floatValue.unit == unit) {
  155. return floatValue.value;
  156. } else {
  157. if (floatValue.unit == VidUsUnit.mm &&
  158. floatValue.unit == VidUsUnit.cm) {
  159. return floatValue.value == null ? null : floatValue.value! * 10;
  160. } else if (floatValue.unit == VidUsUnit.cm &&
  161. floatValue.unit == VidUsUnit.mm) {
  162. return floatValue.value == null ? null : floatValue.value! / 10;
  163. }
  164. }
  165. }
  166. return null;
  167. }
  168. }
  169. class LvStudyCalculatorBase<T extends TopMeasureItem>
  170. extends Calculator<T, double> {
  171. LvStudyCalculatorBase(super.ref);
  172. @protected
  173. late _ValTemp v;
  174. @protected
  175. late _UnitValTemp uv;
  176. @override
  177. void calculate() {
  178. // TODO: implement calculate
  179. }
  180. void restoreVals() {
  181. v = _ValTemp();
  182. uv = _UnitValTemp();
  183. }
  184. @protected
  185. void updateLVEDV() {
  186. if (uv.lvidd == null) {
  187. return;
  188. }
  189. UnitFloatValue? unitValue;
  190. if (GlobalCardiacConfigs.EDVFormulaMode ==
  191. CardiacEDVFormulaMode.teichholz) {
  192. unitValue = UnitFormulas.cardiac.edvTech(uv.lvidd!);
  193. } else if (GlobalCardiacConfigs.EDVFormulaMode ==
  194. CardiacEDVFormulaMode.cube) {
  195. unitValue = UnitFormulas.cardiac.edvCube(uv.lvidd!);
  196. }
  197. if (unitValue != null) {
  198. updateFloatValueByName(
  199. MeasureTerms.LVEDV,
  200. unitValue.value,
  201. unit: unitValue.unit,
  202. );
  203. }
  204. uv.lvedv = unitValue;
  205. }
  206. @protected
  207. void updateLVESV() {
  208. if (uv.lvids == null) {
  209. return;
  210. }
  211. double value = 0;
  212. UnitFloatValue? unitValue;
  213. if (GlobalCardiacConfigs.EDVFormulaMode ==
  214. CardiacEDVFormulaMode.teichholz) {
  215. unitValue = UnitFormulas.cardiac.edvTech(uv.lvids!);
  216. } else if (GlobalCardiacConfigs.EDVFormulaMode ==
  217. CardiacEDVFormulaMode.cube) {
  218. unitValue = UnitFormulas.cardiac.esvCube(uv.lvids!);
  219. }
  220. updateFloatValueByName(MeasureTerms.LVESV, value, unit: VidUsUnit.ml);
  221. if (unitValue != null) {
  222. updateFloatValueByName(
  223. MeasureTerms.LVESV,
  224. unitValue.value,
  225. unit: unitValue.unit,
  226. );
  227. }
  228. uv.lvesv = unitValue;
  229. }
  230. @protected
  231. void updateLVdMass() {
  232. if (uv.ivsd == null || uv.lvidd == null || uv.lvpwd == null) {
  233. return;
  234. }
  235. UnitFloatValue unitValue =
  236. UnitFormulas.cardiac.lvdMass(uv.ivsd!, uv.ivsd!, uv.lvpwd!);
  237. updateFloatValueByName(
  238. MeasureTerms.LVdMass,
  239. unitValue.value,
  240. unit: unitValue.unit,
  241. );
  242. }
  243. @protected
  244. void updatePercentIVS() {
  245. if (uv.ivsd == null || uv.ivss == null) {
  246. return;
  247. }
  248. UnitFloatValue unitValue =
  249. UnitFormulas.cardiac.ivsPercent(uv.ivss!, uv.ivsd!);
  250. updateFloatValueByName(
  251. MeasureTerms.PercentIVS,
  252. unitValue.value,
  253. unit: unitValue.unit,
  254. );
  255. }
  256. @protected
  257. void updateSV() {
  258. if (uv.lvedv == null || uv.lvesv == null) {
  259. return;
  260. }
  261. UnitFloatValue unitValue = UnitFormulas.cardiac.sv(uv.lvedv!, uv.lvesv!);
  262. updateFloatValueByName(
  263. MeasureTerms.SV,
  264. unitValue.value,
  265. unit: unitValue.unit,
  266. );
  267. uv.sv = unitValue;
  268. }
  269. @protected
  270. void updateEF() {
  271. if (uv.lvedv == null || uv.lvesv == null) {
  272. return;
  273. }
  274. UnitFloatValue unitValue = UnitFormulas.cardiac.ef(uv.lvedv!, uv.lvesv!);
  275. updateFloatValueByName(
  276. MeasureTerms.EF,
  277. unitValue.value,
  278. unit: VidUsUnit.percent,
  279. );
  280. }
  281. @protected
  282. void updatePercentFS() {
  283. if (uv.lvidd == null || uv.lvids == null) {
  284. return;
  285. }
  286. UnitFloatValue unitValue = UnitFormulas.cardiac.ef(uv.lvedv!, uv.lvesv!);
  287. updateFloatValueByName(
  288. MeasureTerms.EF,
  289. unitValue.value,
  290. unit: VidUsUnit.percent,
  291. );
  292. }
  293. @protected
  294. void updatePercentLVPW() {
  295. if (uv.lvpws == null || uv.lvpwd == null) {
  296. return;
  297. }
  298. UnitFloatValue unitValue =
  299. UnitFormulas.cardiac.lvpwPercent(uv.lvpws!, uv.lvpwd!);
  300. updateFloatValueByName(
  301. MeasureTerms.PercentLVPW,
  302. unitValue.value,
  303. unit: unitValue.unit,
  304. );
  305. }
  306. @protected
  307. void updateCO() {
  308. if (uv.sv == null || uv.hr == null) {
  309. return;
  310. }
  311. UnitFloatValue unitValue = UnitFormulas.cardiac.co(uv.sv!, hr: uv.hr!);
  312. updateFloatValueByName(
  313. MeasureTerms.CO,
  314. unitValue.value,
  315. unit: unitValue.unit,
  316. );
  317. }
  318. @protected
  319. void updateCI() {
  320. if (uv.sv == null || uv.hr == null) {
  321. return;
  322. }
  323. if (GlobalPatientConfig.bsa == 0) {
  324. return;
  325. }
  326. UnitFloatValue unitValue = UnitFormulas.cardiac
  327. .ci(uv.sv!, hr: uv.hr!, bsa: GlobalPatientConfig.bsa);
  328. updateFloatValueByName(
  329. MeasureTerms.CI,
  330. unitValue.value,
  331. unit: unitValue.unit,
  332. );
  333. }
  334. @protected
  335. void updateLVEDVI() {
  336. if (uv.lvedv == null) {
  337. return;
  338. }
  339. if (GlobalPatientConfig.bsa == 0) {
  340. return;
  341. }
  342. UnitFloatValue unitValue =
  343. UnitFormulas.cardiac.lvevi(uv.lvedv!, bsa: GlobalPatientConfig.bsa);
  344. updateFloatValueByName(
  345. MeasureTerms.LVEDVI,
  346. unitValue.value,
  347. unit: unitValue.unit,
  348. );
  349. }
  350. @protected
  351. void updateLVESVI() {
  352. if (uv.lvesv == null) {
  353. return;
  354. }
  355. if (GlobalPatientConfig.bsa == 0) {
  356. return;
  357. }
  358. UnitFloatValue unitValue =
  359. UnitFormulas.cardiac.lvevi(uv.lvesv!, bsa: GlobalPatientConfig.bsa);
  360. updateFloatValueByName(
  361. MeasureTerms.LVESVI,
  362. unitValue.value,
  363. unit: unitValue.unit,
  364. );
  365. }
  366. @protected
  367. void updateSI() {
  368. if (uv.sv == null) {
  369. return;
  370. }
  371. if (GlobalPatientConfig.bsa == 0) {
  372. return;
  373. }
  374. UnitFloatValue unitValue =
  375. UnitFormulas.cardiac.si(uv.sv!, bsa: GlobalPatientConfig.bsa);
  376. updateFloatValueByName(
  377. MeasureTerms.SI,
  378. unitValue.value,
  379. unit: unitValue.unit,
  380. );
  381. }
  382. @protected
  383. void updateLVIDdIndex() {
  384. if (uv.lvidd == null) {
  385. return;
  386. }
  387. if (GlobalPatientConfig.bsa == 0) {
  388. return;
  389. }
  390. UnitFloatValue unitValue =
  391. UnitFormulas.cardiac.lvidIndex(uv.lvidd!, bsa: GlobalPatientConfig.bsa);
  392. updateFloatValueByName(
  393. MeasureTerms.LVIDdIndex,
  394. unitValue.value,
  395. unit: unitValue.unit,
  396. );
  397. }
  398. @protected
  399. void updateLVIDsIndex() {
  400. if (uv.lvids == null) {
  401. return;
  402. }
  403. if (GlobalPatientConfig.bsa == 0) {
  404. return;
  405. }
  406. UnitFloatValue unitValue =
  407. UnitFormulas.cardiac.lvidIndex(uv.lvids!, bsa: GlobalPatientConfig.bsa);
  408. updateFloatValueByName(
  409. MeasureTerms.LVIDsIndex,
  410. unitValue.value,
  411. unit: unitValue.unit,
  412. );
  413. }
  414. @protected
  415. void updateLVIDdN() {
  416. if (uv.lvidd == null) {
  417. return;
  418. }
  419. if (GlobalPatientConfig.weight == 0) {
  420. return;
  421. }
  422. UnitFloatValue unitValue =
  423. UnitFormulas.cardiac.lvidIndex(uv.lvidd!, bsa: GlobalPatientConfig.bsa);
  424. updateFloatValueByName(
  425. MeasureTerms.LVIDdN,
  426. unitValue.value,
  427. unit: unitValue.unit,
  428. );
  429. }
  430. @protected
  431. void updateLVIDsN() {
  432. if (uv.lvids == null) {
  433. return;
  434. }
  435. if (GlobalPatientConfig.weight == 0) {
  436. return;
  437. }
  438. var unitWeightValue =
  439. UnitFloatValue(GlobalPatientConfig.weight, VidUsUnit.kg);
  440. UnitFloatValue unitValue =
  441. UnitFormulas.cardiac.lvidN(uv.lvids!, unitWeightValue);
  442. updateFloatValueByName(
  443. MeasureTerms.LVIDsN,
  444. unitValue.value,
  445. unit: unitValue.unit,
  446. );
  447. }
  448. @protected
  449. void updateFloatValueByName(
  450. String name,
  451. double value, {
  452. VidUsUnit? unit,
  453. }) {
  454. ref.measuredFeatures;
  455. final feature = ref.feature!;
  456. final outputMeta = ref.meta.outputs.firstWhere((x) => x.name == name);
  457. feature.updateFloatValue(outputMeta, value, unit ?? outputMeta.unit);
  458. }
  459. VidUsUnit updateUnitBySpeciesType(VidUsUnit unit, String name) {
  460. if (GlobalPatientConfig.speciesType != SpeciesType.mouse) {
  461. return unit;
  462. }
  463. switch (name) {
  464. case MeasureTerms.LVEDV:
  465. return VidUsUnit.mil;
  466. case MeasureTerms.LVESV:
  467. return VidUsUnit.mil;
  468. case MeasureTerms.LVEDVI:
  469. return VidUsUnit.mil;
  470. case MeasureTerms.LVESVI:
  471. return VidUsUnit.mil;
  472. case MeasureTerms.SI:
  473. return VidUsUnit.mlm2;
  474. case MeasureTerms.CO:
  475. return VidUsUnit.mlmin;
  476. case MeasureTerms.CI:
  477. return VidUsUnit.mlmincm2;
  478. case MeasureTerms.LVdMass:
  479. return VidUsUnit.mg;
  480. case MeasureTerms.FS:
  481. return VidUsUnit.percent;
  482. case MeasureTerms.EF:
  483. return VidUsUnit.percent;
  484. case MeasureTerms.PercentLVPW:
  485. return VidUsUnit.percent;
  486. case MeasureTerms.SV:
  487. return VidUsUnit.mil;
  488. case MeasureTerms.SV_Card:
  489. return VidUsUnit.mlmin;
  490. case MeasureTerms.SV_Diam:
  491. return VidUsUnit.cm;
  492. case MeasureTerms.SV_Trace:
  493. return VidUsUnit.cm;
  494. case MeasureTerms.IVSd:
  495. return VidUsUnit.mm;
  496. case MeasureTerms.LVIDd:
  497. return VidUsUnit.mm;
  498. case MeasureTerms.LVPWd:
  499. return VidUsUnit.mm;
  500. case MeasureTerms.IVSs:
  501. return VidUsUnit.mg;
  502. case MeasureTerms.LVIDs:
  503. return VidUsUnit.mm;
  504. case MeasureTerms.LVPWs:
  505. return VidUsUnit.mm;
  506. case MeasureTerms.CO_2D:
  507. return VidUsUnit.mlmin;
  508. case MeasureTerms.CO_M: // 脉动心输出量
  509. return VidUsUnit.mlmin;
  510. case MeasureTerms.CO_P: // 脉动心输出量
  511. return VidUsUnit.mlmin;
  512. default:
  513. return unit;
  514. }
  515. }
  516. }
  517. class _ValTemp {
  518. double? ivsd;
  519. double? lvidd;
  520. double? lvpwd;
  521. double? ivss;
  522. double? lvids;
  523. double? lvpws;
  524. double? lvedv;
  525. double? lvesv;
  526. double? sv;
  527. int? hr = GlobalPatientConfig.hr; // TODO: from vid ext
  528. }
  529. class _UnitValTemp {
  530. UnitFloatValue? ivsd;
  531. UnitFloatValue? lvidd;
  532. UnitFloatValue? lvpwd;
  533. UnitFloatValue? ivss;
  534. UnitFloatValue? lvids;
  535. UnitFloatValue? lvpws;
  536. UnitFloatValue? lvedv;
  537. UnitFloatValue? lvesv;
  538. UnitFloatValue? sv;
  539. int? hr = GlobalPatientConfig.hr; // TODO: from vid ext
  540. }