Beispiel #1
0
        public HashBasedIEquatibleGeoCell(double latmin, double lonmin, double latmax, double lonmax, ITimeSegment time)
        {
            LatMax = latmax;
            LatMin = latmin;
            LonMax = lonmax;
            LonMin = lonmin;
            Time   = time;

            double[] doubles = new double[] { latmin, latmax, lonmin, lonmax };
            int[]    ints    = new int[] { time.FirstDay, time.LastDay, time.FirstYear, time.LastYear, time.StartHour, time.StopHour };

            byte[] bytes = new byte[sizeof(double) * doubles.Length + sizeof(int) * ints.Length];

            int offset = 0;

            for (int i = 0; i < doubles.Length; i++)
            {
                byte[] b = BitConverter.GetBytes(doubles[i]);
                Buffer.BlockCopy(b, 0, bytes, offset, sizeof(double));
                offset += sizeof(double);
            }

            for (int i = 0; i < ints.Length; i++)
            {
                byte[] b = BitConverter.GetBytes(ints[i]);
                Buffer.BlockCopy(b, 0, bytes, offset, sizeof(int));
                offset += sizeof(int);
            }

            hash     = SHA1Hash.HashAsync(bytes).Result;
            hashCode = BitConverter.ToInt32(BitConverter.GetBytes(hash), 0);
        }
        public DataCoverageResult GetCoverage(ITimeSegment t)
        {
            var doubleIntervals = GetTimeIntervals(t).Select(interval => timeAxisProjection.ProjectIntervalToTheAxis(interval)).ToArray();

            bool uncertatintyAvailable = true;

            foreach (var interval in doubleIntervals)
            {
                var coverage = coverageEvaluator.EvaluateInterval(grid, interval.Item1, interval.Item2);
                switch (coverage)
                {
                case DataCoverageResult.OutOfData:
                    return(DataCoverageResult.OutOfData);

                    break;

                case DataCoverageResult.DataWithoutUncertainty:
                    uncertatintyAvailable = false;
                    break;

                case DataCoverageResult.DataWithUncertainty:
                    //nothing here
                    break;

                default: throw new NotSupportedException();
                }
            }
            return(uncertatintyAvailable ? DataCoverageResult.DataWithUncertainty : DataCoverageResult.DataWithoutUncertainty);
        }
Beispiel #3
0
 public void RemoveTimeSegment(ITimeSegment ts)
 {
     lock (mTimeSegmentList.SyncRoot)
     {
         mTimeSegmentList.Remove(ts);
     }
 }
Beispiel #4
0
        public IndexBoundingBox GetBoundingBox(ITimeSegment t)
        {
            Debug.Assert(t.FirstYear != t.LastYear || t.FirstDay <= t.LastDay);
            int lastDay = t.LastDay;

            bool isLeapYear = (t.FirstYear == t.LastYear && DateTime.IsLeapYear(t.FirstYear));
            var  p1         = DaysOfYearConversions.ProjectFirstDay(t.FirstDay, isLeapYear);
            var  p2         = DaysOfYearConversions.ProjectLastDay(t.LastDay, isLeapYear);

            IndexBoundingBox bb;

            if (lastDay < t.FirstDay)
            {
                bb = new IndexBoundingBox()
                {
                    first = 0, last = 11
                }
            }
            ;                                                         //new year overlap
            else
            {
                bb = new IndexBoundingBox()
                {
                    first = (int)Math.Floor(p1),
                    last  = (int)Math.Floor(p2 - 1e-2) //the shift is less than "1 day" is needed to handle exact end of the month
                }
            };

            return(bb);
        }
Beispiel #5
0
        public double[] getAproximationGrid(ITimeSegment timeSegment)
        {
            IPs ips = GetTempIPs(timeSegment);

            double[] result = ips.Indices.Select(idx => axis[idx]).ToArray();
            return(result);
        }
Beispiel #6
0
 public IndexBoundingBox GetBoundingBox(ITimeSegment t)
 {
     return(new IndexBoundingBox()
     {
         first = 0, last = 0
     });
 }
