Esempio n. 1
0
        private void ExternalGraphImageFormResized(object sender, EventArgs e)
        {
            BackgroundWorker    bgwGenerateGraphImage = new BackgroundWorker();
            SimpleShowImageForm f1 = sender as SimpleShowImageForm;

            bgwGenerateGraphImage.DoWork += (sndr, args) =>
            {
                ThreadSafeOperations.SetLoadingCircleState(wcUpdatimgGraph, true, true, wcUpdatimgGraph.Color);

                Image <Bgr, byte> img = FillGraphImage(f1.pb1.Size);
                args.Result = new object[] { img };
            };

            bgwGenerateGraphImage.RunWorkerCompleted += (sndr, args) =>
            {
                Image <Bgr, byte> resImg = (args.Result as object[])[0] as Image <Bgr, byte>;

                ServiceTools.ExecMethodInSeparateThread(this, delegate()
                {
                    f1.UpdateBitmap(resImg.Bitmap);
                });

                ThreadSafeOperations.SetLoadingCircleState(wcUpdatimgGraph, false, false, wcUpdatimgGraph.Color);
            };

            bgwGenerateGraphImage.RunWorkerAsync();
        }
Esempio n. 2
0
        void bgwGraphsPresenterInSeparateWindow_DoWork(object sender, DoWorkEventArgs e)
        {
            ThreadSafeOperations.SetLoadingCircleState(wcUpdatimgGraph, true, true, wcUpdatimgGraph.Color);

            Image <Bgr, byte> img = FillGraphImage(new Size(1280, 1024));

            if (img != null)
            {
                ServiceTools.ExecMethodInSeparateThread(this, delegate()
                {
                    SimpleShowImageForm f1 = new SimpleShowImageForm(img.Bitmap);
                    f1.FormResizing       += ExternalGraphImageFormResized;
                    f1.Show();
                });
            }

            ThreadSafeOperations.SetLoadingCircleState(wcUpdatimgGraph, false, false, wcUpdatimgGraph.Color);
        }
