Update NBS taskmap generator
This commit is contained in:
		| @@ -1,24 +0,0 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
|  | ||||
|     <PropertyGroup> | ||||
|         <OutputType>Exe</OutputType> | ||||
|         <TargetFramework>netcoreapp3.0</TargetFramework> | ||||
|     </PropertyGroup> | ||||
|  | ||||
|     <ItemGroup> | ||||
|       <None Update="appsettings.json"> | ||||
|         <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
|       </None> | ||||
|       <None Update="Data\**\*"> | ||||
|         <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
|       </None> | ||||
|       <None Update="NitrogenInput.json"> | ||||
|         <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
|       </None> | ||||
|     </ItemGroup> | ||||
|  | ||||
|     <ItemGroup> | ||||
|       <ProjectReference Include="..\FarmmapsApi\FarmmapsApi.csproj" /> | ||||
|     </ItemGroup> | ||||
|  | ||||
| </Project> | ||||
| @@ -1,336 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using FarmmapsApi; | ||||
| using FarmmapsApi.Models; | ||||
| using FarmmapsApi.Services; | ||||
| using FarmmapsNbs.Models; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Newtonsoft.Json; | ||||
| using Newtonsoft.Json.Linq; | ||||
| using static FarmmapsApiSamples.Constants; | ||||
|  | ||||
| namespace FarmmapsNbs | ||||
| { | ||||
|     public class NbsApplication : IApplication | ||||
|     { | ||||
|         private const string DownloadFolder = "Downloads"; | ||||
|         private const string SettingsFile = "settings.json"; | ||||
|  | ||||
|         private readonly ILogger<NbsApplication> _logger; | ||||
|         private readonly FarmmapsApiService _farmmapsApiService; | ||||
|         private readonly NitrogenService _nitrogenService; | ||||
|         private readonly GeneralService _generalService; | ||||
|  | ||||
|         private Settings _settings; | ||||
|  | ||||
|         public NbsApplication(ILogger<NbsApplication> logger, FarmmapsApiService farmmapsApiService, | ||||
|             GeneralService generalService, NitrogenService nitrogenService) | ||||
|         { | ||||
|             _logger = logger; | ||||
|             _farmmapsApiService = farmmapsApiService; | ||||
|             _generalService = generalService; | ||||
|             _nitrogenService = nitrogenService; | ||||
|         } | ||||
|  | ||||
|         public async Task RunAsync() | ||||
|         { | ||||
|             var nitrogenInputJson = File.ReadAllText("InputData-NBS.json"); //NitrogenInput.json | ||||
|             List<NitrogenInput> nitrogenInputs = JsonConvert.DeserializeObject<List<NitrogenInput>>(nitrogenInputJson); | ||||
|              | ||||
|             if (!Directory.Exists(DownloadFolder)) | ||||
|                 Directory.CreateDirectory(DownloadFolder); | ||||
|  | ||||
|             // !! this call is needed the first time an api is called with a fresh clientid and secret !! | ||||
|             await _farmmapsApiService.GetCurrentUserCodeAsync(); | ||||
|             var roots = await _farmmapsApiService.GetCurrentUserRootsAsync(); | ||||
|  | ||||
|             foreach (var input in nitrogenInputs) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     await Process(roots, input); | ||||
|                 } | ||||
|                 catch (Exception ex) | ||||
|                 { | ||||
|                     _logger.LogError(ex.Message); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private async Task Process(List<UserRoot> roots, NitrogenInput input) | ||||
|         { | ||||
|              | ||||
|             // !!specify if you are using an already created cropfield: | ||||
|             bool useCreatedCropfield = input. UseCreatedCropfield; | ||||
|             var plantingDate = input.PlantingDate; | ||||
|             var FieldName = input.fieldName; | ||||
|             bool StoreStatistics = input.storeSatelliteStatistics; | ||||
|             var measurementDate = input.MeasurementDate; | ||||
|             string settingsfile = $"Settings_{FieldName}.json"; | ||||
|  | ||||
|             LoadSettings(settingsfile); | ||||
|  | ||||
|             var uploadedRoot = roots.SingleOrDefault(r => r.Name == "Uploaded"); | ||||
|             if (uploadedRoot == null) | ||||
|             { | ||||
|                 _logger.LogError("Could not find a needed root item"); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             var myDriveRoot = roots.SingleOrDefault(r => r.Name == "My drive"); | ||||
|             if (myDriveRoot == null) | ||||
|             { | ||||
|                 _logger.LogError("Could not find a needed root item"); | ||||
|                 return; | ||||
|             } | ||||
|                            | ||||
|             // Use already created cropfield or create new one | ||||
|             Item cropfieldItem; | ||||
|             if (useCreatedCropfield == false || string.IsNullOrEmpty(_settings.CropfieldItemCode)) | ||||
|             { | ||||
|                 _logger.LogInformation("Creating cropfield"); | ||||
|                 cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDriveRoot.Code, | ||||
|                     $"VRA NBS cropfield {input.OutputFileName}", plantingDate.Year, input.GeometryJson.ToString(Formatting.None)); | ||||
|                 _settings.CropfieldItemCode = cropfieldItem.Code; | ||||
|                 SaveSettings(settingsfile); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _logger.LogInformation("Cropfield already exists, trying to get it"); | ||||
|                 cropfieldItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldItemCode); | ||||
|             } | ||||
|  | ||||
|             var geotiffItem = (Item)null; | ||||
|  | ||||
|             // No file input, use most recent satellite image | ||||
|             if (string.IsNullOrEmpty(input.File)) { | ||||
|                 _logger.LogInformation("No specific data given, retrieving most recent satellite image"); | ||||
|  | ||||
|                 // check if satellite task not yet done, do here and save taskcode | ||||
|                 if (useCreatedCropfield == false || string.IsNullOrEmpty(_settings.SatelliteTaskCode)) { | ||||
|                     var satelliteTaskCode = await _generalService.RunSatelliteTask(cropfieldItem); | ||||
|                     _settings.SatelliteTaskCode = satelliteTaskCode; | ||||
|                     SaveSettings(settingsfile); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 // Select a particular satellite item from satelliteTask | ||||
|                 Item satalliteItem = await _generalService.FindSatelliteItem(cropfieldItem, _settings.SatelliteTaskCode, FieldName, StoreStatistics); | ||||
|  | ||||
|                 var satelliteBand = satalliteItem.Data["layers"][0]["name"]; | ||||
|                 var satelliteStatistics = satalliteItem.Data["layers"][0]["renderer"]["band"]["statistics"]; | ||||
|                 Console.WriteLine($"Satellite image date: {satalliteItem.DataDate}"); | ||||
|                 //Console.WriteLine($"Satellite image statistics for band {satelliteBand}: {satelliteStatistics}"); | ||||
|  | ||||
|                 //Store data to csv  | ||||
|                 if (StoreStatistics==true) { | ||||
|                     var SatelliteFile = $"C:\\Akkerweb\\DataSatellite_{FieldName}.csv"; | ||||
|                     var NewLineField = $"\"Field\":{FieldName}" + Environment.NewLine; | ||||
|                     var NewLineDate = $"\"date\":{satalliteItem.DataDate}" + Environment.NewLine; | ||||
|                     var i = 0; | ||||
|                     foreach (var item in satelliteStatistics) { | ||||
|                         //var NewLines2; | ||||
|                         if (i == 0) { | ||||
|                             File.AppendAllText(SatelliteFile, NewLineDate); | ||||
|                             i++; | ||||
|                         } | ||||
|                         File.AppendAllText(SatelliteFile, $"{item}" + Environment.NewLine); | ||||
|  | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 // must be wdvi[1] | ||||
|                 var inputType = (satalliteItem.Data["layers"] as JArray)?[1]["name"].ToString(); | ||||
|                 if (string.IsNullOrEmpty(inputType)) { | ||||
|                     _logger.LogError("Could not get the input type name from the satellite item"); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // download the geotiff | ||||
|                 var SatelliteImageDate = (DateTime)satalliteItem.DataDate; | ||||
|                 var SatelliteDate = SatelliteImageDate.ToString("yyyyMMdd"); | ||||
|                 _logger.LogInformation("Downloading geotiff file"); | ||||
|                 await _farmmapsApiService.DownloadItemAsync(satalliteItem.Code, | ||||
|                     Path.Combine(DownloadFolder, $"nbs_inputSatelliteGeotiff_{input.OutputFileName}_{inputType}_{SatelliteDate}.zip")); | ||||
|  | ||||
|                 // overwrite measurement date by date of satellite item | ||||
|                 measurementDate = satalliteItem.DataDate.Value; | ||||
|  | ||||
|                 geotiffItem = satalliteItem; | ||||
|  | ||||
|  | ||||
|             } | ||||
|  | ||||
|  | ||||
|             // (geo)tiff input: | ||||
|             else if (input.File.Contains(".tif") || input.File.Contains(".geotiff")) { | ||||
|                 _logger.LogInformation("input = tiff data"); | ||||
|                 var dataPath = Path.Combine("Data", input.File); | ||||
|                 geotiffItem = await _generalService.UploadDataAsync(uploadedRoot, GEOTIFF_PROCESSED_ITEMTYPE, dataPath, | ||||
|                         Path.GetFileNameWithoutExtension(input.File)); | ||||
|  | ||||
|                 if (geotiffItem == null) { | ||||
|                     _logger.LogError("Could not find item for uploaded data"); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // json/shape input | ||||
|             else { | ||||
|                 var isGeoJson = input.File.Contains("json"); | ||||
|                 var dataPath = Path.Combine("Data", input.File); | ||||
|                 var shapeItem = isGeoJson ? | ||||
|                     await _generalService.UploadDataAsync(uploadedRoot, SHAPE_PROCESSED_ITEMTYPE, dataPath, Path.GetFileNameWithoutExtension(input.File)) : | ||||
|                     await _generalService.UploadZipWithShapeAsync(uploadedRoot, dataPath, Path.GetFileNameWithoutExtension(input.File)); | ||||
|  | ||||
|                 if (shapeItem == null) { | ||||
|                     _logger.LogError("Could not find item for uploaded data"); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 _logger.LogInformation($"Converting shape to geotiff"); | ||||
|                 geotiffItem = await _generalService.ShapeToGeotiff(shapeItem); | ||||
|                 if (geotiffItem == null) { | ||||
|                     _logger.LogError("Something went wrong with shape to geotiff transformation"); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 _logger.LogInformation("Downloading geotiff file"); | ||||
|                 await _farmmapsApiService.DownloadItemAsync(geotiffItem.Code, | ||||
|                     Path.Combine(DownloadFolder, $"{input.OutputFileName}.input_geotiff.zip")); | ||||
|             } | ||||
|  | ||||
|  | ||||
|             //// check if vandersat task not yet done, do here and save taskcode | ||||
|             //if (useCreatedCropfield == false || string.IsNullOrEmpty(_settings.VanDerSatTaskCode)) { | ||||
|             //    var VanDerSatTaskCode = await _generalService.RunVanDerSatTask(cropfieldItem); | ||||
|             //    _settings.VanDerSatTaskCode = VanDerSatTaskCode; | ||||
|             //    SaveSettings(settingsfile); | ||||
|             //} | ||||
|  | ||||
|             //// Select a particular image item from VanDerSat | ||||
|             //Item VanDerSatItem = await _generalService.FindVanDerSatItem(cropfieldItem, _settings.VanDerSatTaskCode, FieldName, StoreStatistics); | ||||
|  | ||||
|  | ||||
|             //// download the geotiff | ||||
|             //_logger.LogInformation("Downloading geotiff file"); | ||||
|             //await _farmmapsApiService.DownloadItemAsync(VanDerSatItem.Code, | ||||
|             //    Path.Combine(DownloadFolder, $"nbs_VanDerSatGeotiff_{input.OutputFileName}.zip")); | ||||
|  | ||||
|             _logger.LogInformation($"Calculating targetN with targetYield: {input.TargetYield}"); | ||||
|             var targetNItem = await _nitrogenService.CreateTargetNItem(cropfieldItem); | ||||
|             var targetNData = await _nitrogenService.CalculateTargetN(cropfieldItem, targetNItem, plantingDate, | ||||
|                 measurementDate, input.PotatoPurposeType, input.TargetYield); | ||||
|  | ||||
|             if (targetNData == null) { | ||||
|                 _logger.LogError("Something went wrong with TargetN calculation"); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             _logger.LogInformation($"TargetN: {targetNData.TargetN}"); | ||||
|             ////Option to manually adjust the Target N, for test purposes only! | ||||
|             //targetNData.TargetN = 225; | ||||
|             //_logger.LogInformation($"TargetN adjusted: {targetNData.TargetN}"); | ||||
|  | ||||
|             var targetNDataPath = Path.Combine(DownloadFolder, $"{input.OutputFileName}.targetn.json"); | ||||
|             await File.WriteAllTextAsync(targetNDataPath, JsonConvert.SerializeObject(targetNData, Formatting.Indented)); | ||||
|  | ||||
|             _logger.LogInformation("Calculating uptake map"); | ||||
|             var uptakeMapItem = | ||||
|                 await _nitrogenService.CalculateUptakeMap(cropfieldItem, geotiffItem, plantingDate, | ||||
|                     measurementDate, input.InputVariable, input.InputLayerName); | ||||
|             if (uptakeMapItem == null) { | ||||
|                 _logger.LogError("Something went wrong with creating the uptakeMap"); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             _logger.LogInformation("Downloading uptake map"); | ||||
|             await _farmmapsApiService.DownloadItemAsync(uptakeMapItem.Code, | ||||
|                 Path.Combine(DownloadFolder, $"{input.OutputFileName}.uptake.zip")); | ||||
|             _logger.LogInformation("UptakeMap downloaded to {0}", Path.Combine(DownloadFolder, $"{input.OutputFileName}.uptake.zip")); | ||||
|  | ||||
|             _logger.LogInformation("Calculating application map"); | ||||
|             var applicationMapItem = | ||||
|                 await _nitrogenService.CalculateApplicationMap(cropfieldItem, geotiffItem, plantingDate, | ||||
|                     measurementDate, input.InputVariable, targetNData.TargetN, input.InputLayerName); | ||||
|  | ||||
|             if (applicationMapItem == null) { | ||||
|                 _logger.LogError("Something went wrong with creating the applicationMap"); | ||||
|                 return; | ||||
|             } | ||||
|             _logger.LogInformation("Downloading application map"); | ||||
|             await _farmmapsApiService.DownloadItemAsync(applicationMapItem.Code, | ||||
|                 Path.Combine(DownloadFolder, $"{input.OutputFileName}.application.zip")); | ||||
|             _logger.LogInformation("Application map can be found in {0}", Path.Combine(DownloadFolder, $"{input.OutputFileName}.application.zip")); | ||||
|  | ||||
|             //transforming tiff to shape | ||||
|             var tiffItem = applicationMapItem; | ||||
|  | ||||
|             if (tiffItem == null) { | ||||
|                 _logger.LogError("Could not find item for uploaded data"); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             //_logger.LogInformation($"Converting geotiff to shape"); | ||||
|             //var taskmap = await _generalService.GeotiffToShape(tiffItem); | ||||
|             //if (taskmap == null) { | ||||
|             //    _logger.LogError("Something went wrong with geotiff to shape transformation"); | ||||
|             //    return; | ||||
|             //} | ||||
|  | ||||
|             //ApplicationMap (GEOTIFF) To Taskmap | ||||
|             _logger.LogInformation($"Converting geotiff to taskmap"); | ||||
|             var taskmap = await _generalService.CreateTaskmap(cropfieldItem, tiffItem, input.CellWidth, input.CellHeight, input.StartPoint.ToString(Formatting.None), | ||||
|                 input.EndPoint.ToString(Formatting.None), input.Angle); | ||||
|             if (taskmap == null) | ||||
|             { | ||||
|                 _logger.LogError("Something went wrong with geotiff to shape transformation"); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|  | ||||
|             _logger.LogInformation("Downloading taskmap"); | ||||
|             await _farmmapsApiService.DownloadItemAsync(taskmap.Code, | ||||
|                 Path.Combine(DownloadFolder, $"{input.OutputFileName}.taskmap.zip")); | ||||
|  | ||||
|  | ||||
|         } | ||||
|  | ||||
|  | ||||
|         // Functions to save previously created cropfields | ||||
|         private void LoadSettings(string file) | ||||
|         { | ||||
|             if (File.Exists(file)) | ||||
|             { | ||||
|                 var jsonText = File.ReadAllText(file); | ||||
|                 _settings = JsonConvert.DeserializeObject<Settings>(jsonText); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _settings = new Settings(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void SaveSettings(string file) | ||||
|         { | ||||
|             if (_settings == null) | ||||
|                 return; | ||||
|  | ||||
|             var json = JsonConvert.SerializeObject(_settings); | ||||
|             File.WriteAllText(file, json); | ||||
|         } | ||||
|             private void SaveInfo(string file) { | ||||
|             if (_settings == null) | ||||
|                 return; | ||||
|  | ||||
|             var json = JsonConvert.SerializeObject(_settings); | ||||
|             File.WriteAllText(file, json); | ||||
|  | ||||
|         } | ||||
|  | ||||
|       } | ||||
|     } | ||||
		Reference in New Issue
	
	Block a user