Beispiel #7
0
 public ITimeSegment[] GetTimeSegments()
 {
     lock (mTimeSegmentList.SyncRoot)
     {
         ITimeSegment[] tss = new ITimeSegment[mTimeSegmentList.Count];
         mTimeSegmentList.CopyTo(tss, 0);
         return(tss);
     }
 }
        public IPs GetTempIPs(ITimeSegment t)
        {
            IPs    componentResult = component.GetTempIPs(t);
            var    coerced         = ThinningUtils.Thinning(componentResult, countConstraint);
            double sum             = coerced.Weights.Sum();

            System.Diagnostics.Debug.Assert(Math.Abs(sum - 1.0) < 1e-7);
            return(coerced);
        }
Beispiel #9
0
        public IPs GetTempIPs(ITimeSegment t)
        {
            Debug.Assert(t.FirstYear != t.LastYear || t.FirstDay <= t.LastDay);

            bool isLeap = false;

            if (t.FirstYear == t.LastYear && DateTime.IsLeapYear(t.FirstYear))
            {
                isLeap = true;
            }


            int lastDay = t.LastDay;

            if (t.LastDay < t.FirstDay) //handling new year overlap
            {
                lastDay += 365;
            }

            double startProjection = DaysOfYearConversions.ProjectFirstDay(t.FirstDay, isLeap);
            double endProjection   = DaysOfYearConversions.ProjectLastDay(lastDay, isLeap);

            var r = coverageEvaluator.EvaluateInterval(axis, startProjection, endProjection);

            Debug.Assert(r != DataCoverageResult.OutOfData);

            int startIndex, stopIndex;

            double[] weights = weightsProvider.GetWeights(axis, startProjection, endProjection, out startIndex, out stopIndex);

            double[] accumulatedWeights = new double[12];
            for (int i = startIndex; i <= stopIndex; i++)
            {
                accumulatedWeights[i % 12] += weights[i - startIndex];
            }
            List <double> weightsL = new List <double>(12);
            List <int>    indecesL = new List <int>(12);

            for (int i = 0; i < 12; i++)
            {
                if (accumulatedWeights[i] != 0.0) //both number and NAN will cause generation of IP
                {
                    indecesL.Add(i);
                    weightsL.Add(accumulatedWeights[i]);
                }
            }

            IPs integrationPoints = new IPs {
                Indices = indecesL.ToArray(), Weights = weightsL.ToArray(), BoundingIndices = new IndexBoundingBox {
                    first = indecesL[0], last = indecesL[indecesL.Count - 1]
                }
            };

            return(integrationPoints);
        }
        public IndexBoundingBox GetBoundingBox(ITimeSegment t)
        {
            var intervals = GetTimeIntervals(t).Select(irvl => timeAxisProjection.ProjectIntervalToTheAxis(irvl)).ToArray();
            IndexBoundingBox boundingBox = new IndexBoundingBox();

            foreach (var interval in intervals)
            {
                var bb1 = dataMaskProvider.GetBoundingBox(grid, interval.Item1, interval.Item2);
                boundingBox = IndexBoundingBox.Union(boundingBox, bb1);
            }

            return(boundingBox);
        }
        public DataCoverageResult GetCoverage(ITimeSegment t)
        {
            var test = GetBoundingBox(t);

            if (test.IsSingular)
            {
                return(DataCoverageResult.OutOfData);
            }
            else
            {
                return(DataCoverageResult.DataWithoutUncertainty);
            }
        }
Beispiel #12
0
        public IPs GetTempIPs(ITimeSegment t)
        {
            IPs integrationPoints = new IPs()
            {
                BoundingIndices = new IndexBoundingBox()
                {
                    first = 0, last = 0
                },
                Indices = new int[] { 0 },
                Weights = new double[] { 1.0 }
            };

            return(integrationPoints);
        }
Beispiel #13
0
        public DataCoverageResult GetCoverage(ITimeSegment t)
        {
            double tolerance = 1e-5;

            IPs ips = GetTempIPs(t);

            if (ips.Weights.All(e => Math.Abs(e - ips.Weights[0]) < tolerance))
            {
                return(DataCoverageResult.DataWithUncertainty);
            }
            else
            {
                return(DataCoverageResult.DataWithoutUncertainty);
            }
        }
