瀏覽代碼

ef/ lvd mass

Melon 11 月之前
父節點
當前提交
6d6f2d0821

+ 4 - 0
lib/interfaces/process/items/terms.dart

@@ -530,6 +530,10 @@ class MeasureTerms {
   static const DEDistance = "D-E Dist";
   static const EFDistance = "E-F Dist";
 
+  static const EpiLVAd = "Epi LVAd";
+  static const EndoVLAd = "Endo LVAd";
+  static const LVLd = "LVLd";
+
   /// body weight normalized left ventricular internal dimension in diastole
   static const LVIDdN = "LVIDdN";
 

+ 3 - 0
lib/interfaces/process/items/types.dart

@@ -162,4 +162,7 @@ class MeasureTypes {
 
   /// 内膜检测
   static const IntimaDetection = "Intima Detection";
+
+  /// 左心室舒张期质量
+  static const LVdMass = "LVd Mass";
 }

+ 0 - 24
lib/interfaces/process/workspace/cross_frame.dart

@@ -49,27 +49,3 @@ abstract class ICrossFrameContext {
   /// 跨帧测量自动结束事件
   late final FEventHandler<void> measureAutoOver;
 }
-
-/// 跨帧贮存器
-abstract class ICrossFrameStore {
-  /// 原始帧
-  VidUsImage? get originFrame;
-
-  /// 附帧
-  VidUsImage? get subFrame;
-
-  /// 原始帧索引
-  int get originIndex;
-
-  /// 附帧索引
-  int get subIndex;
-
-  /// 帧还原 事件
-  late final FEventHandler<int> frameRestored;
-
-  /// 恢复
-  Future<void> restore();
-
-  /// 跨到指定帧
-  Future<void> crossTo(VidUsImage? frame);
-}

+ 21 - 0
lib/process/calcuators/formulas/cardiac.dart

@@ -121,6 +121,27 @@ class CardiacFormulas {
     return value;
   }
 
+  /// LVd Mass AL
+  static double lvdMassAL(
+    double lvadSaxEpi,
+    double lvadSaxEndo,
+    double lvldApical,
+  ) {
+    double t =
+        math.sqrt(lvadSaxEpi / math.pi) - math.sqrt(lvadSaxEndo / math.pi);
+    double mass = 1.05 *
+        5 /
+        6 *
+        (lvadSaxEpi * (lvldApical + t) - lvadSaxEndo * lvldApical) /
+        1000;
+    return mass;
+  }
+
+  /// LVd Mass Index
+  static double lvdMassIndex(double lvdmass, double bsa) {
+    return lvdmass / bsa * 1000;
+  }
+
   /// %FS
   static double fsPercent(double lvidd, double lvids) {
     return ((lvidd - lvids) / lvidd) * 100;

+ 47 - 0
lib/process/calcuators/lv_mass.dart

@@ -0,0 +1,47 @@
+import 'package:fis_measure/configs/patient.dart';
+import 'package:fis_measure/interfaces/process/items/terms.dart';
+import 'package:fis_measure/process/primitives/combos/lv_mass.dart';
+import 'package:vid/us/vid_us_unit.dart';
+
+import 'calculator.dart';
+import 'formulas/cardiac.dart';
+
+class LvdMassALCal extends Calculator<LVMass, double> {
+  LvdMassALCal(super.ref);
+
+  @override
+  void calculate() {
+    if (ref.feature == null) return;
+
+    final feature = ref.feature!;
+
+    double? epi = pickChildFloatValue(ref.epi);
+    double? endo = pickChildFloatValue(ref.endo);
+    double? l = pickChildFloatValue(ref.l);
+
+    double? lvdmass;
+    double? lvdMassIndex;
+    if (epi != null && endo != null && l != null) {
+      lvdmass = CardiacFormulas.lvdMassAL(epi, endo, l);
+    }
+    if (lvdmass != null && GlobalPatientConfig.bsa > 0) {
+      lvdMassIndex =
+          CardiacFormulas.lvdMassIndex(lvdmass, GlobalPatientConfig.bsa);
+    }
+
+    for (var output in ref.meta.outputs) {
+      switch (output.name) {
+        case MeasureTerms.LVdMass:
+          if (lvdmass != null) {
+            feature.updateFloatValue(output, lvdmass, VidUsUnit.kg);
+          }
+          break;
+        case MeasureTerms.LVdMassIndex:
+          if (lvdMassIndex != null) {
+            feature.updateFloatValue(output, lvdMassIndex, VidUsUnit.gm2);
+          }
+          break;
+      }
+    }
+  }
+}

+ 3 - 0
lib/process/items/factory.dart

@@ -6,6 +6,7 @@ import 'package:fis_measure/process/primitives/carotid_imt.dart';
 import 'package:fis_measure/process/primitives/combos/afi.dart';
 import 'package:fis_measure/process/primitives/combos/area_straightline.dart';
 import 'package:fis_measure/process/primitives/combos/depth2baseline.dart';
+import 'package:fis_measure/process/primitives/combos/lv_mass.dart';
 import 'package:fis_measure/process/primitives/combos/lwh_straightline.dart';
 import 'package:fis_measure/process/primitives/combos/straightline_group.dart';
 import 'package:fis_measure/process/primitives/combos/three_ray.dart';
@@ -81,8 +82,10 @@ class MeasureItemFactory {
   }
 
   static void _registerItemCreators() {
+    // Cardiac
     _singleton._register(
         MeasureTypes.LvStudyByLineGroupTissue, StraightLineGroup.createLvStudy);
+    _singleton._register(MeasureTypes.LVdMass, LVMass.createLVdMass);
 
     // Empty
     _singleton._register(MeasureTypes.Empty, Empty.createEmpty);

+ 0 - 1
lib/process/items/top_item_feature.dart

@@ -1,5 +1,4 @@
 import 'package:fis_measure/interfaces/process/items/item.dart';
-import 'package:fis_measure/interfaces/process/items/item_feature.dart';
 import 'package:flutter/painting.dart';
 
 import 'item_feature.dart';

+ 51 - 0
lib/process/primitives/combos/lv_mass.dart

@@ -0,0 +1,51 @@
+import 'package:fis_measure/interfaces/process/items/item.dart';
+import 'package:fis_measure/interfaces/process/items/item_metas.dart';
+import 'package:fis_measure/interfaces/process/items/terms.dart';
+import 'package:fis_measure/interfaces/process/items/types.dart';
+import 'package:fis_measure/process/calcuators/lv_mass.dart';
+import 'package:fis_measure/process/items/top_item.dart';
+import 'package:fis_measure/process/items/top_item_feature.dart';
+import 'package:fis_measure/process/primitives/straightline.dart';
+import 'package:fis_measure/process/primitives/trace.dart';
+
+class LVMass extends TopMeasureItem<LVMassFeature> {
+  static const String _lvdEpiLKey = MeasureTerms.EpiLVAd;
+  static const String _lvdEndoKey = MeasureTerms.EndoVLAd;
+  static const String _lvldKey = MeasureTerms.LVLd;
+
+  late final Trace epi;
+  late final Trace endo;
+  late final StraightLine l;
+
+  LVMass(ItemMeta meta) : super(meta) {
+    final metaEpi = meta.getChildByName(_lvdEpiLKey)!;
+    final metaEndo = meta.getChildByName(_lvdEndoKey)!;
+    final metaL = meta.getChildByName(_lvldKey)!;
+    epi = Trace.createAreaPerimeter(metaEpi, this);
+    endo = Trace.createAreaPerimeter(metaEndo, this);
+    l = StraightLine.createDistance(metaL, this);
+    childItems.add(epi);
+    childItems.add(endo);
+    childItems.add(l);
+  }
+
+  @override
+  bool get finishAfterUnactive => true;
+
+  @override
+  LVMassFeature buildFeature() => LVMassFeature(this);
+
+  static LVMass createLVdMass(ItemMeta meta, [IMeasureItem? parent]) {
+    if (meta.measureType != MeasureTypes.LVdMass) {
+      throw ArgumentError();
+    }
+    var ins = LVMass(meta);
+    ins.calculator = LvdMassALCal(ins);
+
+    return ins;
+  }
+}
+
+class LVMassFeature extends TopMeasureItemFeature {
+  LVMassFeature(super.refItem);
+}

+ 0 - 33
lib/process/workspace/cross_frame.dart

@@ -101,36 +101,3 @@ class CrossFrameContext implements ICrossFrameContext {
     _isOver = true;
   }
 }
-
-class CrossFrameStore implements ICrossFrameStore {
-  CrossFrameStore() {
-    frameRestored = FEventHandler<int>();
-  }
-
-  @override
-  VidUsImage? get originFrame => throw UnimplementedError();
-
-  @override
-  int get originIndex => throw UnimplementedError();
-
-  @override
-  VidUsImage? get subFrame => throw UnimplementedError();
-
-  @override
-  int get subIndex => throw UnimplementedError();
-
-  @override
-  late final FEventHandler<int> frameRestored;
-
-  @override
-  Future<void> crossTo(VidUsImage? frame) async {
-    // TODO: implement crossTo
-    throw UnimplementedError();
-  }
-
-  @override
-  Future<void> restore() async {
-    // TODO: implement restore
-    throw UnimplementedError();
-  }
-}