Browse Source

颈动脉调整

jeremy 1 year ago
parent
commit
a31d486fba
4 changed files with 517 additions and 14 deletions
  1. 6 0
      Manage/AILabelEnum.cs
  2. 302 2
      Manage/CarotidDiagnosis.cs
  3. 1 0
      Manage/DiagnosisPerImageModel.cs
  4. 208 12
      Service/AIDiagnosisService.cs

+ 6 - 0
Manage/AILabelEnum.cs

@@ -39,4 +39,10 @@ namespace WingAIDiagnosisService.Manage
         Cirrhosis = 7,//肝硬化(弥漫性,良性)
         PCLD = 8,//多囊肝(弥漫性,良性)
     }
+
+    public enum AICarotidLabelEnum
+    {
+        BIRads1 = 0,//未见明显异常
+        Plaque = 1,//斑块(Plaque,局灶性,良性)
+    }
 }

+ 302 - 2
Manage/CarotidDiagnosis.cs

@@ -1,7 +1,307 @@
+using System.Collections.Generic;
+using System.Linq;
+using WingInterfaceLibrary.Enum;
+
 namespace WingAIDiagnosisService.Manage
 {
-    public class CarotidDiagnosis
+    public class CarotidDiagnosis : BaseDiagnosis
     {
-        
+        private AICarotidLabelEnum? _mimanLabel;
+        private DiagnosisPerImageModel _mimanDiagnosisImage = null;
+        public CarotidDiagnosis(List<DiagnosisPerImageModel> recordResult, DiagnosisOrganEnum organ) : base(recordResult, organ)
+        {
+        }
+
+        #region Private 
+
+        private AIDetectedObject CheckFocus(AIDetectedObject message)
+        {
+            return message;
+        }
+
+        private bool IsMiMan(int label)
+        {
+            return false;
+        }
+
+        private bool IsMalignant(int label)
+        {
+            return false;
+        }
+
+        private List<int> ExistingLabels(List<DiagnosisPerImageModel> results)
+        {
+            var existingLabels = new List<int> { (int)AICarotidLabelEnum.BIRads1 };
+            existingLabels.AddRange(results.SelectMany(x => x.GetLabels()));
+            return existingLabels.Distinct().ToList();
+        }
+
+        /// <summary>根据诊断结果返回弥漫病灶类型</summary>
+        /// <param name="results"></param>
+        /// <returns></returns>
+        private void GetMiManLabel(List<DiagnosisPerImageModel> results)
+        {
+        }
+
+        /// <summary>确定病例弥漫性病灶类型</summary>
+        private void ConfirmMiManLabel()
+        {
+            var imageResults = RecordDiagnosisResult.Where(x => x.DataType == DataType.VinnoVidSingle || x.DataType == DataType.ThirdVidSingle)?.ToList() ?? new List<DiagnosisPerImageModel>();
+            var movieResults = RecordDiagnosisResult.Where(x => x.DataType == DataType.VinnoVidMovie || x.DataType == DataType.ThirdVidMovie)?.ToList() ?? new List<DiagnosisPerImageModel>();
+            if (movieResults.Any())
+            {
+                GetMiManLabel(movieResults);
+            }
+            else
+            {
+                GetMiManLabel(imageResults);
+            }
+        }
+
+        /// <summary>查询横截面最大的图</summary>
+        /// <param name="label"></param>
+        /// <returns></returns>
+        private DiagnosisPerImageModel GetMaxLesionSizeImage(AICarotidLabelEnum label)
+        {
+            double maxLesionSize = 0;
+            DiagnosisPerImageModel resultData = null;
+            foreach (var diagResult in RecordDiagnosisResult)
+            {
+                //result 这张图要不要
+                if (!diagResult.GetLabels().Contains((int)label))
+                {
+                    continue;
+                }
+                var isChosed = false;
+                foreach (var organResult in diagResult.DiagResultsForEachOrgan)
+                {
+                    if (isChosed)
+                    {
+                        break;
+                    }
+                    foreach (var detectedObjectInfo in organResult.DetectedObjects)
+                    {
+                        if (detectedObjectInfo.Label == (int)label)
+                        {
+                            var currLesionSize = GetMaxLesionSize(detectedObjectInfo);
+                            if (currLesionSize > maxLesionSize)
+                            {
+                                //要
+                                isChosed = true;
+                                maxLesionSize = currLesionSize;
+                                resultData = diagResult;
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+            return resultData;
+        }
+
+        /// <summary>局灶性选图</summary>
+        /// <returns></returns>
+        private List<DiagnosisPerImageModel> GetFocusImages()
+        {
+            var labels = new List<AICarotidLabelEnum>
+            {
+                AICarotidLabelEnum.Plaque,
+            };
+            var focusImages = new List<AICarotidFocusImageModel>();
+            foreach (var label in labels)
+            {
+                var diagnosisImage = GetMaxLesionSizeImage(label);
+                if (diagnosisImage != null)//!focusImages.Any(x => x.DiagnosisImage.TerminalDataId == diagnosisImage.TerminalDataId && x.DiagnosisImage.AIDiagResult.Index == diagnosisImage.AIDiagResult.Index)
+                {
+                    focusImages.Add(new AICarotidFocusImageModel { Label = label, DiagnosisImage = diagnosisImage });
+                }
+            }
+
+            var resultData = new List<DiagnosisPerImageModel>();
+            var mimanChosed = false;
+            foreach (var diagResult in focusImages)
+            {
+                if (resultData.Any(x => x.RemedicalCode == diagResult.DiagnosisImage.RemedicalCode && x.Index == diagResult.DiagnosisImage.Index))
+                {
+                    continue;
+                }
+                var otherLabels = focusImages.Where(x => x.DiagnosisImage.RemedicalCode != diagResult.DiagnosisImage.RemedicalCode || x.DiagnosisImage.Index != diagResult.DiagnosisImage.Index)
+                    .Select(x => x.Label).ToList();
+                var organResultList = new List<AIDiagnosisResultPerOrgan>();
+                foreach (var organResult in diagResult.DiagnosisImage.DiagResultsForEachOrgan)
+                {
+                    var detectedObjects = organResult.DetectedObjects.Where(x => !otherLabels.Contains((AICarotidLabelEnum)x.Label))?.ToList() ?? new List<AIDetectedObject>();
+                    if (mimanChosed)
+                    {
+                        detectedObjects = detectedObjects.Where(x => !IsMiMan(x.Label))?.ToList() ?? new List<AIDetectedObject>();
+                    }
+                    if (detectedObjects != null && detectedObjects.Any())
+                    {
+                        organResult.DetectedObjects = detectedObjects.ToList();
+                        organResultList.Add(organResult);
+                        if (detectedObjects.Any(x => IsMiMan(x.Label)))
+                        {
+                            mimanChosed = true;
+                        }
+                    }
+                }
+                diagResult.DiagnosisImage.DiagResultsForEachOrgan = organResultList;
+                resultData.Add(diagResult.DiagnosisImage);
+            }
+            return resultData;
+        }
+
+        #endregion
+
+        /// <summary>筛选有效的AI诊断记录</summary>
+        /// <param name="allResult"></param>
+        /// <returns></returns>
+        public override void CheckDiagResultIndex()
+        {
+            var validResult = new List<DiagnosisPerImageModel>();
+            foreach (var diagResult in RecordDiagnosisResult)
+            {
+                var organResultList = new List<AIDiagnosisResultPerOrgan>();
+                foreach (var organResult in diagResult.DiagResultsForEachOrgan)
+                {
+                    var valid = CheckResultValid(organResult);
+                    if (valid != null)
+                    {
+                        organResultList.Add(valid);
+                    }
+                }
+                if (organResultList.Any())
+                {
+                    diagResult.DiagResultsForEachOrgan = organResultList;
+                    validResult.Add(diagResult);
+                }
+            }
+            RecordDiagnosisResult = validResult;
+        }
+
+        /// <summary>筛选报告可用诊断结果</summary>
+        /// <param name="validResults"></param>
+        /// <returns></returns>
+        public override List<DiagnosisPerImageModel> GetReportResults()
+        {
+            if (!RecordDiagnosisResult.Any())
+            {
+                return RecordDiagnosisResult;
+            }
+
+            if (!HasSick())
+            {
+                //未见异常
+                RecordDiagnosisResult = new List<DiagnosisPerImageModel> { RecordDiagnosisResult.FirstOrDefault() };
+            }
+            else
+            {
+                var reportResults = GetFocusImages();
+                if (!reportResults.Any() && _mimanDiagnosisImage != null)
+                {
+                    //只有弥漫的情况
+                    reportResults = new List<DiagnosisPerImageModel> { _mimanDiagnosisImage };
+                }
+                RecordDiagnosisResult = reportResults;
+            }
+            InitialAIImage();
+            return RecordDiagnosisResult;
+        }
+
+        /// <summary>判断并返回有效的诊断描述</summary>
+        /// <param name="message"></param>
+        /// <returns></returns>
+        public override AIDiagnosisResultPerOrgan CheckResultValid(AIDiagnosisResultPerOrgan message)
+        {
+            if (message.Organ != DiagnosisOrganEnum.CarotidArtery)
+            {
+                return null;
+            }
+            var result = message;
+            var validDetectedObjects = new List<AIDetectedObject>();
+            foreach (var obj in message.DetectedObjects)
+            {
+                var obj_new = CheckFocus(obj);
+                if (obj_new != null)
+                {
+                    validDetectedObjects.Add(obj_new);
+                }
+            }
+            if (validDetectedObjects.Any())
+            {
+                result.DetectedObjects = validDetectedObjects;
+                return result;
+            }
+            return null;
+        }
+
+        /// <summary>判断AI诊断结果</summary>
+        /// <returns></returns>
+        public override DiagnosisConclusion GetAIStatus()
+        {
+            var status = DiagnosisConclusion.Unrecognized;
+            bool existMalignant = false;
+            bool existBenign = false;
+            if (RecordDiagnosisResult != null && RecordDiagnosisResult.Any())
+            {
+                foreach (var diagResult in RecordDiagnosisResult)
+                {
+                    if (existMalignant && existBenign)
+                        break;
+                    if (diagResult.PriorityScore > 0 && diagResult.DiagResultsForEachOrgan != null)
+                    {
+                        foreach (var organ in diagResult.DiagResultsForEachOrgan)
+                        {
+                            if (organ.DetectedObjects != null)
+                            {
+                                if (!existMalignant)
+                                {
+                                    if (organ.DetectedObjects.Any(a => IsMalignant(a.Label)))
+                                    {
+                                        existMalignant = true;
+                                    }
+                                }
+
+                                if (!existBenign)
+                                {
+                                    if (organ.DetectedObjects.Any(a => a.Label >= 1))
+                                    {
+                                        existBenign = true;
+                                    }
+                                }
+                            }
+                        }
+
+                        if (existMalignant)
+                        {
+                            status = existBenign ? DiagnosisConclusion.BenignAndMalignant : DiagnosisConclusion.Malignant;
+                        }
+                        else
+                        {
+                            status = existBenign ? DiagnosisConclusion.Benign : DiagnosisConclusion.NoObviousLesion;
+                        }
+                    }
+                }
+            }
+            return status;
+        }
+
+        /// <summary>
+        /// 是否恶性病灶
+        /// </summary>
+        /// <param name="label"></param>
+        /// <returns></returns>
+        protected override bool IsMalignant(AIDetectedObject detectedObject)
+        {
+            return false;
+        }
+
+
+    }
+
+    public class AICarotidFocusImageModel
+    {
+        public AICarotidLabelEnum Label { get; set; }
+        public DiagnosisPerImageModel DiagnosisImage { get; set; }
     }
 }

+ 1 - 0
Manage/DiagnosisPerImageModel.cs

@@ -4,6 +4,7 @@ using AI.Common;
 using AI.DiagSystem;
 using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
+using WingInterfaceLibrary.Enum;
 
 namespace WingAIDiagnosisService.Manage
 {

+ 208 - 12
Service/AIDiagnosisService.cs

@@ -162,7 +162,7 @@ namespace WingAIDiagnosisService.Service
                         var resultData = new DiagnosisImageResult();
                         if (DiagnosisHelper.IsCarotid(imageData))
                         {
-                            if (_isCarotidOn && imageData.ImageCount > DiagnosisHelper.CarotidMinImageCounts)
+                            if (_isCarotidOn)
                             {
                                 //颈动脉
                                 var result = await CarotidDiagnosis(imageData);
@@ -444,17 +444,47 @@ namespace WingAIDiagnosisService.Service
         /// <show>false</show>
         public async Task<DiagnosisReportResult> DiagnosisReportAsync(DiagnosisReportRequest request)
         {
+            var disgnosisReportResult = new DiagnosisReportResult();
             try
             {
-                if (request.Organ == DiagnosisOrganEnum.CarotidArtery)
+                var is3DCarotid = false;
+                if (request.Organ == DiagnosisOrganEnum.CarotidArtery && is3DCarotid)
                 {
                     var result = await GetCarotidAIMeasureResult(request);
                     return result;
                 }
                 else
                 {
-                    var manager = await CreateDiagnosisManagerAsync(request);
-                    var reportPerImages = manager.GetReportResults();
+                    var reportPerImages = new List<DiagnosisPerImageModel>();
+                    if (request.Organ == DiagnosisOrganEnum.CarotidArtery)
+                    {
+                        var leftRemedicals = request.RemedicalList.Where(x => x.CarotidResult.CarotidScanType == CarotidScanTypeEnum.CarotidLeft)?.ToList() ?? new List<DiagnosisRemicalDTO>();
+                        var leftRemedicalCode = string.Empty;
+                        if (leftRemedicals.Any())
+                        {
+                            var managerLeft = await CreateDiagnosisManagerAsync(new DiagnosisReportRequest { Organ = request.Organ, RemedicalList = leftRemedicals });
+                            var perImages = managerLeft.GetReportResults();
+                            leftRemedicalCode = perImages.FirstOrDefault()?.RemedicalCode;
+                            reportPerImages.AddRange(perImages);
+                        }
+                        disgnosisReportResult.CarotidItems.AddRange(GetCarotidLeftReportItems(leftRemedicals.FirstOrDefault(x => x.RemedicalCode == leftRemedicalCode)));
+
+                        var rightRemedicals = request.RemedicalList.Where(x => x.CarotidResult.CarotidScanType == CarotidScanTypeEnum.CarotidRight)?.ToList() ?? new List<DiagnosisRemicalDTO>();
+                        var rightRemedicalCode = string.Empty;
+                        if (rightRemedicals.Any())
+                        {
+                            var managerRight = await CreateDiagnosisManagerAsync(new DiagnosisReportRequest { Organ = request.Organ, RemedicalList = rightRemedicals });
+                            var perImages = managerRight.GetReportResults();
+                            rightRemedicalCode = perImages.FirstOrDefault()?.RemedicalCode;
+                            reportPerImages.AddRange(perImages);
+                        }
+                        disgnosisReportResult.CarotidItems.AddRange(GetCarotidRightReportItems(rightRemedicals.FirstOrDefault(x => x.RemedicalCode == rightRemedicalCode)));
+                    }
+                    else
+                    {
+                        var manager = await CreateDiagnosisManagerAsync(request);
+                        reportPerImages = manager.GetReportResults();
+                    }
                     var diagnosisConclusion = GetDiagnosisConclusion(reportPerImages);
                     var diagnosisOrgans = GetDiagnosisOrgans(reportPerImages);
 
@@ -480,18 +510,167 @@ namespace WingAIDiagnosisService.Service
                         perImageResult.DiagnosisOrgans = organs;
                         diagnosisResult.Add(perImageResult);
                     }
-                    return new DiagnosisReportResult
-                    {
-                        DiagnosisConclusion = (DiagnosisConclusionEnum)diagnosisConclusion,
-                        DiagnosisResult = diagnosisResult,
-                    };
+                    disgnosisReportResult.DiagnosisConclusion = (DiagnosisConclusionEnum)diagnosisConclusion;
+                    disgnosisReportResult.DiagnosisResult = diagnosisResult;
                 }
             }
             catch (Exception ex)
             {
                 Logger.WriteLineWarn($"AIService DiagnosisReport err, {ex}");
             }
-            return new DiagnosisReportResult();
+            return disgnosisReportResult;
+        }
+
+        private List<DataItemDTO> GetCarotidLeftReportItems(DiagnosisRemicalDTO leftData)
+        {
+            var reportItems = new List<DataItemDTO>();
+            if (leftData == null)
+            {
+                reportItems.Add(new DataItemDTO { Key = "bd170b6a-e052-42f0-a778-4ec85138c1c6;33c0aaf8-e48e-4474-af68-b47d2378073f;LeftConclusion", Value = FormatterPlaceholder2($"NoPlaque2") });
+                return reportItems;
+            }
+            var carotidResultInfos = GetCarotidResultInfos(leftData);
+            if (carotidResultInfos.Any(x => x.DetectedObjects.Any(x => x.Label == 1)))
+            {
+                //有斑块
+                reportItems.Add(new DataItemDTO { Key = "bd170b6a-e052-42f0-a778-4ec85138c1c6;33c0aaf8-e48e-4474-af68-b47d2378073f;LeftConclusion", Value = FormatterPlaceholder2($"OnePlaque") });
+                var info = GetReportDetectedObject(carotidResultInfos);
+                var reportDetectedObject = info.Item1;
+                var maxArea = Math.Round(info.Item2 * 0.1, 2);
+                reportItems.Add(new DataItemDTO { Key = "d2449fa2-70e7-45d1-80e3-f69c62652186;98d1e829-b0ee-440d-ae3b-02ff74521357;LeftPlaqueThick", Value = info.Item3.ToString() });
+                var locationItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueLocation);
+                if (locationItem != null)
+                {
+                    reportItems.Add(new DataItemDTO { Key = "6f57bb90-6492-421e-ad3e-6c684b7f7452;6e36fa47-edb2-4ed8-8521-ddb9e1fa5536;LeftPlaquePosition", Value = FormatterPlaceholder2($"{locationItem.Value}") });
+                }
+                var echoItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueEchoPattern);
+                if (echoItem != null)
+                {
+                    reportItems.Add(new DataItemDTO { Key = "ccef71cd-1c52-4614-a54f-d6d58cb8c586;d440eb6e-2630-4787-8700-486d097ba9f1;LeftPlaqueEcho", Value = FormatterPlaceholder2($"{echoItem.Value}") });
+                }
+                var rateOfStenosis = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidRateOfStenosis);
+                if (rateOfStenosis != null)
+                {
+                    var rateOfStenosisValue = string.Empty;
+                    var rate = rateOfStenosis.Value.ToFloat() * 100;
+                    if (rate < 30)
+                    {
+                        rateOfStenosisValue = "Normal";
+                    }
+                    else if (rate >= 30 && rate < 50)
+                    {
+                        rateOfStenosisValue = "Mild";
+                    }
+                    else if (rate >= 50 && rate < 70)
+                    {
+                        rateOfStenosisValue = "Moderate";
+                    }
+                    else if (rate >= 70 && rate < 100)
+                    {
+                        rateOfStenosisValue = "Severe";
+                    }
+                    else
+                    {
+                        rateOfStenosisValue = "Blockage";
+                    }
+                    reportItems.Add(new DataItemDTO { Key = "e3610e58-79c4-4e18-94c9-8928583b9dab;e6da9399-b849-4017-a3b8-e3212f55c4a4;LeftStenosisRate", Value = FormatterPlaceholder2(rateOfStenosisValue) });
+                }
+                var innerDiameter = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidInnerDiameter);
+                if (innerDiameter != null && !string.IsNullOrWhiteSpace(innerDiameter.Value))
+                {
+                    var diagnosisMeasuringLine = JsonConvert.DeserializeObject<AIDiagnosisMeasuringLine>(innerDiameter.Value);
+                    var measuringLineLengthInPixel = Math.Round(diagnosisMeasuringLine.MeasuringLineLengthInPixel * 0.1, 2);
+                    reportItems.Add(new DataItemDTO { Key = "9a6f96bb-b81e-407d-bc84-9d9815e96696;fe948295-b065-46b9-ab25-fe80144d7bff;LeftCarotidAD", Value = measuringLineLengthInPixel.ToString() });
+                }
+
+            }
+            else
+            {
+                // reportItems.Add(new DataItemDTO { Key = "bd170b6a-e052-42f0-a778-4ec85138c1c6;33c0aaf8-e48e-4474-af68-b47d2378073f;LeftConclusion", Value = FormatterPlaceholder2($"NoPlaque2") });
+                reportItems.Add(new DataItemDTO { Key = "bd170b6a-e052-42f0-a778-4ec85138c1c6;33c0aaf8-e48e-4474-af68-b47d2378073f;LeftConclusion", Value = "" });
+                reportItems.Add(new DataItemDTO { Key = "d2449fa2-70e7-45d1-80e3-f69c62652186;98d1e829-b0ee-440d-ae3b-02ff74521357;LeftPlaqueThick", Value = "" });
+                reportItems.Add(new DataItemDTO { Key = "6f57bb90-6492-421e-ad3e-6c684b7f7452;6e36fa47-edb2-4ed8-8521-ddb9e1fa5536;LeftPlaquePosition", Value = "" });
+                reportItems.Add(new DataItemDTO { Key = "ccef71cd-1c52-4614-a54f-d6d58cb8c586;d440eb6e-2630-4787-8700-486d097ba9f1;LeftPlaqueEcho", Value = "" });
+                reportItems.Add(new DataItemDTO { Key = "9a6f96bb-b81e-407d-bc84-9d9815e96696;fe948295-b065-46b9-ab25-fe80144d7bff;LeftCarotidAD", Value = "" });
+                reportItems.Add(new DataItemDTO { Key = "e3610e58-79c4-4e18-94c9-8928583b9dab;e6da9399-b849-4017-a3b8-e3212f55c4a4;LeftStenosisRate", Value = "" });
+            }
+            return reportItems;
+        }
+
+        private List<DataItemDTO> GetCarotidRightReportItems(DiagnosisRemicalDTO rightData)
+        {
+            var reportItems = new List<DataItemDTO>();
+            if (rightData == null)
+            {
+                reportItems.Add(new DataItemDTO { Key = "ec4c775e-601c-48cc-a1a9-f39c8629e3f7;9918912e-b702-4a2b-8b4f-61dcfb846be3;RightConclusion", Value = FormatterPlaceholder2($"NoPlaque2") });
+                return reportItems;
+            }
+            var carotidResultInfos = GetCarotidResultInfos(rightData);
+            if (carotidResultInfos.Any(x => x.DetectedObjects.Any(x => x.Label == 1)))
+            {
+                //有斑块
+                reportItems.Add(new DataItemDTO { Key = "ec4c775e-601c-48cc-a1a9-f39c8629e3f7;9918912e-b702-4a2b-8b4f-61dcfb846be3;RightConclusion", Value = FormatterPlaceholder2($"OnePlaque") });
+                var info = GetReportDetectedObject(carotidResultInfos);
+                var reportDetectedObject = info.Item1;
+                var maxArea = Math.Round(info.Item2 * 0.1, 2);
+                reportItems.Add(new DataItemDTO { Key = "8e467ffb-da00-4d34-9aac-34e4e8f91844;46166cb6-ad3a-4ca2-821e-bd872137fa64;RightPlaqueThick", Value = info.Item3.ToString() });
+                var locationItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueLocation);
+                if (locationItem != null)
+                {
+                    reportItems.Add(new DataItemDTO { Key = "1153870e-10c8-4674-99bf-108937db1060;053091d2-8ea0-4fcb-a222-00b46f60d12f;RightPlaquePosition", Value = FormatterPlaceholder2($"{locationItem.Value}") });
+                }
+                var echoItem = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.QlaqueEchoPattern);
+                if (echoItem != null)
+                {
+                    reportItems.Add(new DataItemDTO { Key = "c82e8655-169f-42be-ac99-5e7a56329924;e77f550d-37f3-492a-98dd-a981535383a5;RightPlaqueEcho", Value = FormatterPlaceholder2($"{echoItem.Value}") });
+                }
+                var rateOfStenosis = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidRateOfStenosis);
+                if (rateOfStenosis != null)
+                {
+                    var rateOfStenosisValue = string.Empty;
+                    var rate = rateOfStenosis.Value.ToFloat() * 100;
+                    if (rate < 30)
+                    {
+                        rateOfStenosisValue = "Normal";
+                    }
+                    else if (rate >= 30 && rate < 50)
+                    {
+                        rateOfStenosisValue = "Mild";
+                    }
+                    else if (rate >= 50 && rate < 70)
+                    {
+                        rateOfStenosisValue = "Moderate";
+                    }
+                    else if (rate >= 70 && rate < 100)
+                    {
+                        rateOfStenosisValue = "Severe";
+                    }
+                    else
+                    {
+                        rateOfStenosisValue = "Blockage";
+                    }
+                    reportItems.Add(new DataItemDTO { Key = "b0092e8a-25ba-4690-b70f-e3525e6aaa39;2e742ddc-fa90-47bb-ac24-664238773b30;RightStenosisRate", Value = FormatterPlaceholder2(rateOfStenosisValue) });
+                }
+                var innerDiameter = GetDescription(reportDetectedObject, DiagnosisDescriptionEnum.CarotidInnerDiameter);
+                if (innerDiameter != null && !string.IsNullOrWhiteSpace(innerDiameter.Value))
+                {
+                    var diagnosisMeasuringLine = JsonConvert.DeserializeObject<AIDiagnosisMeasuringLine>(innerDiameter.Value);
+                    var measuringLineLengthInPixel = Math.Round(diagnosisMeasuringLine.MeasuringLineLengthInPixel * 0.1, 2);
+                    reportItems.Add(new DataItemDTO { Key = "8c7543e9-95f2-4862-b2aa-4c4cb032948e;9f8e95ee-a262-41c2-9d4b-efbc7974b397;RightCarotidAD", Value = measuringLineLengthInPixel.ToString() });
+                }
+
+            }
+            else
+            {
+                // reportItems.Add(new DataItemDTO { Key = "ec4c775e-601c-48cc-a1a9-f39c8629e3f7;9918912e-b702-4a2b-8b4f-61dcfb846be3;RightConclusion", Value = FormatterPlaceholder2($"NoPlaque2") });
+                reportItems.Add(new DataItemDTO { Key = "ec4c775e-601c-48cc-a1a9-f39c8629e3f7;9918912e-b702-4a2b-8b4f-61dcfb846be3;RightConclusion", Value = "" });
+                reportItems.Add(new DataItemDTO { Key = "8e467ffb-da00-4d34-9aac-34e4e8f91844;46166cb6-ad3a-4ca2-821e-bd872137fa64;RightPlaqueThick", Value = "" });
+                    reportItems.Add(new DataItemDTO { Key = "1153870e-10c8-4674-99bf-108937db1060;053091d2-8ea0-4fcb-a222-00b46f60d12f;RightPlaquePosition", Value = "" });
+                    reportItems.Add(new DataItemDTO { Key = "c82e8655-169f-42be-ac99-5e7a56329924;e77f550d-37f3-492a-98dd-a981535383a5;RightPlaqueEcho", Value = "" });
+                    reportItems.Add(new DataItemDTO { Key = "b0092e8a-25ba-4690-b70f-e3525e6aaa39;2e742ddc-fa90-47bb-ac24-664238773b30;RightStenosisRate", Value = "" });
+                    reportItems.Add(new DataItemDTO { Key = "8c7543e9-95f2-4862-b2aa-4c4cb032948e;9f8e95ee-a262-41c2-9d4b-efbc7974b397;RightCarotidAD", Value = "" });
+            }
+            return reportItems;
         }
 
         /// <summary>
