Browse Source

家族史关系解读后结构化

louhr 5 years ago
parent
commit
bcdaba77cf

+ 14 - 26
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/BeHospitalizedAI.java

@@ -5,18 +5,22 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.lantone.qc.kernel.client.CRFServiceClient;
 import com.lantone.qc.kernel.structure.ai.model.CrfOut;
-import com.lantone.qc.kernel.structure.ai.model.EntityEnum;
 import com.lantone.qc.kernel.structure.ai.process.*;
 import com.lantone.qc.pub.Content;
 import com.lantone.qc.pub.model.InputInfo;
 import com.lantone.qc.pub.model.doc.BeHospitalizedDoc;
 import com.lantone.qc.pub.model.entity.*;
-import com.lantone.qc.pub.model.label.*;
+import com.lantone.qc.pub.model.label.ChiefLabel;
+import com.lantone.qc.pub.model.label.FamilyLabel;
+import com.lantone.qc.pub.model.label.PersonalLabel;
+import com.lantone.qc.pub.model.label.PresentLabel;
 import com.lantone.qc.pub.model.vo.CRFVo;
 import com.lantone.qc.pub.util.StringUtil;
-import org.apache.commons.lang3.StringUtils;
 
-import java.util.*;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @ClassName : InHospitalDoc
@@ -130,23 +134,18 @@ public class BeHospitalizedAI {
         presentLabel.setGenerals(loadGeneralDes(aiOut));
         presentLabel.setPacses(loadpacses(aiOut));
     }
