using Adaptation.Shared; using Adaptation.Shared.Methods; using log4net; using System; using System.Collections.Generic; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; namespace Adaptation.FileHandlers.json; public partial class ProcessData : IProcessData { private readonly List _Details; public DateTime Date { get; set; } public string Employee { get; set; } public string JobID { get; set; } public string Layer { get; set; } public string MesEntity { get; set; } public string PSN { get; set; } public string RDS { get; set; } public string Reactor { get; set; } public string Recipe { get; set; } public string Zone { get; set; } List Shared.Properties.IProcessData.Details => _Details; private readonly ILog _Log; public ProcessData() { } public ProcessData(IFileRead fileRead, Logistics logistics, List fileInfoCollection, long tickOffset) { JobID = logistics.JobID; fileInfoCollection.Clear(); _Details = new List(); MesEntity = logistics.MesEntity; _Log = LogManager.GetLogger(typeof(ProcessData)); CSV csv = Parse(fileRead, logistics, fileInfoCollection); _ = GetImageBytes(csv); string directory = Path.GetDirectoryName(logistics.ReportFullPath); string fileName = Path.Combine(directory, $"{Path.GetFileNameWithoutExtension(logistics.ReportFullPath)}.data.json"); string json = JsonSerializer.Serialize(csv, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(fileName, json); if (!string.IsNullOrEmpty(csv.Info?.SampleName) && csv.ProfileHeader.ProfilePoints.Any()) SetValues(logistics, tickOffset, csv); } string IProcessData.GetCurrentReactor(IFileRead fileRead, Logistics logistics, Dictionary reactors) => throw new Exception(string.Concat("See ", nameof(Parse))); Tuple> IProcessData.GetResults(IFileRead fileRead, Logistics logistics, List fileInfoCollection) { Tuple> results; List tests = new(); foreach (object item in _Details) tests.Add(Test.SRP2100); List descriptions = fileRead.GetDescriptions(fileRead, tests, this); if (tests.Count != descriptions.Count) throw new Exception(); for (int i = 0; i < tests.Count; i++) { if (descriptions[i] is not Description description) throw new Exception(); if (description.Test != (int)tests[i]) throw new Exception(); } List fileReadDescriptions = (from l in descriptions select (Description)l).ToList(); string json = JsonSerializer.Serialize(fileReadDescriptions, fileReadDescriptions.GetType()); JsonElement[] jsonElements = JsonSerializer.Deserialize(json); results = new Tuple>(logistics.Logistics1[0], tests.ToArray(), jsonElements, fileInfoCollection); return results; } internal static DateTime GetDateTime(Logistics logistics, long tickOffset, DateTime dateTime) { DateTime result; if (dateTime < logistics.DateTimeFromSequence.AddDays(1) && dateTime > logistics.DateTimeFromSequence.AddDays(-1)) result = new(dateTime.Ticks + tickOffset); else result = logistics.DateTimeFromSequence; return result; } private static (string, string) GetReactorAndRDS(string defaultReactor, string defaultRDS, string text, string formattedText, string[] segments) { string rds; string reactor; if (string.IsNullOrEmpty(text) || segments.Length == 0 || string.IsNullOrEmpty(formattedText)) reactor = defaultReactor; else reactor = segments[0]; if (segments.Length <= 1 || !int.TryParse(segments[1], out int rdsValue) || rdsValue < 99) rds = defaultRDS; else rds = segments[1]; if (reactor.Length > 3) { rds = reactor; reactor = defaultReactor; } return new(reactor, rds); } private static (string, string) GetLayerAndPSN(string defaultLayer, string defaultPSN, string[] segments) { string psn; string layer; if (segments.Length <= 2) { psn = defaultPSN; layer = defaultLayer; } else { string[] segmentsB = segments[2].Split('.'); psn = segmentsB[0]; if (segmentsB.Length <= 1) layer = defaultLayer; else { layer = segmentsB[1]; if (layer.Length > 1 && layer[0] == '0') layer = layer.Substring(1); } } return (layer, psn); } private static string GetZone(string[] segments) { string result; if (segments.Length <= 3) result = string.Empty; else { result = segments[3]; if (result.Length > 1 && result[0] == '0') result = result.Substring(1); } return result; } public static Descriptor GetDescriptor(string text) { Descriptor result; string psn; string rds; string zone; string layer; string wafer; string reactor; string employee; string defaultPSN = string.Empty; string defaultRDS = string.Empty; string defaultZone = string.Empty; string defaultLayer = string.Empty; string defaultReactor = string.Empty; string defaultEmployee = string.Empty; if (Regex.IsMatch(text, @"^[a-zA-z][0-9]{2,4}$")) { wafer = text.ToUpper(); psn = defaultPSN; rds = defaultRDS; zone = defaultZone; layer = defaultLayer; reactor = defaultReactor; employee = defaultEmployee; } else if (string.IsNullOrEmpty(text) || (text.Length is 2 or 3 && Regex.IsMatch(text, "^[a-zA-z]{2,3}"))) { wafer = text; employee = text; psn = defaultPSN; rds = defaultRDS; zone = defaultZone; layer = defaultLayer; reactor = defaultReactor; } else if (Regex.IsMatch(text, @"^[0-9]{2}[.][0-9]{1}[.]?[0-9]{0,1}")) { string[] segments = text.Split('.'); wafer = text; psn = defaultPSN; rds = defaultRDS; layer = segments[1]; reactor = segments[0]; employee = defaultEmployee; if (segments.Length <= 2) zone = defaultZone; else zone = segments[2]; } else { // Remove illegal characters \/:*?"<>| found in the Batch wafer = Regex.Replace(text, @"[\\,\/,\:,\*,\?,\"",\<,\>,\|]", "_").Split('\r')[0].Split('\n')[0]; if (wafer.Length > 2 && wafer[0] == '1' && (wafer[1] == 'T' || wafer[1] == 't')) wafer = wafer.Substring(2); string[] segments = wafer.Split('-'); // bool hasRDS = Regex.IsMatch(wafer, "[-]?([QP][0-9]{4,}|[0-9]{5,})[-]?"); (reactor, rds) = GetReactorAndRDS(defaultReactor, defaultRDS, text, wafer, segments); (layer, psn) = GetLayerAndPSN(defaultLayer, defaultPSN, segments); zone = GetZone(segments); if (segments.Length <= 4) employee = defaultEmployee; else employee = segments[4]; } result = new(employee, layer, psn, rds, reactor, wafer, zone); return result; } #pragma warning disable IDE0060 private static CSV Parse(IFileRead fileRead, Logistics logistics, List fileInfoCollection) #pragma warning restore IDE0060 { CSV result; string json = File.ReadAllText(logistics.ReportFullPath); string directory = Path.GetDirectoryName(logistics.ReportFullPath); string fileName = Path.Combine(directory, $"{Path.GetFileNameWithoutExtension(logistics.ReportFullPath)}.csv"); csv.CSV csv = JsonSerializer.Deserialize(json); if (csv is null) throw new NullReferenceException(nameof(csv)); result = new(csv); if (File.Exists(fileName)) fileInfoCollection.Add(new(fileName)); fileInfoCollection.Add(logistics.FileInfo); return result; } private void SetValues(Logistics logistics, long tickOffset, CSV csv) { string psn; string rds; string zone; string layer; Detail detail; string reactor; List details = new(); string recipe = csv.Info.SampleName; string employee = csv.Info.Operator; string timeFormat = "yyyyMMddHHmmss"; DateTime dateTime = GetDateTime(logistics, tickOffset, csv.Info.DateTime); string uniqueId = string.Concat(logistics.MesEntity, "_", logistics.DateTimeFromSequence.ToString(timeFormat)); // Remove illegal characters \/:*?"<>| found in the Batch Descriptor descriptor = GetDescriptor(csv.Info.SampleName); psn = descriptor.PSN; rds = descriptor.RDS; zone = descriptor.Zone; layer = descriptor.Layer; reactor = descriptor.Reactor; if (string.IsNullOrEmpty(employee)) employee = descriptor.Employee; PSN = psn; RDS = rds; Date = dateTime; Zone = zone; Layer = layer; Recipe = recipe; Reactor = reactor; Employee = employee; JobID = logistics.JobID; foreach (ProfilePoint profilePoint in csv.ProfileHeader.ProfilePoints) { detail = new() { HeaderUniqueId = uniqueId, UniqueId = string.Concat(uniqueId, "_Point-", profilePoint.Number), Depth = profilePoint.Depth.ToString(), Raw = profilePoint.Raw.ToString(), Edited = string.Concat(profilePoint.Edited), Resistivity = string.Concat(profilePoint.Resistivity), CD = string.Concat(profilePoint.CD), }; details.Add(detail); } _Details.AddRange(details); } #nullable enable #pragma warning disable CA1416 internal static List GetDescriptions(JsonElement[] jsonElements) { List results = new(); Description? description; JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString }; foreach (JsonElement jsonElement in jsonElements) { if (jsonElement.ValueKind != JsonValueKind.Object) throw new Exception(); description = JsonSerializer.Deserialize(jsonElement.ToString(), jsonSerializerOptions); if (description is null) continue; results.Add(description); } return results; } private static void GetMinMax(List profilePoints, out double maxDepth, out int concentrationMaxD, out int concentrationMinD, out int resistanceEditedMaxD, out int resistanceEditedMinD, out int resistivityMaxD, out int resistivityMinD) { maxDepth = 30; concentrationMaxD = -99; concentrationMinD = 99; resistanceEditedMaxD = -99; resistanceEditedMinD = 99; resistivityMaxD = -99; resistivityMinD = 99; foreach (ProfilePoint profilePoint in profilePoints) { if (profilePoint.Depth > 0 && profilePoint.Edited is not null && profilePoint.Resistivity is not null && profilePoint.CD is not null) { maxDepth = profilePoint.Depth; if (Math.Log10(profilePoint.Resistivity.Value) < resistivityMinD) resistivityMinD = (int)Math.Log10(profilePoint.Resistivity.Value); if (Math.Ceiling(Math.Log10(profilePoint.Resistivity.Value)) > resistivityMaxD) resistivityMaxD = (int)Math.Ceiling(Math.Log10(profilePoint.Resistivity.Value)); if (Math.Log10(profilePoint.Edited.Value) < resistanceEditedMinD) resistanceEditedMinD = (int)Math.Log10(profilePoint.Edited.Value); if (Math.Ceiling(Math.Log10(profilePoint.Edited.Value)) > resistanceEditedMaxD) resistanceEditedMaxD = (int)Math.Ceiling(Math.Log10(profilePoint.Edited.Value)); if (Math.Log10(profilePoint.CD.Value) < concentrationMinD) concentrationMinD = (int)Math.Log10(profilePoint.CD.Value); if (Math.Ceiling(Math.Log10(profilePoint.CD.Value)) > concentrationMaxD) concentrationMaxD = (int)Math.Ceiling(Math.Log10(profilePoint.CD.Value)); } } } private static PointF GetPointF(double x, double y) => new((float)x, (float)y); private static RectangleF GetRectangleF(double left, double top, double width, double height) => new((float)left, (float)top, (float)width, (float)height); private static void DrawLine(Graphics graphics, Pen pen, double x1, double y1, double x2, double y2) => graphics.DrawLine(pen, (float)x1, (float)y1, (float)x2, (float)y2); private static void DrawString(Graphics graphics, string s, Font font, Brush brush, double x, double y) => graphics.DrawString(s, font, brush, (float)x, (float)y); private static void FillEllipse(Graphics graphics, Brush brush, double x, double y, double width, double height) => graphics.FillEllipse(brush, (float)x, (float)y, (float)width, (float)height); private static void DrawString(Graphics graphics, string s, Font font, Brush brush, double x, double y, StringFormat stringFormat) => graphics.DrawString(s, font, brush, (float)x, (float)y, stringFormat); internal static byte[] GetImageBytes(CSV csv) { if (csv.Info is null) throw new NullReferenceException(nameof(csv.Info)); if (csv.Setup is null) throw new NullReferenceException(nameof(csv.Setup)); if (csv.ProfileHeader is null) throw new NullReferenceException(nameof(csv.ProfileHeader)); if (csv.LayerHeader is null) throw new NullReferenceException(nameof(csv.LayerHeader)); double maxDepth; int concentrationMaxD, concentrationMinD, resistanceEditedMaxD, resistanceEditedMinD, resistivityMaxD, resistivityMinD; GetMinMax(csv.ProfileHeader.ProfilePoints, out maxDepth, out concentrationMaxD, out concentrationMinD, out resistanceEditedMaxD, out resistanceEditedMinD, out resistivityMaxD, out resistivityMinD); int decades; byte[] bytes; double point; int width = 694; int height = 714; int position = -1; Pen pen = Pens.Black; int blocksOfDepth = 6; RectangleF[] rectangles; double topChartArea = 90; double widthOfDepthBlock; double leftChartArea = 60; double widthOfBlacks = 120; Brush brush = Brushes.Black; double widthChartArea = 500; double heightChartArea = 600; StringBuilder layers = new(); Font consolas = new("Consolas", 9); PointF[]? resistivityPoints = null; StringFormat sfFormatRight = new(); Color backgroundColor = Color.White; PointF[]? concentrationPoints = null; Brush resistivityBrush = Brushes.Green; Brush concentrationBrush = Brushes.Blue; Brush resistanceRawBrush = Brushes.Black; Pen resistivityPen = new(Color.Green, 2); Brush resistanceEditedBrush = Brushes.Red; double sizeOfBlock = heightChartArea / 18; Pen concentrationPen = new(Color.Blue, 2); Brush backgroundBrush = Brushes.WhiteSmoke; Pen resistanceRawPen = new(Color.Black, 2); Pen transitionWidthPen = new(Color.Orange); Pen resistanceEditedPen = new(Color.Red, 2); Font consolasBold = new("Consolas", 9); // , FontStyle.Bold) concentrationPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; concentrationPen.DashPattern = new float[] { 5, 4 }; resistanceEditedPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom; resistanceEditedPen.DashPattern = new float[] { 1, 3 }; resistanceRawPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom; resistanceRawPen.DashPattern = new float[] { 1, 3 }; transitionWidthPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; transitionWidthPen.DashPattern = new float[] { 5, 4 }; sfFormatRight.Alignment = StringAlignment.Far; Bitmap bitmap = new(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); Graphics graphics = Graphics.FromImage(bitmap); graphics.Clear(backgroundColor); widthOfDepthBlock = Math.Ceiling(maxDepth / 3) * 3 / 6; // maxDepth = widthOfDepthBlock * blocksOfDepth; decades = resistivityMaxD - resistivityMinD; if (resistanceEditedMaxD - resistanceEditedMinD > decades) decades = resistanceEditedMaxD - resistanceEditedMinD; if (concentrationMaxD - concentrationMinD > decades) decades = concentrationMaxD - concentrationMinD; rectangles = new RectangleF[1]; rectangles[0] = GetRectangleF(leftChartArea, topChartArea, widthChartArea, heightChartArea); graphics.FillRectangles(backgroundBrush, rectangles); rectangles = new RectangleF[18]; rectangles[0] = GetRectangleF(leftChartArea, 10, widthChartArea, 65); // rectangles[1] = GetRectangleF(leftChartArea + widthChartArea, topChartArea, widthOfBlacks, sizeOfBlock * 5); rectangles[1] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 0, widthOfBlacks, sizeOfBlock); rectangles[2] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 1, widthOfBlacks, sizeOfBlock); rectangles[3] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 2, widthOfBlacks, sizeOfBlock); rectangles[4] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 3, widthOfBlacks, sizeOfBlock); rectangles[5] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 4, widthOfBlacks, sizeOfBlock); rectangles[6] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 5, widthOfBlacks, sizeOfBlock); rectangles[7] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 6, widthOfBlacks, sizeOfBlock); rectangles[8] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 7, widthOfBlacks, sizeOfBlock); rectangles[9] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 8, widthOfBlacks, sizeOfBlock); rectangles[10] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 9, widthOfBlacks, sizeOfBlock); rectangles[11] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 10, widthOfBlacks, sizeOfBlock); rectangles[12] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 11, widthOfBlacks, sizeOfBlock); rectangles[13] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 12, widthOfBlacks, sizeOfBlock); rectangles[14] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 13, widthOfBlacks, sizeOfBlock); rectangles[15] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 14, widthOfBlacks, sizeOfBlock); rectangles[16] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 15, widthOfBlacks, sizeOfBlock); rectangles[17] = GetRectangleF(leftChartArea + widthChartArea, topChartArea + sizeOfBlock * 16, widthOfBlacks, sizeOfBlock * 2); graphics.FillRectangles(Brushes.White, rectangles); graphics.DrawRectangles(pen, rectangles); foreach (Layer layer in csv.LayerHeader.Layers) _ = layers.AppendLine(string.Concat("First Pt. ", layer.FirstPoint, " Last Pt. ", layer.LastPoint, " Type ", layer.Type, " Smoothing ", layer.Smoothing, " Correction ", layer.Correction)); _ = layers.AppendLine(string.Join(" ", csv.Info.Comments)); graphics.DrawString(layers.ToString(), consolas, brush, rectangles[0]); graphics.DrawString(string.Concat(csv.Info.SystemId, Environment.NewLine, csv.Info.SoftwareVersion), consolas, brush, rectangles[9]); graphics.DrawString(string.Concat("SURFACE FINISH", Environment.NewLine, csv.Setup.Finish), consolas, brush, rectangles[10]); graphics.DrawString(string.Concat("ORIENTATION", Environment.NewLine, csv.Setup.Orientation), consolas, brush, rectangles[11]); graphics.DrawString(string.Concat("BEVEL ANGLE", Environment.NewLine, csv.Setup.SineBevelAngle), consolas, brush, rectangles[12]); graphics.DrawString(string.Concat("X-STEP (um)", Environment.NewLine, csv.Setup.Steps.First().X), consolas, brush, rectangles[13]); graphics.DrawString(string.Concat("PROBE LOAD (gm)", Environment.NewLine, csv.Setup.ProbeLoad), consolas, brush, rectangles[14]); graphics.DrawString(string.Concat("SPACING (um)", Environment.NewLine, csv.Setup.ProbeSpacing), consolas, brush, rectangles[15]); graphics.DrawString(string.Concat("OPERATOR", Environment.NewLine, csv.Info.Operator), consolas, brush, rectangles[16]); graphics.DrawString(string.Concat("DATE", Environment.NewLine, csv.Info.DateTime.ToString("dd MMM yy"), Environment.NewLine, "TIME", Environment.NewLine, csv.Info.DateTime.ToString("HH:mm:ss tt")), consolas, brush, rectangles[17]); DrawLine(graphics, concentrationPen, 13, 6, 13, 40); graphics.DrawString("C", consolasBold, concentrationBrush, 8, 41); graphics.DrawString("D", consolasBold, concentrationBrush, 8, 53); DrawLine(graphics, resistivityPen, 28, 6, 28, 40); graphics.DrawString("ρ", consolasBold, resistivityBrush, 21, 41); graphics.DrawString("c", consolasBold, resistivityBrush, 21, 53); graphics.DrawString("m", consolasBold, resistivityBrush, 21, 62); DrawLine(graphics, resistanceRawPen, 39, 7, 39, 41); graphics.DrawString("Ω", consolasBold, resistanceRawBrush, 34, 41); DrawLine(graphics, resistanceEditedPen, 51, 7, 51, 41); graphics.DrawString("Ω", consolasBold, resistanceEditedBrush, 46, 41); graphics.DrawString("E", consolasBold, resistanceEditedBrush, 46, 53); for (int iLoop = decades - 1; iLoop >= 0; iLoop += -1) { for (int iLoop_Sub = 1; iLoop_Sub <= 10; iLoop_Sub++) DrawLine(graphics, Pens.LightGray, leftChartArea, topChartArea + heightChartArea - (iLoop * heightChartArea / decades) + heightChartArea / decades * Math.Log10(iLoop_Sub), leftChartArea + widthChartArea, topChartArea + heightChartArea - (iLoop * heightChartArea / decades) + heightChartArea / decades * Math.Log10(iLoop_Sub)); } DrawString(graphics, "0", consolas, brush, leftChartArea - 5, topChartArea + heightChartArea + 5); for (int iLoop = 0; iLoop <= blocksOfDepth - 1; iLoop++) { for (int iLoop_Sub = 1; iLoop_Sub <= 10; iLoop_Sub++) DrawLine(graphics, Pens.LightGray, leftChartArea + (iLoop * widthChartArea / blocksOfDepth) + iLoop_Sub * widthChartArea / blocksOfDepth / 10, topChartArea, leftChartArea + (iLoop * widthChartArea / blocksOfDepth) + (iLoop_Sub * widthChartArea / blocksOfDepth / 10), topChartArea + heightChartArea); DrawString(graphics, ((iLoop + 1) * widthOfDepthBlock).ToString("0.0"), consolas, brush, leftChartArea + 13 + (iLoop + 1) * widthChartArea / blocksOfDepth, topChartArea + heightChartArea + 5, sfFormatRight); } DrawString(graphics, "(um)", consolas, brush, leftChartArea + widthChartArea + 12, topChartArea + heightChartArea + 5); for (int iLoop = 0; iLoop <= decades; iLoop++) { DrawLine(graphics, pen, leftChartArea, topChartArea + (iLoop * heightChartArea / decades), leftChartArea + widthChartArea, topChartArea + (iLoop * heightChartArea / decades)); DrawString(graphics, (decades - iLoop + concentrationMinD).ToString("0"), consolasBold, concentrationBrush, 20, topChartArea - 10 + (iLoop * heightChartArea / decades), sfFormatRight); DrawString(graphics, (decades - iLoop + resistivityMinD).ToString("0"), consolasBold, resistivityBrush, 33, topChartArea - 10 + (iLoop * heightChartArea / decades), sfFormatRight); DrawString(graphics, (decades - iLoop + resistanceEditedMinD).ToString("0"), consolasBold, resistanceRawBrush, 45, topChartArea - 10 + (iLoop * heightChartArea / decades), sfFormatRight); DrawString(graphics, (decades - iLoop + resistanceEditedMinD).ToString("0"), consolasBold, resistanceEditedBrush, 58, topChartArea - 10 + (iLoop * heightChartArea / decades), sfFormatRight); } for (int iLoop = 0; iLoop <= blocksOfDepth; iLoop++) DrawLine(graphics, pen, leftChartArea + (iLoop * widthChartArea / blocksOfDepth), topChartArea, leftChartArea + (iLoop * widthChartArea / blocksOfDepth), topChartArea + heightChartArea); foreach (ProfilePoint profilePoint in csv.ProfileHeader.ProfilePoints) { if (profilePoint.Depth < 0 || profilePoint.Edited is null || profilePoint.Resistivity is null || profilePoint.CD is null) continue; // Rho (Resistivity || Resistivity_ohm_cm) = Green if (profilePoint.Depth < 0 || profilePoint.Edited.Value == 0 || profilePoint.Resistivity.Value == 0 || profilePoint.CD.Value == 0) continue; point = topChartArea + heightChartArea - ((Math.Log10(profilePoint.Resistivity.Value) - resistivityMinD) / decades * heightChartArea); if (point < (90 - 2)) continue; if (point > (topChartArea + heightChartArea + 2)) continue; position += 1; PointF[]? resistivityOldPoints = resistivityPoints; resistivityPoints = new PointF[position + 1]; if (resistivityOldPoints != null) Array.Copy(resistivityOldPoints, resistivityPoints, Math.Min(position + 1, resistivityOldPoints.Length)); PointF[]? concentrationPointsOld = concentrationPoints; concentrationPoints = new PointF[position + 1]; if (concentrationPointsOld != null) Array.Copy(concentrationPointsOld, concentrationPoints, Math.Min(position + 1, concentrationPointsOld.Length)); resistivityPoints[position] = GetPointF(leftChartArea + profilePoint.Depth / maxDepth * widthChartArea, topChartArea + heightChartArea - ((Math.Log10(profilePoint.Resistivity.Value) - resistivityMinD) / decades * heightChartArea)); concentrationPoints[position] = GetPointF(leftChartArea + profilePoint.Depth / maxDepth * widthChartArea, topChartArea + heightChartArea - ((Math.Log10(profilePoint.CD.Value) - concentrationMinD) / decades * heightChartArea)); graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; FillEllipse(graphics, resistanceRawBrush, leftChartArea + profilePoint.Depth / maxDepth * widthChartArea - 2, topChartArea + heightChartArea - ((Math.Log10(profilePoint.Raw) - resistanceEditedMinD) / decades * heightChartArea) - 2, 3, 3); FillEllipse(graphics, resistanceEditedBrush, leftChartArea + profilePoint.Depth / maxDepth * widthChartArea - 2, topChartArea + heightChartArea - ((Math.Log10(profilePoint.Edited.Value) - resistanceEditedMinD) / decades * heightChartArea) - 2, 3, 3); graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default; } graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; if (resistivityPoints is not null) graphics.DrawLines(resistivityPen, resistivityPoints); graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default; graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; if (concentrationPoints is not null) graphics.DrawLines(concentrationPen, concentrationPoints); graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default; using MemoryStream msMemoryStream = new(); bitmap.Save(msMemoryStream, System.Drawing.Imaging.ImageFormat.Png); bytes = new byte[Convert.ToInt32(msMemoryStream.Length) + 1]; _ = msMemoryStream.Read(bytes, 0, bytes.Length); bytes = msMemoryStream.ToArray(); return bytes; } }