private Tuple <IPs, IPs, IPs> GetIPsForCell(ICellRequest cell)
        {
            var timeR = timeAggregator2.GetTempIPs(cell.Time);
            var latR  = latIntegrator2.GetIPsForCell(cell.LatMin, cell.LatMax);
            var lonR  = lonIntegrator2.GetIPsForCell(cell.LonMin, cell.LonMax);

            return(Tuple.Create(timeR, latR, lonR));
        }
        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);
        }
        public async Task <RealValueNodes> GetAsync(ICellRequest cell)
        {
            var variableName = cell.VariableName;
            var timeSegment  = cell.Time;

            var bounds = timeIntegrator.GetBoundingBox(timeSegment);

            if (bounds.IsSingular)
            {
                double[] empty = new double[0];
                return(new RealValueNodes(empty, empty, empty));
            }

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

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


            int[] stationsIdxs = stationLocator.GetRelevantStationsIndices(cell);
            int   stationMinIdx = stationsIdxs.Min(), stationMaxIdx = stationsIdxs.Max();

            int stationsCount = stationsIdxs.Length;

            //data fetching
            origin[timeDimNum]    = bounds.first;
            origin[stationDimNum] = stationMinIdx;
            shape[timeDimNum]     = bounds.last - bounds.first + 1;
            shape[stationDimNum]  = stationMaxIdx - stationMinIdx + 1;
            traceSource.TraceEvent(TraceEventType.Verbose, 2, "Requesting raw data for cell");
            var dataTask = dataStorage.GetDataAsync(variableName, origin, null, shape);

            //integration points calculation
            IPs timeIntegrationPoints = timeIntegrator.GetTempIPs(timeSegment);

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

            var data = await dataTask;

            object missingValue = missingValuesDict.GetMissingValue(variableName);

            if (missingValue != null && missingValue.GetType() != varTypes[variableName])
            {
                traceSource.TraceEvent(TraceEventType.Warning, 1, string.Format("A missing value of the variable \"{0}\"has different type from variable type. Ignoring MV definition", variableName));
                missingValue = null;
            }


            IEnumerable <Utils.IntegrationResult> obsResults;

            if (missingValue != null)
            {
                obsResults = Utils.ArrayMean.IntegrateSequenceWithMVs2D(variableName, data, missingValue, origin, ips);
            }
            else
            {
                obsResults = Utils.ArrayMean.IntegrateSequence2D(variableName, data, origin, ips);
            }

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

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

            int           len        = scaledResults.Length;
            List <double> valuesList = new List <double>(len);
            List <double> latsList   = new List <double>(len);
            List <double> lonsList   = new List <double>(len);

            for (int i = 0; i < len; i++)
            {
                if (!double.IsNaN(scaledResults[i]))
                {
                    valuesList.Add(scaledResults[i]);
                    latsList.Add(stationsLats[stationsIdxs[i]]);
                    lonsList.Add(stationsLons[stationsIdxs[i]]);
                }
            }

            return(new RealValueNodes(latsList.ToArray(), lonsList.ToArray(), valuesList.ToArray()));
        }