+
     public void putFamilyCrfData(JSONObject jsonObject, InputInfo inputInfo){
         if (jsonObject == null) {
             return;
         }
         JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
-        //放置入inputinfo
-        FamilyLabel familyLabel = inputInfo.getBeHospitalizedDoc().getFamilyLabel();
-        familyLabel.setDiags(loadDiags(aiOut));
-        familyLabel.setFamilies(loadFamily(aiOut));
-        EntityProcess entityProcess = new EntityProcess();
-        try {
-            List<DiagInfectious> diagInfectious = entityProcess.addEntity(aiOut, EntityEnum.INFECTIOUS_KEYWORD, DiagInfectious.class);
-            familyLabel.setDiagInfectious(diagInfectious);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
+        //家族史信息处理
+        EntityProcessFamily entityProcess = new EntityProcessFamily();
+        FamilyLabel familyLabel = entityProcess.extractEntity(aiOut);
+        familyLabel.setText(inputInfo.getBeHospitalizedDoc().getFamilyLabel().getText());
     }
+
     public void putPastCrfData(JSONObject jsonObject, InputInfo inputInfo){
         if (jsonObject == null) {
             return;
@@ -178,17 +177,6 @@ public class BeHospitalizedAI {
         List<Clinical> clinicals = entityProcessClinic.extractEntity(aiOut);
         return clinicals;
     }
-    /**
-     * 关系抽取临床表现信息
-     * @param aiOut
-     * @return
-     */
-    public List<Family> loadFamily(JSONObject aiOut) {
-
-        EntityProcessFamily entityProcessFamily= new EntityProcessFamily();
-        List<Family> families = entityProcessFamily.extractEntity(aiOut);
-        return families;
-    }
     /**
      * 关系抽取疾病信息
      * @param aiOut

+ 32 - 0
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/model/Lemma.java

@@ -0,0 +1,32 @@
+package com.lantone.qc.kernel.structure.ai.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @ClassName
+ * @Description 实体信息
+ * @Author fyeman
+ * @Date
+ * @Version 1.0
+ **/
+@Getter
+@Setter
+public class Lemma {
+    private int id;
+    private String text;
+    private String position;
+    private int len;
+    private String property;
+    private Lemma parent;
+    private boolean haveChildren = false;
+    private List<Lemma> relationLemmas = new ArrayList<>();
+
+    public void addRelationLemmas(Lemma lemma) {
+        this.relationLemmas.add(lemma);
+        this.haveChildren = true;
+    }
+}

+ 72 - 6
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/process/EntityProcess.java

@@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.lantone.qc.kernel.structure.ai.model.CrfOut;
 import com.lantone.qc.kernel.structure.ai.model.EntityEnum;
+import com.lantone.qc.kernel.structure.ai.model.Lemma;
+import com.lantone.qc.pub.model.entity.DiagInfectious;
 import com.lantone.qc.pub.model.entity.Negative;
 import org.apache.commons.beanutils.BeanUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -21,6 +23,70 @@ import java.util.regex.Pattern;
  * @Date: 2020/2/2 10:07
  */
 public class EntityProcess {
+
+    /**
+     * 树形结构存储三元组关系,返回传入实体类型为节点的所有关联实体对象
+     * @param aiOut
+     * @param entityType
+     * @return
+     */
+    public List<Lemma> createEntityTree(JSONObject aiOut, String entityType) {
+        List<Lemma> resultLemmaList = new ArrayList<>();
+        JSONObject annotation = aiOut.getJSONObject("annotation");
+        JSONArray entitys = annotation.getJSONArray("T");
+        JSONArray relations = annotation.getJSONArray("R");
+
+        List<Lemma> allLemmaList = loadAllLemmaList(entitys);
+        for (Lemma l : allLemmaList) {
+            if (entityType.equals(l.getProperty())) {
+                findRelationLemma(l, allLemmaList, relations);
+                resultLemmaList.add(l);
+            }
+        }
+        return resultLemmaList;
+    }
+
+    /**
+     * 查找所有实体对象
+     * @param entitys
+     * @return
+     */
+    private List<Lemma> loadAllLemmaList(JSONArray entitys) {
+        List<Lemma> allLemmaList = new ArrayList<>();
+        //所有实体读取
+        for (int i = 0; i < entitys.size(); i++) {
+            if (StringUtils.isEmpty(entitys.get(i).toString())) {
+                continue;
+            }
+            JSONObject entity = entitys.getJSONObject(i);
+            Lemma lemma = new Lemma();
+            lemma.setId(entity.getIntValue("id"));
+            lemma.setText(entity.getString("value"));
+            lemma.setProperty(entity.getString("name"));
+            lemma.setPosition(entity.getString("start"));
+            allLemmaList.add(lemma);
+        }
+        return allLemmaList;
+    }
+
+    /**
+     * 递归查询所有子实体信息
+     * @param lemma
+     * @param allLemmaList
+     * @param relations
+     */
+    private void findRelationLemma(Lemma lemma, List<Lemma> allLemmaList, JSONArray relations) {
+        List<Integer> connectEntityIdList = getConnectEntityIdList(lemma.getId(), relations);
+        for (Lemma l : allLemmaList) {
+            for (Integer reId : connectEntityIdList) {
+                if (l.getId() == reId) {
+                    findRelationLemma(l, allLemmaList, relations);
+                    lemma.addRelationLemmas(l);
+                }
+            }
+        }
+    }
+
     /**
      * 处理关系抽取输出的json
      *
@@ -111,18 +177,18 @@ public class EntityProcess {
 
     public  <T> List<T> addEntity(JSONObject aiOut, EntityEnum entityType, Class<T> t) throws Exception {
         List<T> list = new ArrayList<>();
-        List<Map<String, String>> pastEntityList = processJson(aiOut, entityType.toString());
-        for (Map<String, String> pastEntityMap : pastEntityList) {
-            if (StringUtils.isEmpty(pastEntityMap.get(entityType.toString()))) {
+        List<Map<String, String>> entityList = processJson(aiOut, entityType.toString());
+        for (Map<String, String> entityMap : entityList) {
+            if (StringUtils.isEmpty(entityMap.get(entityType.toString()))) {
                 continue;
             }
             T o = t.newInstance();
-            for (String key : pastEntityMap.keySet()) {
+            for (String key : entityMap.keySet()) {
                 if (key.equals(entityType.toString())) {
-                    BeanUtils.copyProperty(o, "name", pastEntityMap.get(key));
+                    BeanUtils.copyProperty(o, "name", entityMap.get(key));
                 } else if (key.equals(EntityEnum.NEGATIVE.toString())) {
                     Negative negative = new Negative();
-                    negative.setName(StringUtils.isEmpty(pastEntityMap.get(key)) ? "" : pastEntityMap.get(key));
+                    negative.setName(StringUtils.isEmpty(entityMap.get(key)) ? "" : entityMap.get(key));
                     BeanUtils.copyProperty(o, "negative", negative);
                 }
             }

+ 92 - 29
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/process/EntityProcessFamily.java

@@ -3,46 +3,109 @@ package com.lantone.qc.kernel.structure.ai.process;
 
 import com.alibaba.fastjson.JSONObject;
 import com.lantone.qc.kernel.structure.ai.model.EntityEnum;
+import com.lantone.qc.kernel.structure.ai.model.Lemma;
 import com.lantone.qc.pub.model.entity.*;
-import org.apache.commons.lang3.StringUtils;
+import com.lantone.qc.pub.model.label.FamilyLabel;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 
+/**
+ * 家族史标签处理
+ */
 public class EntityProcessFamily extends EntityProcess {
-    public List<Family> extractEntity(JSONObject aiOut) {
+
+    public FamilyLabel extractEntity(JSONObject aiOut) {
+        FamilyLabel familyLabel = new FamilyLabel();
+        //家属情况
         List<Family> families = new ArrayList<>();
-        Family family;
-        Dead dead;
-        List<Map<String, String>> clinicalEntityList = processJson(aiOut, EntityEnum.RELATIVES.toString());
-        for (Map<String, String> clinicalEntityEntry : clinicalEntityList) {
-            if (StringUtils.isEmpty(clinicalEntityEntry.get(EntityEnum.RELATIVES.toString()))) {
-                continue;
+        //读取家属所有本体及关联信息
+        List<Lemma> familyLemmas = createEntityTree(aiOut, EntityEnum.RELATIVES.toString());
+        for (Lemma lemma :familyLemmas) {
+            Family family = new Family();
+            family.setName(lemma.getText());
+            if (lemma.isHaveChildren()) {
+                for (Lemma relationLemma : lemma.getRelationLemmas()) {
+                    if (relationLemma.getProperty().equals(EntityEnum.DEAD.toString())) {
+                        family.setDead(addDeadLemma(relationLemma));
+                    } else if (relationLemma.getProperty().equals(EntityEnum.INFECTIOUS_KEYWORD.toString())) {
+                        family.setDiagInfectious(addInfectious(relationLemma));
+                    } else if (relationLemma.getProperty().equals(EntityEnum.GENETIC_DISEASE_KEYWORD.toString())) {
+                        family.setGeneticDiseaseKeyword(addGeneticDisease(relationLemma));
+                    } else if (relationLemma.getProperty().equals(EntityEnum.DIEASE.toString())) {
+                        family.addDiag(addDiags(relationLemma));
+                    }
+                }
             }
-            family = new Family();
-            dead = new Dead();
-            for (String key : clinicalEntityEntry.keySet()) {
-                String entity = StringUtils.isEmpty(clinicalEntityEntry.get(key)) ? "" : clinicalEntityEntry.get(key);
-                switch (EntityEnum.parseOfValue(key)){
-                    case RELATIVES:
-                        family.setName(clinicalEntityEntry.get(key));
-                        break;
-                    case DEAD:
-                        dead.setName(entity);
-                        family.setDead(dead);
-                        break;
-                    case UNKNOWN:
-                        Unknow unknow = new Unknow();
-                        unknow.setName(entity);
-                        dead.setUnknow(unknow);
-                        break;
+            families.add(family);
+        }
+        familyLabel.setFamilies(families);
+        return familyLabel;
+    }
 
-                }
+    /**
+     * 家属死亡
+     * @param deadLemma
+     * @return
+     */
+    private Dead addDeadLemma(Lemma deadLemma) {
+        Dead dead = new Dead();
+        dead.setName(deadLemma.getText());
+        if (deadLemma.isHaveChildren()) {
+            dead.setDesc(deadLemma.getRelationLemmas().get(0).getText());
+        }
+        return dead;
+    }
 
+    /**
+     * 家属传染病史
+     * @param infectiouLemma
+     * @return
+     */
+    private DiagInfectious addInfectious(Lemma infectiouLemma) {
+        DiagInfectious diagInfectious = new DiagInfectious();
+        diagInfectious.setName(infectiouLemma.getText());
+        if (infectiouLemma.isHaveChildren()) {
+            diagInfectious.setNegative(findNegative(infectiouLemma));
+        }
+        return diagInfectious;
+    }
+
+    /**
+     * 家属遗传病史
+     * @param geneticLemma
+     * @return
+     */
+    private GeneticDiseaseKeyword addGeneticDisease(Lemma geneticLemma) {
+        GeneticDiseaseKeyword geneticDiseaseKeyword = new GeneticDiseaseKeyword();
+        geneticDiseaseKeyword.setName(geneticLemma.getText());
+        if (geneticLemma.isHaveChildren()) {
+            geneticDiseaseKeyword.setNegative(findNegative(geneticLemma));
+        }
+        return geneticDiseaseKeyword;
+    }
+    /**
+     * 家属疾病史
+     * @param diagLemma
+     * @return
+     */
+    private Diag addDiags(Lemma diagLemma) {
+        Diag diag = new Diag();
+        diag.setName(diagLemma.getText());
+        if (diagLemma.isHaveChildren()) {
+            diag.setNegative(findNegative(diagLemma));
+        }
+        return diag;
+    }
+
+    private Negative findNegative(Lemma detailLemma) {
+        for (Lemma lemma : detailLemma.getRelationLemmas()) {
+            if (lemma.getProperty().equals(EntityEnum.NEGATIVE.toString())) {
+                Negative negative = new Negative();
+                negative.setName(lemma.getText());
+                return negative;
             }
-            families.add(family);
         }
-        return families;
+        return null;
     }
 }

+ 4 - 2
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/process/EntityProcessMarital.java

@@ -2,14 +2,16 @@ package com.lantone.qc.kernel.structure.ai.process;
 
 import com.alibaba.fastjson.JSONObject;
 import com.lantone.qc.kernel.structure.ai.model.EntityEnum;
+import com.lantone.qc.kernel.structure.ai.model.Lemma;
 import com.lantone.qc.pub.model.entity.Diag;
+import com.lantone.qc.pub.model.entity.Family;
 import com.lantone.qc.pub.model.label.MaritalLabel;
 
 import java.util.List;
 
 /**
  * @ClassName : EntityProcessMarital
- * @Description :
+ * @Description : 家族史
  * @Author : 楼辉荣
  * @Date: 2020-03-10 10:20
  */
@@ -17,7 +19,7 @@ public class EntityProcessMarital extends EntityProcess {
     public MaritalLabel extractEntity(JSONObject aiOut) {
         MaritalLabel maritalLabel = new MaritalLabel();
         try {
-            List<Diag> diags = addEntity(aiOut, EntityEnum.RELATIVES, Diag.class);
+            List<Lemma> familiesLemma = createEntityTree(aiOut, EntityEnum.RELATIVES.toString());
         } catch (Exception e) {
 
         }

+ 1 - 1
public/src/main/java/com/lantone/qc/pub/model/entity/Dead.java

@@ -9,5 +9,5 @@ import lombok.Setter;
 @Setter
 @Getter
 public class Dead extends General {
-    private Unknow unknow;//死亡情况不详
+    private String desc;
 }

+ 6 - 0
public/src/main/java/com/lantone/qc/pub/model/entity/DiagInfectious.java

@@ -1,10 +1,16 @@
 package com.lantone.qc.pub.model.entity;
 
+import lombok.Getter;
+import lombok.Setter;
+
 /**
  * @ClassName : DiagInfectious
  * @Description : 传染病史
  * @Author : 楼辉荣
  * @Date: 2020-03-05 19:12
  */
+@Getter
+@Setter
 public class DiagInfectious extends General {
+    private Negative negative;
 }

+ 6 - 0
public/src/main/java/com/lantone/qc/pub/model/entity/Family.java

@@ -3,6 +3,8 @@ package com.lantone.qc.pub.model.entity;
 import lombok.Getter;
 import lombok.Setter;
 
+import java.util.List;
+
 /**
  * @ClassName : Family
  * @Description : 家属
@@ -15,5 +17,9 @@ public class Family extends General{
     private Dead dead;
     private GeneticDiseaseKeyword geneticDiseaseKeyword;//家族遗传病
     private DiagInfectious diagInfectious;//传染病史
+    private List<Diag> diags;//疾病名称
 
+    public void addDiag(Diag diag) {
+        this.diags.add(diag);
+    }
 }

+ 5 - 0
public/src/main/java/com/lantone/qc/pub/model/entity/GeneticDiseaseKeyword.java

@@ -1,8 +1,13 @@
 package com.lantone.qc.pub.model.entity;
 
+import lombok.Getter;
+import lombok.Setter;
+
 /**
  * 家族遗传病
  */
+@Setter
+@Getter
 public class GeneticDiseaseKeyword extends General {
     private Negative negative;
 }

+ 0 - 4
public/src/main/java/com/lantone/qc/pub/model/label/FamilyLabel.java

@@ -1,7 +1,5 @@
 package com.lantone.qc.pub.model.label;
 
-import com.lantone.qc.pub.model.entity.Diag;
-import com.lantone.qc.pub.model.entity.DiagInfectious;
 import com.lantone.qc.pub.model.entity.Family;
 import lombok.Getter;
 import lombok.Setter;
@@ -17,7 +15,5 @@ import java.util.List;
 @Setter
 @Getter
 public class FamilyLabel extends GeneralLabel {
-    private List<Diag> diags;
-    private List<DiagInfectious> diagInfectious;//传染病史
     private List<Family> families;
 }