Beispiel #14
0
        protected bool SetConfig()
        {
            if (mConfig == null && mManager != null)
            {
                mConfig = mManager.CreateConfigInstance();
            }

            if (mConfig != null)
            {
                (mConfig as CConfig).Name = textBox_name.Text;
                mConfig.SetValue("Name", textBox_name.Text);

                mConfig.Desc    = textBox_desc.Text;
                mConfig.Type    = CtrlUtil.GetComboBoxText(comboBox_type);
                mConfig.AutoRun = checkBox_autorun.Checked;
                mConfig.Enabled = checkBox_enabled.Checked;

                mConfig.SetValue("StartTime", comboBox_startTime.Text);
                mConfig.SetValue("StopTime", comboBox_stopTime.Text);
                mConfig.SetValue("Delay", comboBox_delayTime.Text);
                mConfig.SetValue("Period", comboBox_period.Text);
                mConfig.Cycle       = (int)numericUpDown_cycleNumber.Value;
                mConfig.PerCycle    = 1;
                mConfig.OnTimeStart = checkBox_onTimeStart.Checked;

                ITimeSegment ts = null;

                mConfig.ClearTimeSegment();
                foreach (DataGridViewRow row in dataGridView_timeSegment.Rows)
                {
                    if (row.Cells[0].Value != null || row.Cells[1].Value != null)
                    {
                        ts = mConfig.AppendTimeSegment();

                        ts.SetValue("StartTime", row.Cells[0].Value != null ? row.Cells[0].Value.ToString() : "");

                        ts.SetValue("StopTime", row.Cells[1].Value != null ? row.Cells[1].Value.ToString() : "");

                        ts.Enabled = Convert.ToBoolean(row.Cells[2].Value);
                    }
                }

                return(true);
            }
            return(false);
        }
        public int[] GetDataIndices(ITimeSegment t)
        {
            var           intervals   = GetTimeIntervals(t);
            var           projections = intervals.Select(a => timeAxisProjection.ProjectIntervalToTheAxis(a));
            HashSet <int> indices     = new HashSet <int>();

            foreach (var projection in projections)
            {
                int[] indices1 = dataMaskProvider.GetIndices(grid, projection.Item1, projection.Item2);
                int   len      = indices1.Length;
                for (int i = 0; i < len; i++)
                {
                    indices.Add(indices1[i]);
                }
            }

            return(indices.ToArray());
        }
Beispiel #16
0
        public DataCoverageResult GetCoverage(ITimeSegment t)
        {
            var componentResult = component.GetCoverage(t);

            if (componentResult == DataCoverageResult.DataWithUncertainty)
            {
                if (t.LastYear - t.FirstYear + 1 >= this.permitedYearsLength)
                {
                    return(DataCoverageResult.DataWithUncertainty);
                }
                else
                {
                    return(DataCoverageResult.DataWithoutUncertainty);
                }
            }
            else
            {
                return(componentResult);
            }
        }
Beispiel #17
0
        public DataCoverageResult GetCoverage(ITimeSegment t)
        {
            var componentResult = component.GetCoverage(t);

            if (componentResult == DataCoverageResult.DataWithUncertainty)
            {
                if (t.FirstYear == this.firstDataYear && t.LastYear == this.lastDataYear)
                {
                    return(DataCoverageResult.DataWithUncertainty);
                }
                else
                {
                    return(DataCoverageResult.DataWithoutUncertainty);
                }
            }
            else
            {
                return(componentResult);
            }
        }
