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()));
        }