using Newtonsoft.Json; using Colourful; using Colourful.Conversion; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data.Entity; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Media; using System.Windows.Threading; using Tango.BL; using Tango.BL.Builders; using Tango.BL.Entities; using Tango.BL.Enumerations; using Tango.BL.FineTuning; using Tango.Core; using Tango.Core.Commands; using Tango.Core.DI; using Tango.Core.Helpers; using Tango.Documents; using Tango.Explorer; using Tango.Integration.Operation; using Tango.PDF; using Tango.PPC.Common; using Tango.PPC.Common.Application; using Tango.PPC.Common.Connection; using Tango.PPC.Common.Navigation; using Tango.PPC.Common.Notifications; using Tango.PPC.Common.Notifications.NotificationItems; using Tango.PPC.Common.Printing; using Tango.PPC.Common.Storage; using Tango.PPC.Jobs.ColorCorrectionTool; using Tango.PPC.Jobs.FineTuning; using Tango.PPC.Jobs.Models; using Tango.PPC.Jobs.Reports; using Tango.PPC.Storage; using Tango.PPC.Storage.Models; using Tango.Settings; using Tango.SharedUI; using ColorMine.ColorSpaces; namespace Tango.PPC.Jobs.Dialogs { public class VectorFineTuningDialogVM : DialogViewVM { private JobHandler _handler; private String _sessionID; #region Properties private RunningJobStatus _runningJobStatus; /// /// Gets or sets the running job status. /// public RunningJobStatus RunningJobStatus { get { return _runningJobStatus; } set { _runningJobStatus = value; RaisePropertyChangedAuto(); } } /// /// Gets or sets the machine provider. /// [TangoInject] public IMachineProvider MachineProvider { get; set; } /// /// Gets or sets the notification provider. /// [TangoInject] public INotificationProvider NotificationProvider { get; set; } /// /// Gets or sets the printing manager. /// [TangoInject] public IPrintingManager PrintingManager { get; set; } [TangoInject] public INavigationManager NavigationManager { get; set; } /// /// Gets or sets the storage provider. /// [TangoInject] public IStorageProvider StorageProvider { get; set; } [TangoInject] public IPPCApplicationManager ApplicationManager { get; set; } public BrushStopModel BrushStopModel { get; set; } public ColorSpaces OpenFromColorSpace { get; set; } private bool _isOutOfGamut; /// /// Gets or sets a value indicating whether this instance is out of gamut. /// public bool IsOutOfGamut { get { return _isOutOfGamut; } set { if (_isOutOfGamut != value) { _isOutOfGamut = value; RaisePropertyChangedAuto(); } } } //private System.Windows.Media.Color _targetcolor; //public System.Windows.Media.Color TargetColor //{ // get { return _targetcolor; } // set // { // _targetcolor = value; // RaisePropertyChanged(nameof(ColorBrush)); // } //} public SolidColorBrush ColorBrush { get { Lab lab = new Lab(TargetL, TargetA, TargetB); Rgb rgb = new Rgb(lab.ToRgb()); return new SolidColorBrush() { Color = Color.FromRgb((byte)rgb.R, (byte)rgb.G, (byte)rgb.B) }; //return new SolidColorBrush(TargetColor); } } protected Double _targetL; public Double TargetL { get { return _targetL; } set { if (_targetL != value) { _targetL = value; RaisePropertyChangedAuto(); } } } protected Double _targetA; /// /// Gets or sets the BrushStopModel a. /// public Double TargetA { get { return _targetA; } set { if (_targetA != value) { _targetA = value; RaisePropertyChangedAuto(); OnLABChanged(); } } } protected Double _targetB; /// /// Gets or sets the BrushStopModel b. /// public Double TargetB { get { return _targetB; } set { if (_targetB != value) { _targetB = value; RaisePropertyChangedAuto(); OnLABChanged(); } } } protected Double? _measuredL; /// /// Gets or sets the Measured l. /// public Double? MeasuredL { get { return _measuredL; } set { if (_measuredL != value) { _measuredL = value; RaisePropertyChangedAuto(); if (ActiveLogModel != null) ActiveLogModel.L = _measuredL; OnLABChanged(); } } } protected Double? _measuredA; /// /// Gets or sets the Measured a. /// public Double? MeasuredA { get { return _measuredA; } set { if (_measuredA != value) { _measuredA = value; RaisePropertyChangedAuto(); if (ActiveLogModel != null) ActiveLogModel.A = _measuredA; OnLABChanged(); } } } protected Double? _measuredB; /// /// Gets or sets the Measured b. /// public Double? MeasuredB { get { return _measuredB; } set { if (_measuredB != value) { _measuredB = value; RaisePropertyChangedAuto(); if (ActiveLogModel != null) ActiveLogModel.B = _measuredB; OnLABChanged(); } } } protected Double? _dL; /// /// Gets or sets the delta L /// public Double? DL { get { return _dL; } set { if (_dL != value) { _dL = value; if (ActiveLogModel != null) ActiveLogModel.dL = _dL == null? 0: (double)_dL; RaisePropertyChangedAuto(); } } } /// /// Gets the measured h for show text in deltaH. /// public double? MeasuredH { get { if(IsValidLAB()) { var converter = new ColourfulConverter { WhitePoint = Illuminants.D65 }; LabColor labColor = new LabColor((double)MeasuredL, (double)MeasuredA, (double)MeasuredB); var LCH_input = converter.ToLChab(labColor); return LCH_input.h; } return null; } } private bool _IsTargetVisible; public bool IsTargetVisible { get { return _IsTargetVisible; } set { if (_IsTargetVisible != value) { _IsTargetVisible = value; RaisePropertyChangedAuto(); } } } protected Double? _dC; /// /// Gets or sets the delta C /// public Double? DC { get { return _dC; } set { if (_dC != value) { _dC = value; if (ActiveLogModel != null) ActiveLogModel.dC = _dC == null ? 0 : (double)_dC; RaisePropertyChangedAuto(); } } } protected Double? _dH; /// /// Gets or sets the delta Hue /// public Double? DH { get { return _dH; } set { if (_dH != value) { _dH = value; if (ActiveLogModel != null) ActiveLogModel.dH = _dH == null ? 0 : (double)_dH; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(MeasuredH)); } } } protected Double? _deltaE; /// /// Gets or sets the delta Hue /// public Double? DeltaE { get { return _deltaE; } set { if (_deltaE != value) { _deltaE = value; RaisePropertyChangedAuto(); } } } private bool _CorrectOnlyHue; public bool CorrectOnlyHue { get { return _CorrectOnlyHue; } set { if(_CorrectOnlyHue != value) { _CorrectOnlyHue = value; if (ActiveLogModel != null) ActiveLogModel.CorrectOnlyHue = _CorrectOnlyHue; VectorCorrection(); RaisePropertyChangedAuto(); } } } protected Double _cyan; /// /// Gets or sets the cyan. /// public Double Cyan { get { return _cyan; } set { if (_cyan != value) { _cyan = value; RaisePropertyChangedAuto(); } } } protected Double _magenta; /// /// Gets or sets the magenta. /// public Double Magenta { get { return _magenta; } set { if (_magenta != value) { _magenta = value; RaisePropertyChangedAuto(); } } } protected Double _yellow; /// /// Gets or sets the yellow. /// public Double Yellow { get { return _yellow; } set { if (_yellow != value) { _yellow = value; RaisePropertyChangedAuto(); } } } protected Double _black; /// /// Gets or sets the black. /// public Double Black { get { return _black; } set { if (_black != value) { _black = value; RaisePropertyChangedAuto(); } } } public int TrialNumber { get { if (ActiveLogModel == null) return 1; return ActiveLogModel.TrialNumber + 1; } } public TestColor TestColor { get; set; } private SynchronizedObservableCollection _trialsLogItems; public SynchronizedObservableCollection TrialsLogitems { get { return _trialsLogItems; } set { _trialsLogItems = value; RaisePropertyChangedAuto(); } } private TrialsLogModel _activeLogModel; public TrialsLogModel ActiveLogModel { get { return _activeLogModel; } set { _activeLogModel = value; RaisePropertyChangedAuto(); } } private TrialsLogModel _selectedLog; public TrialsLogModel SelectedLog { get { return _selectedLog; } set { _selectedLog = value; RaisePropertyChangedAuto(); OKCommand.RaiseCanExecuteChanged(); } } private bool _isExpanderOpened; public bool IsExpanderOpened { get { return _isExpanderOpened; } set { _isExpanderOpened = value; RaisePropertyChangedAuto(); } } private bool _isJobRunning; public bool IsJobRunning { get { return _isJobRunning; } set { _isJobRunning = value; RaisePropertyChangedAuto(); Application.Current.Dispatcher.Invoke(() => { OKCommand.RaiseCanExecuteChanged(); RaisePropertyChanged(nameof(IsDisableInputLAB)); }); } } private bool _isJobFailed; public bool IsJobFailed { get { return _isJobFailed; } set { _isJobFailed = value; RaisePropertyChangedAuto(); } } private String _jobFailedReason; public String JobFailedReason { get { return _jobFailedReason; } set { _jobFailedReason = value; RaisePropertyChangedAuto(); } } private bool IsPrepareToStartJob { get; set; } public bool IsDisableInputLAB { get { return IsJobRunning == true || (TrialsLogitems != null && TrialsLogitems.Count > 10); } } private bool _isManualFineTuning; /// /// Gets or sets a value indicating whether this instance is vector fine tuning. /// /// /// true if this instance is Automatic tab selected; otherwise, manual . /// public bool IsManualFineTuning { get { return _isManualFineTuning; } set { if(_isManualFineTuning != value) { _isManualFineTuning = value; if(_isManualFineTuning ) { _selectedTabIndex = 1; RaisePropertyChanged(nameof(SelectedTabIndex)); } else { _selectedTabIndex = 0; RaisePropertyChanged(nameof(SelectedTabIndex)); } if(ActiveLogModel != null) { ActiveLogModel.IsManualCorrection = IsManualFineTuning; } RaisePropertyChangedAuto(); } } } private bool _isOnlyManual; /// /// Gets or sets a value indicating whether this instance is only manual. Opened from CMYK tab. /// public bool IsOnlyManual { get { return _isOnlyManual; } set { _isOnlyManual = value; RaisePropertyChangedAuto(); } } private int _selectedTabIndex; /// /// Gets or sets the index of the selected category. /// public int SelectedTabIndex { get { return _selectedTabIndex; } set { if (_selectedTabIndex != value) { _selectedTabIndex = value; RaisePropertyChangedAuto(); IsManualFineTuning = (value == 1); InvalidateRelayCommands(); } } } public VisualOffsetModel VisualCorrectionModel { get; set; } private double _lightnessOffset; public double LightnessOffset { get { return _lightnessOffset; } set { if(_lightnessOffset != value) { _lightnessOffset = value; if (ActiveLogModel != null) ActiveLogModel.LightnessOffset = _lightnessOffset; OnLightnessOffsetChanged(); RaisePropertyChangedAuto(); } } } private double _chromaOffset; public double ChromaOffset { get { return _chromaOffset; } set { if (_chromaOffset != value) { _chromaOffset = value; if (ActiveLogModel != null) ActiveLogModel.ChromaOffset = _chromaOffset; OnChromaOffsetChanged(); RaisePropertyChangedAuto(); } } } private double _hueOffset; public double HueOffset { get { return _hueOffset; } set { if (_hueOffset != value) { _hueOffset = value; if (ActiveLogModel != null) ActiveLogModel.HueOffset = _hueOffset; OnHueOffsetChanged(); RaisePropertyChangedAuto(); } } } private int _fineTuningTrialLengthMeters; public int FineTuningTrialLengthMeters { get { return _fineTuningTrialLengthMeters; } set { _fineTuningTrialLengthMeters = value; RaisePropertyChangedAuto(); OnUpdateSettingineTuningTrialLengthMeters(); } } #endregion #region Commands public RelayCommand TestCommand { get; set; } public RelayCommand ByPassTestCommand { get; set; } public RelayCommand StopCommand { get; set; } public RelayCommand ClearTrialsCommand { get; set; } public RelayCommand ExportTrialsCommand { get; set; } public RelayCommand DeleteTrialCommand { get; set; } /// /// Gets or sets the pressed command. /// { }); ; IsExpanderOpened = true; IsTargetVisible = false; TangoIOC.Default.Inject(this); _CorrectOnlyHue = true; IsManualFineTuning = false; IsOnlyManual = false; VisualCorrectionModel = new VisualOffsetModel(); var settings = SettingsManager.Default.GetOrCreate(); FineTuningTrialLengthMeters = settings.FineTuningTrialLengthMeters; } /// /// Initializes at open the dialog. /// public void Init(BrushStopModel brushstop, ColorSpaces colorspace)// double l, double a, double b)//, System.Windows.Media.Color targetColor) { CorrectOnlyHue = false; LightnessOffset = 0.0; ChromaOffset = 0.0; HueOffset = 0.0; DC = null; DL = null; DH = null; DeltaE = null; MachineProvider.MachineOperator.PrintingStarted += MachineOperator_PrintingStarted; MachineProvider.MachineOperator.PrintingEnded += MachineOperator_PrintingEnded; MachineProvider.MachineOperator.PrintingCompleted += MachineOperator_PrintingCompleted; MachineProvider.MachineOperator.JobRunsLogger.JobRunAvailable += JobRunsLogger_JobRunAvailable; BrushStopModel = brushstop.Clone(); BrushStopModel.Guid = brushstop.Guid; IsOutOfGamut = brushstop.IsOutOfGamut; OpenFromColorSpace = colorspace; if (OpenFromColorSpace == ColorSpaces.Catalog && brushstop.ColorCatalogsItem != null) { TargetL = BrushStopModel.ColorCatalogsItem.L; TargetA = BrushStopModel.ColorCatalogsItem.A; TargetB = BrushStopModel.ColorCatalogsItem.B; BrushStopModel.PreventPropertyUpdate = true; BrushStopModel.LiquidVolumes.ResetVolume(); foreach (var liquidVolume in BrushStopModel.LiquidVolumes.Where(x => x.IdsPack.LiquidType.AvailableForStandardUser)) { liquidVolume.Volume = brushstop.ColorCatalogsItem.GetLiquidVolumeByName(liquidVolume.IdsPack.LiquidType.DisplayName); } BrushStopModel.PreventPropertyUpdate = false; IsOnlyManual = false; } else if(OpenFromColorSpace == ColorSpaces.Volume) { BrushStopModel.PreventPropertyUpdate = true; BrushStopModel.L = 0; BrushStopModel.A = 0; BrushStopModel.B = 0; BrushStopModel.PreventPropertyUpdate = false; BrushStopModel.ConvertColorToLAB(); TargetL = BrushStopModel.L; TargetB = BrushStopModel.B; TargetA = BrushStopModel.A; IsOnlyManual = true; } else { TargetL = brushstop.L; TargetB = brushstop.B; TargetA = brushstop.A; BrushStopModel.ConvertColorToVolume(); var blackVolume = BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Black); if (blackVolume.Volume > 0 && blackVolume.Volume < 0.5) { BrushStopModel.PreventPropertyUpdate = true; blackVolume.Volume = 0; BrushStopModel.PreventPropertyUpdate = false; } BrushStopModel.ColorSpace = ColorSpaces.LAB; IsOnlyManual = false; } _sessionID = BrushStopModel.Guid + $"{TargetL}{TargetA}{TargetB}"; Cyan = BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Cyan).Volume; Magenta = BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Magenta).Volume; Yellow = BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Yellow).Volume; Black = BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Black).Volume; MeasuredL = MeasuredB = MeasuredA = null; TestColor = null; TestColor = TrialsLogEngine.Default.GetByBrushStopGuid(BrushStopModel.Guid); if (TestColor == null ) { ActiveLogModel = new TrialsLogModel(0, Cyan, Magenta, Yellow, Black); ActiveLogModel.SuggestionL = TargetL; ActiveLogModel.SuggestionA = TargetA; ActiveLogModel.SuggestionB = TargetB; TrialsLogitems = new SynchronizedObservableCollection(); TrialsLogitems.Add(ActiveLogModel); InitManualCorrection(); //TEST //for(int i = 1; i < 10; i++) //{ // var model = new TrialsLogModel(i , Cyan, Magenta, Yellow, Black); // TrialsLogitems.Insert(0, model); //} } else { TrialsLogitems = new SynchronizedObservableCollection(TestColor.TrialslogList.OrderByDescending(x => x.TrialNumber)); int maxTrialsNumber = TrialsLogitems.Max(x => x.TrialNumber); ActiveLogModel = TrialsLogitems.FirstOrDefault(x => x.TrialNumber == maxTrialsNumber); if (ActiveLogModel == null) { ActiveLogModel = new TrialsLogModel(0, Cyan, Magenta, Yellow, Black); ActiveLogModel.SuggestionL = TargetL; ActiveLogModel.SuggestionA = TargetA; ActiveLogModel.SuggestionB = TargetB; TrialsLogitems.Add(ActiveLogModel); } if (ActiveLogModel.IsTested == false) { MeasuredL = ActiveLogModel.L; MeasuredA = ActiveLogModel.A; MeasuredB = ActiveLogModel.B; } ActiveLogModel.IsActiveTrial = true; ActiveLogModel.IsSelectionEnable = true; var minValue = TrialsLogitems.Min(x => (double?)x.DeltaE); if(minValue != null && minValue < 2) { TrialsLogitems.Where(x=> (double?)x.DeltaE == minValue).ToList().ForEach(i => i.IsBest = true); } UpdateManualCorrection(); LightnessOffset = ActiveLogModel.LightnessOffset; ChromaOffset = ActiveLogModel.ChromaOffset; HueOffset = ActiveLogModel.HueOffset; } OKCommand.RaiseCanExecuteChanged(); TestCommand.RaiseCanExecuteChanged(); ByPassTestCommand.RaiseCanExecuteChanged(); IsVisible = true; RaisePropertyChanged(nameof(TrialsLogitems)); RaisePropertyChanged(nameof(IsDisableInputLAB)); RaisePropertyChanged(nameof(TrialNumber)); RaisePropertyChanged(nameof(ColorBrush)); if(IsOnlyManual) SelectedTabIndex = 1; else SelectedTabIndex = 0; } public void InitManualCorrection() { if (ActiveLogModel == null) return; double l = MeasuredL == null ? TargetL : (double)MeasuredL; double a = MeasuredA == null ? TargetA : (double)MeasuredA; double b = MeasuredB == null ? TargetB : (double)MeasuredB; LabColor labColor = new LabColor(l, a, b); var converter = new ColourfulConverter { WhitePoint = Illuminants.D65 }; var last_LCH = converter.ToLChab(labColor); VisualCorrectionModel.InitLAB(l, a, b, last_LCH.C, last_LCH.h); } public void UpdateManualCorrection() { if(ActiveLogModel == null) return; double l = MeasuredL == null ? ActiveLogModel.SuggestionL: (double) MeasuredL; double a = MeasuredA == null ? ActiveLogModel.SuggestionA : (double)MeasuredA; double b = MeasuredB == null ? ActiveLogModel.SuggestionB : (double)MeasuredB; VisualCorrectionModel.UpdateSourceLAB(l, a, b ); VisualCorrectionModel.UpdateManualColors(); } #region Methods protected override bool CanOK() { return (SelectedLog != null && IsJobRunning == false); } private async void ExportTrialsLog(object obj) { if (!StorageProvider.IsConnected) { await NotificationProvider.ShowError("No storage device connected."); return; } //var result = await NavigationManager. // NavigateForResult( // new StorageNavigationRequest() // { // Intent = StorageNavigationIntent.SaveFile, // DefaultFileName = "Color_Correction_Report", // Filter = ExplorerFileDefinition.PDFFile.Extension, // Title = "Save Color Correction Report", // }); // if (result != null) { DateTime reportDateTime = DateTime.UtcNow.ToLocalTime(); ColorCorrectionRepotVM vm = new ColorCorrectionRepotVM() { JobName = BrushStopModel.SegmentModel.Job.Name, TargetColor = String.Format($"L*{TargetL:0.##} a*{TargetA:0.##} b*{TargetB:0.##}"), }; foreach (var item in TrialsLogitems) { vm.ReportItems.Add(new ColorCorrectionReportLogItem() { TrialsNumber = item.TrialNumber, Date = item.Date, CMYK = item.CMYK, MeasuredLAB = item.LAB, DeltaE = item.DeltaE, IsBest = item.IsBest }); } try { PdfWpfWriter writer = new PdfWpfWriter(); writer.AddElement(new ColorCorrectionReport() { DataContext = vm }); string path = StorageProvider.Drive.Name + "\\Color Correction Report_" + reportDateTime.ToString(@"MM_dd_y_HH_mm") + ExplorerFileDefinition.PDFFile.Extension; if (File.Exists(path)) { path = StorageProvider.Drive.Name + "\\Color Correction Report_" + reportDateTime.ToString(@"MM_dd_y_HH_mm") + "_1" + ExplorerFileDefinition.PDFFile.Extension; } writer.Save(path); await NotificationProvider.ShowSuccess("Color Correction Report saved successfully."); LogManager.Log($"Color Correction Report saved successfully to file {path}."); } catch (Exception ex) { LogManager.Log(ex, $"Error saving color correction report to file."); await NotificationProvider.ShowError($"An error occurred while trying to save the color correction report.\n{ex.Message}"); } } } private async void ClearTrialsLog(object obj) { if (TrialsLogitems.Count > 1) { if (false == await NotificationProvider.ShowQuestion("“All the trials will be cleared.")) { return; } ActiveLogModel = TrialsLogitems.FirstOrDefault(x => x.TrialNumber == 0); ActiveLogModel.L = ActiveLogModel.A = ActiveLogModel.B = null; ActiveLogModel.SuggestionL = TargetL; ActiveLogModel.SuggestionA = TargetA; ActiveLogModel.SuggestionB = TargetB; ActiveLogModel.NewSuggestionL = ActiveLogModel.NewSuggestionA = ActiveLogModel.NewSuggestionB = 0; ActiveLogModel.DeltaE = null; ActiveLogModel.IsTested = false; TrialsLogitems.Clear(); if (TestColor != null) { TrialsLogEngine.Default.Delete(TestColor); } TrialsLogitems.Add(ActiveLogModel); RaisePropertyChanged(nameof(TrialsLogitems)); RaisePropertyChanged(nameof(IsDisableInputLAB)); RaisePropertyChanged(nameof(TrialNumber)); VectorCorrection(); ClearFoNextTrial(); InvalidateRelayCommands(); } } private void DeleteTrialLog(object obj) { if (SelectedLog != null) { if (SelectedLog.TrialNumber != 0) { bool isLastItem = (TrialsLogitems.Count - 1) == SelectedLog.TrialNumber; TrialsLogitems.Remove(SelectedLog); int trialNumber = 0; foreach (var trial in TrialsLogitems.OrderBy(x => x.TrialNumber)) { trial.TrialNumber = trialNumber; trialNumber++; } var max = TrialsLogitems.Max(x => x.TrialNumber); ActiveLogModel = TrialsLogitems.FirstOrDefault(x => x.TrialNumber == max); if (isLastItem) { ActiveLogModel.IsTested = false; _measuredL = ActiveLogModel.L; _measuredB = ActiveLogModel.B; _measuredA = ActiveLogModel.A; RaisePropertyChanged(nameof(MeasuredL)); RaisePropertyChanged(nameof(MeasuredA)); RaisePropertyChanged(nameof(MeasuredB)); } if (TestColor != null) { TestColor.TrialslogList.Clear(); TestColor.TrialslogList.AddRange(TrialsLogitems); TrialsLogEngine.Default.UpdateTest(TestColor); } RaisePropertyChanged(nameof(IsDisableInputLAB)); SelectedLog = null; var minDelataE = TrialsLogitems.Min(x => x.DeltaE); if (minDelataE != null && minDelataE < 2) TrialsLogitems.ToList().ForEach(x => x.IsBest = (x.DeltaE == minDelataE)); RaisePropertyChanged(nameof(TrialNumber)); } else if (TrialsLogitems.Count == 1) { ActiveLogModel.L = ActiveLogModel.A = ActiveLogModel.B = null; ActiveLogModel.NewSuggestionL = ActiveLogModel.NewSuggestionA = ActiveLogModel.NewSuggestionB = 0; ActiveLogModel.DeltaE = null; ActiveLogModel.IsTested = false; if (TestColor != null) { TrialsLogEngine.Default.Delete(TestColor); } SelectedLog = null; _measuredL = null; _measuredB = null; _measuredA = null; IsTargetVisible = false; RaisePropertyChanged(nameof(MeasuredL)); RaisePropertyChanged(nameof(MeasuredA)); RaisePropertyChanged(nameof(MeasuredB)); RaisePropertyChanged(nameof(TrialsLogitems)); RaisePropertyChanged(nameof(IsDisableInputLAB)); } VectorCorrection(); UpdateManualCorrection(); LightnessOffset = ActiveLogModel.LightnessOffset; ChromaOffset = ActiveLogModel.ChromaOffset; HueOffset = ActiveLogModel.HueOffset; InvalidateRelayCommands(); } } protected override async void Accept() { if (IsBusy) return; IsBusy = true; OnClose(); if (SelectedLog.TrialNumber == 0) { IsBusy = false; base.Accept(); return; } //var prevtrial = TrialsLogitems.FirstOrDefault( x=> x.TrialNumber == (SelectedLog.TrialNumber -1)); if(SelectedLog != null && SelectedLog.DeltaE != null && SelectedLog.DeltaE >=2)//by Hagai { if (false == await NotificationProvider.ShowQuestion("Please note that the color you have chosen is not the closest one.")) { IsBusy = false; return; } } // SaveTest(GetExcelDataItems(SelectedLog, true)); BrushStopModel.PreventPropertyUpdate = true; BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Cyan).Volume = SelectedLog.C; BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Magenta).Volume = SelectedLog.M; BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Yellow).Volume = SelectedLog.Y; BrushStopModel.PreventPropertyUpdate = false; BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Black).Volume = SelectedLog.K; BrushStopModel.PreventPropertyUpdate = true; BrushStopModel.L = SelectedLog.SuggestionL; BrushStopModel.A = SelectedLog.SuggestionA; BrushStopModel.B = SelectedLog.SuggestionB; BrushStopModel.PreventPropertyUpdate = false; if (TestColor != null) { TrialsLogEngine.Default.Delete(TestColor); } try { using (ObservablesContext db = ObservablesContext.CreateDefault()) { var selectedRun = await db.JobRuns.FirstOrDefaultAsync(x => x.Guid == SelectedLog.JobRunGuid); if (selectedRun != null) { VectorFineTuningRunModel model = JsonConvert.DeserializeObject(selectedRun.FineTuningString); model.Approved = true; selectedRun.FineTuningString = JsonConvert.SerializeObject(model); await db.SaveChangesAsync(); } } } catch (Exception ex) { LogManager.Log(ex, "Error updating the selected job run fine tuning db entry."); } IsBusy = false; base.Accept(); } protected override void Cancel() { OnClose(); if (TestColor != null )// update test { if (TrialsLogitems.Count == 1 && (MeasuredL == null || MeasuredA == null || MeasuredB == null)) { TrialsLogEngine.Default.Delete(TestColor); } else if (TrialsLogitems.Count > 0) { TestColor.L = TargetL; TestColor.A = TargetA; TestColor.B = TargetB; TestColor.OpenedFromCatalog = OpenFromColorSpace == ColorSpaces.Catalog; TestColor.OpenedFromCMYK = OpenFromColorSpace == ColorSpaces.Volume; TestColor.BrushStopGuid = BrushStopModel.Guid; TestColor.TrialslogList.Clear(); TestColor.TrialslogList.AddRange(TrialsLogitems); TrialsLogEngine.Default.UpdateTest(TestColor); //if(ActiveLogModel != null && !ActiveLogModel.IsTested) //{ // SaveTest(GetExcelDataItems(ActiveLogModel, false)); //} } } else if(TrialsLogitems.Count > 0 && (TrialsLogitems.Count > 1 || (MeasuredL != null && MeasuredA != null && MeasuredB != null) || ( IsManualFineTuning && (LightnessOffset != 0 || HueOffset != 0 || ChromaOffset != 0)))) { TestColor = new TestColor(); TestColor.BrushStopGuid = BrushStopModel.Guid; TestColor.L = TargetL; TestColor.A = TargetA; TestColor.B = TargetB; TestColor.OpenedFromCatalog = OpenFromColorSpace == ColorSpaces.Catalog; TestColor.OpenedFromCMYK = OpenFromColorSpace == ColorSpaces.Volume; TestColor.TrialslogList.AddRange(TrialsLogitems); TrialsLogEngine.Default.AddTest(TestColor); //if (ActiveLogModel != null && !ActiveLogModel.IsTested // && (MeasuredL != null && MeasuredA != null && MeasuredB != null) //|| (IsManualFineTuning && (LightnessOffset != 0 || HueOffset != 0 || ChromaOffset != 0))) //{ // SaveTest(GetExcelDataItems(ActiveLogModel, false)); //} } base.Cancel(); } private void OnClose() { MachineProvider.MachineOperator.PrintingStarted -= MachineOperator_PrintingStarted; MachineProvider.MachineOperator.PrintingEnded -= MachineOperator_PrintingEnded; MachineProvider.MachineOperator.PrintingCompleted -= MachineOperator_PrintingCompleted; MachineProvider.MachineOperator.JobRunsLogger.JobRunAvailable -= JobRunsLogger_JobRunAvailable; } private bool IsValidLAB() { if (MeasuredL == null || MeasuredL < 0 || MeasuredL > 100 || MeasuredA == null || MeasuredA < -128 || MeasuredA > 127 || MeasuredB == null || MeasuredB < -128 || MeasuredB > 127) return false; return true; } public void ClearFoNextTrial() { if(IsOnlyManual) SelectedTabIndex = 1; CorrectOnlyHue = false; _measuredL = null; _measuredB = null; _measuredA = null; RaisePropertyChanged(nameof(MeasuredL)); RaisePropertyChanged(nameof(MeasuredA)); RaisePropertyChanged(nameof(MeasuredB)); IsTargetVisible = false; if (ActiveLogModel != null) { VisualCorrectionModel.ClearAll(ActiveLogModel.SuggestionL, ActiveLogModel.SuggestionA, ActiveLogModel.SuggestionB); } else { VisualCorrectionModel.ClearAll(TargetL, TargetA, TargetB); } LightnessOffset = 0.0; ChromaOffset = 0.0; HueOffset = 0.0; DC = null; DL = null; DH = null; DeltaE = null; VisualCorrectionModel.UpdateManualColors(); } private void OnLABChanged() { if (ActiveLogModel == null) return; if (IsValidLAB()) { BrushStopModel.PreventPropertyUpdate = true; BrushStopModel.L = (double)MeasuredL; BrushStopModel.A = (double)MeasuredA; BrushStopModel.B = (double)MeasuredB; BrushStopModel.PreventPropertyUpdate = false; //BrushStopModel.ConvertColor(); //if(BrushStopModel.IsOutOfGamut) //{ // await NotificationProvider.ShowInfo("Color is out of gamut!"); //} double dL, dC, dH; //DeltaE = DeltaE_CMC(TargetL, TargetA, TargetB, (double)MeasuredL, (double)MeasuredA, (double)MeasuredB, out dL, out dC, out dH); //DeltaE = DeltaE_CMC( (double)MeasuredL, (double)MeasuredA, (double)MeasuredB, TargetL, TargetA, TargetB, out dL, out dC, out dH); DeltaE = DeltaE_CMC( TargetL, TargetA, TargetB, (double)MeasuredL, (double)MeasuredA, (double)MeasuredB, out dL, out dC, out dH); DL = dL; DC = (Double?)dC; DH = (Double?)dH; ActiveLogModel.DeltaE = DeltaE; VectorCorrection(); UpdateManualCorrection(); OnLightnessOffsetChanged(); OnChromaOffsetChanged(); OnHueOffsetChanged(); IsTargetVisible = true; // ValidationTests(); } else if(DeltaE != null) { DL = DC = DH = DeltaE = null; IsTargetVisible = false; } TestCommand.RaiseCanExecuteChanged(); ByPassTestCommand.RaiseCanExecuteChanged(); } private void OnLightnessOffsetChanged() { if (ActiveLogModel == null ) return; VisualCorrectionModel.LightnessOffset = LightnessOffset; VisualCorrectionModel.ManualCorrection(LightnessOffset, ChromaOffset, HueOffset); ActiveLogModel.VectorCorrectionL = VisualCorrectionModel.L; ActiveLogModel.VectorCorrectionA = VisualCorrectionModel.A; ActiveLogModel.VectorCorrectionB = VisualCorrectionModel.B; VisualCorrectionModel.IsOutOfGamut = IsOutOfGammot(); TestCommand.RaiseCanExecuteChanged(); ByPassTestCommand.RaiseCanExecuteChanged(); } private void OnChromaOffsetChanged() { if (ActiveLogModel == null ) return; VisualCorrectionModel.ChromaOffset = ChromaOffset; VisualCorrectionModel.ManualCorrection(LightnessOffset, ChromaOffset, HueOffset); ActiveLogModel.VectorCorrectionL = VisualCorrectionModel.L; ActiveLogModel.VectorCorrectionA = VisualCorrectionModel.A; ActiveLogModel.VectorCorrectionB = VisualCorrectionModel.B; VisualCorrectionModel.IsOutOfGamut = IsOutOfGammot(); TestCommand.RaiseCanExecuteChanged(); ByPassTestCommand.RaiseCanExecuteChanged(); } private void OnHueOffsetChanged() { if (ActiveLogModel == null ) return; VisualCorrectionModel.HueOffset = HueOffset; VisualCorrectionModel.ManualCorrection(LightnessOffset, ChromaOffset, HueOffset); ActiveLogModel.VectorCorrectionL = VisualCorrectionModel.L; ActiveLogModel.VectorCorrectionA = VisualCorrectionModel.A; ActiveLogModel.VectorCorrectionB = VisualCorrectionModel.B; VisualCorrectionModel.IsOutOfGamut = IsOutOfGammot(); TestCommand.RaiseCanExecuteChanged(); ByPassTestCommand.RaiseCanExecuteChanged(); } private bool IsOutOfGammot() { BrushStopModel.ColorSpace = ColorSpaces.LAB; BrushStopModel.PreventPropertyUpdate = true; BrushStopModel.L = ActiveLogModel.VectorCorrectionL; BrushStopModel.A = ActiveLogModel.VectorCorrectionA; BrushStopModel.B = ActiveLogModel.VectorCorrectionB; BrushStopModel.PreventPropertyUpdate = false; BrushStopModel.IsOutputOfGamut(ColorSpaces.LAB); return BrushStopModel.IsOutOfGamut; } private void OnUpdateSettingineTuningTrialLengthMeters() { if (FineTuningTrialLengthMeters != 0) { var settings = SettingsManager.Default.GetOrCreate(); settings.FineTuningTrialLengthMeters = FineTuningTrialLengthMeters; settings.Save(); } } #endregion #region Job private void BypassTest() { BrushStopModel.PreventPropertyUpdate = true; CalculateSuggestionLAB(ActiveLogModel); BrushStopModel.PreventPropertyUpdate = true; BrushStopModel.L = ActiveLogModel.NewSuggestionL; BrushStopModel.A = ActiveLogModel.NewSuggestionA; BrushStopModel.B = ActiveLogModel.NewSuggestionB; BrushStopModel.PreventPropertyUpdate = false; //calculate CMYK if (OpenFromColorSpace == ColorSpaces.LAB || ((MeasuredL != null && MeasuredA != null && MeasuredB != null) || IsManualFineTuning && (LightnessOffset != 0.0 || ChromaOffset != 0.0 || HueOffset != 0.0))) { BrushStopModel.FineTuningConverter(ActiveLogModel.C, ActiveLogModel.M, ActiveLogModel.Y, ActiveLogModel.K); if (BrushStopModel.IsOutOfGamut) { ActiveLogModel.NewSuggestionL = BrushStopModel.L; ActiveLogModel.NewSuggestionA = BrushStopModel.A; ActiveLogModel.NewSuggestionB = BrushStopModel.B; } } BrushStopModel.ColorSpace = ColorSpaces.LAB; UpdateOnEndJob(); InvalidateRelayCommands(); } private async void StartJob() { if(IsJobRunning || IsPrepareToStartJob) return; if (ActiveLogModel.DeltaE != null && ActiveLogModel.DeltaE <= 0.5) { if (true == await NotificationProvider.ShowQuestion("Previous trial seems to be very close; no more trials are recommended")) return; } IsPrepareToStartJob = true; BrushStopModel.PreventPropertyUpdate = true; CalculateSuggestionLAB(ActiveLogModel); BrushStopModel.PreventPropertyUpdate = true; BrushStopModel.L = ActiveLogModel.NewSuggestionL; BrushStopModel.A = ActiveLogModel.NewSuggestionA; BrushStopModel.B = ActiveLogModel.NewSuggestionB; BrushStopModel.PreventPropertyUpdate = false; //calculate CMYK if ( OpenFromColorSpace == ColorSpaces.LAB || ((MeasuredL != null && MeasuredA != null && MeasuredB != null) || IsManualFineTuning && (LightnessOffset != 0.0 || ChromaOffset != 0.0 || HueOffset != 0.0))) { BrushStopModel.FineTuningConverter(ActiveLogModel.C, ActiveLogModel.M, ActiveLogModel.Y, ActiveLogModel.K); if (BrushStopModel.IsOutOfGamut) { ActiveLogModel.NewSuggestionL = BrushStopModel.L; ActiveLogModel.NewSuggestionA = BrushStopModel.A; ActiveLogModel.NewSuggestionB = BrushStopModel.B; } BrushStopModel.ColorSpace = ColorSpaces.LAB; } // var settings = SettingsManager.Default.GetOrCreate(); using (ObservablesContext db = ObservablesContext.CreateDefault()) { Job job = new Job(); job.Guid = BrushStopModel.SegmentModel.Job.Guid; job.ID = BrushStopModel.SegmentModel.Job.ID; job.EnableLubrication = true; job.Designation = JobDesignations.FineTuning; job.Machine = await new MachineBuilder(db).Set(MachineProvider.Machine.Guid).WithConfiguration().WithSpools().WithCats().WithVersion().BuildAsync(); var trialNumber = ActiveLogModel.TrialNumber + 1; job.Name = BrushStopModel.SegmentModel.Job.Name; job.Rml = await new RmlBuilder(db).Set(BrushStopModel.SegmentModel.Job.Rml.Guid).WithActiveParametersGroup().WithCAT(MachineProvider.Machine.Guid).WithCCT().WithGbdAndLub().WithLiquidFactors().WithSpools().BuildAsync(); job.SpoolType = db.SpoolTypes.FirstOrDefault(x => x.Guid == BrushStopModel.SegmentModel.Job.SpoolGuid);// db.SpoolTypes.FirstOrDefault(x => x.Guid == settings.SpoolTypeGuid); job.WindingMethod = db.WindingMethods.FirstOrDefault(); job.VectorFineTuningRunModel = CreateFineTuningRunModel(); Segment segment = new Segment(); segment.Name = "VFT Segment"; segment.Length = FineTuningTrialLengthMeters;//settings.FineTuningTrialLengthMeters; segment.Job = job; segment.JobGuid = job.Guid; job.Segments.Add(segment); BrushStop stop = new BrushStop(); stop.Segment = segment; stop.ColorSpace = db.ColorSpaces.FirstOrDefault(x => x.Code == (int)ColorSpaces.Volume); stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, job.Rml.GetActiveProcessGroup().ProcessParametersTables.FirstOrDefault()); stop.BestMatchR = BrushStopModel.BestMatchRed; stop.BestMatchG = BrushStopModel.BestMatchGreen; stop.BestMatchB = BrushStopModel.BestMatchBlue; stop.L = BrushStopModel.L; stop.A = BrushStopModel.A; stop.B = BrushStopModel.B; BrushStopModel.LiquidVolumes.SetVolumesOnBrushStop(stop); segment.BrushStops.Add(stop); try { await PrintingManager.Print(job, db); } catch (Exception ex) { LogManager.Log(ex, "Could not start the test job."); await NotificationProvider.ShowError($"{ex.Message}."); IsJobRunning = false; IsPrepareToStartJob = false; } } IsPrepareToStartJob = false; } private bool CanStartJob(object arg) { return (!IsJobRunning && ActiveLogModel != null && TrialsLogitems.Count <= 10 && (ActiveLogModel.TrialNumber == 0 //asked by Hagai to job first trial without correction || ((!IsManualFineTuning && IsValidLAB()) || (IsManualFineTuning && (LightnessOffset != 0.0 || ChromaOffset != 0.0 || HueOffset != 0.0)))) ); } private void MachineOperator_PrintingStarted(object sender, PrintingEventArgs e) { if (IsVisible) { _handler = e.JobHandler; e.JobHandler.StatusChanged += JobHandler_StatusChanged; e.JobHandler.Stopped += JobHandler_Stopped; e.JobHandler.Completed += JobHandler_Completed; e.JobHandler.Failed += JobHandler_Failed; InvokeUI(() => { IsJobFailed = false; IsJobRunning = true; }); //e.JobHandler.CanCancelChanged += JobHandler_CanCancelChanged; } } private void JobHandler_Failed(object sender, Exception e) { InvokeUI(() => { IsJobFailed = true; IsJobRunning = false; }); JobFailedReason = e.FlattenMessage(); } /// /// Handles the Stopped event of the JobHandler. /// /// The source of the event. /// The instance containing the event data. private void JobHandler_Stopped(object sender, EventArgs e) { if (_handler != null) { _handler.StatusChanged -= JobHandler_StatusChanged; _handler.Stopped -= JobHandler_Stopped; _handler.Completed -= JobHandler_Completed; //_handler.CanCancelChanged -= JobHandler_CanCancelChanged; InvokeUI(() => { IsJobRunning = false; InvalidateRelayCommands(); }); } } /// /// Handles the JobHandler StatusChanged event. /// /// The sender. /// The e. private void JobHandler_StatusChanged(object sender, RunningJobStatus e) { InvokeUI(() => { RunningJobStatus = e; }); } private void MachineOperator_PrintingEnded(object sender, PrintingEventArgs e) { } private void MachineOperator_PrintingCompleted(object sender, PrintingEventArgs e) { LogManager.Log($"'{e.Job.Name}' printing complete. Job designation is {e.Job.Designation}."); // if (e.Job.Designation == BL.Enumerations.JobDesignations.FineTuning) //{ // NotificationProvider.PushNotification(new MessageNotificationItem(String.Format("'{0}' fine tuning completed successfully", e.Job.Name), "Tap to approve or repeat.", MessageNotificationItem.MessageNotificationItemTypes.Success, () => // { // })); //} //if (IsVisible) //{ // IsJobRunning = false; // Dispatcher.CurrentDispatcher.Invoke(() => // { // ActiveLogModel.IsTested = true; // ActiveLogModel.Date = DateTime.UtcNow; // if (ActiveLogModel != null && ActiveLogModel.TrialNumber < 10) // { // ActiveLogModel = new TrialsLogModel(ActiveLogModel.TrialNumber + 1, Cyan, Magenta, Yellow, Black); // _trialsLogItems.Add( ActiveLogModel); // RaisePropertyChanged(nameof(TrialsLogitems)); // } // _measuredL = null; // _measuredA = null; // _measuredB = null; // RaisePropertyChanged(nameof(MeasuredL)); // RaisePropertyChanged(nameof(MeasuredA)); // RaisePropertyChanged(nameof(MeasuredB)); // }); //} } private void JobHandler_Completed(object sender, EventArgs e) { if (_handler != null) { if (IsVisible) { IsJobRunning = false; } InvokeUI(() => { UpdateOnEndJob(); InvalidateRelayCommands(); }); _handler.StatusChanged -= JobHandler_StatusChanged; _handler.Stopped -= JobHandler_Stopped; _handler.Completed -= JobHandler_Completed; } } private void StopTest() { if (_handler != null) { _handler.Cancel(); InvokeUI(() => { IsJobRunning = false; InvalidateRelayCommands(); }); } } private void UpdateOnEndJob() { ActiveLogModel.IsTested = true; Cyan = BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Cyan).Volume; Magenta = BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Magenta).Volume; Yellow = BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Yellow).Volume; Black = BrushStopModel.LiquidVolumes.GetLiquidVolume(LiquidTypes.Black).Volume; if (ActiveLogModel != null && TrialsLogitems.Count <= 10) { var suggestionL = ActiveLogModel.NewSuggestionL; var suggestionA = ActiveLogModel.NewSuggestionA; var suggestionB = ActiveLogModel.NewSuggestionB; ActiveLogModel = new TrialsLogModel(ActiveLogModel.TrialNumber + 1, Cyan, Magenta, Yellow, Black); ActiveLogModel.SuggestionL = suggestionL; ActiveLogModel.SuggestionA = suggestionA; ActiveLogModel.SuggestionB = suggestionB; ActiveLogModel.VectorCorrectionL = suggestionL; ActiveLogModel.VectorCorrectionA = suggestionA; ActiveLogModel.VectorCorrectionB = suggestionB; TrialsLogitems.Insert(0, ActiveLogModel); var minDelataE = TrialsLogitems.Min(x => (double?)x.DeltaE); if (minDelataE != null && minDelataE < 2) TrialsLogitems.ToList().ForEach(x => x.IsBest = ((double?)x.DeltaE == minDelataE)); RaisePropertyChanged(nameof(TrialsLogitems)); RaisePropertyChanged(nameof(TrialNumber)); // UpdateManualCorrection(); ClearFoNextTrial(); } RaisePropertyChanged(nameof(IsDisableInputLAB)); } #endregion #region Delta E double DeltaE_CMC(double L1, double a1, double b1, double L2, double a2, double b2, out double dL, out double dC, out double dH) { double SL; if (L1 < 16) SL = 0.511; else SL = L1 * 0.040975 / (1 + 0.01765 * L1); //chroma calculation double C1 = Math.Sqrt(a1 * a1 + b1 * b1); double C2 = Math.Sqrt(a2 * a2 + b2 * b2); var deltaC = C1 - C2; double SC = (0.0638 * C1 / (1 + 0.0131 * C1)) + 0.638; double C1_P4 = Math.Pow(C1, 4); double F = Math.Sqrt(C1_P4 / (C1_P4 + 1900)); double H1 = Math.Atan2(b1, a1) * (180 / Math.PI); if (H1 < 0) H1 = H1 + 360; double T; if ((H1 >= 164) & (H1 <= 345)) T = 0.56 + Math.Abs(0.2 * Math.Cos((H1 + 168) *Math.PI / 180)); else //if ((H1 > 345) | (H1 < 164)) T = 0.36 + Math.Abs(0.4 * Math.Cos((H1 + 35) *Math.PI / 180)); double SH = SC * (T * F + 1 - F); var deltaL = L1 - L2; //hue calculation double delta_a = a1 - a2; double delta_b = b1 - b2; var deltaH = Math.Sqrt(Math.Max(delta_a * delta_a + delta_b * delta_b - deltaC * deltaC, 0.0)); double dECMC = Math.Sqrt(Math.Pow(deltaL / (2 * SL), 2) + Math.Pow(deltaC / SC, 2) + Math.Pow(deltaH / SH, 2)); dL = (deltaL / (2 * SL)) *(-1); dC = (deltaC / SC)*(-1); LabColor target_labColor = new LabColor(L1, a1, b1); LabColor labColor = new LabColor(L2, a2, b2); var converter = new ColourfulConverter { WhitePoint = Illuminants.D65 }; var LCH_input = converter.ToLChab(labColor); var LCH_target = converter.ToLChab(target_labColor); if(LCH_target.h > LCH_input.h) dH = (deltaH / SH) * (-1); else dH = (deltaH / SH); return dECMC; } double DeltaE_regular(double L1, double a1, double b1, double L2, double a2, double b2) { return Math.Sqrt(Math.Pow(L1 - L2, 2) + Math.Pow(a1 - a2, 2) + Math.Pow(b1 - b2, 2)); } private async void ValidationTests() { //if (ActiveLogModel.DeltaE <= 0.5) //{ // await NotificationProvider.ShowInfo("Previous trial seems to be very close; no more trials are recommended"); // return ; //} if (TrialsLogitems.Count == 1 || ActiveLogModel.DeltaE == null) return; int currentTrialNumber = ActiveLogModel.TrialNumber; if (TrialsLogitems.Count >= 3) { var item = TrialsLogitems.FirstOrDefault(x => x.TrialNumber == currentTrialNumber - 2); var item1 = TrialsLogitems.FirstOrDefault(x => x.TrialNumber == currentTrialNumber - 1); var item2 = ActiveLogModel; if(item1 != null && item2 != null && item != null && item2.DeltaE != null && item1.DeltaE != null && item.DeltaE != null) {//dEi+2- dEi+1>0.5 and dEi+1-dEi>0.5 if ( ( item2.DeltaE - item1.DeltaE) > 0.5 && (item1.DeltaE - item.DeltaE) > 0.5) { await NotificationProvider.ShowInfo("It seems that we can’t get you any closer"); return; } //Math.Abs //| dEi+1- dEi | and |dEi+2 -dEi+1|<=0.1. if (Math.Abs((double)item1.DeltaE - (double)item.DeltaE) <= 0.1 && Math.Abs((double)item2.DeltaE - (double)item1.DeltaE) <= 0.1) { await NotificationProvider.ShowInfo("It seems that we can’t get you any closer"); return; } } } if (TrialsLogitems.Count > 2) { var item = TrialsLogitems.FirstOrDefault(x => x.TrialNumber == currentTrialNumber - 1); var item1 = ActiveLogModel; if (item == null || item1 == null) return; if (Math.Abs((double)item1.C - (double)item.C) < 0.1 && Math.Abs((double)item1.M - (double)item.M) < 0.1 && Math.Abs((double)item1.Y - (double)item.Y) < 0.1 && Math.Abs((double)item1.K - (double)item.K) < 0.1) { await NotificationProvider.ShowInfo("It seems that we can’t get you any closer"); return; } if( MeasuredL == null || MeasuredA == null || MeasuredB == null || item.L == null || item1.L == null || item.A == null || item1.B == null || item.A == null || item1.A == null) return; var deltaE_reg = DeltaE_regular(TargetL, TargetA, TargetB, (double)MeasuredL, (double)MeasuredA, (double)MeasuredB); if ((Math.Abs((double)item1.L - (double)item.L) < 0.1 && Math.Abs((double)item1.A - (double)item.A) < 0.1 && Math.Abs((double)item1.B - (double)item.B) < 0.1) || deltaE_reg < 0.2) { await NotificationProvider.ShowInfo("It seems that we can’t get you any closer"); return; } } return; } private bool CalculateSuggestionLAB(TrialsLogModel trial) { if ((MeasuredL != null && MeasuredA != null && MeasuredB != null) || IsManualFineTuning && (LightnessOffset != 0.0 || ChromaOffset != 0.0 || HueOffset != 0.0)) { if(IsManualFineTuning) { LabColor labColor = new LabColor(trial.SuggestionL, trial.SuggestionA, trial.SuggestionB); var converter = new ColourfulConverter { WhitePoint = Illuminants.D65 }; var LCH = converter.ToLChab(labColor); Lch lch = VisualCorrectionModel.Correction(LCH.L, LCH.C, LCH.h, LightnessOffset, ChromaOffset, HueOffset); trial.NewSuggestionL = lch.L; trial.NewSuggestionA = lch.C * Math.Cos(lch.H * (Math.PI / 180)); trial.NewSuggestionB = lch.C * Math.Sin(lch.H * (Math.PI / 180)); } else if ( CorrectOnlyHue) { var converter = new ColourfulConverter { WhitePoint = Illuminants.D65 }; LabColor labColorTarget = new LabColor(TargetL, TargetA, TargetB); var LCH_target = converter.ToLChab(labColorTarget); LabColor labColorSuggestion = new LabColor(ActiveLogModel.SuggestionL, ActiveLogModel.SuggestionA, ActiveLogModel.SuggestionB); var LCH_suggestion = converter.ToLChab(labColorSuggestion); LabColor labColorNew = new LabColor((double)trial.VectorCorrectionL, (double)trial.VectorCorrectionA, (double)trial.VectorCorrectionB); var LCH_new = converter.ToLChab(labColorNew); double L = LCH_suggestion.L; double C = LCH_suggestion.C; double H = LCH_suggestion.h + (LCH_target.h - LCH_new.h); LabColor lab = converter.ToLab(new LChabColor(L, C, H)); trial.NewSuggestionL = lab.L; trial.NewSuggestionA = lab.a; trial.NewSuggestionB = lab.b; LogManager.Log($" Fine Tuning. Suggestion (calculated) LAB L:'{trial.NewSuggestionL}'A:'{trial.NewSuggestionA}' B:'{trial.NewSuggestionB}'."); return true; } else { var settings = SettingsManager.Default.GetOrCreate(); bool bNotChangeL = false; if(settings.FineTuningMinLimitdL > 0) { var dL = Math.Abs((double)trial.VectorCorrectionL - trial.SuggestionL); var dA = Math.Abs((double)trial.VectorCorrectionA - trial.SuggestionA); var dB = Math.Abs((double)trial.VectorCorrectionB - trial.SuggestionB); if(dL < settings.FineTuningMinLimitdL && (dL < dA || dL < dB)) { bNotChangeL = true; } } trial.NewSuggestionL = bNotChangeL ? trial.SuggestionL : LimitToRange((trial.SuggestionL + (TargetL - (double)trial.VectorCorrectionL)), 0, 100); trial.NewSuggestionA = LimitToRange((trial.SuggestionA + (TargetA - (double)trial.VectorCorrectionA)), -128, 127); trial.NewSuggestionB = LimitToRange((trial.SuggestionB + (TargetB - (double)trial.VectorCorrectionB)), -128, 127); LogManager.Log($" Fine Tuning. Suggestion (calculated) LAB L:'{trial.NewSuggestionL}'A:'{trial.NewSuggestionA}' B:'{trial.NewSuggestionB}'."); return true; } } else { trial.NewSuggestionL = trial.SuggestionL; trial.NewSuggestionA = trial.SuggestionA; trial.NewSuggestionB = trial.SuggestionB; } return false; } public double LimitToRange(double value, double inclusiveMinimum, double inlusiveMaximum) { if (value >= inclusiveMinimum) { if (value <= inlusiveMaximum) { return value; } return inlusiveMaximum; } return inclusiveMinimum; } #endregion #region JobRun Extensions private VectorFineTuningRunModel CreateFineTuningRunModel() { VectorFineTuningRunModel model = new VectorFineTuningRunModel(); model.Type = IsManualFineTuning ? FineTuningTypes.ManualFineTuning : FineTuningTypes.FineTuning; model.FineTuningSessionID = _sessionID; model.FineTuningTrialNumber = ActiveLogModel.TrialNumber + 1; model.JobName = BrushStopModel.SegmentModel.Job.Name; model.FineTuningTargetL = TargetL; model.FineTuningTargetA = TargetA; model.FineTuningTargetB = TargetB; model.FineTuningSuggestionL = BrushStopModel.L; model.FineTuningSuggestionA = BrushStopModel.A; model.FineTuningSuggestionB = BrushStopModel.B; model.FineTuningMeasuredL = MeasuredL; model.FineTuningMeasuredA = MeasuredA; model.FineTuningMeasuredB = MeasuredB; model.CorrectOnlyHue = CorrectOnlyHue; model.Lightness = LightnessOffset; model.Chroma = ChromaOffset; model.Hue = HueOffset; model.DeltaL = DL; model.DeltaH = DH; model.DeltaC = DC; model.DeltaE = DeltaE; return model; } private void JobRunsLogger_JobRunAvailable(object sender, Integration.JobRuns.JobRunAvailableEventArgs e) { ActiveLogModel.JobRunGuid = e.JobRun.Guid; } /// /// Vectors the correction. /// protected void VectorCorrection() { if(ActiveLogModel == null) return; if ( !IsValidLAB()) { ActiveLogModel.VectorCorrectionL = MeasuredL == null ? ActiveLogModel.SuggestionL : (double)MeasuredL; ActiveLogModel.VectorCorrectionA = MeasuredA == null ? ActiveLogModel.SuggestionA : (double)MeasuredA; ActiveLogModel.VectorCorrectionB = MeasuredB == null ? ActiveLogModel.SuggestionB : (double)MeasuredB; return; } ActiveLogModel.VectorCorrectionL = (double)MeasuredL; ActiveLogModel.VectorCorrectionA = (double)MeasuredA; ActiveLogModel.VectorCorrectionB = (double)MeasuredB; return; } #endregion #region save in excel protected List GetExcelDataItems(TrialsLogModel model, bool isAccepted) { String nameRML = BrushStopModel.SegmentModel.Job.Rml.DisplayName; String jobName = BrushStopModel.SegmentModel.Job.Name; String machine_SN = BrushStopModel.SegmentModel.Job.Machine.DeviceName; List items = new List(){ new ExcelFTTestsData() { Date = model.Date.ToString(), Job_Name = jobName, FVT_ID = model.TrialNumber.ToString(), Machine_SN = machine_SN, RML = nameRML, Target_L = TargetL.ToString("###.##"), Target_A = TargetA.ToString("###.##"), Target_B = TargetB.ToString("###.##"), Suggested_L = model.SuggestionL.ToString("###.##"), Suggested_A = model.SuggestionA.ToString("###.##"), Suggested_B = model.SuggestionB.ToString("###.##"), Suggested_C = model.C.ToString("0.##"), Suggested_M = model.M.ToString("0.##"), Suggested_Y = model.Y.ToString("0.##"), Suggested_K = model.K.ToString("0.##"), Result_L = model.NewSuggestionL.ToString("###.##"), Result_A = model.NewSuggestionA.ToString("###.##"), Result_B = model.NewSuggestionB.ToString("###.##"), delta_L = model.dL.ToString("###.##"), delta_C = model.dC.ToString("###.##"), delta_H = model.dH.ToString("###.##"), delta_E_CMC = model.DeltaEDisplay, OOG = model.SuggestedColor, Type = model.IsManualCorrection ? "Visual " + model.LightnessOffset.ToString("#.#") + "L+ " + model.ChromaOffset.ToString("#.#") + "C+ " + model.HueOffset.ToString("#.#") + "H" : model.CorrectOnlyHue ? "Vector H" : "Vector", User_selected_option = isAccepted? "accepted" : "",//????? User_finished_process = model.IsTested ? "tested" : "not tested" } }; return items; } protected void SaveTest(List items) { if (items == null || items.Count == 0) return; Task.Factory.StartNew(() => { ExcelWriter writer = null; try { IsFree = false; String dbFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "Color Fine tuning"); Directory.CreateDirectory(dbFolder); Stream stream = null; String nameRML = BrushStopModel.SegmentModel.Job.Rml.DisplayName; String jobName = BrushStopModel.SegmentModel.Job.Name; String mashine_SN = BrushStopModel.SegmentModel.Job.Machine.DeviceName; string fileName = String.Format($"{TargetL.ToString("##0")}_{TargetA.ToString("##0")}_{TargetB.ToString("##0")}_{nameRML}_{jobName}.xlsx"); string file = Path.Combine(dbFolder, fileName); bool dispose = false; if (File.Exists(file)) { stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); dispose = true; } else { stream = EmbeddedResourceHelper.GetEmbeddedResourceStream("Tango.PPC.Jobs.FineTuning.FTVTemplate.xlsx"); } if (stream == null) return; byte[] data = new byte[stream.Length]; stream.Read(data, 0, data.Length); File.WriteAllBytes(file, data); if (dispose) { stream.Dispose(); } writer = new ExcelWriter(file); writer.WriteData(items, "Sheet1"); writer.Dispose(); writer = null; } catch (Exception ex) { LogManager.Log(ex, $"Error exporting data."); InvokeUI(async () => { await NotificationProvider.ShowError($"An error occurred while trying to export the data. Make sure the excel file is closed and data is valid.\n{ex.FlattenMessage()}"); }); } finally { IsFree = true; if (writer != null) writer.Dispose(); } }); } #endregion } }