Beispiel #18
0
        public double[] getAproximationGrid(ITimeSegment timeSegment)
        {
            //TODO: for now only a bounds of the region are returned as a approximation grid

            var doubleIntervals = GetTimeIntervals(timeSegment).Select(interval => timeAxisProjection.ProjectIntervalToTheAxis(interval)).ToArray();

            if (doubleIntervals.Length == 1 && doubleIntervals[0].Item1 == doubleIntervals[0].Item2)
            {
                return new double[] { doubleIntervals[0].Item1 }
            }
            ;
            int N     = doubleIntervals.Length * 2;
            int halfN = N / 2;

            double[] result = new double[N];
            for (int i = 0; i < halfN; i++)
            {
                result[i * 2]     = doubleIntervals[i].Item1;
                result[i * 2 + 1] = doubleIntervals[i].Item2;
            }
            return(result);
        }
Beispiel #19
0
 public double[] getAproximationGrid(ITimeSegment timeSegment)
 {
     return(this.component.getAproximationGrid(timeSegment));
 }
Beispiel #20
0
 public DataCoverageResult GetCoverage(ITimeSegment t)
 {
     return(this.decoratedProvider.GetCoverage(t));
 }
Beispiel #21
0
        public IPs GetTempIPs(ITimeSegment t)
        {
            var           intervals = GetTimeIntervals(t);
            var           projections = intervals.Select(a => timeAxisProjection.ProjectIntervalToTheAxis(a));
            List <int>    indecesList = new List <int>(1024);
            List <double> weightsList = new List <double>(1024);
            int           start, stop;

            double[] weights    = null;
            double   sumWeights = 0.0;

            foreach (var projection in projections)
            {
                weights = weightsProvider.GetWeights(grid, projection.Item1, projection.Item2, out start, out stop);
                if (weights.Length == 0)
                {
                    return new IPs {
                               Indices = new int[0], Weights = new double[0]
                    }
                }
                ;
                else
                {
                    weightsList.AddRange(weights);

                    indecesList.AddRange(Enumerable.Range(start, stop - start + 1));
                }
            }
            if (weights == null)
            {
                throw new InvalidOperationException("ProjectIntervalToTheAxis returned no intervals");
            }

            IPs integrationPoints;

            Dictionary <int, double> weightsDict = new Dictionary <int, double>(1024);
            int N = weightsList.Count;

            for (int i = 0; i < N; i++)
            {
                int    idx = indecesList[i];
                double w   = weightsList[i];
                if (weightsDict.ContainsKey(idx))
                {
                    weightsDict[idx] += w;
                }
                else
                {
                    weightsDict.Add(idx, w);
                }
                sumWeights += w;
            }
            int M = weightsDict.Count;

            double[] resultWeigths = new double[M];
            int[]    resultIdx     = new int[M];
            int      iter          = 0;
            double   multipier     = 1.0 / sumWeights;

            foreach (var item in weightsDict)
            {
                resultWeigths[iter] = item.Value * multipier;
                resultIdx[iter]     = item.Key;
                iter++;
            }
            integrationPoints = new IPs {
                Indices = resultIdx, Weights = resultWeigths, BoundingIndices = new IndexBoundingBox {
                    first = resultIdx.Min(), last = resultIdx.Max()
                }
            };

            Debug.Assert(Math.Abs(integrationPoints.Weights.Sum() - 1.0) < 1e-6, string.Format("the difference is {0}", Math.Abs(integrationPoints.Weights.Sum() - 1.0)));
            return(integrationPoints);
        }
 public DataCoverageResult GetCoverage(ITimeSegment t)
 {
     return(component.GetCoverage(t));
 }
