Ejemplo n.º 1
0
 public void Export()
 {
     Validate();
     using (Client = Connect())
         using (var progressReporter = new ProgressBarReporter())
         {
             ExportAll(progressReporter);
         }
 }
Ejemplo n.º 2
0
        private void ExportAll(ProgressBarReporter progressBarReporter)
        {
            var analyticalGroups = Client.Get(new GetAnalyticalGroups())
                                   .DomainObjects;

            var(requests, summary) = BuildRequestsAndSummary(analyticalGroups);

            Log.Info($"Exporting observations {summary} ...");

            var responses = requests
                            .Select(request => Client.LazyGet <Observation, GetObservationsV2, SearchResultObservation>(request, progressReporter: progressBarReporter))
                            .ToList();

            var observedPropertiesByGroup = Context
                                            .AnalyticalGroupIds
                                            .Select((name, i) =>
            {
                var group = analyticalGroups
                            .First(ag => ag.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));

                return(new AnalyticalGroupInfo
                {
                    Group = group,
                    GroupOrder = i,
                    Properties = group.AnalyticalGroupItems.Select(item => item.ObservedProperty.CustomId).ToList()
                });
            })
                                            .ToList();

            progressBarReporter.ExpectedCount = responses.Sum(response => response.TotalCount);

            Log.Info($"Loading all {progressBarReporter.ExpectedCount} matching observations ...");

            var stopwatch = Stopwatch.StartNew();

            var items = responses
                        .SelectMany(response => response
                                    .DomainObjects
                                    .Where(item => item.NumericResult != null)
                                    )
                        .ToList();

            progressBarReporter.Dispose();

            Log.Info($"{items.Count} numeric observations loaded in {stopwatch.Elapsed.Humanize(2)}.");

            var resultColumns = items
                                .Select(item =>
            {
                var observedPropertyName = item.ObservedProperty.CustomId;
                var groupInfo            = observedPropertiesByGroup
                                           .FirstOrDefault(gi => gi.Properties.Contains(observedPropertyName));

                return(new ResultColumn
                {
                    ObservedPropertyId = item.ObservedProperty.CustomId,
                    Unit = item.ObservedProperty.DefaultUnit?.CustomId,
                    MethodId = item.AnalysisMethod?.MethodId,
                    AnalyticalGroup = groupInfo?.Group?.Name,
                    AnalyticalGroupOrder = groupInfo?.GroupOrder ?? 0,
                    ObservedPropertyOrder = groupInfo?.Properties?.IndexOf(observedPropertyName) ?? 0
                });
            })
                                .DistinctBy(rc => new{ rc.ObservedPropertyId, rc.Unit, rc.MethodId, rc.AnalyticalGroup })
                                .OrderBy(column => column.AnalyticalGroupOrder)
                                .ThenBy(column => column.ObservedPropertyOrder)
                                .ThenBy(column => column.ObservedPropertyId)
                                .ThenBy(column => column.MethodId)
                                .ThenBy(column => column.Unit)
                                .ToList();

            if (Context.Overwrite && File.Exists(Context.CsvOutputPath))
            {
                Log.Warn($"Overwriting existing file '{Context.CsvOutputPath}'.");
            }

            var headers = new[]
            {
                "Lab: Sample ID",
                "Location ID",
                "Observed Date",
                $"Observed Time_UTC{Context.UtcOffset:m}",
                "Latitude",
                "Longitude",
                "County",
                "Medium",
                "Location Groups",
            }
            .Concat(resultColumns.SelectMany(column => new[]
            {
                EscapeCsvColumn($"{column.ObservedPropertyId}_Value"),
                EscapeCsvColumn($"{column.ObservedPropertyId}_{DistinctColumnUnitLabel(resultColumns, column)}")
            }))
            .ToList();

            Log.Info($"Exporting observations to '{Context.CsvOutputPath}' ...");

            var rowCount         = 0;
            var observationCount = 0;

            using (var stream = File.OpenWrite(Context.CsvOutputPath))
                using (var writer = new StreamWriter(stream, new UTF8Encoding(true)))
                {
                    var headerRow = string.Join(",", headers);
                    writer.WriteLine(headerRow);

                    var utcOffset = Context.UtcOffset.ToTimeSpan();

                    foreach (var group in items.GroupBy(item => new
                    {
                        item.FieldVisit.StartTime,
                        item.LabResultDetails?.LabSampleId,
                        item.SamplingLocation.CustomId
                    })
                             .OrderBy(g => g.Key.StartTime)
                             .ThenBy(g => g.Key.LabSampleId)
                             .ThenBy(g => g.Key.CustomId))
                    {
                        var observations = group.ToList();
                        var first        = observations.First();
                        var location     = first.SamplingLocation;

                        if (!first.FieldVisit?.StartTime.HasValue ?? true)
                        {
                            throw new ExpectedException($"{"observation".ToQuantity(observations.Count)} at location '{location.CustomId}' have no timestamp.");
                        }

                        var time = first.FieldVisit.StartTime.Value.ToDateTimeOffset().Add(utcOffset);

                        var columns = new List <string>(headerRow.Length)
                        {
                            EscapeCsvColumn(first.LabResultDetails?.LabSampleId),
                            EscapeCsvColumn(location.CustomId),
                            $"{time:yyyy-MM-dd}",
                            $"{time:HH:mm:ss}",
                            location.Latitude,
                            location.Longitude,
                            EscapeCsvColumn(location.Address?.CountyCode),
                            EscapeCsvColumn(first.Medium.CustomId),
                            EscapeCsvColumn(string.Join(";", location.SamplingLocationGroups.Select(sg => sg.Name)))
                        };

                        do
                        {
                            var(row, remainingObservations, writtenObservations) = WriteRow(resultColumns, observations, columns);

                            writer.WriteLine(row);

                            ++rowCount;
                            observationCount += writtenObservations;

                            observations = remainingObservations;
                        } while (observations.Any());
                    }
                }

            Log.Info($"Exported {"distinct observation".ToQuantity(observationCount)} observations over {"row".ToQuantity(rowCount)} to '{Context.CsvOutputPath}'.");
        }