Browse Source

1.添加规则:病程中未记录抗生素用量
2.药品提取修改逻辑:只取用量、用法、频率等出现在药品之后的药品

huj 4 years ago
parent
commit
79d7072879

+ 280 - 0
kernel/src/main/java/com/lantone/qc/kernel/catalogue/threelevelward/THR03077.java

@@ -0,0 +1,280 @@
+package com.lantone.qc.kernel.catalogue.threelevelward;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.lantone.qc.kernel.catalogue.QCCatalogue;
+import com.lantone.qc.kernel.util.CatalogueUtil;
+import com.lantone.qc.kernel.util.SimilarityUtil;
+import com.lantone.qc.pub.model.InputInfo;
+import com.lantone.qc.pub.model.OutputInfo;
+import com.lantone.qc.pub.model.doc.DoctorAdviceDoc;
+import com.lantone.qc.pub.model.doc.LeaveHospitalDoc;
+import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDiscussionDoc;
+import com.lantone.qc.pub.model.doc.operation.OperationDoc;
+import com.lantone.qc.pub.model.entity.Drug;
+import com.lantone.qc.pub.model.label.LeaveHospitalLabel;
+import com.lantone.qc.pub.model.label.ThreeLevelWardLabel;
+import com.lantone.qc.pub.util.DateUtil;
+import com.lantone.qc.pub.util.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * @author HUJING
+ * @create 2020-08-28 14:10
+ * @desc 病程中未记录抗生素用量
+ **/
+@Component
+public class THR03077 extends QCCatalogue {
+    @Autowired
+    SimilarityUtil similarityUtil;
+
+    public void start(InputInfo inputInfo, OutputInfo outputInfo) {
+        status.set("0");
+        List<DoctorAdviceDoc> doctorAdviceDocs = inputInfo.getDoctorAdviceDocs();
+        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
+        List<OperationDoc> operationDocs = inputInfo.getOperationDocs();
+        LeaveHospitalDoc leaveHospitalDoc = inputInfo.getLeaveHospitalDoc();
+        if (doctorAdviceDocs.size() == 0) {
+            return;
+        }
+        //抗生素及开医嘱时间(包括加用过抗生素的时间)     key:抗生素名    "2020-08-20,2020-08-21 ..."
+        Map<String, List<String>> antibioticDate = Maps.newHashMap();
+        //抗生素加用集合   key:抗生素名    value:  0:未加用,1及以上:加用次数
+        Map<String, Integer> antibioticStatus = Maps.newHashMap();
+        //抗生素及各初始剂量     key:抗生素名    value:抗生素第一次使用时剂量
+        Map<String, List<Double>> antibioticValue = Maps.newHashMap();
+
+        List<Map<String, String>> docAdvStruct = doctorAdviceDocs
+                .stream()
+                .filter(Objects::nonNull)
+                .map(DoctorAdviceDoc::getStructureMap)
+                .filter(x -> StringUtil.isNotBlank(x.get("药品类型")) && x.get("药品类型").contains("抗生素") && StringUtil.isNotBlank(x.get("医嘱单次剂量")))
+                .filter(x -> StringUtil.isNotBlank(x.get("医嘱状态判别")) && !x.get("医嘱状态判别").contains("已停止"))
+                .collect(Collectors.toList());
+
+        String drugName = null, value = null, startDateStr = null;
+        for (Map<String, String> structMap : docAdvStruct) {
+            drugName = structMap.get("医嘱项目名称");
+            value = structMap.get("医嘱单次剂量");
+            startDateStr = structMap.get("医嘱开始时间");
+            drugName = removeBracket(drugName);
+            collectAntibioticInfo(antibioticDate, antibioticStatus, antibioticValue, drugName, value, startDateStr);
+        }
+
+        //把抗生素没加用过的抗生素删除
+        for (Map.Entry<String, Integer> as : antibioticStatus.entrySet()) {
+            if (as.getValue() == 0) {
+                antibioticDate.remove(as.getKey());
+                antibioticValue.remove(as.getKey());
+            }
+        }
+        //抗生素加用过的集合如果为空,则一个抗生素都没有加用过,直接返回0
+        if (antibioticDate.size() == 0) {
+            return;
+        }
+
+        //病程记录中没有用量的抗生素及查房时间       key:抗生素名    "2020-08-20,2020-08-21 ..."
+        Map<String, List<String>> antibioticDateCourse = Maps.newHashMap();
+        String dateStr = null;
+        /*********************************************查房记录********************************************************/
+        if (threeLevelWardDocs.size() > 0) {
+            List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDocs.get(0).getAllDoctorWradDocs();
+            for (ThreeLevelWardDoc doc : allDoctorWradDocs) {
+                if (doc.getThreeLevelWardLabel().size() == 0) {
+                    continue;
+                }
+                dateStr = doc.getStructureMap().get("查房日期");
+                ThreeLevelWardLabel label = doc.getThreeLevelWardLabel().get(0);
+                List<Drug> drugs = label.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, dateStr, drugs);
+            }
+        }
+        /*********************************************术后首程********************************************************/
+        if (operationDocs.size() > 0) {
+            List<OperationDiscussionDoc> operationDiscussionDocs = operationDocs
+                    .stream()
+                    .map(OperationDoc::getOperationDiscussionDoc)
+                    .filter(Objects::nonNull)
+                    .filter(x -> x.getOperationDiscussionLabel() != null)
+                    .collect(Collectors.toList());
+            for (OperationDiscussionDoc discussionDoc : operationDiscussionDocs) {
+                dateStr = discussionDoc.getStructureMap().get("记录日期");
+                if (StringUtil.isBlank(dateStr)) {
+                    continue;
+                }
+                List<Drug> drugs = discussionDoc.getOperationDiscussionLabel().getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, dateStr, drugs);
+            }
+        }
+        /*********************************************出院小结********************************************************/
+        if (leaveHospitalDoc != null) {
+            LeaveHospitalLabel leaveHospitalLabel = leaveHospitalDoc.getLeaveHospitalLabel();
+            dateStr = leaveHospitalDoc.getStructureMap().get("出院时间");
+            if (leaveHospitalLabel != null && StringUtil.isNotBlank(dateStr)) {
+                List<Drug> drugs = leaveHospitalLabel.getDrugs();
+                getCourseDrugInfo(antibioticDateCourse, dateStr, drugs);
+            }
+        }
+        //将病程日期排序
+        antibioticDateCourse.forEach((x, y) -> y.sort(Comparator.naturalOrder()));
+
+        /**
+         * 1.antibioticDate:从医嘱中取   key:抗生素名    value:医嘱中该抗生素所有加用时的时间(包括初始使用时间)
+         * 2.antibioticDateWard:从查房记录中取     key:抗生素名    value:病程记录中该抗生素所有没有用量时的查房时间(包括初始使用时间)
+         * 3.医嘱中该抗生素初始使用时间往后两天内,查房记录中该抗生素初始使用时间也在这两天内,则满足一半。
+         * 4.医嘱中该抗生素加用时的时间往后两天内,查房记录中该抗生素加用时间也在这两天内,则满足条件,该抗生素通过该条规则
+         */
+        StringBuffer sb = new StringBuffer();
+        String drugKey = null, start = null, change = null, wardStartStr = null, wardChangeStr = null;
+        List<String> dateList = null;
+        for (Map.Entry<String, List<String>> ad : antibioticDate.entrySet()) {
+            drugKey = ad.getKey();
+            String drugStandardWord = similarityUtil.getDrugStandardWord(drugKey);
+            if (StringUtil.isNotBlank(drugStandardWord)) {
+                drugKey = drugStandardWord;
+            }
+            if (antibioticDateCourse.containsKey(drugKey)) {
+                dateList = ad.getValue();
+                List<String> wardDateStr = antibioticDateCourse.get(drugKey);
+                for (int i = 0; i < dateList.size(); i++) {
+                    start = dateList.get(i);        //抗生素开医嘱时间
+                    Date adStart = DateUtil.dateZeroClear(StringUtil.parseDateTime(start));
+                    for (int j = 0; j < wardDateStr.size(); j++) {
+                        wardStartStr = wardDateStr.get(j);         //查房记录开抗生素时间
+                        Date wardStart = StringUtil.parseDateTime(wardStartStr);
+                        if ((adStart.before(wardStart) && !CatalogueUtil.compareTime(adStart, wardStart, 48 * 60L))
+                                || (wardStart.before(adStart) && !CatalogueUtil.compareTime(wardStart, adStart, 24 * 60L))) {
+                            infoAppend(sb, drugKey, start);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (sb.toString().length() > 0) {
+            status.set("-1");
+            info.set(sb.toString().substring(0, sb.toString().length() - 1));
+        }
+    }
+
+    /**
+     * 收集各模块药品信息
+     *
+     * @param antibioticDateWard 病程中抗生素使用所有时间
+     * @param dateStr            记录日期
+     * @param drugs              模型提取出的药品列表
+     */
+    private void getCourseDrugInfo(Map<String, List<String>> antibioticDateWard, String dateStr, List<Drug> drugs) {
+        for (Drug drug : drugs) {
+            String wardDrug = drug.getName();
+            wardDrug = removeBracket(wardDrug);
+            String drugStandardWord = similarityUtil.getDrugStandardWord(wardDrug);
+            if (StringUtil.isNotBlank(drugStandardWord)) {
+                wardDrug = drugStandardWord;
+            }
+            if (drug.getConsumption() == null) {
+                if (antibioticDateWard.containsKey(wardDrug)) {
+                    antibioticDateWard.get(wardDrug).add(dateStr);
+                } else {
+                    antibioticDateWard.put(wardDrug, Lists.newArrayList(dateStr));
+                }
+            }
+        }
+    }
+
+    /**
+     * 收集抗生素各种信息
+     *
+     * @param antibioticDate   抗生素使用所有时间
+     * @param antibioticStatus 抗生素用量改变状态
+     * @param antibioticValue  抗生素及用量
+     * @param drugName         抗生素名称
+     * @param value            抗生素用量
+     * @param startDateStr     抗生素使用时间(医嘱开始时间或查房时间)
+     */
+    private void collectAntibioticInfo(Map<String, List<String>> antibioticDate, Map<String, Integer> antibioticStatus,
+                                       Map<String, List<Double>> antibioticValue, String drugName, String value, String startDateStr) {
+        double v = -1;
+        try {
+            v = Double.parseDouble(getNumber(value));
+        } catch (Exception e) {
+            System.out.println("THR03074:       " + drugName + ":" + value + "解析异常");
+        }
+        if (v < 0) {
+            return;
+        }
+        if (v > 100) {
+            v = v / 1000;
+        }
+        if (!antibioticValue.containsKey(drugName)) {
+            antibioticValue.put(drugName, Lists.newArrayList(v));
+            antibioticDate.put(drugName, Lists.newArrayList(startDateStr));
+            antibioticStatus.put(drugName, 0);
+        } else {
+            //1.如果抗生素剂量有变化,则记录该抗生素开始时间
+            List<Double> beforeValue = antibioticValue.get(drugName);
+            if (beforeValue.get(beforeValue.size() - 1) != v) {
+                beforeValue.add(v);
+                antibioticValue.put(drugName, beforeValue);//添加该抗生素更大的值
+                antibioticStatus.put(drugName, antibioticStatus.get(drugName) + 1);
+                antibioticDate.get(drugName).add(startDateStr);
+                return;
+            }
+            //2.如果抗生素剂量两次开启的时间间隔相差3天,也记录该抗生素开始时间
+            if (antibioticDate.get(drugName).size() > 0) {
+                List<String> currentAntibioticDate = antibioticDate.get(drugName);
+                String lastDate = currentAntibioticDate.get(currentAntibioticDate.size() - 1);
+                if (CatalogueUtil.compareTime(StringUtil.parseDateTime(lastDate), StringUtil.parseDateTime(startDateStr), 72 * 60L)) {
+                    beforeValue.add(v);
+                    antibioticValue.put(drugName, beforeValue);//添加该抗生素值
+                    antibioticStatus.put(drugName, antibioticStatus.get(drugName) + 1);
+                    antibioticDate.get(drugName).add(startDateStr);
+                }
+            }
+        }
+    }
+
+    public static String getNumber(String content) {
+        String group = "";
+        String compile = "([1-9]\\d*\\.?\\d*)|(0\\.\\d*[1-9]|\\.\\d*[1-9]|0)";
+        Pattern p = Pattern.compile(compile);
+        Matcher matcher = p.matcher(content);
+        if (matcher.find()) {
+            group = matcher.group(0);
+        }
+        return group;
+    }
+
+    /**
+     * 如果文本包含中括号([海正]美罗培南针),取括号之后的文字
+     *
+     * @param str
+     * @return
+     */
+    private String removeBracket(String str) {
+        if (str.contains("]") && str.indexOf("]") != str.length() - 1) {
+            return str.substring(str.indexOf("]") + 1);
+        }
+        return str;
+    }
+
+    /**
+     * 拼接提示信息
+     *
+     * @param sb
+     * @param drugKey
+     * @param date
+     */
+    private void infoAppend(StringBuffer sb, String drugKey, String date) {
+        sb.append(drugKey).append("(").append(DateUtil.formatDate(StringUtil.parseDateTime(date))).append(")").append(",");
+    }
+
+}

+ 19 - 0
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/process/EntityProcess.java

@@ -241,6 +241,25 @@ public class EntityProcess {
         return null;
     }
 
+    /**
+     * 只找出现在lemma实体位置之后的实体
+     * @param detailLemma
+     * @param t
+     * @param entityType
+     * @param <T>
+     * @return
+     * @throws Exception
+     */
+    protected <T> T findTAfter(Lemma detailLemma, T t, String entityType) throws Exception {
+        for (Lemma lemma : detailLemma.getRelationLemmas()) {
+            if (lemma.getProperty().equals(entityType) && detailLemma.getFrom() < lemma.getFrom()) {
+                BeanUtils.copyProperty(t, "name", lemma.getText());
+                return t;
+            }
+        }
+        return null;
+    }
+
 //    /**
 //     * 疾病名称需要映射操作
 //     * @param lemma

+ 5 - 5
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/process/EntityProcessDrug.java

@@ -23,11 +23,11 @@ public class EntityProcessDrug extends EntityProcess {
             for (Lemma lemma : DrugLemmas) {
                 Drug drug = new Drug();
                 drug.setName(lemma.getText());
-                drug.setConsumption(findT(lemma, new Consumption(), EntityEnum.CONSUMPTION.toString().split("-")[0]));
-                drug.setUsageWardRound(findT(lemma, new UsageWardRound(), EntityEnum.USAGE_WARD_ROUND.toString()));
-                drug.setFrequency(findT(lemma, new Frequency(), EntityEnum.FREQUENCY.toString()));
-                drug.setStop(findT(lemma, new Stop(), EntityEnum.STOP.toString()));
-                drug.setReasonsForAntibiotic(findT(lemma, new ReasonsForAntibiotic(), EntityEnum.REASONS_FOR_ANTIBIOTIC.toString()));
+                drug.setConsumption(findTAfter(lemma, new Consumption(), EntityEnum.CONSUMPTION.toString().split("-")[0]));
+                drug.setUsageWardRound(findTAfter(lemma, new UsageWardRound(), EntityEnum.USAGE_WARD_ROUND.toString()));
+                drug.setFrequency(findTAfter(lemma, new Frequency(), EntityEnum.FREQUENCY.toString()));
+                drug.setStop(findTAfter(lemma, new Stop(), EntityEnum.STOP.toString()));
+                drug.setReasonsForAntibiotic(findTAfter(lemma, new ReasonsForAntibiotic(), EntityEnum.REASONS_FOR_ANTIBIOTIC.toString()));
                 drugs.add(drug);
             }
         } catch (Exception e) {

+ 12 - 12
kernel/src/main/java/com/lantone/qc/kernel/structure/ai/process/EntityProcessThreeLevelWard.java

@@ -166,7 +166,7 @@ public class EntityProcessThreeLevelWard extends EntityProcess {
             for (Lemma lemma : laboratoryPackageLemmas) {
                 LaboratoryPackage laboratoryPackage = new LaboratoryPackage();
                 laboratoryPackage.setName(lemma.getText());
-                laboratoryPackage.setCheckTime(findT(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));
+                laboratoryPackage.setCheckTime(findTAfter(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));
                 laboratoryPackages.add(laboratoryPackage);
             }
             threeLevelWardLabel.setLaboratoryPackages(laboratoryPackages);
@@ -180,12 +180,12 @@ public class EntityProcessThreeLevelWard extends EntityProcess {
                 for (Lemma relationLemma : lemma.getRelationLemmas()) {
                     if (relationLemma.getProperty().equals(EntityEnum.LABORATORY_PACKAGE.toString())) {
                         LaboratoryPackage laboratoryPackage = new LaboratoryPackage();
-                        laboratoryPackage.setCheckTime(findT(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));
-                        laboratory.setLaboratoryPackage(findT(lemma, laboratoryPackage, EntityEnum.LABORATORY_PACKAGE.toString()));//实验室检查套餐
+                        laboratoryPackage.setCheckTime(findTAfter(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));
+                        laboratory.setLaboratoryPackage(findTAfter(lemma, laboratoryPackage, EntityEnum.LABORATORY_PACKAGE.toString()));//实验室检查套餐
                     }
                 }
-                laboratory.setCheckTime(findT(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));//检查时间
-                laboratory.setLaboratoryResults(findT(lemma, new LaboratoryResults(), EntityEnum.LABORATORY_RESULTS.toString()));//实验室检查结果
+                laboratory.setCheckTime(findTAfter(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));//检查时间
+                laboratory.setLaboratoryResults(findTAfter(lemma, new LaboratoryResults(), EntityEnum.LABORATORY_RESULTS.toString()));//实验室检查结果
                 laboratories.add(laboratory);
             }
             threeLevelWardLabel.setLaboratories(laboratories);
@@ -196,8 +196,8 @@ public class EntityProcessThreeLevelWard extends EntityProcess {
             for (Lemma lemma : auxiliaryExaminationLemmas) {
                 AuxiliaryExamination auxiliaryExamination = new AuxiliaryExamination();
                 auxiliaryExamination.setName(lemma.getText());
-                auxiliaryExamination.setCheckTime(findT(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));
-                auxiliaryExamination.setAuxiliaryExaminationResults(findT(lemma, new AuxiliaryExaminationResults(), EntityEnum.AUXILIARY_EXAMINATION_RESULTS.toString()));
+                auxiliaryExamination.setCheckTime(findTAfter(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));
+                auxiliaryExamination.setAuxiliaryExaminationResults(findTAfter(lemma, new AuxiliaryExaminationResults(), EntityEnum.AUXILIARY_EXAMINATION_RESULTS.toString()));
                 auxiliaryExaminations.add(auxiliaryExamination);
             }
             threeLevelWardLabel.setAuxiliaryExaminations(auxiliaryExaminations);
@@ -208,11 +208,11 @@ public class EntityProcessThreeLevelWard extends EntityProcess {
             for (Lemma lemma : DrugLemmas) {
                 Drug drug = new Drug();
                 drug.setName(lemma.getText());
-                drug.setConsumption(findT(lemma, new Consumption(), EntityEnum.CONSUMPTION.toString().split("-")[0]));
-                drug.setUsageWardRound(findT(lemma, new UsageWardRound(), EntityEnum.USAGE_WARD_ROUND.toString()));
-                drug.setFrequency(findT(lemma, new Frequency(), EntityEnum.FREQUENCY.toString()));
-                drug.setStop(findT(lemma, new Stop(), EntityEnum.STOP.toString()));
-                drug.setReasonsForAntibiotic(findT(lemma, new ReasonsForAntibiotic(), EntityEnum.REASONS_FOR_ANTIBIOTIC.toString()));
+                drug.setConsumption(findTAfter(lemma, new Consumption(), EntityEnum.CONSUMPTION.toString().split("-")[0]));
+                drug.setUsageWardRound(findTAfter(lemma, new UsageWardRound(), EntityEnum.USAGE_WARD_ROUND.toString()));
+                drug.setFrequency(findTAfter(lemma, new Frequency(), EntityEnum.FREQUENCY.toString()));
+                drug.setStop(findTAfter(lemma, new Stop(), EntityEnum.STOP.toString()));
+                drug.setReasonsForAntibiotic(findTAfter(lemma, new ReasonsForAntibiotic(), EntityEnum.REASONS_FOR_ANTIBIOTIC.toString()));
                 drugs.add(drug);
             }
             threeLevelWardLabel.setDrugs(drugs);