Beispiel #23
0
        /// <summary>
        /// Returns an array of ordered continuous time intervals depicted by time segment
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        protected static IEnumerable <Tuple <DateTime, DateTime> > GetTimeIntervals(ITimeSegment t)
        {
            int firstDay  = t.FirstDay;
            int lastDay   = t.LastDay;
            int firstYear = t.FirstYear;
            int lastYear  = t.LastYear;
            int startHour = t.StartHour;
            int stopHour  = t.StopHour;

            bool isLeap            = (lastYear == firstYear && DateTime.IsLeapYear(firstYear));
            bool toTheEndOfTheYear = (isLeap && lastDay == 366) || (!isLeap && lastDay == 365);
            bool fullDay           = startHour == 0 && stopHour == 24;



            if (fullDay && firstDay == 1 && toTheEndOfTheYear)
            {
                //whole years
                yield return(Tuple.Create(new DateTime(firstYear, 1, 1), new DateTime(lastYear + 1, 1, 1)));

                yield break;
            }



            bool isNewYearCrossed = lastDay < firstDay;

            Debug.Assert(lastYear > firstYear || !isNewYearCrossed);

            if (fullDay)
            {
                if (isNewYearCrossed)
                {
                    //we need to iterate one year less, as we iterate new year crossing
                    for (int year = firstYear; year < lastYear; year++)
                    {
                        yield return(Tuple.Create(
                                         new DateTime(year, 1, 1) + TimeSpan.FromDays(firstDay - 1),
                                         new DateTime(year + 1, 1, 1) + TimeSpan.FromDays(lastDay)));
                    }
                }
                else
                {
                    for (int year = firstYear; year <= lastYear; year++)
                    {
                        yield return(Tuple.Create(
                                         new DateTime(year, 1, 1) + TimeSpan.FromDays(firstDay - 1),
                                         new DateTime(year, 1, 1) + TimeSpan.FromDays(lastDay)));
                    }
                }
            }
            else
            {
                DateTime dayStart; //reusable structures in the loop bodies
                TimeSpan startHourTimeSpan = TimeSpan.FromHours(startHour);
                TimeSpan stopHourTimrSpan  = TimeSpan.FromHours(stopHour);

                //part of the day specified
                if (isNewYearCrossed)
                {
                    int overlapedLastDay;
                    //we need to iterate one year less, as we iterate new year crossing
                    for (int year = firstYear; year < lastYear; year++)
                    {
                        overlapedLastDay = lastDay + (DateTime.IsLeapYear(year) ? 366 : 365);
                        for (int day = firstDay; day <= overlapedLastDay; day++)
                        {
                            dayStart = new DateTime(year, 1, 1) + TimeSpan.FromDays(day - 1);
                            yield return(Tuple.Create(
                                             dayStart + startHourTimeSpan,
                                             dayStart + stopHourTimrSpan));
                        }
                    }
                }
                else
                {
                    for (int year = firstYear; year <= lastYear; year++)
                    {
                        int effectiveLastDay = (DateTime.IsLeapYear(year) && lastDay == 365) ? 366 : lastDay;
                        for (int day = firstDay; day <= effectiveLastDay; day++)
                        {
                            dayStart = new DateTime(year, 1, 1) + TimeSpan.FromDays(day - 1);
                            yield return(Tuple.Create(
                                             dayStart + startHourTimeSpan,
                                             dayStart + stopHourTimrSpan
                                             ));
                        }
                    }
                }
            }
        }
        protected override async Task <double[]> EvaluateCellsBatchAsync(IRequestContext context, ComputationalContext computationalContext, IEnumerable <GeoCellTuple> cells)
        {
            await SaveObservationsAndDalanayDiagsForCells(context, computationalContext, cells);

            VariogramModule.IVariogramFitter variogramFitter = new LMDotNetVariogramFitter.Fitter();

            Dictionary <ITimeSegment, VariogramModule.IVariogram> variograms = new Dictionary <ITimeSegment, VariogramModule.IVariogram>();

            Dictionary <ITimeSegment, IObservationsInformation> observations = (Dictionary <ITimeSegment, IObservationsInformation>)computationalContext["observations"];

            LimitedConcurrencyLevelTaskScheduler lclts = new LimitedConcurrencyLevelTaskScheduler(Environment.ProcessorCount);
            TaskFactory taskFactory = new TaskFactory(lclts);

            var variogramTasks = observations.Select(pair => taskFactory.StartNew(() =>
            {
                ITimeSegment ts = pair.Key;
                TraceVerbose(string.Format("Fitting variogram for {0} ({1} observations)", ts, pair.Value.Observations.Length));
                Stopwatch sw1 = Stopwatch.StartNew();
                var lats      = pair.Value.Observations.Select(o => o.Latitude).ToArray();
                var lons      = pair.Value.Observations.Select(o => o.Longitude).ToArray();
                var vals      = pair.Value.Observations.Select(o => o.Value).ToArray();
                var pointSet  = new EmpVariogramBuilder.PointSet(lats, lons, vals);

                var dist = FuncConvert.ToFSharpFunc(new Converter <Tuple <double, double>, FSharpFunc <Tuple <double, double>, double> >(t1 =>
                                                                                                                                         FuncConvert.ToFSharpFunc(new Converter <Tuple <double, double>, double>(t2 => SphereMath.GetDistance(t1.Item1, t1.Item2, t2.Item1, t2.Item2)))));

                var empVar           = EmpVariogramBuilder.EmpiricalVariogramBuilder.BuildEmpiricalVariogram(pointSet, dist);
                var fitted_variogram = variogramFitter.Fit(empVar);
                VariogramModule.IVariogram effectiveVariogram = null;
                sw1.Stop();

                if (FSharpOption <VariogramModule.IDescribedVariogram> .get_IsSome(fitted_variogram))
                {
                    effectiveVariogram = fitted_variogram.Value;
                    TraceVerbose(string.Format("Variogram fited for {0} ({1} observations) in {2}", ts, pair.Value.Observations.Length, sw1.Elapsed));
                }
                else
                {
                    TraceWarning(string.Format("Variogram fitting failed for {0} ({1} observations) in {2}. Using fallback variogram", ts, pair.Value.Observations.Length, sw1.Elapsed));
                    effectiveVariogram = variogramFitter.GetFallback(empVar);
                }
                lock ("saving_variograms")
                {
                    variograms.Add(ts, effectiveVariogram);
                }
            }));

            TraceVerbose(string.Format("Starting calculations of linear weights for all cells"));
            Stopwatch sw2     = Stopwatch.StartNew();
            var       weigths = CalcLinearWeights(computationalContext, cells);

            sw2.Stop();
            TraceVerbose(string.Format("calculations of linear weights for all cells ended in {0}", sw2.Elapsed));

            TraceVerbose(string.Format("Waiting for all variograms to be computed"));
            await Task.WhenAll(variogramTasks);

            TraceVerbose(string.Format("All variograms are computed. Calculating variances and values"));

            Stopwatch sw3          = Stopwatch.StartNew();
            var       resultValues = cells.Zip(weigths, (cell, weightTuple) =>
            {
                ITimeSegment ts = cell.Time;
                var weight      = weightTuple.Item2;
                VariogramModule.IVariogram variogram = variograms[ts];
                var observation = observations[ts].Observations;

                Debug.Assert(Math.Abs(weight.Sum(w => w.Weight) - 1.0) < 1e-10);

                double sill = variogram.Sill;

                double cellLat = (cell.LatMax + cell.LatMin) * 0.5;
                double cellLon = (cell.LonMax + cell.LonMin) * 0.5;
                //var = cov(0)+ sum sum (w[i]*w[j]*cov(i,j))-2.0*sum(w[i]*cov(x,i))
                double cov_at_0 = sill;

                double acc = cov_at_0;     //cov(0)
                for (int i = 0; i < weight.Length; i++)
                {
                    double w    = weight[i].Weight;
                    int idx1    = weight[i].DataIndex;
                    double lat1 = observation[idx1].Latitude;
                    double lon1 = observation[idx1].Longitude;
                    for (int j = 0; j < i; j++)
                    {
                        int idx2    = weight[j].DataIndex;
                        double lat2 = observation[idx2].Latitude;
                        double lon2 = observation[idx2].Longitude;
                        double dist = SphereMath.GetDistance(lat1, lon1, lat2, lon2);
                        double cov  = sill - variogram.GetGamma(dist);
                        acc        += 2.0 * w * weight[j].Weight * cov;
                    }
                    acc         += w * w * cov_at_0; //diagonal elements
                    double dist2 = SphereMath.GetDistance(lat1, lon1, cellLat, cellLon);
                    double cov2  = sill - variogram.GetGamma(dist2);
                    acc         -= 2.0 * w * cov2;
                }
                return(Tuple.Create(cell, Math.Sqrt(acc), weight.Sum(w => observation[w.DataIndex].Value * w.Weight)));
            }).ToArray();

            sw3.Stop();
            TraceVerbose(string.Format("All sigmas calulated in {0}", sw3.Elapsed));
            computationalContext.Add("results", resultValues);
            return(resultValues.Select(r => r.Item2).ToArray());
        }