Esempio n. 3
0
        private Image <Bgr, byte> FillGraphImage(Size imgSize)
        {
            string curDirPath = Directory.GetCurrentDirectory() + "\\logs\\";

            DirectoryInfo dirInfo = new DirectoryInfo(curDirPath);

            List <Dictionary <string, object> > lReadData = new List <Dictionary <string, object> >();

            if (defaultGraphsTimeSpan)
            {
                graphsTimeSpan = new Tuple <DateTime, DateTime>(DateTime.UtcNow.AddDays(-1), DateTime.UtcNow);
            }

            GraphVariablesTypes currVarType = GraphVariablesTypes.none;

            if (rbtnPressureGraph.Checked)
            {
                currVarType = GraphVariablesTypes.Pressure;
            }
            if (rbtnAirTempGraph.Checked)
            {
                currVarType = GraphVariablesTypes.AirTemp;
            }
            if (rbtnWaterTempGraph.Checked)
            {
                currVarType = GraphVariablesTypes.WaterTemp;
            }
            if (rbtnWindSpeedGraph.Checked)
            {
                currVarType = GraphVariablesTypes.WindSpeed;
            }


            if ((fRenderer == null) || (!prevGraphsTimeSpan.Equals(graphsTimeSpan) || currVarType != prevGraphVariable))
            {
                fRenderer = new MultipleScatterAndFunctionsRepresentation(imgSize);
                switch (currVarType)
                {
                case GraphVariablesTypes.Pressure:
                {
                    currValueColor = new Bgr(Color.Blue);
                    break;
                }

                case GraphVariablesTypes.AirTemp:
                {
                    currValueColor = new Bgr(Color.Red);
                    break;
                }

                case GraphVariablesTypes.WaterTemp:
                {
                    currValueColor = new Bgr(Color.RoyalBlue);
                    break;
                }

                case GraphVariablesTypes.WindSpeed:
                {
                    currValueColor = new Bgr(Color.Gray);
                    break;
                }

                default:
                {
                    currValueColor = new Bgr(Color.Blue);
                    break;
                }
                }
            }
            else if (fRenderer != null)
            {
                if (fRenderer.TheImage.Size != imgSize)
                {
                    fRenderer.ResizeCanvas(imgSize);
                }
            }



            if (!prevGraphsTimeSpan.Equals(graphsTimeSpan))
            {
                IEnumerable <string> ncFileNames = Directory.EnumerateFiles(curDirPath,
                                                                            "IoffeVesselInfoStream-MeteoDataLog-*.nc",
                                                                            SearchOption.TopDirectoryOnly);
                foreach (string ncFileName in ncFileNames)
                {
                    Tuple <DateTime, DateTime> currFileDateTimeRange = null;
                    try
                    {
                        currFileDateTimeRange = ServiceTools.GetNetCDFfileTimeStampsRange(ncFileName);
                    }
                    catch (Exception ex)
                    {
                        #region report

#if DEBUG
                        ServiceTools.ExecMethodInSeparateThread(this, () =>
                        {
                            theLogWindow = ServiceTools.LogAText(theLogWindow,
                                                                 "an exception has been thrown during file reading: " + Environment.NewLine + ncFileName +
                                                                 Environment.NewLine + "message: " + ex.Message + Environment.NewLine +
                                                                 ServiceTools.CurrentCodeLineDescription());
                        });
#else
                        ServiceTools.ExecMethodInSeparateThread(this, () =>
                        {
                            ServiceTools.logToTextFile(errorLogFilename,
                                                       "an exception has been thrown during file reading: " + Environment.NewLine + ncFileName +
                                                       Environment.NewLine + "message: " + ex.Message + Environment.NewLine +
                                                       ServiceTools.CurrentCodeLineDescription(), true, true);
                        });
#endif

                        #endregion report
                    }

                    if (currFileDateTimeRange == null)
                    {
                        continue;
                    }

                    if ((currFileDateTimeRange.Item1 >= graphsTimeSpan.Item1) &&
                        (currFileDateTimeRange.Item1 <= graphsTimeSpan.Item2) ||
                        (currFileDateTimeRange.Item2 >= graphsTimeSpan.Item1) &&
                        (currFileDateTimeRange.Item2 <= graphsTimeSpan.Item2))
                    {
                        Dictionary <string, object> dictFileData = null;
                        try
                        {
                            dictFileData = NetCDFoperations.ReadDataFromFile(ncFileName);
                        }
                        catch (Exception ex)
                        {
                            #region report

#if DEBUG
                            ServiceTools.ExecMethodInSeparateThread(this, () =>
                            {
                                theLogWindow = ServiceTools.LogAText(theLogWindow,
                                                                     "an exception has been thrown during file reading: " + Environment.NewLine +
                                                                     ncFileName +
                                                                     Environment.NewLine + "message: " + ex.Message + Environment.NewLine +
                                                                     ServiceTools.CurrentCodeLineDescription());
                            });
#else
                            ServiceTools.ExecMethodInSeparateThread(this, () =>
                            {
                                ServiceTools.logToTextFile(errorLogFilename,
                                                           "an exception has been thrown during file reading: " + Environment.NewLine + ncFileName +
                                                           Environment.NewLine + "message: " + ex.Message + Environment.NewLine +
                                                           ServiceTools.CurrentCodeLineDescription(), true, true);
                            });
#endif

                            #endregion report
                        }

                        if (dictFileData != null)
                        {
                            lReadData.Add(dictFileData);
                        }
                    }
                }


                foreach (Dictionary <string, object> currFileDataDict in lReadData)
                {
                    if (currFileDataDict == null)
                    {
                        continue;
                    }

                    string varNameDateTime = "DateTime";

                    List <long> currFileDateTimeLongTicksList =
                        new List <long>((currFileDataDict[varNameDateTime] as long[]));
                    List <DateTime> currFileDateTimeList =
                        currFileDateTimeLongTicksList.ConvertAll(longVal => new DateTime(longVal));

                    string           varNameMeteoData      = "MeteoData";
                    List <MeteoData> currFileMeteoDataList =
                        MeteoData.OfDenseMatrix(currFileDataDict[varNameMeteoData] as DenseMatrix);

                    if (tsMeteoDataForGraphs == null)
                    {
                        try
                        {
                            tsMeteoDataForGraphs = new TimeSeries <MeteoData>(currFileMeteoDataList, currFileDateTimeList,
                                                                              true);
                        }
                        catch (Exception ex)
                        {
                            #region report

#if DEBUG
                            ServiceTools.ExecMethodInSeparateThread(this, () =>
                            {
                                theLogWindow = ServiceTools.LogAText(theLogWindow,
                                                                     "couldn`t create timeseries: exception has been thrown" + Environment.NewLine +
                                                                     ServiceTools.CurrentCodeLineDescription() + Environment.NewLine + "message: " +
                                                                     ex.Message);
                            });
#else
                            ServiceTools.ExecMethodInSeparateThread(this, () =>
                            {
                                ServiceTools.logToTextFile(errorLogFilename,
                                                           "couldn`t create timeseries: exception has been thrown" + Environment.NewLine +
                                                           ServiceTools.CurrentCodeLineDescription() + Environment.NewLine + "message: " +
                                                           ex.Message, true, true);
                            });
#endif

                            #endregion report
                        }
                    }
                    else
                    {
                        try
                        {
                            tsMeteoDataForGraphs.AddSubseriaData(currFileMeteoDataList, currFileDateTimeList, true);
                        }
                        catch (Exception ex)
                        {
                            #region report

#if DEBUG
                            ServiceTools.ExecMethodInSeparateThread(this, () =>
                            {
                                theLogWindow = ServiceTools.LogAText(theLogWindow,
                                                                     "couldn`t create timeseries: exception has been thrown" + Environment.NewLine +
                                                                     ServiceTools.CurrentCodeLineDescription() + Environment.NewLine + "message: " +
                                                                     ex.Message);
                            });
#else
                            ServiceTools.ExecMethodInSeparateThread(this, () =>
                            {
                                ServiceTools.logToTextFile(errorLogFilename,
                                                           "couldn`t create timeseries: exception has been thrown" + Environment.NewLine +
                                                           ServiceTools.CurrentCodeLineDescription() + Environment.NewLine + "message: " +
                                                           ex.Message, true, true);
                            });
#endif

                            #endregion report
                        }
                    }
                }



                if (tsMeteoDataForGraphs == null)
                {
                    return(null);
                }

                tsMeteoDataForGraphs.SortByTimeStamps();
                tsMeteoDataForGraphs.RemoveDuplicatedTimeStamps();

                DateTime utcNow = DateTime.UtcNow;
                if (defaultGraphsTimeSpan)
                {
                    tsMeteoDataForGraphs.RemoveValues(dt => (utcNow - dt).TotalSeconds > 86400);
                }
                else
                {
                    tsMeteoDataForGraphs.RemoveValues(
                        dt => !((dt >= graphsTimeSpan.Item1) && (dt <= graphsTimeSpan.Item2)));
                }


                List <TimeSeries <MeteoData> > subSeriesBy1Minute =
                    tsMeteoDataForGraphs.SplitByTimeSpan(new TimeSpan(0, 1, 0));
                List <double>         lSubSeriesEntriesCount = subSeriesBy1Minute.ConvertAll(subs => (double)subs.Count);
                DescriptiveStatistics statsCounts            = new DescriptiveStatistics(lSubSeriesEntriesCount);
                aveMinuteEntriesCount = Convert.ToInt32(statsCounts.Mean);


                // = tsMeteoData.TimeStamps.ConvertAll(dt => (dt - maxDateTime).TotalSeconds);
            }



            List <MeteoData> meteoDataList = tsMeteoDataForGraphs.DataValues;
            DateTime         maxDateTime   = tsMeteoDataForGraphs.TimeStamps.Max();



            if ((currVarType != prevGraphVariable) || !prevGraphsTimeSpan.Equals(graphsTimeSpan))
            {
                double        minVarValue         = 0.0d;
                double        maxVarValue         = 1.0d;
                List <double> currVarToShowValues = new List <double>();
                switch (currVarType)
                {
                case GraphVariablesTypes.Pressure:
                {
                    currVarToShowValues = meteoDataList.ConvertAll(mdt => mdt.pressure);

                    TimeSeries <double> currVarTS = new TimeSeries <double>(currVarToShowValues,
                                                                            tsMeteoDataForGraphs.TimeStamps);
                    currVarTS.RemoveValues(dVal => dVal <= 900.0d);

                    currVarToShowValues = new List <double>(currVarTS.DataValues);
                    currFileSecondsList = currVarTS.TimeStamps.ConvertAll(dt => (dt - maxDateTime).TotalSeconds);

                    fRenderer.yAxisValuesConversionToRepresentTicksValues =
                        new Func <double, string>(dVal => dVal.ToString("F1"));
                    break;
                }

                case GraphVariablesTypes.AirTemp:
                {
                    currVarToShowValues = meteoDataList.ConvertAll(mdt => mdt.airTemperature);

                    TimeSeries <double> currVarTS = new TimeSeries <double>(currVarToShowValues,
                                                                            tsMeteoDataForGraphs.TimeStamps);
                    currVarTS.RemoveValues(dVal => ((dVal < -20.0d) || (dVal > 50.0d)));

                    currVarToShowValues = new List <double>(currVarTS.DataValues);
                    currFileSecondsList = currVarTS.TimeStamps.ConvertAll(dt => (dt - maxDateTime).TotalSeconds);

                    fRenderer.yAxisValuesConversionToRepresentTicksValues =
                        new Func <double, string>(dVal => dVal.ToString("F2"));
                    break;
                }

                case GraphVariablesTypes.WaterTemp:
                {
                    currVarToShowValues = meteoDataList.ConvertAll(mdt => mdt.waterTemperature);

                    TimeSeries <double> currVarTS = new TimeSeries <double>(currVarToShowValues,
                                                                            tsMeteoDataForGraphs.TimeStamps);
                    currVarTS.RemoveValues(dVal => ((dVal < -20.0d) || (dVal > 50.0d)));

                    currVarToShowValues = new List <double>(currVarTS.DataValues);
                    currFileSecondsList = currVarTS.TimeStamps.ConvertAll(dt => (dt - maxDateTime).TotalSeconds);



                    fRenderer.yAxisValuesConversionToRepresentTicksValues =
                        new Func <double, string>(dVal => dVal.ToString("F2"));
                    break;
                }

                case GraphVariablesTypes.WindSpeed:
                {
                    currVarToShowValues = meteoDataList.ConvertAll(mdt => mdt.windSpeed);

                    TimeSeries <double> currVarTS = new TimeSeries <double>(currVarToShowValues,
                                                                            tsMeteoDataForGraphs.TimeStamps);
                    currVarTS.RemoveValues(dVal => ((dVal < 0.0d) || (dVal > 50.0d)));

                    currVarToShowValues = new List <double>(currVarTS.DataValues);
                    currFileSecondsList = currVarTS.TimeStamps.ConvertAll(dt => (dt - maxDateTime).TotalSeconds);

                    fRenderer.yAxisValuesConversionToRepresentTicksValues =
                        new Func <double, string>(dVal => dVal.ToString("F1"));
                    break;
                }

                default:
                    return(null);
                }

                dvVarValues = DenseVector.OfEnumerable(currVarToShowValues);
                dvVarValues = dvVarValues.Conv(Extensions.StandardConvolutionKernels.gauss, aveMinuteEntriesCount * 10);
            }



            fRenderer.dvScatterFuncValues.Add(dvVarValues);
            fRenderer.dvScatterXSpace.Add(DenseVector.OfEnumerable(currFileSecondsList));

            fRenderer.xAxisValuesConversionToRepresentTicksValues = (dValSec) =>
            {
                DateTime currDT = tsMeteoDataForGraphs.TimeStamps.Max().AddSeconds(dValSec);
                return(currDT.ToString("yyyy-MM-dd" + Environment.NewLine + "HH:mm"));
            };

            fRenderer.scatterLineColors.Add(currValueColor);
            fRenderer.scatterDrawingVariants.Add(SequencesDrawingVariants.polyline);
            fRenderer.xSpaceMin           = currFileSecondsList.Min();
            fRenderer.xSpaceMax           = currFileSecondsList.Max();
            fRenderer.overallFuncMin      = dvVarValues.Min();
            fRenderer.overallFuncMax      = dvVarValues.Max();
            fRenderer.fixSpecifiedMargins = true;

            fRenderer.Represent();

            Image <Bgr, byte> retImg = fRenderer.TheImage;

            // расположим надпись
            string strSign = "current value: " + dvVarValues.Last().ToString("F2");

            List <TextBarImage> textBarsCases = new List <TextBarImage>();

            TextBarImage tbimTopLeftSign = new TextBarImage(strSign, retImg);
            tbimTopLeftSign.PtSurroundingBarStart =
                new Point(fRenderer.LeftServiceSpaceGapX + tbimTopLeftSign.textHalfHeight,
                          fRenderer.TopServiceSpaceGapY + tbimTopLeftSign.textHalfHeight);
            textBarsCases.Add(tbimTopLeftSign);

            TextBarImage tbimBtmLeftSign = new TextBarImage(strSign, retImg);
            tbimBtmLeftSign.PtSurroundingBarStart = new Point(fRenderer.LeftServiceSpaceGapX + tbimBtmLeftSign.textHalfHeight,
                                                              retImg.Height - fRenderer.BtmServiceSpaceGapY - tbimBtmLeftSign.textHalfHeight - tbimBtmLeftSign.textHeight * 2);
            textBarsCases.Add(tbimBtmLeftSign);

            TextBarImage tbimTopRightSign = new TextBarImage(strSign, retImg);
            tbimTopRightSign.PtSurroundingBarStart =
                new Point(
                    retImg.Width - fRenderer.RightServiceSpaceGapX - tbimTopRightSign.textHalfHeight -
                    tbimTopRightSign.textBarSize.Width, fRenderer.TopServiceSpaceGapY + tbimTopLeftSign.textHalfHeight);
            textBarsCases.Add(tbimTopRightSign);

            TextBarImage tbimBtmRightSign = new TextBarImage(strSign, retImg);
            tbimBtmRightSign.PtSurroundingBarStart =
                new Point(
                    retImg.Width - fRenderer.RightServiceSpaceGapX - tbimBtmRightSign.textHalfHeight -
                    tbimBtmRightSign.textBarSize.Width,
                    retImg.Height - fRenderer.BtmServiceSpaceGapY - tbimBtmRightSign.textHalfHeight -
                    tbimBtmRightSign.textHeight * 2);
            textBarsCases.Add(tbimBtmRightSign);

            textBarsCases.Sort((case1, case2) => (case1.SubImageInTextRect.CountNonzero().Sum() > case2.SubImageInTextRect.CountNonzero().Sum()) ? 1 : -1);

            MCvFont theFont = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_PLAIN, 2.0d, 2.0d)
            {
                thickness = 2,
            };
            // retImg.Draw(strSign, textBarsCases[0].ptTextBaselineStart, Emgu.CV.CvEnum.FontFace.HersheyPlain, 2.0d, new Bgr(Color.Green), 2);
            retImg.Draw(strSign, ref theFont, textBarsCases[0].ptTextBaselineStart, new Bgr(Color.Green));
            retImg.Draw(textBarsCases[0].rectSurroundingBar, new Bgr(Color.Green), 2);

            prevGraphsTimeSpan = graphsTimeSpan;
            prevGraphVariable  = currVarType;

            return(retImg);
        }