@@ -987,10 +1166,11 @@ namespace WingAIDiagnosisService.Service
             return carotidResultInfos;
         }
 
-        private Tuple<WingInterfaceLibrary.DTO.Comment.AIDetectedObject, int> GetReportDetectedObject(List<WingInterfaceLibrary.DTO.Comment.AIDiagnosisResultPerOrgan> carotidResultInfos)
+        private Tuple<WingInterfaceLibrary.DTO.Comment.AIDetectedObject, int, string> GetReportDetectedObject(List<WingInterfaceLibrary.DTO.Comment.AIDiagnosisResultPerOrgan> carotidResultInfos)
         {
             WingInterfaceLibrary.DTO.Comment.AIDetectedObject detectedObject = null;
             var maxArea = 0;
+            var maxAreaString = string.Empty;
             foreach (var organInfo in carotidResultInfos)
             {
                 var plaqueDetectedObjects = organInfo.DetectedObjects.Where(x => x.Label == 1);
@@ -1009,11 +1189,12 @@ namespace WingAIDiagnosisService.Service
                         {
                             detectedObject = dob;
                             maxArea = currArea;
+                            maxAreaString = $"{Math.Round(diagnosisLesionSize.VerticalLengthInPixel * 0.1, 2)} × {Math.Round(diagnosisLesionSize.HorizontalLengthInPixel * 0.1, 2)}";
                         }
                     }
                 }
             }