Beispiel #25
0
 public abstract Task <IObservationsInformation> GetObservationsAsync(IStorageContext context, string variableName, object missingValue, double latmin, double latmax, double lonmin, double lonmax, ITimeSegment timeSegment);
Beispiel #26
0
 public DataCoverageResult GetCoverage(ITimeSegment t)
 {
     return(DataCoverageResult.DataWithUncertainty);
 }
Beispiel #27
0
 public double[] getAproximationGrid(ITimeSegment timeSegment)
 {
     return(value);
 }
Beispiel #28
0
 public IndexBoundingBox GetBoundingBox(ITimeSegment t)
 {
     return(this.component.GetBoundingBox(t));
 }
Beispiel #29
0
 public IPs GetTempIPs(ITimeSegment t)
 {
     return(this.component.GetTempIPs(t));
 }
Beispiel #30
0
        public async override Task <IObservationsInformation> GetObservationsAsync(IStorageContext context, string variableName, object missingValue, double latmin, double latmax, double lonmin, double lonmax, ITimeSegment timeSegment)
        {
            IndexBoundingBox bounds;

            var r1 = TimeIntegrator.GetBoundingBox(timeSegment, out bounds);

            if (r1 == DataCoverageResult.OutOfData)
            {
                return(new ObservationsInformation(new GeoPointWithValue2D[0]));
            }

            int[] origin = new int[2];
            int[] shape  = new int[2];

            int timeDimNum    = timeDimNumber[variableName];
            int stationDimNum = stationsDimNumber[variableName];

            int stationsCount = StationsLats.Length;

            //data fetching
            origin[timeDimNum]    = bounds.first;
            origin[stationDimNum] = 0;
            shape[timeDimNum]     = bounds.last - bounds.first + 1;
            shape[stationDimNum]  = stationsCount;
            var dataTask = context.GetDataAsync(variableName, origin, null, shape);

            //integartion points calculation
            IPs timeIntegrationPoints;
            var r2 = TimeIntegrator.GetTempIPs(timeSegment, out timeIntegrationPoints);

            if (r2 == DataCoverageResult.OutOfData)
            {
                throw new InvalidOperationException("Inconsistent behavior of Time Integrator: Bounding box calculation gave non-outOfData, but weights calculates gave outOfData");
            }

            System.Diagnostics.Debug.Assert(r1 == r2);

            IPs[][] ips = new IPs[stationsCount][];
            for (int i = 0; i < stationsCount; i++)
            {
                var curr = new IPs[2];
                ips[i] = curr;
                curr[stationDimNum] = new IPs()
                {
                    Weights = new double[] { 1.0 }, Indices = new int[] { i }, BoundingIndices = new IndexBoundingBox()
                    {
                        first = i, last = i
                    }
                };
                curr[timeDimNum] = timeIntegrationPoints;
            }

            var data = await dataTask;

            var obsResults = Utils.ArrayIntegrator.IntegrateSequenceWithMVs2D(variableName, data, missingValue, origin, ips);

            double scaleFacotor = dataRepresentationDictionary.ScaleFactors[variableName];
            double addOffset    = dataRepresentationDictionary.AddOffsets[variableName];

            var scaledResults = obsResults.Select(r => (r.Integral / r.SumOfWeights) * scaleFacotor + addOffset).ToArray();

            GeoPointWithValue2D[] obs = new GeoPointWithValue2D[stationsCount];
            for (int i = 0; i < stationsCount; i++)
            {
                obs[i] = new GeoPointWithValue2D(StationsLats[i], StationsLons[i], scaledResults[i]);
            }
            obs = obs.Where(ob => !double.IsNaN(ob.Value)).ToArray();

            return(new ObservationsInformation(obs));
        }