Esempio n. 4
0
        // private List<bool> bgwFinished = new List<bool>();
        public void CollectPositioningData()
        {
#if DEBUG
            int concurrentFilesProcessingCount = 1;
#else
            int concurrentFilesProcessingCount = 2;
            try
            {
                concurrentFilesProcessingCount = Convert.ToInt32(defaultProperties["MaxConcurrentFilesProcessingCount"]);
            }
            catch (Exception ex)
            {
                theLogWindow = ServiceTools.LogAText(theLogWindow,
                                                     "ERROR! exception thrown: " + ex.Message + Environment.NewLine +
                                                     "MaxConcurrentFilesProcessingCount value can`t be read. " + Environment.NewLine +
                                                     "Using default value = " + concurrentFilesProcessingCount);
            }
#endif



            theLogWindow = ServiceTools.LogAText(theLogWindow, "started on " + DateTime.UtcNow.ToString("s"));


            string        strImagesDir = ParentForm.richTextBox1.Text;
            DirectoryInfo imagesDir    = new DirectoryInfo(strImagesDir);

            if (!imagesDir.Exists)
            {
                theLogWindow = ServiceTools.LogAText(theLogWindow,
                                                     "Операция не выполнена. Не найдена директория:" + Environment.NewLine + strImagesDir +
                                                     Environment.NewLine, true);
                return;
            }


            // оказалось, что маска - case-insensitive
            lImagesFileInfos = new List <FileInfo>(imagesDir.GetFiles("*.jpg", SearchOption.TopDirectoryOnly));

            List <FileInfo> lImagesFileInfoWithExistingSunDiskInfo = lImagesFileInfos.ConvertAll <FileInfo>(fInfoSrc =>
            {
                string sunDiskInfoFileName = fInfoSrc.DirectoryName + "\\" +
                                             Path.GetFileNameWithoutExtension(fInfoSrc.FullName) + "-SunDiskInfo.xml";
                if (File.Exists(sunDiskInfoFileName))
                {
                    return(fInfoSrc);
                }
                else
                {
                    return(null);
                }
            });
            lImagesFileInfoWithExistingSunDiskInfo.RemoveAll(fInfo => fInfo == null);

            theLogWindow = ServiceTools.LogAText(theLogWindow,
                                                 "files already processed before: " + lImagesFileInfoWithExistingSunDiskInfo.Count);

            lImagesFileInfos.RemoveAll(fInfo => lImagesFileInfoWithExistingSunDiskInfo.Contains(fInfo));
            int filesCountToProcess        = lImagesFileInfos.Count;
            int filesCountAlreadyProcessed = lImagesFileInfoWithExistingSunDiskInfo.Count;

            lImagesFileInfos.AddRange(lImagesFileInfoWithExistingSunDiskInfo);



            //List<BackgroundWorker> bgwList = new List<BackgroundWorker>();
            //for (int i = 0; i < 2; i++)
            //{
            //    //bgwFinished.Add(true);
            //    //bgwList.Add(null);
            //}

            int currDataIdx = 1;

            foreach (FileInfo finfo in lImagesFileInfos)
            {
                //int currentBgwID = -1;
                while ((cbgBgwList.Count >= concurrentFilesProcessingCount) && (!hasToStopCollecting))
                {
                    Application.DoEvents();
                    Thread.Sleep(0);
                }

                //while ((bgwFinished.Sum(boolVal => (boolVal) ? ((int)0) : ((int)1)) == bgwFinished.Count) && (!hasToStopCollecting))
                //{
                //    Application.DoEvents();
                //    Thread.Sleep(0);
                //}
                if (hasToStopCollecting)
                {
                    break;
                }

                //for (int i = 0; i < concurrentFilesProcessingCount; i++)
                //{
                theLogWindow = ServiceTools.LogAText(theLogWindow,
                                                     "" + currDataIdx + " / " + filesCountToProcess + " (+ " + filesCountAlreadyProcessed +
                                                     " processed before)");
                theLogWindow = ServiceTools.LogAText(theLogWindow, Environment.NewLine + "starting: " + finfo.Name);


                //object[] BGWorker2Args = new object[] { finfo, defaultProperties, currentBgwID };
                object[] BGWorker2Args = new object[] { finfo, defaultProperties };

                BackgroundWorker currBgw = new BackgroundWorker();
                // bgwList[currentBgwID] = currBgw;
                currBgw.DoWork             += currBgw_DoWork;
                currBgw.RunWorkerCompleted += currBgw_RunWorkerCompleted;
                currBgw.RunWorkerAsync(BGWorker2Args);

                cbgBgwList.Add(finfo.FullName);

                if (filesCountToProcess > 0)
                {
                    int progress = Convert.ToInt32(100.0d * (double)currDataIdx / (double)filesCountToProcess);
                    ThreadSafeOperations.UpdateProgressBar(ParentForm.pbUniversalProgressBar, progress);
                    Interlocked.Increment(ref currDataIdx);
                }
            }


            while (cbgBgwList.Count > 0)
            {
                Application.DoEvents();
                Thread.Sleep(0);
            }

            if (hasToStopCollecting)
            {
                return;
            }



            // сохраним на будущее
            string   strMedianPerc5StatsXMLFileName = (string)defaultProperties["DefaultMedianPerc5StatsXMLFile"];
            FileInfo MedianPerc5StatsXMLFileInfo    = new FileInfo(strMedianPerc5StatsXMLFileName);
            string   strMedianPerc5StatsXMLFilePath = MedianPerc5StatsXMLFileInfo.DirectoryName;
            strMedianPerc5StatsXMLFilePath += (strMedianPerc5StatsXMLFilePath.Last() == '\\') ? ("") : ("\\");
            string computedDeviationsXMLfilesPath = strMedianPerc5StatsXMLFilePath + "azimuth-dev-stats\\";
            if (!ServiceTools.CheckIfDirectoryExists(computedDeviationsXMLfilesPath))
            {
                theLogWindow = ServiceTools.LogAText(theLogWindow,
                                                     "couldn`t locate or create directory " + computedDeviationsXMLfilesPath);
                return;
            }

            string computedAzimuthDeviationsXMLFile = computedDeviationsXMLfilesPath + "PreComputedSunAnglesDeviationsData.xml";

            List <AngleSunDeviationCalcResult> lResList =
                new List <AngleSunDeviationCalcResult>(cbAnglesSunDeviationCalcResults);
            ServiceTools.WriteObjectToXML(lResList, computedAzimuthDeviationsXMLFile);
            ServiceTools.WriteDictionaryToXml(defaultProperties, defaultPropertiesXMLfileName, false);


            // теперь посчитаем статистику
            List <AngleSunDeviationCalcResult> azimuthResults = new List <AngleSunDeviationCalcResult>(lResList);
            List <AngleSunDeviationCalcResult> zenithResults  = new List <AngleSunDeviationCalcResult>(lResList);
            azimuthResults.RemoveAll(
                azimuthSunDeviationCalcResult =>
                ((!azimuthSunDeviationCalcResult.calculationSucceeded) ||
                 (!azimuthSunDeviationCalcResult.AzimuthDeviationCanBeComputed)));
            zenithResults.RemoveAll(
                sunDeviationCalcResult =>
                ((!sunDeviationCalcResult.calculationSucceeded) ||
                 (!sunDeviationCalcResult.ZenithDeviationCanBeComputed)));

            List <double> azimuthDevValues =
                azimuthResults.ConvertAll <double>(
                    azimuthSunDeviationCalcResult => azimuthSunDeviationCalcResult.computedAzimuthDeviationDeg);

            List <double> zenithDevValues =
                zenithResults.ConvertAll <double>(
                    azimuthSunDeviationCalcResult => azimuthSunDeviationCalcResult.computedZenithDeviationDeg);


            ServiceTools.ExecMethodInSeparateThread(ParentForm, delegate()
            {
                HistogramDataAndProperties histAzimuthData =
                    new HistogramDataAndProperties(DenseVector.OfEnumerable(azimuthDevValues), 100);
                HistogramCalcAndShowForm hAzimuthForm = new HistogramCalcAndShowForm("azimuth sun angle deviations (deg.)",
                                                                                     defaultProperties);
                hAzimuthForm.HistToRepresent = histAzimuthData;
                hAzimuthForm.Show();
                hAzimuthForm.Represent();
            });



            ServiceTools.ExecMethodInSeparateThread(ParentForm, delegate()
            {
                HistogramDataAndProperties histZenithData =
                    new HistogramDataAndProperties(DenseVector.OfEnumerable(zenithDevValues), 100);
                HistogramCalcAndShowForm hZenithForm = new HistogramCalcAndShowForm("zenith sun angle deviations (deg.)",
                                                                                    defaultProperties);
                hZenithForm.HistToRepresent = histZenithData;
                hZenithForm.Show();
                hZenithForm.Represent();
            });



            ThreadSafeOperations.UpdateProgressBar(ParentForm.pbUniversalProgressBar, 0);
        }