-            return new Tuple<WingInterfaceLibrary.DTO.Comment.AIDetectedObject, int>(detectedObject, maxArea);
+            return new Tuple<WingInterfaceLibrary.DTO.Comment.AIDetectedObject, int, string>(detectedObject, maxArea, maxAreaString);
         }
 
         private WingInterfaceLibrary.DTO.Comment.AIDiagnosisDescription GetDescription(WingInterfaceLibrary.DTO.Comment.AIDetectedObject detectedObject, DiagnosisDescriptionEnum descriptionType)
@@ -1052,6 +1233,8 @@ namespace WingAIDiagnosisService.Service
                     return new LiverDiagnosis(recordResults, request.Organ);
                 case DiagnosisOrganEnum.Thyroid://甲状腺
                     return new ThyroidDiagnosis(recordResults, request.Organ);
+                case DiagnosisOrganEnum.CarotidArtery://颈动脉
+                    return new CarotidDiagnosis(recordResults, request.Organ);
                 default:
                     throw new Exception($"not support organ type:{request.Organ.ToString()}");
             }
@@ -1067,6 +1250,14 @@ namespace WingAIDiagnosisService.Service
             resampleInputData.PlaqueAIImagePath = DiagnosisHelper.GetCacheFilePath(DiagnosisHelper.JPGFileSuffix);
             resampleInputData.YShapeAIImagePath = DiagnosisHelper.GetCacheFilePath(DiagnosisHelper.JPGFileSuffix);
             var resampleResult = TryResample(imageData, resampleInputData);
+            if (imageData.ImageCount <= DiagnosisHelper.CarotidMinImageCounts)
+            {
+                return new CarotidResultDTO
+                {
+                    CarotidScanType = (CarotidScanTypeEnum)resampleInputData.ScanType,
+                    CarotidScanDirection = (CarotidScanDirectionEnum)resampleInputData.CarotidScanDirection,
+                };
+            }
             if (resampleResult.ResampleErrorCode == ResampleErrorCode.Success)
             {
                 var carotidAIImageTokens = new List<CarotidAIImage>();
@@ -1311,6 +1502,11 @@ namespace WingAIDiagnosisService.Service
                         benignLabels = new List<int> { 1, 2, 7 };
                         malignantLabels = new List<int> { 3, 4, 5, 6 };
                     }
+                    else if (diagnosisResult.Organ == DiagnosisOrganEnum.CarotidArtery)
+                    {
+                        benignLabels = new List<int> { 1 };
+                        malignantLabels = new List<int> { };
+                    }
                     var labels = diagnosisResult.DetectedObjects.Select(x => x.Label);
                     if (labels.Contains(0))
                     {