forked from FarmMaps/FarmMapsApiClient
Compare commits
119 Commits
Author | SHA1 | Date | |
---|---|---|---|
bb4e795abc | |||
788c071739 | |||
aace4a32f8 | |||
166fd1f66d | |||
9c65d3c6c6 | |||
5a4a04a3ec | |||
cb999caf46 | |||
721b33b4e5 | |||
334d890f13 | |||
f8a412be64 | |||
3da2b71d62 | |||
b7b669bcfd | |||
0f9fe0a433 | |||
5c38ff99dc | |||
|
c29f996d23 | ||
44cde0fe15 | |||
0767b3fff8 | |||
f2bd127554 | |||
73e09f79f4 | |||
706352170a | |||
e07fb2de7a | |||
2790beaa88 | |||
694d7ce90b | |||
8cebe9f2c2 | |||
a1696c38c7 | |||
c2515281d1 | |||
fa2075cbc6 | |||
6a3baeb8ad | |||
61985f9079 | |||
7c5bbf0fbe | |||
915df2ac6b | |||
d1747427bc | |||
111b4e576f | |||
1bc326cfd2 | |||
c673f8ddc4 | |||
8bbf808c55 | |||
dd651629cb | |||
407ef09d21 | |||
250020be78 | |||
a8efaf93c2 | |||
5da74c2db0 | |||
245e82adbc | |||
bea4d207d0 | |||
462e66baea | |||
e0aae4afaf | |||
bd846e9f0d | |||
e7de64d04c | |||
1b6128f52a | |||
fefd348930 | |||
1ddafc6d87 | |||
7baf16db74 | |||
89d2af5944 | |||
c7ab62c911 | |||
beaf00a043 | |||
4459a4e76d | |||
766674c731 | |||
d5f715ef92 | |||
760f3fad64 | |||
93469b605c | |||
b758913693 | |||
f71f072be7 | |||
a94fb260c8 | |||
761221d936 | |||
39a2024718 | |||
6d14299852 | |||
cf5ac33b3f | |||
6debe82085 | |||
3ad594d83f | |||
101b683daa | |||
ee70322ddf | |||
c02b232837 | |||
1c04dfe1af | |||
2acd4930b1 | |||
a29b973268 | |||
c33a8c8a11 | |||
bb14c4e4b0 | |||
693c82db2e | |||
79cc135bbd | |||
764df7ce91 | |||
|
ab9a23221f | ||
|
59bde76903 | ||
751b154bb9 | |||
|
ad49bafa07 | ||
|
f3a2b33810 | ||
02708ba01d | |||
|
2196036135 | ||
331acf6353 | |||
8c104f5eee | |||
f230bd0022 | |||
fb373b7539 | |||
f972699fe9 | |||
5066969e98 | |||
07985f6fcf | |||
048964a466 | |||
d03a699114 | |||
541bbf2a93 | |||
ecfc76105f | |||
|
b56b38c308 | ||
d9fa663de9 | |||
a065a28e01 | |||
c1801a2327 | |||
67ff626e87 | |||
67af431140 | |||
1691e09bf9 | |||
|
54272e1339 | ||
7005269701 | |||
bbf2db0040 | |||
65a0398444 | |||
10b6cc8cd1 | |||
d1bfd92c78 | |||
c8b82a2ed3 | |||
2336bb138a | |||
38cb1e27a5 | |||
a331437433 | |||
276cce1808 | |||
17765f17b0 | |||
690807a632 | |||
f16ad90f68 | |||
e6244ff74b |
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,4 +1,6 @@
|
|||||||
.idea/
|
.idea/
|
||||||
.vs/
|
.vs/
|
||||||
bin/
|
bin/
|
||||||
obj/
|
obj/
|
||||||
|
appsettings.secrets.json
|
||||||
|
FarmmapsBulkSatDownload/DBsettings.secrets.json
|
111
FarmMapsBlight/BlightApplication.cs
Normal file
111
FarmMapsBlight/BlightApplication.cs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
using FarmmapsApi;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using FarmMapsBlight.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
|
||||||
|
namespace FarmMapsBlight
|
||||||
|
{
|
||||||
|
public class BlightApplication : IApplication
|
||||||
|
{
|
||||||
|
private const string DownloadFolder = "Downloads";
|
||||||
|
private const string SettingsFile = "settings.json";
|
||||||
|
|
||||||
|
private readonly ILogger<BlightApplication> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly BlightService _blightService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
private Settings _settings;
|
||||||
|
|
||||||
|
public BlightApplication(ILogger<BlightApplication> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService, BlightService haulmkillingService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
_blightService = haulmkillingService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunAsync()
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(DownloadFolder))
|
||||||
|
Directory.CreateDirectory(DownloadFolder);
|
||||||
|
|
||||||
|
LoadSettings();
|
||||||
|
|
||||||
|
// !! 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();
|
||||||
|
|
||||||
|
var myDrive = roots.SingleOrDefault(r => r.Name == "USER_FILES");
|
||||||
|
if (myDrive == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find a needed root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
|
||||||
|
if (uploadedRoot == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find a needed root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Item cropfieldItem;
|
||||||
|
if (string.IsNullOrEmpty(_settings.CropfieldItemCode))
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Creating cropfield");
|
||||||
|
int year = DateTime.Now.Year;
|
||||||
|
string emergenDate = new DateTime(year, 4, 25).ToString("o");
|
||||||
|
string cropFieldData = "{\"area\":10.96,\"final\":true,\"soilCode\":\"1\",\"soilName\":\"Zand\",\"varietyCode\":\"10019\",\"varietyName\":\"Abana\",\"cropTypeCode\":\"1010101\",\"cropTypeName\":\"Aardappel\",\"rootDepthMax\":45,\"emergenceDate\":\"" + emergenDate + "\",\"productionPurposeCode\":\"003\",\"productionPurposeName\":\"Consumptie\"}";
|
||||||
|
cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDrive.Code, "Cropfield Blight", year,
|
||||||
|
@"{""type"":""Polygon"",""coordinates"":[[[4.617786844284247,52.22533706956424],[4.618642601314543,52.225938364585989],[4.6192153806397,52.22563988897754],[4.619192414656403,52.2256242822442],[4.620306732153958,52.225031745661528],[4.620542019225217,52.22519855319158],[4.621157509147853,52.22487436515405],[4.623387917230182,52.22367660757213],[4.624563444939009,52.22304740241544],[4.624562779355982,52.223046635247019],[4.624534908813479,52.22302596787506],[4.627873021330343,52.221240670658399],[4.627504935938338,52.220104419135129],[4.627324878706837,52.22020569669098],[4.627320696113512,52.22020660117888],[4.626707169518044,52.22053923770041],[4.624700376420229,52.221619047547488],[4.623471571183885,52.22227447969577],[4.623471511010673,52.22227500174403],[4.623468838689317,52.22228052566992],[4.617786844284247,52.22533706956424]]]}", cropFieldData);
|
||||||
|
_settings.CropfieldItemCode = cropfieldItem.Code;
|
||||||
|
SaveSettings();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Cropfield already exists trying to get");
|
||||||
|
cropfieldItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldItemCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
var blightItem = await _blightService.CreateAdvice(cropfieldItem);
|
||||||
|
if (blightItem == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// advice as json
|
||||||
|
Console.WriteLine(blightItem.Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadSettings()
|
||||||
|
{
|
||||||
|
if (File.Exists(SettingsFile))
|
||||||
|
{
|
||||||
|
var jsonText = File.ReadAllText(SettingsFile);
|
||||||
|
_settings = JsonConvert.DeserializeObject<Settings>(jsonText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_settings = new Settings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveSettings()
|
||||||
|
{
|
||||||
|
if (_settings == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var json = JsonConvert.SerializeObject(_settings);
|
||||||
|
File.WriteAllText(SettingsFile, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
76
FarmMapsBlight/BlightService.cs
Normal file
76
FarmMapsBlight/BlightService.cs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using FarmMapsBlight.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using static FarmmapsApi.Extensions;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
namespace FarmMapsBlight
|
||||||
|
{
|
||||||
|
public class BlightService
|
||||||
|
{
|
||||||
|
private readonly ILogger<BlightService> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
public BlightService(ILogger<BlightService> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Item> CreateAdvice(Item cropfieldItem)
|
||||||
|
{
|
||||||
|
var taskRequest = new TaskRequest()
|
||||||
|
{
|
||||||
|
TaskType = "vnd.farmmaps.task.blight"
|
||||||
|
};
|
||||||
|
|
||||||
|
var fungicide1 = "{\"ai1\": \"propamocarb\", \"ai2\": \"fluopicolide\", \"ai3\": \"cymoxanil\", \"code\": \"infinito12curz\", \"name\": \"infinito 1,2 l + curzate partner 0,2 kg\", \"maxdose\": \"1\", \"mindose\": \"1\", \"safedays\": \"14\", \"emergence\": true, \"newgrowth\": \"1\", \"contentai1\": \"525.2\", \"contentai2\": \"62.5\", \"contentai3\": \"600\", \"fastgrowth\": true, \"contentunit\": \"l/ha + kg/ha\", \"rainfastness\": \"2.5\", \"tuberfilling\": true, \"aidescription\": \"(propamocarb + fluopicolide) 1.2 l/ha + cymoxanil 0.2 kg/ha\", \"curativescore\": \"2\", \"dryingtimemax\": \"2\", \"dryingtimemin\": \"2\", \"vracompatible\": false, \"maxapplications\": \"4\", \"preventivescore\": \"3\", \"recommendeddose\": \"1\", \"tuberprotection\": \"3.3\", \"eradicativescore\": \"2\", \"earlytubersetting\": true, \"protectioncategory\": \"2\", \"applicationrateunit\": null, \"ctgbregistrationnumber\": \"12927 n + 12755 n\"}";
|
||||||
|
var fungicide2 = "{\"ai1\": \"fluazinam\", \"ai2\": \"cymoxanil\", \"ai3\": null, \"code\": \"kunshi\", \"name\": \"kunshi\", \"maxdose\": \"0.5\", \"mindose\": \"0.4\", \"safedays\": \"1\", \"emergence\": false, \"newgrowth\": \"1\", \"contentai1\": \"375\", \"contentai2\": \"250\", \"contentai3\": \"0\", \"fastgrowth\": true, \"contentunit\": \"g/kg\", \"rainfastness\": \"2.5\", \"tuberfilling\": false, \"aidescription\": \"(fluazinam + cymoxanil) 0.5 kg/ha\", \"curativescore\": \"2\", \"dryingtimemax\": \"2\", \"dryingtimemin\": \"1\", \"vracompatible\": true, \"maxapplications\": \"5\", \"preventivescore\": \"2.9\", \"recommendeddose\": \"0.5\", \"tuberprotection\": \"3.3\", \"eradicativescore\": \"1\", \"earlytubersetting\": false, \"protectioncategory\": \"1\", \"applicationrateunit\": \"kg/ha\", \"ctgbregistrationnumber\": \"14371 n\"}";
|
||||||
|
|
||||||
|
List<Spray> sprays = new List<Spray>();
|
||||||
|
sprays.Add(new Spray() { fungicide = JsonConvert.DeserializeObject<Fungicide>(fungicide1), sprayTime = new DateTime(2020, 9, 1), dose = 0.6, isVRA = false });
|
||||||
|
sprays.Add(new Spray() { fungicide = JsonConvert.DeserializeObject<Fungicide>(fungicide2), sprayTime = new DateTime(2020, 9, 1), dose = 0.6, isVRA = false });
|
||||||
|
|
||||||
|
taskRequest.attributes["sprays"] = JsonConvert.SerializeObject(sprays);
|
||||||
|
|
||||||
|
var taskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskRequest);
|
||||||
|
await PollTask(TimeSpan.FromSeconds(3), async (tokenSource) =>
|
||||||
|
{
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
|
||||||
|
_logger.LogInformation($"Checking blight task status: { itemTaskStatus.State}");
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
|
||||||
|
if (itemTask.State == ItemTaskState.Error)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemName = $"Blight";
|
||||||
|
var blightAdviceItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
|
||||||
|
BLIGHT_ITEMTYPE, itemName);
|
||||||
|
|
||||||
|
// incorrect filter task is finished after updating
|
||||||
|
|
||||||
|
// i => i.Updated >= itemTask.Finished && i.Name.ToLower().Contains(itemName.ToLower())
|
||||||
|
if (blightAdviceItem == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find the blight item under cropfield");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return blightAdviceItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
FarmMapsBlight/FarmMapsBlight.csproj
Normal file
12
FarmMapsBlight/FarmMapsBlight.csproj
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FarmmapsApi\FarmmapsApi.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
6
FarmMapsBlight/FarmMapsBlight.csproj.user
Normal file
6
FarmMapsBlight/FarmMapsBlight.csproj.user
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ShowAllFiles>false</ShowAllFiles>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
48
FarmMapsBlight/Models/Fungicide.cs
Normal file
48
FarmMapsBlight/Models/Fungicide.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FarmMapsBlight.Models
|
||||||
|
{
|
||||||
|
public class Fungicide
|
||||||
|
{
|
||||||
|
public string code { get; set; }
|
||||||
|
public string name { get; set; }
|
||||||
|
public string ctgbregistrationnumber { get; set; }
|
||||||
|
public string ai1 { get; set; }
|
||||||
|
public string ai2 { get; set; }
|
||||||
|
public string ai3 { get; set; }
|
||||||
|
public double contentai1 { get; set; }
|
||||||
|
public double contentai2 { get; set; }
|
||||||
|
public double contentai3 { get; set; }
|
||||||
|
public string contentunit { get; set; }
|
||||||
|
public string aidescription { get; set; }
|
||||||
|
public int protectioncategory { get; set; }
|
||||||
|
public double preventivescore { get; set; }
|
||||||
|
public double curativescore { get; set; }
|
||||||
|
public string applicationrateunit { get; set; }
|
||||||
|
public double recommendeddose { get; set; }
|
||||||
|
public double newgrowth { get; set; }
|
||||||
|
public double tuberprotection { get; set; }
|
||||||
|
public double dryingtimemin { get; set; }
|
||||||
|
public double dryingtimemax { get; set; }
|
||||||
|
public double rainfastness { get; set; }
|
||||||
|
public double mindose { get; set; }
|
||||||
|
public double maxdose { get; set; }
|
||||||
|
public int? maxapplications { get; set; }
|
||||||
|
public bool vracompatible { get; set; }
|
||||||
|
public double eradicativescore { get; set; }
|
||||||
|
public bool emergence { get; set; }
|
||||||
|
public bool fastgrowth { get; set; }
|
||||||
|
public bool earlytubersetting { get; set; }
|
||||||
|
public bool tuberfilling { get; set; }
|
||||||
|
public int? safedays { get; set; }
|
||||||
|
public double takeback
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return curativescore * 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
FarmMapsBlight/Models/Irrigation.cs
Normal file
11
FarmMapsBlight/Models/Irrigation.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace FarmMapsBlight.Models
|
||||||
|
{
|
||||||
|
public class Irrigation
|
||||||
|
{
|
||||||
|
public DateTime startTime { get; set; }
|
||||||
|
public DateTime endTime { get; set; }
|
||||||
|
public double mm { get; set; }
|
||||||
|
}
|
||||||
|
}
|
7
FarmMapsBlight/Models/Settings.cs
Normal file
7
FarmMapsBlight/Models/Settings.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace FarmMapsBlight.Models
|
||||||
|
{
|
||||||
|
public class Settings
|
||||||
|
{
|
||||||
|
public string CropfieldItemCode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
12
FarmMapsBlight/Models/Spray.cs
Normal file
12
FarmMapsBlight/Models/Spray.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace FarmMapsBlight.Models
|
||||||
|
{
|
||||||
|
public class Spray
|
||||||
|
{
|
||||||
|
public DateTime sprayTime { get; set; }
|
||||||
|
public Fungicide fungicide { get; set; }
|
||||||
|
public double dose { get; set; }
|
||||||
|
public bool isVRA { get; set; }
|
||||||
|
}
|
||||||
|
}
|
23
FarmMapsBlight/Program.cs
Normal file
23
FarmMapsBlight/Program.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using FarmmapsApi;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace FarmMapsBlight
|
||||||
|
{
|
||||||
|
public class Program : FarmmapsProgram<BlightApplication>
|
||||||
|
{
|
||||||
|
private static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
await new Program().Start(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Configure(IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
serviceCollection.AddLogging(opts => opts
|
||||||
|
.AddConsole()
|
||||||
|
.AddFilter("System.Net.Http", LogLevel.Warning))
|
||||||
|
.AddTransient<BlightService>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,11 +3,29 @@ namespace FarmmapsApiSamples
|
|||||||
public static class Constants
|
public static class Constants
|
||||||
{
|
{
|
||||||
public const string USERINPUT_ITEMTYPE = "vnd.farmmaps.itemtype.user.input";
|
public const string USERINPUT_ITEMTYPE = "vnd.farmmaps.itemtype.user.input";
|
||||||
|
public const string TEMPORAL_ITEMTYPE = "vnd.farmmaps.itemtype.temporal";
|
||||||
public const string GEOTIFF_ITEMTYPE = "vnd.farmmaps.itemtype.geotiff";
|
public const string GEOTIFF_ITEMTYPE = "vnd.farmmaps.itemtype.geotiff";
|
||||||
public const string GEOTIFF_PROCESSED_ITEMTYPE = "vnd.farmmaps.itemtype.geotiff.processed";
|
public const string GEOTIFF_PROCESSED_ITEMTYPE = "vnd.farmmaps.itemtype.geotiff.processed";
|
||||||
public const string CROPFIELD_ITEMTYPE = "vnd.farmmaps.itemtype.cropfield";
|
public const string CROPFIELD_ITEMTYPE = "vnd.farmmaps.itemtype.cropfield";
|
||||||
public const string SHAPE_PROCESSED_ITEMTYPE = "vnd.farmmaps.itemtype.shape.processed";
|
public const string SHAPE_PROCESSED_ITEMTYPE = "vnd.farmmaps.itemtype.shape.processed";
|
||||||
|
public const string ISOXML_PROCESSED_ITEMTYPE = "vnd.farmmaps.itemtype.iso11783.taskdata.processed";
|
||||||
public const string SHAPE_ITEMTYPE = "vnd.farmmaps.itemtype.shape";
|
public const string SHAPE_ITEMTYPE = "vnd.farmmaps.itemtype.shape";
|
||||||
|
public const string GEOJSON_ITEMTYPE = "vnd.farmmaps.itemtype.geojson";
|
||||||
|
public const string BLIGHT_ITEMTYPE = "vnd.farmmaps.itemtype.blight";
|
||||||
|
public const string CROPREC_ITEMTYPE = "vnd.farmmaps.itemtype.crprec.operation";
|
||||||
|
|
||||||
public const string VRANBS_TASK = "vnd.farmmaps.task.vranbs";
|
public const string VRANBS_TASK = "vnd.farmmaps.task.vranbs";
|
||||||
|
public const string VRAHERBICIDE_TASK = "vnd.farmmaps.task.vraherbicide";
|
||||||
|
public const string VRAHAULMKILLING_TASK = "vnd.farmmaps.task.vrahaulmkilling";
|
||||||
|
public const string VRAPLANTING_TASK = "vnd.farmmaps.task.vrapoten";
|
||||||
|
public const string VRAZONERING_TASK = "vnd.farmmaps.task.vrazonering";
|
||||||
|
public const string SATELLITE_TASK = "vnd.farmmaps.task.sentinelhub"; //"vnd.farmmaps.task.satellite";
|
||||||
|
public const string VANDERSAT_TASK = "vnd.farmmaps.task.vandersat";
|
||||||
|
public const string TASKMAP_TASK = "vnd.farmmaps.task.taskmap";
|
||||||
|
public const string WORKFLOW_TASK = "vnd.farmmaps.task.workflow";
|
||||||
|
public const string BOFEK_TASK = "vnd.farmmaps.task.bofek";
|
||||||
|
public const string SHADOW_TASK = "vnd.farmmaps.task.shadow";
|
||||||
|
public const string AHN_TASK = "vnd.farmmaps.task.ahn";
|
||||||
|
public const string WATBAL_TASK = "vnd.farmmaps.task.watbal";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,20 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Google.Apis" Version="1.44.1" />
|
<PackageReference Include="Google.Apis" Version="1.44.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.1.2" />
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.1.14" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.2" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.14" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.2" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.14" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.14" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.2" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.14" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.2" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.14" />
|
||||||
<PackageReference Include="IdentityModel.OidcClient" Version="3.1.2" />
|
<PackageReference Include="IdentityModel.OidcClient" Version="3.1.2" />
|
||||||
|
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
|
||||||
<PackageReference Include="Winista.MimeDetect" Version="1.0.1" />
|
<PackageReference Include="Winista.MimeDetect" Version="1.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Secrets\Secrets.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FarmmapsApi.HttpMessageHandlers;
|
using FarmmapsApi.HttpMessageHandlers;
|
||||||
@ -6,6 +7,10 @@ using FarmmapsApi.Services;
|
|||||||
using IdentityModel.Client;
|
using IdentityModel.Client;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Serilog;
|
||||||
|
using Serilog.Events;
|
||||||
|
using Serilog.Filters;
|
||||||
|
|
||||||
namespace FarmmapsApi
|
namespace FarmmapsApi
|
||||||
{
|
{
|
||||||
@ -15,6 +20,7 @@ namespace FarmmapsApi
|
|||||||
{
|
{
|
||||||
IConfiguration config = new ConfigurationBuilder()
|
IConfiguration config = new ConfigurationBuilder()
|
||||||
.AddJsonFile("appsettings.json", false, true)
|
.AddJsonFile("appsettings.json", false, true)
|
||||||
|
.AddJsonFile("appsettings.secrets.json", false, true)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var configuration = config.Get<Configuration>();
|
var configuration = config.Get<Configuration>();
|
||||||
@ -36,11 +42,13 @@ namespace FarmmapsApi
|
|||||||
.AddHttpClient<FarmmapsApiService>()
|
.AddHttpClient<FarmmapsApiService>()
|
||||||
.AddHttpMessageHandler<FarmmapsAuthenticationHandler>()
|
.AddHttpMessageHandler<FarmmapsAuthenticationHandler>()
|
||||||
.Services;
|
.Services;
|
||||||
|
|
||||||
|
|
||||||
Configure(serviceCollection);
|
Configure(serviceCollection);
|
||||||
|
|
||||||
var serviceProvider = serviceCollection.BuildServiceProvider();
|
var serviceProvider = serviceCollection.BuildServiceProvider();
|
||||||
|
|
||||||
|
ConfigureLogger(serviceProvider);
|
||||||
|
|
||||||
await serviceProvider.GetService<FarmmapsApiService>().AuthenticateAsync();
|
await serviceProvider.GetService<FarmmapsApiService>().AuthenticateAsync();
|
||||||
// await serviceProvider.GetService<FarmmapsEventHub>().StartEventHub();
|
// await serviceProvider.GetService<FarmmapsEventHub>().StartEventHub();
|
||||||
|
|
||||||
@ -48,5 +56,24 @@ namespace FarmmapsApi
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void Configure(IServiceCollection serviceCollection);
|
protected abstract void Configure(IServiceCollection serviceCollection);
|
||||||
|
|
||||||
|
private static void ConfigureLogger(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
var isMicrosoftNamespace = Matching.FromSource("Microsoft");
|
||||||
|
var isSystem = Matching.FromSource("System");
|
||||||
|
|
||||||
|
Log.Logger = new LoggerConfiguration()
|
||||||
|
.MinimumLevel.Verbose()
|
||||||
|
.WriteTo.Logger(l =>
|
||||||
|
l.WriteTo.Logger(l2 => l2
|
||||||
|
.Filter.ByExcluding(v => isMicrosoftNamespace(v) || isSystem(v))
|
||||||
|
.WriteTo.Console())
|
||||||
|
)
|
||||||
|
.WriteTo.File(path: "Logs/log.log", rollingInterval: RollingInterval.Day)
|
||||||
|
.CreateLogger();
|
||||||
|
|
||||||
|
var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>();
|
||||||
|
loggerFactory.AddSerilog();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,8 +7,11 @@
|
|||||||
public string BasePath { get; set; }
|
public string BasePath { get; set; }
|
||||||
public string DiscoveryEndpointUrl { get; set; }
|
public string DiscoveryEndpointUrl { get; set; }
|
||||||
public string RedirectUri { get; set; }
|
public string RedirectUri { get; set; }
|
||||||
|
public string GrantClientId { get; set; }
|
||||||
public string ClientId { get; set; }
|
public string ClientId { get; set; }
|
||||||
public string ClientSecret { get; set; }
|
public string ClientSecret { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
public string[] Scopes { get; set; }
|
public string[] Scopes { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
29
FarmmapsApi/Models/SatelliteStatistics.cs
Normal file
29
FarmmapsApi/Models/SatelliteStatistics.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FarmmapsApi.Models
|
||||||
|
{
|
||||||
|
public class SatelliteStatistics
|
||||||
|
{
|
||||||
|
public string fieldName;
|
||||||
|
public DateTime satelliteDate;
|
||||||
|
public string satelliteBand;
|
||||||
|
public double max;
|
||||||
|
public double min;
|
||||||
|
public double mean;
|
||||||
|
public double mode;
|
||||||
|
public double median;
|
||||||
|
public double stddev;
|
||||||
|
public double minPlus;
|
||||||
|
public double curtosis;
|
||||||
|
public double maxMinus;
|
||||||
|
public double skewness;
|
||||||
|
public double variance;
|
||||||
|
public int populationCount;
|
||||||
|
public double variationCoefficient;
|
||||||
|
public double confidenceIntervalLow;
|
||||||
|
public double confidenceIntervalHigh;
|
||||||
|
public double confidenceIntervalErrorMargin;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
@ -53,9 +54,16 @@ namespace FarmmapsApi.Services
|
|||||||
throw new AuthenticationException("Already seems to be authenticated");
|
throw new AuthenticationException("Already seems to be authenticated");
|
||||||
|
|
||||||
var disco = await _openIdConnectService.GetDiscoveryDocumentAsync();
|
var disco = await _openIdConnectService.GetDiscoveryDocumentAsync();
|
||||||
var token = await _openIdConnectService.GetTokenClientCredentialsAsync(disco.TokenEndpoint,
|
|
||||||
_configuration.ClientId, _configuration.ClientSecret);
|
|
||||||
|
|
||||||
|
var usePasswordGrant = string.IsNullOrEmpty(_configuration.ClientId) ||
|
||||||
|
string.IsNullOrEmpty(_configuration.ClientSecret);
|
||||||
|
|
||||||
|
var token = usePasswordGrant ?
|
||||||
|
await _openIdConnectService.GetTokenUsernamePasswordAsync(disco.TokenEndpoint,
|
||||||
|
_configuration.GrantClientId, _configuration.Username, _configuration.Password) :
|
||||||
|
await _openIdConnectService.GetTokenClientCredentialsAsync(disco.TokenEndpoint,
|
||||||
|
_configuration.ClientId, _configuration.ClientSecret);
|
||||||
|
|
||||||
if (token.IsError)
|
if (token.IsError)
|
||||||
throw new AuthenticationException(token.Error);
|
throw new AuthenticationException(token.Error);
|
||||||
|
|
||||||
@ -88,7 +96,19 @@ namespace FarmmapsApi.Services
|
|||||||
|
|
||||||
var jsonString = await response.Content.ReadAsStringAsync();
|
var jsonString = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
return JsonConvert.DeserializeObject<List<UserRoot>>(jsonString);
|
var roots = JsonConvert.DeserializeObject<List<UserRoot>>(jsonString);
|
||||||
|
roots.ForEach(v =>
|
||||||
|
{
|
||||||
|
v.Name = GetSuffixFromSystemItemCode(v.Code);
|
||||||
|
});
|
||||||
|
|
||||||
|
return roots;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetSuffixFromSystemItemCode(string itemCode)
|
||||||
|
{
|
||||||
|
string[] strArray = itemCode.Split(":");
|
||||||
|
return strArray.Length == 2 ? strArray[1] : throw new ArgumentException("No system item code :" + itemCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Item> GetItemAsync(string itemCode, string itemType = null, JObject dataFilter = null)
|
public async Task<Item> GetItemAsync(string itemCode, string itemType = null, JObject dataFilter = null)
|
||||||
@ -284,6 +304,7 @@ namespace FarmmapsApi.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="FileNotFoundException"></exception>
|
/// <exception cref="FileNotFoundException"></exception>
|
||||||
public async Task<UploadResults> UploadFile(string filePath, string parentItemCode,
|
public async Task<UploadResults> UploadFile(string filePath, string parentItemCode,
|
||||||
|
string geoJsonString = null,
|
||||||
Action<IUploadProgress> progressCallback = null)
|
Action<IUploadProgress> progressCallback = null)
|
||||||
{
|
{
|
||||||
if (!File.Exists(filePath))
|
if (!File.Exists(filePath))
|
||||||
@ -292,25 +313,27 @@ namespace FarmmapsApi.Services
|
|||||||
var mimeTypes = new MimeTypes();
|
var mimeTypes = new MimeTypes();
|
||||||
var mimeType = mimeTypes.GetMimeTypeFromFile(filePath);
|
var mimeType = mimeTypes.GetMimeTypeFromFile(filePath);
|
||||||
|
|
||||||
|
var mimeString = mimeType?.ToString() ?? "application/json";
|
||||||
|
|
||||||
await using var uploadStream = new FileStream(filePath, FileMode.OpenOrCreate);
|
await using var uploadStream = new FileStream(filePath, FileMode.OpenOrCreate);
|
||||||
|
|
||||||
var request = new FileRequest()
|
var request = new FileRequest()
|
||||||
{
|
{
|
||||||
Name = Path.GetFileName(filePath),
|
Name = Path.GetFileName(filePath),
|
||||||
ParentCode = parentItemCode,
|
ParentCode = parentItemCode,
|
||||||
Size = uploadStream.Length
|
Size = uploadStream.Length,
|
||||||
|
Geometry = string.IsNullOrEmpty(geoJsonString) ? null : JObject.Parse(geoJsonString)
|
||||||
};
|
};
|
||||||
|
|
||||||
using var httpClient = CreateConfigurableHttpClient(_httpClient);
|
using var httpClient = CreateConfigurableHttpClient(_httpClient);
|
||||||
var farmmapsUploader = new FarmmapsUploader(httpClient, uploadStream, request,
|
var farmmapsUploader = new FarmmapsUploader(httpClient, uploadStream, request,
|
||||||
mimeType.ToString(), ResourceEndpoints.ITEMS_UPLOAD_RESOURCE);
|
mimeString, ResourceEndpoints.ITEMS_UPLOAD_RESOURCE);
|
||||||
|
|
||||||
Uri location = null;
|
Uri location = null;
|
||||||
farmmapsUploader.ProgressChanged += progressCallback;
|
farmmapsUploader.ProgressChanged += progressCallback;
|
||||||
farmmapsUploader.UploadSessionData += data => location = data.UploadUri;
|
farmmapsUploader.UploadSessionData += data => location = data.UploadUri;
|
||||||
|
|
||||||
var progress = await farmmapsUploader.UploadAsync();
|
var progress = await farmmapsUploader.UploadAsync();
|
||||||
|
|
||||||
return new UploadResults(progress, location);
|
return new UploadResults(progress, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,10 +68,7 @@ namespace FarmmapsApi.Services
|
|||||||
contentStream.ThrowIfNull(nameof(contentStream));
|
contentStream.ThrowIfNull(nameof(contentStream));
|
||||||
|
|
||||||
_streamLength = ContentStream.CanSeek ? ContentStream.Length : UnknownSize;
|
_streamLength = ContentStream.CanSeek ? ContentStream.Length : UnknownSize;
|
||||||
|
ChunkSize = 2 * 0x100000;
|
||||||
var twoMB = 2 * 0x100000;
|
|
||||||
ChunkSize = twoMB;
|
|
||||||
body.ChunkSize = ChunkSize;
|
|
||||||
Body = body;
|
Body = body;
|
||||||
|
|
||||||
Path = path;
|
Path = path;
|
||||||
|
@ -12,136 +12,233 @@ using static FarmmapsApiSamples.Constants;
|
|||||||
|
|
||||||
namespace FarmmapsApi.Services
|
namespace FarmmapsApi.Services
|
||||||
{
|
{
|
||||||
public class GeneralService
|
public class GeneralService {
|
||||||
{
|
|
||||||
private readonly ILogger<GeneralService> _logger;
|
private readonly ILogger<GeneralService> _logger;
|
||||||
private readonly FarmmapsApiService _farmmapsApiService;
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
|
||||||
public GeneralService(ILogger<GeneralService> logger, FarmmapsApiService farmmapsApiService)
|
public GeneralService(ILogger<GeneralService> logger, FarmmapsApiService farmmapsApiService) {
|
||||||
{
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_farmmapsApiService = farmmapsApiService;
|
_farmmapsApiService = farmmapsApiService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Item> CreateCropfieldItemAsync(string parentItemCode, string name, int year, string fieldGeomJson)
|
public async Task<Item> CreateCropfieldItemAsync(string parentItemCode, string name, int year,
|
||||||
{
|
string fieldGeomJson, string data = "{}") {
|
||||||
var currentYear = new DateTime(year, 1, 1);
|
var currentYear = new DateTime(year, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||||
var cropfieldItemRequest = new ItemRequest()
|
var cropfieldItemRequest = new ItemRequest() {
|
||||||
{
|
|
||||||
ParentCode = parentItemCode,
|
ParentCode = parentItemCode,
|
||||||
ItemType = CROPFIELD_ITEMTYPE,
|
ItemType = CROPFIELD_ITEMTYPE,
|
||||||
Name = name,
|
Name = name,
|
||||||
DataDate = currentYear,
|
DataDate = currentYear,
|
||||||
DataEndDate = currentYear.AddYears(1).AddDays(-1),
|
DataEndDate = currentYear.AddYears(1).AddDays(-1),
|
||||||
Data = JObject.Parse("{}"),
|
Data = JObject.Parse(data),
|
||||||
Geometry = JObject.Parse(fieldGeomJson)
|
Geometry = JObject.Parse(fieldGeomJson)
|
||||||
};
|
};
|
||||||
|
|
||||||
return await _farmmapsApiService.CreateItemAsync(cropfieldItemRequest);
|
return await _farmmapsApiService.CreateItemAsync(cropfieldItemRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Item> UploadDataAsync(UserRoot root, string itemType, string filePath, string itemName)
|
public async Task<Item> UploadDataAsync(UserRoot root, string itemType, string filePath, string itemName, string geoJsonString = null)
|
||||||
{
|
{
|
||||||
var startUpload = DateTime.UtcNow;
|
var startUpload = DateTime.UtcNow.AddSeconds(-3);
|
||||||
var result = await _farmmapsApiService.UploadFile(filePath, root.Code,
|
var result = await _farmmapsApiService.UploadFile(filePath, root.Code, geoJsonString,
|
||||||
progress => _logger.LogInformation($"Status: {progress.Status} - BytesSent: {progress.BytesSent}"));
|
progress =>
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Status: {progress.Status} - BytesSent: {progress.BytesSent}");
|
||||||
|
|
||||||
|
if(progress.Status == UploadStatus.Failed && progress.Exception != null)
|
||||||
|
_logger.LogError(progress.Exception.Message ?? "No further error");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
if (result.Progress.Status == UploadStatus.Failed)
|
if (result.Progress.Status == UploadStatus.Failed)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return await FindChildItemAsync(root.Code, itemType, itemName,
|
return await FindChildItemAsync(root.Code, itemType, itemName,
|
||||||
i => i.Created >= startUpload &&
|
i => i.Created >= startUpload &&
|
||||||
i.Name.ToLower().Contains(itemName.ToLower()));
|
i.Name.ToLower().Contains(itemName.ToLower()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Item> UploadZipWithShapeAsync(UserRoot root, string filePath, string itemName)
|
public async Task<Item> UploadZipWithShapeAsync(UserRoot root, string filePath, string itemName, string geoJsonString = null)
|
||||||
{
|
{
|
||||||
|
var startUpload = DateTime.UtcNow.AddSeconds(-3);
|
||||||
var startUpload = DateTime.UtcNow;
|
var result = await _farmmapsApiService.UploadFile(filePath, root.Code, geoJsonString,
|
||||||
var result = await _farmmapsApiService.UploadFile(filePath, root.Code,
|
|
||||||
progress => _logger.LogInformation($"Status: {progress.Status} - BytesSent: {progress.BytesSent}"));
|
progress => _logger.LogInformation($"Status: {progress.Status} - BytesSent: {progress.BytesSent}"));
|
||||||
|
|
||||||
if (result.Progress.Status == UploadStatus.Failed)
|
if (result.Progress.Status == UploadStatus.Failed)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var zipName = Path.GetFileName(filePath);
|
return await FindChildItemAsync(root.Code, SHAPE_PROCESSED_ITEMTYPE, itemName,
|
||||||
Item shapeItem = null;
|
i => i.Created >= startUpload &&
|
||||||
await PollTask(TimeSpan.FromSeconds(3), async source =>
|
i.Name.ToLower().Contains(itemName.ToLower())); ;
|
||||||
{
|
|
||||||
_logger.LogInformation($"Searching for {itemName} item");
|
|
||||||
var uploadedFilesChildren = await _farmmapsApiService.GetItemChildrenAsync(root.Code);
|
|
||||||
var zipItems = uploadedFilesChildren.Where(i => i.Name.Contains(zipName));
|
|
||||||
|
|
||||||
foreach (var zipItem in zipItems)
|
|
||||||
{
|
|
||||||
List<Item> items = await _farmmapsApiService.GetItemChildrenAsync(zipItem.Code,
|
|
||||||
SHAPE_PROCESSED_ITEMTYPE);
|
|
||||||
|
|
||||||
items = items.Where(i => i.Created >= startUpload).OrderByDescending(i => i.Created).ToList();
|
|
||||||
|
|
||||||
if (items.Any())
|
|
||||||
{
|
|
||||||
shapeItem = items.First(i => i.Name.Contains(itemName));
|
|
||||||
if(shapeItem != null)
|
|
||||||
{
|
|
||||||
source.Cancel();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return shapeItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Item> ShapeToGeotiff(Item shapeItem)
|
public async Task<Item> ShapeToGeotiff(Item shapeItem, int resolution = 1, params string[] inputLayerNames)
|
||||||
{
|
{
|
||||||
var shapeToGeotiffRequest = new TaskRequest()
|
var startUpload = DateTime.UtcNow.AddSeconds(-3);
|
||||||
|
var taskStatus = await RunAndWaitForTask(shapeItem, "vnd.farmmaps.task.shapetogeotiff", request =>
|
||||||
{
|
{
|
||||||
TaskType = "vnd.farmmaps.task.shapetogeotiff"
|
request.attributes["resolution"] = resolution.ToString();
|
||||||
};
|
if(inputLayerNames.Length > 0)
|
||||||
var taskCode = await _farmmapsApiService.QueueTaskAsync(shapeItem.Code, shapeToGeotiffRequest);
|
request.attributes["inputLayers"] = $"[{string.Join(",", inputLayerNames.Select(v => $"\"{v}\""))}]";
|
||||||
|
});
|
||||||
|
|
||||||
await PollTask(TimeSpan.FromSeconds(3), async (tokenSource) =>
|
if (taskStatus.State == ItemTaskState.Error)
|
||||||
{
|
return null;
|
||||||
_logger.LogInformation("Checking shapetogeotiff task status");
|
|
||||||
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(shapeItem.Code, taskCode);
|
return await FindChildItemAsync(shapeItem.ParentCode, GEOTIFF_PROCESSED_ITEMTYPE, shapeItem.Name,
|
||||||
|
i => i.Created >= startUpload &&
|
||||||
|
i.Name.ToLower().Contains(shapeItem.Name.ToLower()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<Item> GeotiffToShape(Item tiffItem)
|
||||||
|
{
|
||||||
|
var taskmapRequest = new TaskRequest {TaskType = TASKMAP_TASK};
|
||||||
|
taskmapRequest.attributes["cellWidth"] = "3";
|
||||||
|
taskmapRequest.attributes["cellHeight"] = "1";
|
||||||
|
taskmapRequest.attributes["angle"] = "0";
|
||||||
|
|
||||||
|
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(tiffItem.Code, taskmapRequest);
|
||||||
|
|
||||||
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) => {
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(tiffItem.Code, itemTaskCode);
|
||||||
|
_logger.LogInformation($"Waiting on converting geotiff to shape; status: {itemTaskStatus.State}");
|
||||||
if (itemTaskStatus.IsFinished)
|
if (itemTaskStatus.IsFinished)
|
||||||
tokenSource.Cancel();
|
tokenSource.Cancel();
|
||||||
});
|
});
|
||||||
|
|
||||||
_logger.LogInformation("Data shape converted to geotiff");
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(tiffItem.Code, itemTaskCode);
|
||||||
|
if (itemTask.State == ItemTaskState.Error) {
|
||||||
|
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// the parent of the shape item is now the tiff item
|
//the taskmap is a child of the input tiff *** Update feb 2021: it is a child of the cropfield.
|
||||||
shapeItem = await _farmmapsApiService.GetItemAsync(shapeItem.Code);
|
var itemName = "Taskmap";
|
||||||
return await _farmmapsApiService.GetItemAsync(shapeItem.ParentCode);
|
var taskMapItem = await FindChildItemAsync(tiffItem.ParentCode,
|
||||||
|
SHAPE_PROCESSED_ITEMTYPE, itemName);
|
||||||
|
if (taskMapItem == null) {
|
||||||
|
_logger.LogError("Could not find the shape taskmap as a child item under the input");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return taskMapItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create taskmap based on width, height and direction
|
||||||
|
|
||||||
|
public async Task<Item> CreateTaskmap(Item cropfieldItem, Item tiffItem, string outputType, string cellWidth, string cellHeight,
|
||||||
|
string startPoint, string inputLayerName = null, string ddiCode = "0001", string centered = "false", string endPoint = null, string angle = null, string precision = null,
|
||||||
|
string cropTypeName = null, string costumerName = null, string ProductGroupName = null, string productName = null,
|
||||||
|
string resolution = "3", string unitScale = null, string maximumClasses = null)
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
var taskmapRequest = new TaskRequest { TaskType = TASKMAP_TASK };
|
||||||
|
taskmapRequest.attributes["inputLayerName"] = inputLayerName;
|
||||||
|
taskmapRequest.attributes["inputCode"] = tiffItem.Code;
|
||||||
|
taskmapRequest.attributes["operation"] = outputType; // Currently onlye "shape" supported, if ISOXML is supported this should be an input
|
||||||
|
taskmapRequest.attributes["cellWidth"] = cellWidth; //metres
|
||||||
|
taskmapRequest.attributes["cellHeight"] = cellHeight; //metres
|
||||||
|
taskmapRequest.attributes["startPoint"] = startPoint; // Coordinates WGS84
|
||||||
|
taskmapRequest.attributes["centered"] = centered;
|
||||||
|
if (outputType == "isoxml") taskmapRequest.attributes["ddiCode"] = ddiCode; // ddi is obligatory for isoxml, if not given set to 0001
|
||||||
|
if (angle == null) taskmapRequest.attributes["endPoint"] = endPoint; // Coordinates WGS84
|
||||||
|
if (endPoint == null) taskmapRequest.attributes["angle"] = angle; // degrees between 0.0 and 360.0
|
||||||
|
|
||||||
|
|
||||||
|
// Optional attributes
|
||||||
|
if (precision != null) taskmapRequest.attributes["precision"] = precision;
|
||||||
|
if (cropTypeName != null) taskmapRequest.attributes["cropTypeName"] = cropTypeName;
|
||||||
|
if (costumerName != null) taskmapRequest.attributes["costumerName"] = costumerName;
|
||||||
|
if (ProductGroupName != null) taskmapRequest.attributes["ProductGroupName"] = ProductGroupName;
|
||||||
|
if (productName != null) taskmapRequest.attributes["productName"] = productName;
|
||||||
|
if (resolution != null) taskmapRequest.attributes["resolution"] = resolution;
|
||||||
|
if (unitScale != null) taskmapRequest.attributes["unitScale"] = unitScale;
|
||||||
|
if (maximumClasses != null) taskmapRequest.attributes["maximumClasses"] = maximumClasses; // Can be used for shapefile too
|
||||||
|
|
||||||
|
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskmapRequest);
|
||||||
|
|
||||||
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) => {
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
_logger.LogInformation($"Waiting on conversion to Taskmap; status: {itemTaskStatus.State}");
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
if (itemTask.State == ItemTaskState.Error)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//the taskmap is a child of the input tiff
|
||||||
|
var itemName = "Taskmap";
|
||||||
|
Item taskMapItem = null;
|
||||||
|
if (outputType == "isoxml") {taskMapItem = await FindChildItemAsync(tiffItem.ParentCode,
|
||||||
|
ISOXML_PROCESSED_ITEMTYPE, itemName);
|
||||||
|
}
|
||||||
|
else if (outputType== "shape") {
|
||||||
|
taskMapItem = await FindChildItemAsync(tiffItem.ParentCode,
|
||||||
|
|
||||||
|
SHAPE_PROCESSED_ITEMTYPE, outputType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError("OutputType not specified, could not determine if output should be shape or ISOXML");
|
||||||
|
taskMapItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (taskMapItem == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find the shape/isoxml taskmap as a child item under the cropfield");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return taskMapItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<ItemTaskStatus> RunAndWaitForTask(Item subjectItem, string taskIdentifier,
|
||||||
|
Action<TaskRequest> configureCallback = null, int retrySeconds = 3) {
|
||||||
|
var taskRequest = new TaskRequest() {
|
||||||
|
TaskType = taskIdentifier
|
||||||
|
};
|
||||||
|
configureCallback?.Invoke(taskRequest);
|
||||||
|
|
||||||
|
var taskCode = await _farmmapsApiService.QueueTaskAsync(subjectItem.Code, taskRequest);
|
||||||
|
|
||||||
|
await PollTask(TimeSpan.FromSeconds(retrySeconds), async (tokenSource) => {
|
||||||
|
_logger.LogInformation($"Checking {taskIdentifier} task status");
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(subjectItem.Code, taskCode);
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
_logger.LogInformation($"{taskIdentifier} finished");
|
||||||
|
|
||||||
|
return await _farmmapsApiService.GetTaskStatusAsync(subjectItem.Code, taskCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Item> FindChildItemAsync(string parentCode, string itemType, string containsName,
|
public async Task<Item> FindChildItemAsync(string parentCode, string itemType, string containsName,
|
||||||
Func<Item, bool> filter = null, int maxTries = 10)
|
Func<Item, bool> filter = null, int maxTries = 10) {
|
||||||
{
|
|
||||||
Item dataItem = null;
|
Item dataItem = null;
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
await PollTask(TimeSpan.FromSeconds(3), async source =>
|
await PollTask(TimeSpan.FromSeconds(3), async source => {
|
||||||
{
|
|
||||||
_logger.LogInformation($"Trying to get {containsName} data");
|
_logger.LogInformation($"Trying to get {containsName} data");
|
||||||
var uploadedFilesChildren = await _farmmapsApiService.GetItemChildrenAsync(parentCode, itemType);
|
var uploadedFilesChildren = await _farmmapsApiService.GetItemChildrenAsync(parentCode, itemType);
|
||||||
if (uploadedFilesChildren.Count > 0)
|
Func<Item, bool> func = filter ?? (i => i.Name.ToLower().Contains(containsName.ToLower()));
|
||||||
{
|
dataItem = uploadedFilesChildren.FirstOrDefault(func);
|
||||||
Func<Item, bool> func = filter ?? (i => i.Name.ToLower().Contains(containsName.ToLower()));
|
if (dataItem != null || tries == maxTries) {
|
||||||
dataItem = uploadedFilesChildren.FirstOrDefault(func);
|
|
||||||
source.Cancel();
|
source.Cancel();
|
||||||
}
|
}
|
||||||
else if (tries == maxTries)
|
|
||||||
{
|
|
||||||
source.Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
tries++;
|
tries++;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (dataItem == null)
|
if (dataItem == null) {
|
||||||
{
|
|
||||||
_logger.LogError("dataItem not found");
|
_logger.LogError("dataItem not found");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -149,5 +246,442 @@ namespace FarmmapsApi.Services
|
|||||||
_logger.LogInformation($"Found {containsName} item");
|
_logger.LogInformation($"Found {containsName} item");
|
||||||
return dataItem;
|
return dataItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Item> RunBofekTask(Item cropfieldItem) {
|
||||||
|
var taskmapRequest = new TaskRequest { TaskType = BOFEK_TASK };
|
||||||
|
|
||||||
|
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskmapRequest);
|
||||||
|
|
||||||
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) => {
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
_logger.LogInformation($"Waiting on retreiving BOFEK data; status: {itemTaskStatus.State}");
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
if (itemTask.State == ItemTaskState.Error) {
|
||||||
|
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//the BOFEK data is a child of the cropfield
|
||||||
|
var itemName = "bofek";
|
||||||
|
var bofekItem = await FindChildItemAsync(cropfieldItem.Code,
|
||||||
|
SHAPE_PROCESSED_ITEMTYPE, itemName);
|
||||||
|
if (bofekItem == null) {
|
||||||
|
_logger.LogError("Could not find the BOFEK data as a child item under the cropfield");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bofekItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Item> RunAhnTask(Item cropfieldItem) {
|
||||||
|
var taskmapRequest = new TaskRequest { TaskType = AHN_TASK };
|
||||||
|
|
||||||
|
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskmapRequest);
|
||||||
|
|
||||||
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) => {
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
_logger.LogInformation($"Waiting on retreiving AHN data; status: {itemTaskStatus.State}");
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
if (itemTask.State == ItemTaskState.Error) {
|
||||||
|
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//the AHN data is a child of the cropfield
|
||||||
|
var itemName = "ahn";
|
||||||
|
var ahnItem = await FindChildItemAsync(cropfieldItem.Code,
|
||||||
|
GEOTIFF_PROCESSED_ITEMTYPE, itemName);
|
||||||
|
if (ahnItem == null) {
|
||||||
|
_logger.LogError("Could not find the AHN data as a child item under the cropfield");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ahnItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Item> RunShadowTask(Item cropfieldItem) {
|
||||||
|
var taskmapRequest = new TaskRequest { TaskType = SHADOW_TASK };
|
||||||
|
|
||||||
|
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskmapRequest);
|
||||||
|
|
||||||
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) => {
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
_logger.LogInformation($"Waiting on calculation shadow data; status: {itemTaskStatus.State}");
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
if (itemTask.State == ItemTaskState.Error) {
|
||||||
|
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//the shadow data is a child of the cropfield
|
||||||
|
var itemName = "shadow";
|
||||||
|
var shadowItem = await FindChildItemAsync(cropfieldItem.Code,
|
||||||
|
GEOTIFF_PROCESSED_ITEMTYPE, itemName);
|
||||||
|
if (shadowItem == null) {
|
||||||
|
_logger.LogError("Could not find the shadow data as a child item under the cropfield");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shadowItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<string> RunSatelliteTask(Item cropfieldItem) {
|
||||||
|
|
||||||
|
_logger.LogInformation("Gathering satellite information for cropfield, this might take a while!");
|
||||||
|
|
||||||
|
var taskmapRequest = new TaskRequest { TaskType = SATELLITE_TASK };
|
||||||
|
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskmapRequest);
|
||||||
|
|
||||||
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) => {
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
_logger.LogInformation($"Waiting on satellite data; status: {itemTaskStatus.State}");
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
|
||||||
|
if (itemTask.State == ItemTaskState.Error) {
|
||||||
|
_logger.LogError($"Something went wrong when trying to process satellite data; {itemTask.Message}");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemTask.Code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<Item> FindSatelliteItem(Item cropfieldItem, string satelliteTaskCode) {
|
||||||
|
|
||||||
|
var taskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, satelliteTaskCode);
|
||||||
|
|
||||||
|
var temporalItem = await FindChildItemAsync(cropfieldItem.Code, TEMPORAL_ITEMTYPE,
|
||||||
|
"Cropfield Satellite items", item => item.SourceTask == SATELLITE_TASK &&
|
||||||
|
taskStatus.Finished >= item.Created &&
|
||||||
|
taskStatus.Finished <= item.Created.Value.AddHours(1));
|
||||||
|
|
||||||
|
|
||||||
|
if (temporalItem == null) {
|
||||||
|
_logger.LogError("Temporal item not found");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var satelliteTiffs = await _farmmapsApiService.GetItemChildrenAsync(temporalItem.Code);
|
||||||
|
|
||||||
|
_logger.LogInformation("Available satellite images:");
|
||||||
|
var count = 0;
|
||||||
|
TimeSpan.FromSeconds(0.5);
|
||||||
|
foreach (var item in satelliteTiffs) {
|
||||||
|
|
||||||
|
Console.WriteLine($"Satellite image #{count}: {item.DataDate}");
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Enter satellite image number for NBS application");
|
||||||
|
int element = Int32.Parse(Console.ReadLine());
|
||||||
|
var selectedSatelliteItem = satelliteTiffs[element];
|
||||||
|
|
||||||
|
if (selectedSatelliteItem == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Satellite item not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectedSatelliteItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Item>> FindSatelliteItems(Item cropfieldItem, string satelliteTaskCode)
|
||||||
|
{
|
||||||
|
|
||||||
|
var taskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, satelliteTaskCode);
|
||||||
|
|
||||||
|
if (taskStatus.State == ItemTaskState.Error)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(taskStatus.Message);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// find satellite data geotiffs
|
||||||
|
var temporalItem = await FindChildItemAsync(cropfieldItem.Code, TEMPORAL_ITEMTYPE,
|
||||||
|
"Cropfield Satellite items", item => item.SourceTask == SATELLITE_TASK &&
|
||||||
|
taskStatus.Finished >= item.Created &&
|
||||||
|
taskStatus.Finished <= item.Created.Value.AddHours(1));
|
||||||
|
|
||||||
|
if (temporalItem == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Temporal item not found");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var satelliteTiffs = await _farmmapsApiService.GetItemChildrenAsync(temporalItem.Code);
|
||||||
|
return satelliteTiffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task<string> DownloadSatelliteStats(List<Item> satelliteTiffs, string fieldName = null, List<string> satelliteBands = null, string downloadFolder = null)
|
||||||
|
{
|
||||||
|
|
||||||
|
string satelliteDataStatisticsFile = Path.Combine(downloadFolder, $"satelliteStats_{fieldName}.csv");
|
||||||
|
File.Delete(satelliteDataStatisticsFile); // Delete the SatelliteFile file if exists
|
||||||
|
string headerLineStats = $"FieldName,satelliteDate,satelliteBand,max,min,mean,mode,median,stddev,minPlus,curtosis,maxMinus,skewness,variance,populationCount,variationCoefficient,confidenceIntervalLow, confidenceIntervalHigh,confidenceIntervalErrorMargin" + Environment.NewLine;
|
||||||
|
File.AppendAllText(satelliteDataStatisticsFile, headerLineStats);
|
||||||
|
foreach (var satelliteTiff in satelliteTiffs)
|
||||||
|
{
|
||||||
|
List<JToken> layers = satelliteTiff.Data["layers"].Children().ToList();
|
||||||
|
foreach (JToken layer in layers)
|
||||||
|
{
|
||||||
|
DateTime satelliteImageDate = (DateTime)satelliteTiff.DataDate;
|
||||||
|
string satelliteBand = layer["name"].ToString();
|
||||||
|
if (satelliteBands.Contains(satelliteBand))
|
||||||
|
{
|
||||||
|
JToken satelliteStatisticsJtoken = layer["renderer"]["band"]["statistics"];
|
||||||
|
if (satelliteStatisticsJtoken == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"{satelliteImageDate.ToString("yyyy-MM-dd")} no statistics found for satelliteBand '{satelliteBand}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SatelliteStatistics satelliteStatistics = satelliteStatisticsJtoken.ToObject<SatelliteStatistics>();
|
||||||
|
satelliteStatistics.fieldName = fieldName;
|
||||||
|
satelliteStatistics.satelliteDate = satelliteImageDate;
|
||||||
|
satelliteStatistics.satelliteBand = satelliteBand;
|
||||||
|
File.AppendAllText(satelliteDataStatisticsFile, $"" +
|
||||||
|
$"{satelliteStatistics.fieldName}," +
|
||||||
|
$"{satelliteStatistics.satelliteDate.ToString("yyyy-MM-dd")}," +
|
||||||
|
$"{satelliteStatistics.satelliteBand}," +
|
||||||
|
$"{satelliteStatistics.max}," +
|
||||||
|
$"{satelliteStatistics.min}," +
|
||||||
|
$"{satelliteStatistics.mean}," +
|
||||||
|
$"{satelliteStatistics.mode}," +
|
||||||
|
$"{satelliteStatistics.median}," +
|
||||||
|
$"{satelliteStatistics.stddev}," +
|
||||||
|
$"{satelliteStatistics.minPlus}," +
|
||||||
|
$"{satelliteStatistics.curtosis}," +
|
||||||
|
$"{satelliteStatistics.maxMinus}," +
|
||||||
|
$"{satelliteStatistics.skewness}," +
|
||||||
|
$"{satelliteStatistics.variance}," +
|
||||||
|
$"{satelliteStatistics.populationCount}," +
|
||||||
|
$"{satelliteStatistics.variationCoefficient}," +
|
||||||
|
$"{satelliteStatistics.confidenceIntervalLow}," +
|
||||||
|
$"{satelliteStatistics.confidenceIntervalHigh}," +
|
||||||
|
$"{satelliteStatistics.confidenceIntervalErrorMargin}" +
|
||||||
|
Environment.NewLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return satelliteDataStatisticsFile;
|
||||||
|
}
|
||||||
|
public async Task<List<SatelliteStatistics>> ListSatelliteStatistics(Item satelliteTiff, List<string> satelliteBands = null, string fieldName = null)
|
||||||
|
{
|
||||||
|
SatelliteStatistics satelliteStatistics;
|
||||||
|
List<SatelliteStatistics> listSatelliteStatistics = new List<SatelliteStatistics>();
|
||||||
|
List<JToken> layers = satelliteTiff.Data["layers"].Children().ToList();
|
||||||
|
foreach (JToken layer in layers)
|
||||||
|
{
|
||||||
|
DateTime satelliteImageDate = (DateTime)satelliteTiff.DataDate;
|
||||||
|
string satelliteBand = layer["name"].ToString();
|
||||||
|
//_logger.LogInformation($"Date '{satelliteImageDate.ToString("yyyy-MM-dd")}': satelliteBand: {satelliteBand}");
|
||||||
|
if (satelliteBands.Contains(satelliteBand))
|
||||||
|
{
|
||||||
|
JToken satelliteStatisticsJtoken = layer["renderer"]["band"]["statistics"];
|
||||||
|
if (satelliteStatisticsJtoken == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"{satelliteImageDate.ToString("yyyy-MM-dd")} no statistics found for satelliteBand '{satelliteBand}'");
|
||||||
|
//Console.WriteLine($"Available data: {item.Data}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//_logger.LogInformation($"Adding satelliteStatistics to listSatelliteStatistics");
|
||||||
|
satelliteStatistics = satelliteStatisticsJtoken.ToObject<SatelliteStatistics>();
|
||||||
|
satelliteStatistics.fieldName = fieldName;
|
||||||
|
satelliteStatistics.satelliteDate = satelliteImageDate;
|
||||||
|
satelliteStatistics.satelliteBand = satelliteBand;
|
||||||
|
listSatelliteStatistics.Add(satelliteStatistics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// _logger.LogInformation($"this satelliteBand is not in your list satelliteBands");
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
return listSatelliteStatistics;
|
||||||
|
}
|
||||||
|
|
||||||
|
//VanDerSat
|
||||||
|
public async Task<string> RunVanDerSatTask(Item cropfieldItem) {
|
||||||
|
_logger.LogInformation("Gathering VanDerSat information for cropfield, this might take a while!");
|
||||||
|
|
||||||
|
var taskmapRequest = new TaskRequest { TaskType = VANDERSAT_TASK };
|
||||||
|
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskmapRequest);
|
||||||
|
|
||||||
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) => {
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
_logger.LogInformation($"Waiting on VanDerSat data; status: {itemTaskStatus.State}");
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
|
||||||
|
if (itemTask.State == ItemTaskState.Error) {
|
||||||
|
_logger.LogError($"Something went wrong when trying to process VanDerSat data; {itemTask.Message}");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemTask.Code;
|
||||||
|
}
|
||||||
|
public async Task<Item> FindVanDerSatItem(Item cropfieldItem, string VanDerSatTaskCode, string FieldName, bool StoreStatistics) {
|
||||||
|
|
||||||
|
var taskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, VanDerSatTaskCode);
|
||||||
|
|
||||||
|
|
||||||
|
// find VanDerSat data temporal
|
||||||
|
var temporalItem = await FindChildItemAsync(cropfieldItem.Code, TEMPORAL_ITEMTYPE, "Van der Sat");
|
||||||
|
|
||||||
|
|
||||||
|
if (temporalItem == null) {
|
||||||
|
_logger.LogError("Temporal item not found");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var VanDerSatiffs = await _farmmapsApiService.GetItemChildrenAsync(temporalItem.Code);
|
||||||
|
|
||||||
|
_logger.LogInformation("Available VanDerSat images:");
|
||||||
|
var count = 0;
|
||||||
|
TimeSpan.FromSeconds(0.5);
|
||||||
|
foreach (var item in VanDerSatiffs) {
|
||||||
|
|
||||||
|
//Console.WriteLine($"Van der Sat image #{count}: {item.DataDate}");
|
||||||
|
//if (count == 0 ) {
|
||||||
|
// Console.WriteLine($"vandersat image #{count}: {item.Data}");
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (StoreStatistics == true) {
|
||||||
|
var VanDerSatBand = item.Data["layers"][0]["name"];
|
||||||
|
var VanderSatFile = $"C:\\Akkerweb\\{FieldName}_{VanDerSatBand}.csv";
|
||||||
|
var NewLineField = $"Field,Date,Mean,Min,Max,Standard deviation, ConfidenceInterval low, ConfidenceInterval high" + Environment.NewLine;
|
||||||
|
if (count == 0) {
|
||||||
|
File.AppendAllText(VanderSatFile, NewLineField);
|
||||||
|
var numbervandersat = VanDerSatiffs.Count;
|
||||||
|
Console.WriteLine($"{numbervandersat} Van der Sat images found");
|
||||||
|
}
|
||||||
|
|
||||||
|
var VanderSatStatistics = item.Data["layers"][0]["renderer"]["band"]["statistics"];
|
||||||
|
var VanDerSatImageDate = (DateTime)item.DataDate;
|
||||||
|
var VanderSatDate = VanDerSatImageDate.ToString("yyyy-MM-dd");
|
||||||
|
var NewLineDate = $"\"date\":{VanderSatDate}" + Environment.NewLine;
|
||||||
|
if (VanderSatStatistics == null) {
|
||||||
|
Console.WriteLine($"{VanderSatDate} no statistics found");
|
||||||
|
//Console.WriteLine($"Available data: {item.Data}");
|
||||||
|
} else {
|
||||||
|
File.AppendAllText(VanderSatFile, $"{FieldName},{VanderSatDate},{VanderSatStatistics["mean"]},{VanderSatStatistics["min"]},{VanderSatStatistics["max"]},{VanderSatStatistics["stddev"]},{VanderSatStatistics["confidenceIntervalLow"]},{VanderSatStatistics["confidenceIntervalHigh"]}" + Environment.NewLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
//_logger.LogInformation("Enter VanDerSat image number");
|
||||||
|
//int element = Int32.Parse(Console.ReadLine());
|
||||||
|
int element = 0;
|
||||||
|
var selectedVanDerSatItem = VanDerSatiffs[element];
|
||||||
|
|
||||||
|
if (selectedVanDerSatItem == null) {
|
||||||
|
_logger.LogError("VanDerSat item not found");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectedVanDerSatItem;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
public async Task<string> RunWatBalTask(Item cropfieldItem) {
|
||||||
|
|
||||||
|
_logger.LogInformation("Gathering WatBal information for cropfield, this might take a while!");
|
||||||
|
|
||||||
|
var taskmapRequest = new TaskRequest { TaskType = WATBAL_TASK };
|
||||||
|
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskmapRequest);
|
||||||
|
|
||||||
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) => {
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
_logger.LogInformation($"Waiting on VanDerSat data; status: {itemTaskStatus.State}");
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
|
||||||
|
if (itemTask.State == ItemTaskState.Error) {
|
||||||
|
_logger.LogError($"Something went wrong when trying to process WatBal data; {itemTask.Message}");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemTask.Code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<Item> FindWatBalItem(Item cropfieldItem, string WatBalTaskCode, string FieldName, bool StoreStatistics) {
|
||||||
|
|
||||||
|
var taskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, WatBalTaskCode);
|
||||||
|
|
||||||
|
|
||||||
|
// find WatBal data temporal
|
||||||
|
var temporalItem = await FindChildItemAsync(cropfieldItem.Code, TEMPORAL_ITEMTYPE, "Watbal",
|
||||||
|
item => item.SourceTask == WATBAL_TASK && taskStatus.Finished >= item.Created && taskStatus.Finished <= item.Created.Value.AddHours(1));
|
||||||
|
|
||||||
|
if (temporalItem == null) {
|
||||||
|
_logger.LogError("Temporal item not found");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var WatBalData = await _farmmapsApiService.GetItemChildrenAsync(temporalItem.Code);
|
||||||
|
|
||||||
|
_logger.LogInformation("Available WatBal Data:");
|
||||||
|
var count = 0;
|
||||||
|
TimeSpan.FromSeconds(0.5);
|
||||||
|
foreach (var item in WatBalData) {
|
||||||
|
|
||||||
|
Console.WriteLine($"WatBal data #{count}: {item.DataDate}");
|
||||||
|
if (count == 0) {
|
||||||
|
Console.WriteLine($"WatBalData #{count}: {item.Data}");
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int element = 0;
|
||||||
|
var selectedWatBalItem = WatBalData[element];
|
||||||
|
|
||||||
|
if (selectedWatBalItem == null) {
|
||||||
|
_logger.LogError("WatBal item not found");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectedWatBalItem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FarmmapsApi.Models;
|
using FarmmapsApi.Models;
|
||||||
|
using IdentityModel;
|
||||||
using IdentityModel.Client;
|
using IdentityModel.Client;
|
||||||
|
|
||||||
namespace FarmmapsApi.Services
|
namespace FarmmapsApi.Services
|
||||||
@ -40,6 +41,19 @@ namespace FarmmapsApi.Services
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<TokenResponse> GetTokenUsernamePasswordAsync(string tokenEndpointUrl, string grantClientId, string username, string password)
|
||||||
|
{
|
||||||
|
return await _httpClient.RequestPasswordTokenAsync(new PasswordTokenRequest()
|
||||||
|
{
|
||||||
|
Address = tokenEndpointUrl,
|
||||||
|
UserName = username,
|
||||||
|
Password = password,
|
||||||
|
ClientId = grantClientId,
|
||||||
|
GrantType = OidcConstants.GrantTypes.Password,
|
||||||
|
Scope = string.Join(" ", _configuration.Scopes)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<TokenResponse> RefreshTokensAsync(string tokenEndpointUrl, string refreshToken)
|
public async Task<TokenResponse> RefreshTokensAsync(string tokenEndpointUrl, string refreshToken)
|
||||||
{
|
{
|
||||||
return await _httpClient.RequestRefreshTokenAsync(new RefreshTokenRequest()
|
return await _httpClient.RequestRefreshTokenAsync(new RefreshTokenRequest()
|
||||||
|
@ -1,16 +1,35 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FarmmapsNbs", "FarmmapsNbs\FarmmapsNbs.csproj", "{E08EF7E9-F09E-42D8-825C-164E458C78F4}"
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.30320.27
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsNbs", "FarmmapsNbs\FarmmapsNbs.csproj", "{E08EF7E9-F09E-42D8-825C-164E458C78F4}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FarmmapsApi", "FarmmapsApi\FarmmapsApi.csproj", "{1FA9E50B-F45E-4534-953A-37C783D03C74}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsApi", "FarmmapsApi\FarmmapsApi.csproj", "{1FA9E50B-F45E-4534-953A-37C783D03C74}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "General", "General", "{6FA66E07-A59E-480E-B5D1-DBEFC4E4583D}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "General", "General", "{6FA66E07-A59E-480E-B5D1-DBEFC4E4583D}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
README.MD = README.MD
|
.gitignore = .gitignore
|
||||||
.gitignore = .gitignore
|
README.MD = README.MD
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FarmmapsHerbicide", "FarmmapsHerbicide\FarmmapsHerbicide.csproj", "{731A88CD-9DC4-4969-86F2-2315830A6998}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsHerbicide", "FarmmapsHerbicide\FarmmapsHerbicide.csproj", "{731A88CD-9DC4-4969-86F2-2315830A6998}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsHaulmkilling", "FarmmapsHaulmkilling\FarmmapsHaulmkilling.csproj", "{DFA89D0B-5400-4374-B824-8367B76B4B6E}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsPoten", "FarmmapsPoten\FarmmapsPoten.csproj", "{AAFAB03A-6F5C-4D91-991F-867B7898F981}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmMapsBlight", "FarmMapsBlight\FarmMapsBlight.csproj", "{892E0932-5D11-4A37-979E-CEDB39C2E181}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsZonering", "FarmmapsZonering\FarmmapsZonering.csproj", "{91A58C4A-4A80-4079-B43D-9B851206194F}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsDataDownload", "FarmmapsDataDownload\FarmmapsDataDownload.csproj", "{32ED9500-AAAB-4030-9C7A-F611A85DF890}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsBulkSatDownload", "FarmmapsBulkSatDownload\FarmmapsBulkSatDownload.csproj", "{772DBDCD-9FAA-40A7-8551-2C1620C4AB67}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Secrets", "Secrets\Secrets.csproj", "{C4EE5ECA-253A-4B71-9F67-D231AC4517D6}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsCleanUp", "FarmmapsCleanUp\FarmmapsCleanUp.csproj", "{5E4387F9-5953-4A9B-BCA5-DF3964EED3CB}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -30,5 +49,43 @@ Global
|
|||||||
{731A88CD-9DC4-4969-86F2-2315830A6998}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{731A88CD-9DC4-4969-86F2-2315830A6998}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{731A88CD-9DC4-4969-86F2-2315830A6998}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{731A88CD-9DC4-4969-86F2-2315830A6998}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{731A88CD-9DC4-4969-86F2-2315830A6998}.Release|Any CPU.Build.0 = Release|Any CPU
|
{731A88CD-9DC4-4969-86F2-2315830A6998}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DFA89D0B-5400-4374-B824-8367B76B4B6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DFA89D0B-5400-4374-B824-8367B76B4B6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DFA89D0B-5400-4374-B824-8367B76B4B6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DFA89D0B-5400-4374-B824-8367B76B4B6E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AAFAB03A-6F5C-4D91-991F-867B7898F981}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AAFAB03A-6F5C-4D91-991F-867B7898F981}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AAFAB03A-6F5C-4D91-991F-867B7898F981}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AAFAB03A-6F5C-4D91-991F-867B7898F981}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{892E0932-5D11-4A37-979E-CEDB39C2E181}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{892E0932-5D11-4A37-979E-CEDB39C2E181}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{892E0932-5D11-4A37-979E-CEDB39C2E181}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{892E0932-5D11-4A37-979E-CEDB39C2E181}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{91A58C4A-4A80-4079-B43D-9B851206194F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{91A58C4A-4A80-4079-B43D-9B851206194F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{91A58C4A-4A80-4079-B43D-9B851206194F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{91A58C4A-4A80-4079-B43D-9B851206194F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{32ED9500-AAAB-4030-9C7A-F611A85DF890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{32ED9500-AAAB-4030-9C7A-F611A85DF890}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{32ED9500-AAAB-4030-9C7A-F611A85DF890}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{32ED9500-AAAB-4030-9C7A-F611A85DF890}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{772DBDCD-9FAA-40A7-8551-2C1620C4AB67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{772DBDCD-9FAA-40A7-8551-2C1620C4AB67}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{772DBDCD-9FAA-40A7-8551-2C1620C4AB67}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{772DBDCD-9FAA-40A7-8551-2C1620C4AB67}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C4EE5ECA-253A-4B71-9F67-D231AC4517D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C4EE5ECA-253A-4B71-9F67-D231AC4517D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C4EE5ECA-253A-4B71-9F67-D231AC4517D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C4EE5ECA-253A-4B71-9F67-D231AC4517D6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5E4387F9-5953-4A9B-BCA5-DF3964EED3CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5E4387F9-5953-4A9B-BCA5-DF3964EED3CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5E4387F9-5953-4A9B-BCA5-DF3964EED3CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5E4387F9-5953-4A9B-BCA5-DF3964EED3CB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {88AA58C4-40E6-4FC6-B501-6557C7E9DA81}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
602
FarmmapsBulkSatDownload/BulkSatDownloadApplication.cs
Normal file
602
FarmmapsBulkSatDownload/BulkSatDownloadApplication.cs
Normal file
@ -0,0 +1,602 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using FarmmapsBulkSatDownload.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Npgsql;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FarmmapsBulkSatDownload
|
||||||
|
{
|
||||||
|
public class BulkSatDownloadApplication : IApplication
|
||||||
|
{
|
||||||
|
private readonly ILogger<BulkSatDownloadApplication> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly BulkSatDownloadService _bulkSatDownloadService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
public const string settingsfile = "Settings.json";
|
||||||
|
public const int firstAvailableYear = 2017;
|
||||||
|
private Settings _settings;
|
||||||
|
|
||||||
|
public BulkSatDownloadApplication(ILogger<BulkSatDownloadApplication> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService, BulkSatDownloadService bulkSatDownloadService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
_bulkSatDownloadService = bulkSatDownloadService;
|
||||||
|
}
|
||||||
|
public async Task RunAsync()
|
||||||
|
{
|
||||||
|
// Check if we have permission
|
||||||
|
// !! 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();
|
||||||
|
|
||||||
|
BulkSatDownloadInput bulkSatDownloadInput;
|
||||||
|
List<BulkSatDownloadInput> bulkSatDownloadInputList;
|
||||||
|
// Below are two options to for bulk download: (1) from and to database or (2) inputs from json, output to csv
|
||||||
|
// For illustration we make two lists bulkSatDownloadInputListDB and bulkSatDownloadInputListCsv and then choose which one we will use
|
||||||
|
List<BulkSatDownloadInput> bulkSatDownloadInputListDB;
|
||||||
|
List<BulkSatDownloadInput> bulkSatDownloadInputListCsv;
|
||||||
|
DateTime lastdownloadedimagedate;
|
||||||
|
int cropYear;
|
||||||
|
|
||||||
|
//Use doDB to decide if reading from/writing to database (doDB = true) or
|
||||||
|
//read from file BulkSatDownloadInput.json and write satellite statistics to file(s) specified in BulkSatDownloadInput.json
|
||||||
|
//note in case of doDB == true you will need to provide a file "DBsettings.secrets.json" with login details for the database
|
||||||
|
//see empty example "DBsettings.json"
|
||||||
|
bool doDB = false;
|
||||||
|
if (doDB == true)
|
||||||
|
{
|
||||||
|
// Option 1: When using database need to (1) fill in database data in DBsettings.secrets.json; (2) write tailor made SELECT query for fieldinputs in following lines;
|
||||||
|
// (3) Write tailor made INSERT INTO query in Task Process() below;
|
||||||
|
// Initialize databases. Username, password etc stored in file "DBsettings.secrets.json".
|
||||||
|
// Crashes if "DBsettings.secrets.json" is absent or empty
|
||||||
|
DB dbparcels = JsonConvert.DeserializeObject<DB>(File.ReadAllText("DBsettings.secrets.json"));
|
||||||
|
string schemaname = "bigdata";
|
||||||
|
string parceltablename = "parcel_bollenrevolutie_tulips2020"; //"parcelsijbrandij" "parcel"; "parcel_flowerbulbs"; "parcel_disac"; ""parcel_bollenrevolutie_tulips2020""
|
||||||
|
string groenmonitortablename = "groenmonitor_bollenrevolutie_tulips2020"; //"groenmonitorsijbrandij" "groenmonitor" "groenmonitor_flowerbulbs" "groenmonitor_disac" "groenmonitor_bollenrevolutie_tulips2020"
|
||||||
|
// The view 'groenmonitorlatestviewname' contains per parcelid (arbid) the year in which it "exists" and the date of the latest image downloaded. It is used to prevent unneccessary downloading of image statistics already in the database
|
||||||
|
string groenmonitorlatestviewname = "groenmonitorlatest_bollenrevolutie_tulips2020"; //"groenmonitorsijbrandijlatest" "groenmonitorlatest" "groenmonitorlatest_flowerbulbs" "groenmonitorlatest_disac" "groenmonitorlatest_bollenrevolutie_tulips2020"
|
||||||
|
|
||||||
|
// Database query and connection. Geometry must be in WGS84 coordinate system, EPSG 4326
|
||||||
|
// Apparently the FarmmapsApi cannot handle MultiPolygon, so we need to convert to single Polygon
|
||||||
|
// In case database returns a MultiPolygon use ST_NumGeometries(pt.geom) to count the number of polygons
|
||||||
|
// If necessary use WHERE ST_NumGeometries(pt.geom) = 1 to select only single polygons
|
||||||
|
//
|
||||||
|
// FarmMaps get's its satellite images from www.groenmonitor.nl through the https://agrodatacube.wur.nl/.
|
||||||
|
// Many images are available at www.groenmonitor.nl, the https://agrodatacube.wur.nl/ serves only the clean images, 10-30 per year, 2019 onwards. Possibly more images will be added for earlier years
|
||||||
|
// For other images contact www.groenmonitor.nl, gerbert.roerink@wur.nl
|
||||||
|
bulkSatDownloadInputListDB = new List<BulkSatDownloadInput>();
|
||||||
|
List<string> satelliteBands = new List<string> { "wdvi", "ndvi" };
|
||||||
|
string connectionString = dbparcels.GetConnectionString();
|
||||||
|
string readSql = string.Format(
|
||||||
|
@"
|
||||||
|
SELECT pt.arbid, pt.year, gml.lastwenrdate, ST_AsGeoJSON(ST_Transform((ST_DUMP(pt.geom)).geom::geometry(Polygon),4326)) AS geojson_polygon_wgs84,
|
||||||
|
COALESCE(pt.cropfielditemcode,'') AS cropfielditemcode,
|
||||||
|
CASE WHEN pt.year >= DATE_PART('year', CURRENT_DATE) THEN '' ELSE COALESCE(pt.satellitetaskcode,'') END AS satellitetaskcode
|
||||||
|
FROM {0}.{1} pt, {0}.{2} gml
|
||||||
|
WHERE
|
||||||
|
pt.arbid = gml.arbid
|
||||||
|
AND pt.satellitetaskcode IS NULL
|
||||||
|
ORDER BY pt.arbid
|
||||||
|
LIMIT 5;", schemaname, parceltablename, groenmonitorlatestviewname); //LIMIT x for testing
|
||||||
|
|
||||||
|
using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
|
||||||
|
// Read data (run query) = build a list of fields for which to download images
|
||||||
|
NpgsqlCommand command = connection.CreateCommand();
|
||||||
|
command.CommandText = readSql;
|
||||||
|
NpgsqlDataReader dr = command.ExecuteReader();
|
||||||
|
while (dr.Read())
|
||||||
|
{
|
||||||
|
bulkSatDownloadInput = new BulkSatDownloadInput();
|
||||||
|
bulkSatDownloadInput.fieldID = dr.GetInt16(0);
|
||||||
|
bulkSatDownloadInput.fieldName = string.Format($"{parceltablename}_{bulkSatDownloadInput.fieldID}");
|
||||||
|
bulkSatDownloadInput.cropYear = dr.GetInt16(1); ;
|
||||||
|
bulkSatDownloadInput.lastdownloadedimagedate = dr.GetDateTime(2);
|
||||||
|
bulkSatDownloadInput.GeometryJson = JObject.Parse(dr.GetString(3));
|
||||||
|
bulkSatDownloadInput.SatelliteBands = satelliteBands;
|
||||||
|
bulkSatDownloadInput.cropfielditemcode = dr.GetString(4);
|
||||||
|
bulkSatDownloadInput.satellitetaskcode = dr.GetString(5);
|
||||||
|
bulkSatDownloadInput.database = dbparcels;
|
||||||
|
bulkSatDownloadInput.schemaname = schemaname;
|
||||||
|
bulkSatDownloadInput.cropfieldtable = parceltablename;
|
||||||
|
bulkSatDownloadInput.satelllitetable = groenmonitortablename;
|
||||||
|
bulkSatDownloadInputListDB.Add(bulkSatDownloadInput);
|
||||||
|
}
|
||||||
|
connection.Close();
|
||||||
|
}
|
||||||
|
// Now choose which list you want to use
|
||||||
|
bulkSatDownloadInputList = bulkSatDownloadInputListDB;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Option 2: Example without database. Comment out this part if you want to use database
|
||||||
|
// Read cropfields "BulkSatDownloadInput.json" and write all stats to a single csv file
|
||||||
|
// Write all stats for multiple fields will be written to a single csv file
|
||||||
|
string downloadFolder;
|
||||||
|
string fileNameStats;
|
||||||
|
string headerLineStats = $"FieldName,satelliteDate,satelliteBand,max,min,mean,mode,median,stddev,minPlus,curtosis,maxMinus,skewness,variance,populationCount,variationCoefficient,confidenceIntervalLow, confidenceIntervalHigh,confidenceIntervalErrorMargin" + Environment.NewLine;
|
||||||
|
var fieldsInputJson = File.ReadAllText("BulkSatDownloadInput.json");
|
||||||
|
bulkSatDownloadInputListCsv = JsonConvert.DeserializeObject<List<BulkSatDownloadInput>>(fieldsInputJson);
|
||||||
|
for (int i = 0; i < bulkSatDownloadInputListCsv.Count; i++)
|
||||||
|
{
|
||||||
|
downloadFolder = bulkSatDownloadInputListCsv[i].downloadFolder;
|
||||||
|
fileNameStats = Path.Combine(downloadFolder, bulkSatDownloadInputListCsv[i].fileNameStats);
|
||||||
|
if (!Directory.Exists(downloadFolder))
|
||||||
|
Directory.CreateDirectory(downloadFolder);
|
||||||
|
bulkSatDownloadInputListCsv[i].fileNameStats = fileNameStats;
|
||||||
|
// Header same as in GeneralService.DownloadSatelliteStats
|
||||||
|
// Delete fileNameStats if existing. Create a new file. Add a header to csv file
|
||||||
|
File.Delete(fileNameStats);
|
||||||
|
File.AppendAllText(fileNameStats, headerLineStats);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now choose which list you want to use
|
||||||
|
bulkSatDownloadInputList = bulkSatDownloadInputListCsv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each input download all images. Keep track to time, important when doing bulk downloads
|
||||||
|
var watch = System.Diagnostics.Stopwatch.StartNew();
|
||||||
|
TimeSpan tsSofar = new TimeSpan();
|
||||||
|
TimeSpan tsRemaining;
|
||||||
|
TimeSpan tsTotalEstimated;
|
||||||
|
|
||||||
|
for (int i = 0; i < bulkSatDownloadInputList.Count; i++)
|
||||||
|
{
|
||||||
|
watch.Restart();
|
||||||
|
bulkSatDownloadInput = bulkSatDownloadInputList[i];
|
||||||
|
if (string.IsNullOrEmpty(bulkSatDownloadInput.fileNameStats) == false) _logger.LogInformation(string.Format($"// FarmmapsBulkSatDownload: Downloading stats for field {i+1} out of {bulkSatDownloadInputList.Count} to single csv file {bulkSatDownloadInput.fileNameStats}"));
|
||||||
|
if (bulkSatDownloadInput.database != null) _logger.LogInformation(string.Format($"// FarmmapsBulkSatDownload: Downloading stats for field {i+1} out of {bulkSatDownloadInputList.Count} to database {bulkSatDownloadInput.schemaname}.{bulkSatDownloadInput.satelllitetable}"));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Process(roots, bulkSatDownloadInput);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex.Message);
|
||||||
|
}
|
||||||
|
watch.Stop();
|
||||||
|
// add this downloadtime to the cropfieldtable.
|
||||||
|
// Only if cropfieldtable has a field called 'downloadtime' type 'time'!
|
||||||
|
//using (NpgsqlConnection connection = new NpgsqlConnection(dbparcels.GetConnectionString()))
|
||||||
|
//{
|
||||||
|
// connection.Open();
|
||||||
|
// NpgsqlCommand updateCmd = connection.CreateCommand();
|
||||||
|
// string updateSql = string.Format($"UPDATE {schemaname}.{parceltablename} SET downloadtime = '{strTime(watch.Elapsed)}' WHERE arbid = {bulkSatDownloadInput.fieldID};");
|
||||||
|
// updateCmd.CommandText = updateSql;
|
||||||
|
// int r = updateCmd.ExecuteNonQuery();
|
||||||
|
// if (r != 1)
|
||||||
|
// throw new Exception("// FarmmapsBulkSatDownload: Update downloadtime Failed");
|
||||||
|
// connection.Close();
|
||||||
|
//}
|
||||||
|
//_logger.LogInformation($"// FarmmapsBulkSatDownload: Added downloadtime = '{strTime(watch.Elapsed)}' to {schemaname}.{parceltablename} ");
|
||||||
|
tsSofar = tsSofar + watch.Elapsed;
|
||||||
|
tsTotalEstimated = tsSofar / (i + 1) * bulkSatDownloadInputList.Count;
|
||||||
|
tsRemaining = tsTotalEstimated - tsSofar;
|
||||||
|
_logger.LogInformation(string.Format($"// Time (hh:mm:ss): this field: {strTime(watch.Elapsed)}. Sofar: {strTime(tsSofar)}. Total: {strTime(tsTotalEstimated)}. Remaining: {strTime(tsRemaining)}"));
|
||||||
|
}
|
||||||
|
string strExeFilePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
||||||
|
string strWorkPath = Path.GetDirectoryName(strExeFilePath);
|
||||||
|
_logger.LogInformation(string.Format($"// FarmmapsBulkSatDownload:"));
|
||||||
|
_logger.LogInformation(string.Format($"// FarmmapsBulkSatDownload: Done! List of all downloaded cropfieldItems stored in {Path.Combine(strWorkPath,settingsfile)}"));
|
||||||
|
_logger.LogInformation(string.Format($"// FarmmapsBulkSatDownload: If you plan to rerun certain fields then adding cropfielditemcode to your input can greatly speed up your application!"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Process(List<UserRoot> roots, BulkSatDownloadInput input)
|
||||||
|
{
|
||||||
|
//PO20220311: first time a call is made to download satellite images or statistics, an empty list is returned
|
||||||
|
//If we wait a bit longer, e.g. 10 secs, then e.g. a list of 3 images may be returned
|
||||||
|
//If we wait still longer, maybe 4 images.
|
||||||
|
//The solution implemented below is to fire calls as long as the number of images returned keeps increasing
|
||||||
|
//While in between each call, sleep for sleepSecs
|
||||||
|
//Continue this until the number no longer increases or the maximum number of calls has been reached
|
||||||
|
//If you set sleepSecs to a very low value, e.g. 5 secs, then after 1 call you might get images and after 2nd call still zero images.
|
||||||
|
//to be on the safe side, better bit higher value.
|
||||||
|
//Just accept this may take a while, have a coffee, we suggest sleepSecs = 30;
|
||||||
|
int sleepSecs = 30;
|
||||||
|
int callCntMax = 4 * 60 / sleepSecs; //4*60 = max 4 minutes
|
||||||
|
//For example we may set: "sleepSecs = 10;" and "callCntMax = 24;" and following result:
|
||||||
|
//Call no: 1. Giving FarmMaps 10 seconds to get SatelliteItems...
|
||||||
|
//Call no: 1: Received 2 images
|
||||||
|
//Call no: 2. Giving FarmMaps 10 seconds to get SatelliteItems...
|
||||||
|
//Call no: 2: Received 7 images
|
||||||
|
//Call no: 3. Giving FarmMaps 10 seconds to get SatelliteItems...
|
||||||
|
//Call no: 3: Received 7 images
|
||||||
|
//And the firing of calls would stop because the number of images returned is no longer increasing
|
||||||
|
//In the worst case, this could would lead to a total sleeping period of "sleepSecsSum = sleepSecs * callCntMax" seconds. After that we give up
|
||||||
|
|
||||||
|
//PO20230801: I also tried creating a cropfieldItem with startDate '2017-01-01' and endDate '2023-08-01'
|
||||||
|
//so that only one RunSatelliteTask would need to be executed and statistics would be returned for the e.g. 233 images in this period from start to end date
|
||||||
|
//instead of running 7 tasks (one per year) for a single field
|
||||||
|
//But code doing that returned much less images than those 233 records which I should be getting.
|
||||||
|
//So in the end, stick to downloading stats per year, even if it is for the same location in multiple years
|
||||||
|
|
||||||
|
string cropfielditemcode;
|
||||||
|
string satellitetaskcode;
|
||||||
|
Item cropfieldItem;
|
||||||
|
bool satelliteItemsAvailable;
|
||||||
|
bool statsAvailable;
|
||||||
|
DateTime dtSatelliteDate;
|
||||||
|
string strSatelliteDate;
|
||||||
|
List<Item> satelliteItemsCropYear;
|
||||||
|
StringBuilder sbInsertSql;
|
||||||
|
StringBuilder sbInsertSqlInto;
|
||||||
|
StringBuilder sbInsertSqlUpdate;
|
||||||
|
StringBuilder sbInsertSqlValues;
|
||||||
|
List<SatelliteStatistics> listSatelliteStatistics;
|
||||||
|
SatelliteStatistics satelliteStatistics_wdvi;
|
||||||
|
SatelliteStatistics satelliteStatistics_ndvi;
|
||||||
|
int cntDatesDownloaded;
|
||||||
|
|
||||||
|
string satelliteSource = "akkerwebwenr"; //same as in groenmonitorlatestviewname SQL code
|
||||||
|
int fieldID = input.fieldID;
|
||||||
|
string fieldName = input.fieldName;
|
||||||
|
int cropYear = input.cropYear;
|
||||||
|
List<string> satelliteBands = input.SatelliteBands;
|
||||||
|
string downloadFolder = input.downloadFolder;
|
||||||
|
string fileNameStats = input.fileNameStats;
|
||||||
|
DB database = input.database;
|
||||||
|
string schemaname = input.schemaname;
|
||||||
|
string cropfieldtable = input.cropfieldtable;
|
||||||
|
string satelllitetable = input.satelllitetable;
|
||||||
|
DateTime lastDownloadedSatelliteDate = input.lastdownloadedimagedate;
|
||||||
|
cropfielditemcode = input.cropfielditemcode;
|
||||||
|
satellitetaskcode = input.satellitetaskcode;
|
||||||
|
int satelliteItemsCropYearCntPrev;
|
||||||
|
int satelliteItemsCropYearCnt;
|
||||||
|
int callCnt;
|
||||||
|
int sleepSecsSum;
|
||||||
|
|
||||||
|
LoadSettings(settingsfile);
|
||||||
|
|
||||||
|
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
|
||||||
|
if (uploadedRoot == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find a needed root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var myDriveRoot = roots.SingleOrDefault(r => r.Name == "USER_FILES");
|
||||||
|
if (myDriveRoot == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find a needed root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(cropfielditemcode))
|
||||||
|
{
|
||||||
|
_logger.LogInformation(string.Format($"Creating cropfield '{fieldName}' in the year {cropYear}"));
|
||||||
|
cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDriveRoot.Code,
|
||||||
|
$"DataCropfield {fieldName}", cropYear, input.GeometryJson.ToString(Formatting.None));
|
||||||
|
cropfielditemcode = cropfieldItem.Code;
|
||||||
|
// If working with a database, add this cropfieldItem.Code to the database so that next case same cropField is requested, will be faster
|
||||||
|
if (database != null)
|
||||||
|
{
|
||||||
|
// add this cropfielditemcode to the cropfieldtable
|
||||||
|
using (NpgsqlConnection connection = new NpgsqlConnection(database.GetConnectionString()))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
NpgsqlCommand updateCmd = connection.CreateCommand();
|
||||||
|
string updateSql = string.Format($"UPDATE {schemaname}.{cropfieldtable} SET cropfielditemcode = '{cropfieldItem.Code}' WHERE arbid = {fieldID};");
|
||||||
|
updateCmd.CommandText = updateSql;
|
||||||
|
//Console.WriteLine(insertCmd.CommandText);
|
||||||
|
int r = updateCmd.ExecuteNonQuery();
|
||||||
|
if (r != 1)
|
||||||
|
throw new Exception("// FarmmapsBulkSatDownload: Update cropfielditemcode Failed");
|
||||||
|
connection.Close();
|
||||||
|
}
|
||||||
|
_logger.LogInformation($"// FarmmapsBulkSatDownload: Added cropfieldItem.Code '{cropfieldItem.Code}' for parcelid {fieldID} to {schemaname}.{cropfieldtable} ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// WOULD IT BE POSSIBLE TO GET AVAILABLE Item MEMBER VALUES FOR A GIVEN cropfielditemcode?
|
||||||
|
cropfieldItem = new Item();
|
||||||
|
cropfieldItem.Code = cropfielditemcode;
|
||||||
|
cropfieldItem.Name = "DataCropfield " + fieldName;
|
||||||
|
_logger.LogInformation($"// FarmmapsBulkSatDownload: CropfieldItem.Code for parcelid {fieldID} already there in {schemaname}.{cropfieldtable}: '{cropfieldItem.Code}'");
|
||||||
|
}
|
||||||
|
_settings.cropFieldItems.Add(cropfieldItem);
|
||||||
|
SaveSettings(settingsfile);
|
||||||
|
|
||||||
|
//Create satelliteTaskCode & save satelliteTaskCode.Code to settingsfile for retracing last call (can be useful if failed)
|
||||||
|
//_logger.LogInformation(string.Format($"Running RunSatelliteTask for cropfieldItem '{cropfielditemcode}' and saving settings to {settingsfile}"));
|
||||||
|
//var satelliteTaskCode = await _generalService.RunSatelliteTask(cropfieldItem);
|
||||||
|
if (string.IsNullOrEmpty(satellitetaskcode))
|
||||||
|
{
|
||||||
|
_logger.LogInformation(string.Format($"Running RunSatelliteTask for cropfieldItem '{cropfielditemcode}'"));
|
||||||
|
satellitetaskcode = await _generalService.RunSatelliteTask(cropfieldItem);
|
||||||
|
// If working with a database, add this cropfieldItem.Code to the database so that next case same cropField is requested, will be faster
|
||||||
|
if (database != null)
|
||||||
|
{
|
||||||
|
// add this satellitetaskcode to the cropfieldtable
|
||||||
|
using (NpgsqlConnection connection = new NpgsqlConnection(database.GetConnectionString()))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
NpgsqlCommand updateCmd = connection.CreateCommand();
|
||||||
|
string updateSql = string.Format($"UPDATE {schemaname}.{cropfieldtable} SET satellitetaskcode = '{satellitetaskcode}' WHERE arbid = {fieldID};");
|
||||||
|
updateCmd.CommandText = updateSql;
|
||||||
|
//Console.WriteLine(insertCmd.CommandText);
|
||||||
|
int r = updateCmd.ExecuteNonQuery();
|
||||||
|
if (r != 1)
|
||||||
|
throw new Exception("// FarmmapsBulkSatDownload: Update satellitetaskcode Failed");
|
||||||
|
connection.Close();
|
||||||
|
}
|
||||||
|
_logger.LogInformation($"// FarmmapsBulkSatDownload: Added satellitetaskcode '{satellitetaskcode}' for cropfieldItem.Code '{cropfieldItem.Code}' to {schemaname}.{cropfieldtable} ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"// FarmmapsBulkSatDownload: satellitetaskcode for parcelid {fieldID} already there in {schemaname}.{cropfieldtable}: '{satellitetaskcode}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO also log satellitetaskcode to settings, how?
|
||||||
|
// SaveSettings(settingsfile);
|
||||||
|
|
||||||
|
// Getting satellite items. Only for years for which available
|
||||||
|
satelliteItemsCropYearCntPrev = 0;
|
||||||
|
satelliteItemsCropYearCnt = 0;
|
||||||
|
sleepSecsSum = 0;
|
||||||
|
satelliteItemsCropYear = null;
|
||||||
|
if (cropYear >= firstAvailableYear && cropYear <= DateTime.Now.Year)
|
||||||
|
{
|
||||||
|
_logger.LogInformation(string.Format($"Running FindSatelliteItems for cropfieldItem.Code '{cropfieldItem.Code}', SatelliteTaskCode '{satellitetaskcode}'"));
|
||||||
|
//Call first time
|
||||||
|
callCnt = 1;
|
||||||
|
//if callCntMax == 0 then don't sleep
|
||||||
|
//if callCntMax = 1 then sleep first 1x
|
||||||
|
if (callCntMax > 0)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Call no: {callCnt}. Giving FarmMaps {sleepSecs} seconds to get SatelliteItems...");
|
||||||
|
System.Threading.Thread.Sleep(1000 * sleepSecs);
|
||||||
|
sleepSecsSum = sleepSecsSum + sleepSecs;
|
||||||
|
}
|
||||||
|
satelliteItemsCropYear = await _generalService.FindSatelliteItems(cropfieldItem, satellitetaskcode);
|
||||||
|
satelliteItemsCropYearCntPrev = satelliteItemsCropYear.Count;
|
||||||
|
_logger.LogInformation($"Call no: {callCnt}. Received {satelliteItemsCropYearCntPrev} images");
|
||||||
|
callCnt++;
|
||||||
|
satelliteItemsCropYearCnt = satelliteItemsCropYearCntPrev;
|
||||||
|
//if callCntMax > 1 then sleep untill (1) no more increase in number of images received OR (2) maximum number of calls reached
|
||||||
|
if (callCntMax > 1)
|
||||||
|
{
|
||||||
|
//Call second time
|
||||||
|
_logger.LogInformation($"Call no: {callCnt}. Giving FarmMaps another {sleepSecs} seconds to get SatelliteItems...");
|
||||||
|
System.Threading.Thread.Sleep(1000 * sleepSecs);
|
||||||
|
satelliteItemsCropYear = await _generalService.FindSatelliteItems(cropfieldItem, satellitetaskcode);
|
||||||
|
satelliteItemsCropYearCnt = satelliteItemsCropYear.Count;
|
||||||
|
_logger.LogInformation($"Call no: {callCnt}. Received {satelliteItemsCropYearCnt} images");
|
||||||
|
sleepSecsSum = sleepSecsSum + sleepSecs;
|
||||||
|
//As long as there is progress, keep calling
|
||||||
|
callCnt++;
|
||||||
|
while (callCnt <= callCntMax && (satelliteItemsCropYearCnt == 0 || satelliteItemsCropYearCnt > satelliteItemsCropYearCntPrev))
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Surprise! The longer we wait, the more images we get. Sleep and call once more");
|
||||||
|
satelliteItemsCropYearCntPrev = satelliteItemsCropYearCnt;
|
||||||
|
_logger.LogInformation($"Call no: {callCnt} (max: {callCntMax}). Giving FarmMaps another {sleepSecs} seconds to get SatelliteItems...");
|
||||||
|
System.Threading.Thread.Sleep(1000 * sleepSecs);
|
||||||
|
satelliteItemsCropYear = await _generalService.FindSatelliteItems(cropfieldItem, satellitetaskcode);
|
||||||
|
satelliteItemsCropYearCnt = satelliteItemsCropYear.Count;
|
||||||
|
_logger.LogInformation($"Call no: {callCnt}. Received {satelliteItemsCropYearCnt} images");
|
||||||
|
callCnt++;
|
||||||
|
sleepSecsSum = sleepSecsSum + sleepSecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"// FarmmapsBulkSatDownload: crop year {cropYear} is out of bounds. No stats will be written!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (satelliteItemsCropYearCnt == 0)
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"// FarmmapsBulkSatDownload: after calling one or more times and " +
|
||||||
|
$"sleeping in total {sleepSecsSum} seconds, still no images found. " +
|
||||||
|
$"Please check your settings for parameters callCntMax and sleepSecs in FarmmapsBulkSatDownload.cs or contact FarmMaps");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checking if satellite items found
|
||||||
|
satelliteItemsAvailable = true;
|
||||||
|
if (satelliteItemsCropYear == null)
|
||||||
|
{
|
||||||
|
satelliteItemsAvailable = false;
|
||||||
|
_logger.LogInformation($"// FarmmapsBulkSatDownload: No satellite tiffs found for fieldName '{fieldName}', cropYear {cropYear}, cropfielditemcode '{cropfielditemcode}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (satelliteItemsCropYear.Count == 0)
|
||||||
|
{
|
||||||
|
satelliteItemsAvailable = false;
|
||||||
|
_logger.LogInformation($"// FarmmapsBulkSatDownload: No satellite tiffs found for fieldName '{fieldName}', cropYear {cropYear}, cropfielditemcode '{cropfielditemcode}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the list by date
|
||||||
|
if (satelliteItemsAvailable) satelliteItemsCropYear = satelliteItemsCropYear.OrderBy(x => x.DataDate).ToList();
|
||||||
|
|
||||||
|
// Download statistics to a single csv file
|
||||||
|
if (satelliteItemsAvailable && downloadFolder != null && fileNameStats != null)
|
||||||
|
{
|
||||||
|
// Write statistics for all images for all fieldName and cropYear to a single csv file, fileNameStats
|
||||||
|
_logger.LogInformation($"Downloading stats for field '{fieldName}' in cropyear {cropYear} to {fileNameStats}");
|
||||||
|
string downloadedStats = await _generalService.DownloadSatelliteStats(satelliteItemsCropYear, fieldName, satelliteBands, downloadFolder);
|
||||||
|
// Add contents of this csv file to the single large csv file
|
||||||
|
var retainedLines = File.ReadAllLines(downloadedStats).Skip(1);
|
||||||
|
File.AppendAllLines(fileNameStats, retainedLines);
|
||||||
|
File.Delete(downloadedStats);
|
||||||
|
// Optionally, also download the zipped tiffs. This can be a lot of files and increase runtime
|
||||||
|
if (false)
|
||||||
|
{
|
||||||
|
foreach (Item selectedSatelliteItem in satelliteItemsCropYear)
|
||||||
|
{
|
||||||
|
// download the geotiffs. Returns a zip file with always these three files:
|
||||||
|
// data.dat.aux.xml
|
||||||
|
// thumbnail.jpg
|
||||||
|
// wenr.tif. Contains 5 layers: (1) ndvi, (2) wdvi, (3) Red, (4) Green and (5) Blue
|
||||||
|
var SatelliteDate = selectedSatelliteItem.DataDate.Value.ToString("yyyyMMdd");
|
||||||
|
_logger.LogInformation($"Downloading geotiff file for field {fieldName}, date {SatelliteDate}");
|
||||||
|
string fileName = string.Format($"satelliteGeotiff_{fieldName}_{SatelliteDate}"); // no need to add satelliteBand in the name because the tif contains all bands
|
||||||
|
string fileNameZip = string.Format($"{fileName}.zip");
|
||||||
|
string fileNameGeotiff = string.Format($"{fileName}.tif");
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(selectedSatelliteItem.Code, Path.Combine(downloadFolder, fileNameZip));
|
||||||
|
if (false)
|
||||||
|
{
|
||||||
|
// Extract the file "wenr.tif" from zip, rename it to fileNameGeotiff
|
||||||
|
ZipFile.ExtractToDirectory(Path.Combine(downloadFolder, fileNameZip), downloadFolder, true);
|
||||||
|
File.Delete(Path.Combine(downloadFolder, fileNameGeotiff)); // Delete the fileNameGeotiff file if exists
|
||||||
|
File.Move(Path.Combine(downloadFolder, "wenr.tif"), Path.Combine(downloadFolder, fileNameGeotiff)); // Rename the oldFileName into newFileName
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
string[] filesToDelete = new string[] { fileNameZip, "wenr.tif", "thumbnail.jpg", "data.dat.aux.xml" };
|
||||||
|
foreach (string f in filesToDelete)
|
||||||
|
{
|
||||||
|
File.Delete(Path.Combine(downloadFolder, f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Download statistics to database
|
||||||
|
if (satelliteItemsAvailable && database != null)
|
||||||
|
{
|
||||||
|
// Tailormade code for writing to database
|
||||||
|
// No unnecessary intermediate step here of writing to csv and getting stats for all images in the crop year.
|
||||||
|
// Efficient is to check if there is any image for which stats are to be added to database and add only add these new stats for not yet archived dates directly to database
|
||||||
|
// A full check of downloaded dates versus available dates in the database is not made here.
|
||||||
|
// We assume only new images will be added (i.e. for later dates), assuming no historical images are added in groenmonitor (check!).
|
||||||
|
// And we assume farmMaps always nicely generates statistics, no hick-ups
|
||||||
|
// Under this assumptions, we only need to compare with the lastDownloadedSatelliteDate from the database
|
||||||
|
cntDatesDownloaded = 0;
|
||||||
|
using (NpgsqlConnection connection = new NpgsqlConnection(database.GetConnectionString()))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
foreach (Item satelliteItem in satelliteItemsCropYear)
|
||||||
|
{
|
||||||
|
dtSatelliteDate = satelliteItem.DataDate.Value;
|
||||||
|
strSatelliteDate = dtSatelliteDate.ToString("yyyy-MM-dd");
|
||||||
|
listSatelliteStatistics = await _generalService.ListSatelliteStatistics(satelliteItem, satelliteBands, fieldName);
|
||||||
|
statsAvailable = true;
|
||||||
|
if (listSatelliteStatistics == null)
|
||||||
|
{
|
||||||
|
statsAvailable = false;
|
||||||
|
_logger.LogWarning($"No stats found for satellite, fieldName '{fieldName}', date '{strSatelliteDate}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (listSatelliteStatistics.Count == 0)
|
||||||
|
{
|
||||||
|
statsAvailable = false;
|
||||||
|
_logger.LogWarning($"No stats found for satellite, fieldName '{fieldName}', date '{strSatelliteDate}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (statsAvailable)
|
||||||
|
{
|
||||||
|
if (dtSatelliteDate <= input.lastdownloadedimagedate)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"// Stats for parcelid {fieldID}, date '{strSatelliteDate}' already there in {schemaname}.{satelllitetable}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cntDatesDownloaded++;
|
||||||
|
// Map satelliteStatistics to groenmonitorTable
|
||||||
|
satelliteStatistics_wdvi = listSatelliteStatistics.SingleOrDefault(p => p.satelliteBand == "wdvi");
|
||||||
|
satelliteStatistics_ndvi = listSatelliteStatistics.SingleOrDefault(p => p.satelliteBand == "ndvi");
|
||||||
|
sbInsertSql = new StringBuilder();
|
||||||
|
sbInsertSqlInto = new StringBuilder();
|
||||||
|
sbInsertSqlUpdate = new StringBuilder();
|
||||||
|
sbInsertSqlValues = new StringBuilder();
|
||||||
|
sbInsertSqlInto.Append($"INSERT INTO {schemaname}.{satelllitetable} (parcelid,date,source");
|
||||||
|
sbInsertSqlValues.Append($"VALUES ({fieldID},'{strSatelliteDate}','{satelliteSource}'");
|
||||||
|
sbInsertSqlUpdate.Append($"ON CONFLICT (parcelid,date,source) DO UPDATE SET parcelid={fieldID}, date='{strSatelliteDate}',source='{satelliteSource}'");
|
||||||
|
if (satelliteBands.Contains("wdvi"))
|
||||||
|
{
|
||||||
|
if (satelliteStatistics_wdvi != null)
|
||||||
|
{
|
||||||
|
sbInsertSqlInto.Append(",wdvi_pixelcount,wdvi_max,wdvi_mean,wdvi_min,wdvi_stdev,wdvi_median");
|
||||||
|
sbInsertSqlValues.Append($",{satelliteStatistics_wdvi.populationCount},{satelliteStatistics_wdvi.max},{satelliteStatistics_wdvi.mean},{satelliteStatistics_wdvi.min},{satelliteStatistics_wdvi.stddev},{satelliteStatistics_wdvi.median}");
|
||||||
|
sbInsertSqlUpdate.Append($",wdvi_pixelcount={satelliteStatistics_wdvi.populationCount},wdvi_max={satelliteStatistics_wdvi.max},wdvi_mean={satelliteStatistics_wdvi.mean},wdvi_min={satelliteStatistics_wdvi.min},wdvi_stdev={satelliteStatistics_wdvi.stddev},wdvi_median={satelliteStatistics_wdvi.median}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"wdvi missing for cropfielditemcode {cropfielditemcode}, date '{strSatelliteDate}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (satelliteBands.Contains("ndvi"))
|
||||||
|
{
|
||||||
|
if (satelliteStatistics_ndvi != null)
|
||||||
|
{
|
||||||
|
sbInsertSqlInto.Append(",ndvi_pixelcount,ndvi_max,ndvi_mean,ndvi_min,ndvi_stdev,ndvi_median");
|
||||||
|
sbInsertSqlValues.Append($",{satelliteStatistics_ndvi.populationCount},{satelliteStatistics_ndvi.max},{satelliteStatistics_ndvi.mean},{satelliteStatistics_ndvi.min},{satelliteStatistics_ndvi.stddev},{satelliteStatistics_ndvi.median}");
|
||||||
|
sbInsertSqlUpdate.Append($",ndvi_pixelcount={satelliteStatistics_ndvi.populationCount},ndvi_max={satelliteStatistics_ndvi.max},ndvi_mean={satelliteStatistics_ndvi.mean},ndvi_min={satelliteStatistics_ndvi.min},ndvi_stdev={satelliteStatistics_ndvi.stddev},ndvi_median={satelliteStatistics_ndvi.median}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"ndvi missing for cropfielditemcode {cropfielditemcode}, date '{strSatelliteDate}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sbInsertSqlInto.Append(")");
|
||||||
|
sbInsertSqlValues.Append(")");
|
||||||
|
sbInsertSql.AppendLine(sbInsertSqlInto.ToString());
|
||||||
|
sbInsertSql.AppendLine(sbInsertSqlValues.ToString());
|
||||||
|
sbInsertSql.AppendLine(sbInsertSqlUpdate.ToString());
|
||||||
|
//string strInsertSql = sbInsertSql.ToString();
|
||||||
|
NpgsqlCommand insertCmd = connection.CreateCommand();
|
||||||
|
insertCmd.CommandText = sbInsertSql.ToString();
|
||||||
|
//Console.WriteLine(insertCmd.CommandText);
|
||||||
|
int r = insertCmd.ExecuteNonQuery();
|
||||||
|
if (r != 1)
|
||||||
|
throw new Exception("// FarmmapsBulkSatDownload: Insert Failed");
|
||||||
|
_logger.LogInformation($"// Added stats to {schemaname}.{satelllitetable} for parcelid {fieldID}, date '{strSatelliteDate}'. cntDatesDownloaded: {cntDatesDownloaded}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connection.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 settings = new Settings();
|
||||||
|
settings.cropFieldItems = new List<Item>();
|
||||||
|
_settings = settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveSettings(string file)
|
||||||
|
{
|
||||||
|
if (_settings == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var json = JsonConvert.SerializeObject(_settings);
|
||||||
|
File.WriteAllText(file, json);
|
||||||
|
}
|
||||||
|
private string strTime(TimeSpan ts)
|
||||||
|
{
|
||||||
|
return String.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
227
FarmmapsBulkSatDownload/BulkSatDownloadInput.json
Normal file
227
FarmmapsBulkSatDownload/BulkSatDownloadInput.json
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fieldName": "MyField_1", // FarmMaps minimum needs are: fieldName, cropYear & geometryJson
|
||||||
|
"cropYear": 2023,
|
||||||
|
"fieldID": 1,
|
||||||
|
"SatelliteBands": [ "ci-red", "ndvi", "wdvi" ], // ["ndvi"] or ["wdvi"] or both: [ "wdvi", "ndvi" ]
|
||||||
|
"lastdownloadedimagedate": "2023-01-01", //downloads images from this date till end of the year
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ],
|
||||||
|
[ 5.567425915520115, 52.547725375100377 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"downloadFolder": "C:\\workdir\\groenmonitor\\", //if not yet existing this folder will be created
|
||||||
|
"fileNameStats": "BulkSatDownload.csv", //if file exists, probably will be overwritten. Check code in BulkSatDownloadApplication.cs
|
||||||
|
"database": null, // keep null to work with json and csv. Check code in BulkSatDownloadApplication.cs if reading/writing to/from database
|
||||||
|
"schemaname": null,
|
||||||
|
"cropfieldtable": null,
|
||||||
|
"satelllitetable": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldName": "MyField_2", // FarmMaps minimum needs are: fieldName, cropYear & geometryJson
|
||||||
|
"cropYear": 2022, // for testing same field last year (i.e. 2021)
|
||||||
|
"fieldID": 2,
|
||||||
|
"SatelliteBands": [ "ci-red", "ndvi", "wdvi" ], // ["ndvi"] or ["wdvi"] or both: [ "wdvi", "ndvi" ]
|
||||||
|
"lastdownloadedimagedate": "2022-01-01", //downloads images from this date till end of the year
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ],
|
||||||
|
[ 5.567425915520115, 52.547725375100377 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"downloadFolder": "C:\\workdir\\groenmonitor\\",
|
||||||
|
"fileNameStats": "BulkSatDownload.csv",
|
||||||
|
"database": null,
|
||||||
|
"schemaname": null,
|
||||||
|
"cropfieldtable": null,
|
||||||
|
"satelllitetable": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldName": "MyField_3", // FarmMaps minimum needs are: fieldName, cropYear & geometryJson
|
||||||
|
"cropYear": 2021,
|
||||||
|
"fieldID": 3,
|
||||||
|
"SatelliteBands": [ "ci-red", "ndvi", "wdvi" ], // ["ndvi"] or ["wdvi"] or both: [ "wdvi", "ndvi" ]
|
||||||
|
"lastdownloadedimagedate": "2021-01-01", //downloads images from this date till end of the year
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ],
|
||||||
|
[ 5.567425915520115, 52.547725375100377 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"downloadFolder": "C:\\workdir\\groenmonitor\\",
|
||||||
|
"fileNameStats": "BulkSatDownload.csv",
|
||||||
|
"database": null,
|
||||||
|
"schemaname": null,
|
||||||
|
"cropfieldtable": null,
|
||||||
|
"satelllitetable": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldName": "MyField_4", // FarmMaps minimum needs are: fieldName, cropYear & geometryJson
|
||||||
|
"cropYear": 2020,
|
||||||
|
"fieldID": 4,
|
||||||
|
"SatelliteBands": [ "ci-red", "ndvi", "wdvi" ], // ["ndvi"] or ["wdvi"] or both: [ "wdvi", "ndvi" ]
|
||||||
|
"lastdownloadedimagedate": "2020-01-01", //downloads images from this date till end of the year
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ],
|
||||||
|
[ 5.567425915520115, 52.547725375100377 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"downloadFolder": "C:\\workdir\\groenmonitor\\",
|
||||||
|
"fileNameStats": "BulkSatDownload.csv",
|
||||||
|
"database": null,
|
||||||
|
"schemaname": null,
|
||||||
|
"cropfieldtable": null,
|
||||||
|
"satelllitetable": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldName": "MyField_5", // FarmMaps minimum needs are: fieldName, cropYear & geometryJson
|
||||||
|
"cropYear": 2019,
|
||||||
|
"fieldID": 5,
|
||||||
|
"SatelliteBands": [ "ci-red", "ndvi", "wdvi" ], // ["ndvi"] or ["wdvi"] or both: [ "wdvi", "ndvi" ]
|
||||||
|
"lastdownloadedimagedate": "2019-01-01", //downloads images from this date till end of the year
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ],
|
||||||
|
[ 5.567425915520115, 52.547725375100377 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"downloadFolder": "C:\\workdir\\groenmonitor\\",
|
||||||
|
"fileNameStats": "BulkSatDownload.csv",
|
||||||
|
"database": null,
|
||||||
|
"schemaname": null,
|
||||||
|
"cropfieldtable": null,
|
||||||
|
"satelllitetable": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldName": "MyField_6", // FarmMaps minimum needs are: fieldName, cropYear & geometryJson
|
||||||
|
"cropYear": 2018,
|
||||||
|
"fieldID": 6,
|
||||||
|
"SatelliteBands": [ "ci-red", "ndvi", "wdvi" ], // ["ndvi"] or ["wdvi"] or both: [ "wdvi", "ndvi" ]
|
||||||
|
"lastdownloadedimagedate": "2018-01-01", //downloads images from this date till end of the year
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ],
|
||||||
|
[ 5.567425915520115, 52.547725375100377 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"downloadFolder": "C:\\workdir\\groenmonitor\\",
|
||||||
|
"fileNameStats": "BulkSatDownload.csv",
|
||||||
|
"database": null,
|
||||||
|
"schemaname": null,
|
||||||
|
"cropfieldtable": null,
|
||||||
|
"satelllitetable": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldName": "MyField_6", // FarmMaps minimum needs are: fieldName, cropYear & geometryJson
|
||||||
|
"cropYear": 2017,
|
||||||
|
"fieldID": 7,
|
||||||
|
"SatelliteBands": [ "ci-red", "ndvi", "wdvi" ], // ["ndvi"] or ["wdvi"] or both: [ "wdvi", "ndvi" ]
|
||||||
|
"lastdownloadedimagedate": "2017-01-01", //downloads images from this date till end of the year
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ],
|
||||||
|
[ 5.567425915520115, 52.547725375100377 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"downloadFolder": "C:\\workdir\\groenmonitor\\",
|
||||||
|
"fileNameStats": "BulkSatDownload.csv",
|
||||||
|
"database": null,
|
||||||
|
"schemaname": null,
|
||||||
|
"cropfieldtable": null,
|
||||||
|
"satelllitetable": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldName": "MyField_8", // FarmMaps minimum needs are: fieldName, cropYear & geometryJson. Actually no Satellite data before 2017. This here to illustrate the program does not crash
|
||||||
|
"cropYear": 2016,
|
||||||
|
"fieldID": 8,
|
||||||
|
"SatelliteBands": [ "ci-red", "ndvi", "wdvi" ], // ["ndvi"] or ["wdvi"] or both: [ "wdvi", "ndvi" ]
|
||||||
|
"lastdownloadedimagedate": "2016-01-01", //downloads images from this date till end of the year
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ],
|
||||||
|
[ 5.567425915520115, 52.547725375100377 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"downloadFolder": "C:\\workdir\\groenmonitor\\",
|
||||||
|
"fileNameStats": "BulkSatDownload.csv",
|
||||||
|
"database": null,
|
||||||
|
"schemaname": null,
|
||||||
|
"cropfieldtable": null,
|
||||||
|
"satelllitetable": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldName": "MyField_9", // FarmMaps minimum needs are: fieldName, cropYear & geometryJson. Actually no Satellite data before 2017. This here to illustrate the program does not crash
|
||||||
|
"cropYear": 2015,
|
||||||
|
"fieldID": 9,
|
||||||
|
"SatelliteBands": [ "ci-red", "ndvi", "wdvi" ], // ["ndvi"] or ["wdvi"] or both: [ "wdvi", "ndvi" ]
|
||||||
|
"lastdownloadedimagedate": "2015-01-01", //downloads images from this date till end of the year
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ],
|
||||||
|
[ 5.567425915520115, 52.547725375100377 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"downloadFolder": "C:\\workdir\\groenmonitor\\",
|
||||||
|
"fileNameStats": "BulkSatDownload.csv",
|
||||||
|
"database": null,
|
||||||
|
"schemaname": null,
|
||||||
|
"cropfieldtable": null,
|
||||||
|
"satelllitetable": null
|
||||||
|
}
|
||||||
|
]
|
29
FarmmapsBulkSatDownload/BulkSatDownloadService.cs
Normal file
29
FarmmapsBulkSatDownload/BulkSatDownloadService.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using FarmmapsBulkSatDownload.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using static FarmmapsApi.Extensions;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
namespace FarmmapsBulkSatDownload
|
||||||
|
{
|
||||||
|
public class BulkSatDownloadService
|
||||||
|
{
|
||||||
|
private readonly ILogger<BulkSatDownloadService> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
public BulkSatDownloadService(ILogger<BulkSatDownloadService> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
6
FarmmapsBulkSatDownload/DBsettings.json
Normal file
6
FarmmapsBulkSatDownload/DBsettings.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"User": "",
|
||||||
|
"Password": "",
|
||||||
|
"Database": "",
|
||||||
|
"Host": ""
|
||||||
|
}
|
32
FarmmapsBulkSatDownload/FarmmapsBulkSatDownload.csproj
Normal file
32
FarmmapsBulkSatDownload/FarmmapsBulkSatDownload.csproj
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<WarningLevel>5</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Npgsql" Version="5.0.5" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Data\**\*">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="BulkSatDownloadInput.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="DBsettings.secrets.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FarmmapsApi\FarmmapsApi.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
25
FarmmapsBulkSatDownload/Models/BulkSatDownloadInput.cs
Normal file
25
FarmmapsBulkSatDownload/Models/BulkSatDownloadInput.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace FarmmapsBulkSatDownload.Models
|
||||||
|
{
|
||||||
|
public class BulkSatDownloadInput
|
||||||
|
{
|
||||||
|
public string fieldName { get; set; }
|
||||||
|
public int cropYear { get; set; }
|
||||||
|
public int fieldID { get; set; }
|
||||||
|
public List<string> SatelliteBands { get; set; }
|
||||||
|
public DateTime lastdownloadedimagedate { get; set; }
|
||||||
|
public JObject GeometryJson { get; set; }
|
||||||
|
public string cropfielditemcode { get; set; }
|
||||||
|
public string satellitetaskcode { get; set; }
|
||||||
|
public string downloadFolder { get; set; }
|
||||||
|
public string fileNameStats { get; set; }
|
||||||
|
public DB database { get; set; }
|
||||||
|
public string schemaname { get; set; }
|
||||||
|
public string cropfieldtable { get; set; }
|
||||||
|
public string satelllitetable { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
47
FarmmapsBulkSatDownload/Models/DB.cs
Normal file
47
FarmmapsBulkSatDownload/Models/DB.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Npgsql;
|
||||||
|
|
||||||
|
namespace FarmmapsBulkSatDownload.Models
|
||||||
|
{
|
||||||
|
public class DB
|
||||||
|
{
|
||||||
|
public string Database;
|
||||||
|
public string User;
|
||||||
|
public string Password;
|
||||||
|
public string Host;
|
||||||
|
|
||||||
|
public string GetConnectionString()
|
||||||
|
{
|
||||||
|
NpgsqlConnectionStringBuilder sb = new NpgsqlConnectionStringBuilder();
|
||||||
|
sb.Database = Database;
|
||||||
|
sb.Host = Host;
|
||||||
|
sb.Username = User;
|
||||||
|
sb.Password = Password;
|
||||||
|
sb.Port = 5432;
|
||||||
|
|
||||||
|
return sb.ConnectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ExecuteNonQuery(string sql)
|
||||||
|
{
|
||||||
|
using (NpgsqlConnection conn = new NpgsqlConnection(GetConnectionString()))
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
NpgsqlCommand command = conn.CreateCommand();
|
||||||
|
command.CommandText = sql;
|
||||||
|
int r = command.ExecuteNonQuery();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public NpgsqlConnection CreateConnection()
|
||||||
|
{
|
||||||
|
NpgsqlConnection conn = new NpgsqlConnection(GetConnectionString());
|
||||||
|
conn.Open();
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
10
FarmmapsBulkSatDownload/Models/Settings.cs
Normal file
10
FarmmapsBulkSatDownload/Models/Settings.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
|
||||||
|
namespace FarmmapsBulkSatDownload
|
||||||
|
{
|
||||||
|
public class Settings
|
||||||
|
{
|
||||||
|
public List<Item> cropFieldItems { get; set; }
|
||||||
|
}
|
||||||
|
}
|
21
FarmmapsBulkSatDownload/Program.cs
Normal file
21
FarmmapsBulkSatDownload/Program.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace FarmmapsBulkSatDownload
|
||||||
|
{
|
||||||
|
class Program : FarmmapsProgram<BulkSatDownloadApplication>
|
||||||
|
{
|
||||||
|
private static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
await new Program().Start(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Configure(IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
serviceCollection.AddLogging()
|
||||||
|
.AddTransient<BulkSatDownloadService>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
143
FarmmapsCleanUp/CleanUpApplication.cs
Normal file
143
FarmmapsCleanUp/CleanUpApplication.cs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using FarmmapsBulkSatDownload.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Npgsql;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
namespace FarmmapsCleanup
|
||||||
|
{
|
||||||
|
public class CleanupApplication : IApplication
|
||||||
|
{
|
||||||
|
private readonly ILogger<CleanupApplication> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly CleanupService _cleanupService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
public CleanupApplication(ILogger<CleanupApplication> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService, CleanupService cleanupService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
_cleanupService = cleanupService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunAsync()
|
||||||
|
{
|
||||||
|
// !! 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();
|
||||||
|
|
||||||
|
//Establish a database connection. Expecting you are using same database server as in project FarmmapsBulkSatDownload
|
||||||
|
DB dbparcels = JsonConvert.DeserializeObject<DB>(File.ReadAllText("DBsettings.secrets.json"));
|
||||||
|
string schemaname = "bigdata";
|
||||||
|
string parceltablename = "parcel_bollenrevolutie_tulips2020"; //"parcelsijbrandij" "parcel"; "parcel_flowerbulbs"; "parcel_disac"; ""parcel_bollenrevolutie_tulips2020""
|
||||||
|
|
||||||
|
//Query to get lists of items to delete from FarmmapsDatabase and from parceltablename
|
||||||
|
string cropfielditemcode;
|
||||||
|
string satellitetaskcode;
|
||||||
|
List<string> cropfieldItemCodes = new List<string>();
|
||||||
|
List<string> satellitetaskCodes = new List<string>();
|
||||||
|
string connectionString = dbparcels.GetConnectionString();
|
||||||
|
string readSql = string.Format(
|
||||||
|
@"
|
||||||
|
SELECT pt.cropfielditemcode, pt.satellitetaskcode
|
||||||
|
FROM {0}.{1} pt
|
||||||
|
WHERE
|
||||||
|
pt.arbid IN(1,2)
|
||||||
|
ORDER BY pt.arbid
|
||||||
|
;", schemaname, parceltablename);
|
||||||
|
|
||||||
|
string updateCropfieldItemCodesSql = string.Format(
|
||||||
|
@"
|
||||||
|
UPDATE {0}.{1}
|
||||||
|
SET cropfielditemcode=NULL
|
||||||
|
WHERE arbid IN(1,2)
|
||||||
|
;", schemaname, parceltablename); //Same WHERE AS above
|
||||||
|
string updateSatellitetaskCodesSql = string.Format(
|
||||||
|
@"
|
||||||
|
UPDATE {0}.{1}
|
||||||
|
SET satellitetaskcode=NULL
|
||||||
|
WHERE arbid IN(1,2)
|
||||||
|
;", schemaname, parceltablename); //Same WHERE AS above
|
||||||
|
|
||||||
|
using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
|
||||||
|
// Read data (run query) = build a list of fields for which to download images
|
||||||
|
NpgsqlCommand command = connection.CreateCommand();
|
||||||
|
command.CommandText = readSql;
|
||||||
|
NpgsqlDataReader dr = command.ExecuteReader();
|
||||||
|
while (dr.Read())
|
||||||
|
{
|
||||||
|
cropfielditemcode = dr.GetString(0);
|
||||||
|
satellitetaskcode = dr.GetString(1);
|
||||||
|
if(!string.IsNullOrEmpty(cropfielditemcode))
|
||||||
|
cropfieldItemCodes.Add(cropfielditemcode);
|
||||||
|
if (!string.IsNullOrEmpty(satellitetaskcode))
|
||||||
|
satellitetaskCodes.Add(satellitetaskcode);
|
||||||
|
}
|
||||||
|
connection.Close();
|
||||||
|
}
|
||||||
|
_logger.LogWarning($"// FarmmapsCleanUp: WARNING: you are about to delete {cropfieldItemCodes.Count} cropfieldItemCodes and {satellitetaskCodes.Count} satellitetaskCodes from the FarmMaps database and your own table {schemaname}.{parceltablename}");
|
||||||
|
_logger.LogInformation($"// Nice of you to clean up after the work is done. You would typically do this for cropfieldItemCodes used only once.");
|
||||||
|
_logger.LogInformation($"// You do NOT want to do this if you think you may later on still want to use these items.");
|
||||||
|
_logger.LogInformation($"// Please carefully check the SQL queries 'readSql' 'updateSql' in CleanUpApplication.cs before proceeding.");
|
||||||
|
|
||||||
|
_logger.LogInformation($"// FarmmapsCleanUp: delete selected cropfieldItemCodes from FarmMaps database and table {schemaname}.{parceltablename}? 0 = no, 1 = yes");
|
||||||
|
int i;
|
||||||
|
i = Int32.Parse(Console.ReadLine());
|
||||||
|
if (i == 1)
|
||||||
|
{
|
||||||
|
await _farmmapsApiService.DeleteItemsAsync(cropfieldItemCodes);
|
||||||
|
//TODO _farmmapsApiService.DeleteItemsAsync throws an error: {StatusCode: 415, ReasonPhrase: 'Unsupported Media Type', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers: {...}}
|
||||||
|
//what is wrong with cropfieldItemCodes?
|
||||||
|
//and shouldn't we be telling _farmmapsApiService.DeleteItemsAsync what item type to delete?
|
||||||
|
using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
NpgsqlCommand updateCmd = connection.CreateCommand();
|
||||||
|
updateCmd.CommandText = updateCropfieldItemCodesSql;
|
||||||
|
int r = updateCmd.ExecuteNonQuery();
|
||||||
|
if (r == -1)
|
||||||
|
throw new Exception("// FarmmapsCleanUp: Update cropfielditemcode Failed");
|
||||||
|
connection.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_logger.LogInformation($"// FarmmapsCleanUp: delete selected satellitetaskCodes from FarmMaps database and table {schemaname}.{parceltablename}? 0 = no, 1 = yes");
|
||||||
|
i = Int32.Parse(Console.ReadLine());
|
||||||
|
if (i == 1)
|
||||||
|
{
|
||||||
|
await _farmmapsApiService.DeleteItemsAsync(satellitetaskCodes);
|
||||||
|
//TODO _farmmapsApiService.DeleteItemsAsync throws an error: {StatusCode: 415, ReasonPhrase: 'Unsupported Media Type', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers: {...}}
|
||||||
|
//what is wrong with satellitetaskCodes?
|
||||||
|
//and shouldn't we be telling _farmmapsApiService.DeleteItemsAsync what item type to delete?
|
||||||
|
using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
NpgsqlCommand updateCmd = connection.CreateCommand();
|
||||||
|
updateCmd.CommandText = updateSatellitetaskCodesSql;
|
||||||
|
int r = updateCmd.ExecuteNonQuery();
|
||||||
|
if (r == -1)
|
||||||
|
throw new Exception("// FarmmapsCleanUp: Update cropfielditemcode Failed");
|
||||||
|
connection.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_logger.LogInformation($"// FarmmapsCleanUp: done! Hit any key to exit ...");
|
||||||
|
Console.ReadKey();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
FarmmapsCleanUp/CleanUpService.cs
Normal file
28
FarmmapsCleanUp/CleanUpService.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using static FarmmapsApi.Extensions;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
namespace FarmmapsCleanup
|
||||||
|
{
|
||||||
|
public class CleanupService
|
||||||
|
{
|
||||||
|
private readonly ILogger<CleanupService> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
public CleanupService(ILogger<CleanupService> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
23
FarmmapsCleanUp/FarmmapsCleanUp.csproj
Normal file
23
FarmmapsCleanUp/FarmmapsCleanUp.csproj
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Npgsql" Version="5.0.5" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Data\**\*">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FarmmapsApi\FarmmapsApi.csproj" />
|
||||||
|
<ProjectReference Include="..\FarmmapsBulkSatDownload\FarmmapsBulkSatDownload.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
21
FarmmapsCleanUp/Program.cs
Normal file
21
FarmmapsCleanUp/Program.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace FarmmapsCleanup
|
||||||
|
{
|
||||||
|
class Program : FarmmapsProgram<CleanupApplication>
|
||||||
|
{
|
||||||
|
private static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
await new Program().Start(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Configure(IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
serviceCollection.AddLogging()
|
||||||
|
.AddTransient<CleanupService>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
361
FarmmapsDataDownload/DataDownloadApplication.cs
Normal file
361
FarmmapsDataDownload/DataDownloadApplication.cs
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using FarmmapsDataDownload.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
namespace FarmmapsDataDownload
|
||||||
|
{
|
||||||
|
public class DataDownloadApplication : IApplication
|
||||||
|
{
|
||||||
|
//private const string DownloadFolder = "Downloads";
|
||||||
|
private const string SettingsFile = "settings.json";
|
||||||
|
|
||||||
|
private readonly ILogger<DataDownloadApplication> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly DataDownloadService _dataDownloadService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
private Settings _settings;
|
||||||
|
|
||||||
|
public DataDownloadApplication(ILogger<DataDownloadApplication> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService, DataDownloadService dataDownloadService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
_dataDownloadService = dataDownloadService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunAsync()
|
||||||
|
{
|
||||||
|
string fieldsInputJson = File.ReadAllText("DataDownloadInput.json");
|
||||||
|
|
||||||
|
List<DataDownloadInput> fieldsInputs = JsonConvert.DeserializeObject<List<DataDownloadInput>>(fieldsInputJson);
|
||||||
|
|
||||||
|
// !! 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 fieldsInputs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Process(roots, input);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Process(List<UserRoot> roots, DataDownloadInput input)
|
||||||
|
{
|
||||||
|
//PO20220311: first time a call is made to download satellite images or statistics, an empty list is returned
|
||||||
|
//If we wait a bit longer, e.g. 10 secs, then e.g. a list of 3 images may be returned
|
||||||
|
//If we wait still longer, maybe 4 images.
|
||||||
|
//The solution implemented below is to fire calls as long as the number of images returned keeps increasing
|
||||||
|
//While in between each call, sleep for sleepSecs
|
||||||
|
//Continue this until the number no longer increases or the maximum number of calls has been reached
|
||||||
|
//Out of politeness, don't be too impatient. Don't set sleepSecs to 5 or 10 or 30 secs. Just accept this may take a while, have a coffee, we suggest sleepSecs = 60;
|
||||||
|
int sleepSecs = 60;
|
||||||
|
int callCntMax = 4;
|
||||||
|
//For example we may set: "sleepSecs = 10;" and "callCntMax = 24;" and following result:
|
||||||
|
//Call no: 1. Giving FarmMaps 10 seconds to get SatelliteItems...
|
||||||
|
//Call no: 1: Received 2 images
|
||||||
|
//Call no: 2. Giving FarmMaps 10 seconds to get SatelliteItems...
|
||||||
|
//Call no: 2: Received 7 images
|
||||||
|
//Call no: 3. Giving FarmMaps 10 seconds to get SatelliteItems...
|
||||||
|
//Call no: 3: Received 7 images
|
||||||
|
//And the firing of calls would stop because the number of images returned is no longer increasing
|
||||||
|
//In the worst case, this could would lead to a total sleeping period of "sleepSecsSum = sleepSecs * callCntMax" seconds. After that we give up
|
||||||
|
|
||||||
|
//This is an ugly fix. Neater would if FarmMaps would just take a bit longer and then do always deliver all satellite images on first call.
|
||||||
|
//Once this has been fixed on the side of FarmMaps we can set callCntMax = 0 and the code below will work smoothly without any sleeping
|
||||||
|
|
||||||
|
string downloadFolder = input.DownloadFolder;
|
||||||
|
if (string.IsNullOrEmpty(downloadFolder)) {
|
||||||
|
downloadFolder = "Downloads";
|
||||||
|
}
|
||||||
|
if (!Directory.Exists(downloadFolder))
|
||||||
|
Directory.CreateDirectory(downloadFolder);
|
||||||
|
|
||||||
|
// !!specify if you are using an already created cropfield:
|
||||||
|
bool useCreatedCropfield = input.UseCreatedCropfield;
|
||||||
|
var cropYear = input.CropYear;
|
||||||
|
var fieldName = input.fieldName;
|
||||||
|
bool storeSatelliteStatistics = input.StoreSatelliteStatisticsSingleImage;
|
||||||
|
bool storeSatelliteStatisticsCropYear = input.StoreSatelliteStatisticsCropYear;
|
||||||
|
//List<string> SatelliteBands = new List<string>(1) { input.SatelliteBand };
|
||||||
|
List<string> satelliteBands = input.SatelliteBands;
|
||||||
|
string headerLineStats = $"FieldName,satelliteDate,satelliteBand,max,min,mean,mode,median,stddev,minPlus,curtosis,maxMinus,skewness,variance,populationCount,variationCoefficient,confidenceIntervalLow, confidenceIntervalHigh,confidenceIntervalErrorMargin" + Environment.NewLine;
|
||||||
|
|
||||||
|
|
||||||
|
string settingsfile = $"Settings_{fieldName}.json";
|
||||||
|
|
||||||
|
LoadSettings(settingsfile);
|
||||||
|
|
||||||
|
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
|
||||||
|
if (uploadedRoot == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find a needed root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var myDriveRoot = roots.SingleOrDefault(r => r.Name == "USER_FILES");
|
||||||
|
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,
|
||||||
|
$"DataCropfield {input.OutputFileName}", cropYear, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get croprecordings
|
||||||
|
if (input.GetCropRecordings)
|
||||||
|
{
|
||||||
|
var crprecItem = input.CrprecItem;
|
||||||
|
_logger.LogInformation($"Trying to get crop recordings of croprecording: {crprecItem}");
|
||||||
|
|
||||||
|
var cropRec = await _farmmapsApiService.GetItemChildrenAsync(crprecItem, CROPREC_ITEMTYPE);
|
||||||
|
if (cropRec == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Something went wrong while obtaining the croprecordings");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cropRecPath = Path.Combine(downloadFolder, $"croprecordings_{crprecItem}.json");
|
||||||
|
_logger.LogInformation($"Found {cropRec.Count} crop recordings");
|
||||||
|
var count = 0;
|
||||||
|
await Task.Delay(500);
|
||||||
|
foreach (var item in cropRec)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Crop recording #{count}: {item.Name}");
|
||||||
|
File.AppendAllText(cropRecPath, item.Data +Environment.NewLine);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
_logger.LogInformation($"Downloaded file {cropRecPath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get shadow data
|
||||||
|
if (input.GetShadowData)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Calculate shadow map for field");
|
||||||
|
var shadowItem = await _generalService.RunShadowTask(cropfieldItem);
|
||||||
|
if (shadowItem == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Something went wrong while obtaining the shadow map");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Downloading shadow map");
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(shadowItem.Code,
|
||||||
|
Path.Combine(downloadFolder, $"{input.OutputFileName}_shadow.zip"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Get satellite data
|
||||||
|
if (input.GetSatelliteData)
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Call first time
|
||||||
|
int callCnt = 1;
|
||||||
|
int sleepSecsSum = 0;
|
||||||
|
//if callCntMax == 0 then don't sleep
|
||||||
|
//if callCntMax = 1 then sleep first 1x
|
||||||
|
if (callCntMax > 0)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Call no: {callCnt}. Giving FarmMaps {sleepSecs} seconds to get SatelliteItems...");
|
||||||
|
System.Threading.Thread.Sleep(1000 * sleepSecs);
|
||||||
|
sleepSecsSum = sleepSecsSum + sleepSecs;
|
||||||
|
}
|
||||||
|
List<Item> satelliteItemsCropYear = await _generalService.FindSatelliteItems(cropfieldItem, _settings.SatelliteTaskCode);
|
||||||
|
int satelliteItemsCropYearCntPrev = satelliteItemsCropYear.Count;
|
||||||
|
_logger.LogInformation($"Call no: {callCnt}. Received {satelliteItemsCropYearCntPrev} images");
|
||||||
|
callCnt++;
|
||||||
|
int satelliteItemsCropYearCnt = satelliteItemsCropYearCntPrev;
|
||||||
|
//if callCntMax > 1 then sleep untill (1) no more increase in number of images received OR (2) maximum number of calls reached
|
||||||
|
if (callCntMax > 1)
|
||||||
|
{
|
||||||
|
//Call second time
|
||||||
|
_logger.LogInformation($"Call no: {callCnt}. Giving FarmMaps another {sleepSecs} seconds to get SatelliteItems...");
|
||||||
|
System.Threading.Thread.Sleep(1000 * sleepSecs);
|
||||||
|
satelliteItemsCropYear = await _generalService.FindSatelliteItems(cropfieldItem, _settings.SatelliteTaskCode);
|
||||||
|
satelliteItemsCropYearCnt = satelliteItemsCropYear.Count;
|
||||||
|
_logger.LogInformation($"Call no: {callCnt}. Received {satelliteItemsCropYearCnt} images");
|
||||||
|
sleepSecsSum = sleepSecsSum + sleepSecs;
|
||||||
|
//As long as there is progress, keep calling
|
||||||
|
callCnt++;
|
||||||
|
while (callCnt <= callCntMax && (satelliteItemsCropYearCnt == 0 || satelliteItemsCropYearCnt > satelliteItemsCropYearCntPrev))
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Surprise! The longer we wait, the more images we get. Sleep and call once more");
|
||||||
|
satelliteItemsCropYearCntPrev = satelliteItemsCropYearCnt;
|
||||||
|
_logger.LogInformation($"Call no: {callCnt} (max: {callCntMax}). Giving FarmMaps another {sleepSecs} seconds to get SatelliteItems...");
|
||||||
|
System.Threading.Thread.Sleep(1000 * sleepSecs);
|
||||||
|
satelliteItemsCropYear = await _generalService.FindSatelliteItems(cropfieldItem, _settings.SatelliteTaskCode);
|
||||||
|
satelliteItemsCropYearCnt = satelliteItemsCropYear.Count;
|
||||||
|
_logger.LogInformation($"Call no: {callCnt}. Received {satelliteItemsCropYearCnt} images");
|
||||||
|
callCnt++;
|
||||||
|
sleepSecsSum = sleepSecsSum + sleepSecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (satelliteItemsCropYearCnt == 0)
|
||||||
|
{
|
||||||
|
_logger.LogWarning($"DataDownloadApplication.cs: after calling one or more times and " +
|
||||||
|
$"sleeping in total {sleepSecsSum} seconds, still no images found. " +
|
||||||
|
$"Please check your settings for parameters callCntMax and sleepSecs in DataDownloadApplication.cs or contact FarmMaps");
|
||||||
|
}
|
||||||
|
|
||||||
|
satelliteItemsCropYear = satelliteItemsCropYear.OrderBy(x => x.DataDate).ToList();
|
||||||
|
|
||||||
|
if (input.StoreSatelliteStatisticsSingleImage == true && satelliteItemsCropYearCnt > 0) {
|
||||||
|
_logger.LogInformation("Available satellite images:");
|
||||||
|
var count = 0;
|
||||||
|
TimeSpan.FromSeconds(0.5);
|
||||||
|
foreach (var item in satelliteItemsCropYear)
|
||||||
|
{
|
||||||
|
|
||||||
|
Console.WriteLine($"Satellite image #{count}: {item.DataDate}");
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Enter satellite image number");
|
||||||
|
int element = Int32.Parse(Console.ReadLine());
|
||||||
|
var selectedSatelliteItem = satelliteItemsCropYear[element];
|
||||||
|
|
||||||
|
var SatelliteDate = selectedSatelliteItem.DataDate.Value.ToString("yyyyMMdd");
|
||||||
|
string fileName = string.Format($"satelliteGeotiff_{fieldName}_{SatelliteDate}"); // no need to add satelliteBand in the name because the tif contains all bands
|
||||||
|
string fileNameZip = Path.Combine(downloadFolder, string.Format($"{fileName}.zip"));
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(selectedSatelliteItem.Code, fileNameZip);
|
||||||
|
|
||||||
|
// Download a csv file with stats
|
||||||
|
List<Item> selectedSatelliteItems = new List<Item>(1) { selectedSatelliteItem };
|
||||||
|
string fileNameStats = Path.Combine(downloadFolder, string.Format($"satelliteStats_{fieldName}_{SatelliteDate}.csv"));
|
||||||
|
_logger.LogInformation($"First call to get DownloadSatelliteStats for selected image...");
|
||||||
|
string downloadedStats = await _generalService.DownloadSatelliteStats(selectedSatelliteItems, fieldName, satelliteBands, downloadFolder);
|
||||||
|
|
||||||
|
//rename the csv file with stats
|
||||||
|
//if the targe file already exists, delete it
|
||||||
|
File.Delete(fileNameStats);
|
||||||
|
//rename
|
||||||
|
File.Move(downloadedStats, fileNameStats);
|
||||||
|
|
||||||
|
// name the tif file
|
||||||
|
string fileNameTifzipped = Path.Combine(downloadFolder, string.Format($"sentinelhub_{SatelliteDate}.tif"));
|
||||||
|
string fileNameGeotiff = Path.Combine(downloadFolder, string.Format($"sentinelhub_{fieldName}_{SatelliteDate}.tif"));
|
||||||
|
// download the geotiffs. Returns a zip file with always these two files:
|
||||||
|
// thumbnail.jpg
|
||||||
|
// sentinelhub_yyyyMMdd.tif. Contains 4 layers: (1) ndvi, (2) wdvi, (3) ci-red and (4) natural. Natural has 3 layers inside: redBand, blueBand and greenBand
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
// Extract the file fileNameTifzipped from zip, rename it to fileNameGeotiff
|
||||||
|
ZipFile.ExtractToDirectory(fileNameZip, downloadFolder, true);
|
||||||
|
//if the targe file already exists, delete it
|
||||||
|
File.Delete(fileNameGeotiff);
|
||||||
|
//rename
|
||||||
|
File.Move(fileNameTifzipped, fileNameGeotiff);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
File.Delete(fileNameZip);
|
||||||
|
File.Delete(Path.Combine(downloadFolder, "thumbnail.jpg"));
|
||||||
|
}
|
||||||
|
//_logger.LogInformation($"Downloaded files {fileNameGeotiff} and {fileNameStats} to {downloadFolder}");
|
||||||
|
_logger.LogInformation($"Downloaded files to {downloadFolder}");
|
||||||
|
|
||||||
|
}
|
||||||
|
if (input.StoreSatelliteStatisticsCropYear == true) {
|
||||||
|
string fileNameStats = Path.Combine(downloadFolder, string.Format($"satelliteStats_{fieldName}_{cropYear}.csv"));
|
||||||
|
File.Delete(fileNameStats);
|
||||||
|
_logger.LogInformation($"First call to get DownloadSatelliteStats for whole cropYear...");
|
||||||
|
string downloadedStats = await _generalService.DownloadSatelliteStats(satelliteItemsCropYear, fieldName, satelliteBands, downloadFolder);
|
||||||
|
File.Move(downloadedStats, fileNameStats);
|
||||||
|
_logger.LogInformation($"Downloaded file {fileNameStats} with stats for field '{fieldName}', cropyear {cropYear}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Get vanDerSat data
|
||||||
|
if (input.GetVanDerSatData)
|
||||||
|
{
|
||||||
|
// check if satellite 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 satellite item from satelliteTask
|
||||||
|
Item vanDerSatItem = await _generalService.FindVanDerSatItem(cropfieldItem, _settings.VanDerSatTaskCode, fieldName, input.StoreVanDerSatStatistics);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
30
FarmmapsDataDownload/DataDownloadInput.json
Normal file
30
FarmmapsDataDownload/DataDownloadInput.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"UseCreatedCropfield": false, // if false, program will make new CropfieldItemCode and SatelliteTaskCode; if true, the program will read CropfieldItemCode and SatelliteTaskCode from a file called "..\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Settings_{fieldName}.json", which will be faster
|
||||||
|
"outputFileName": "test_BvdTFieldlabG92",
|
||||||
|
"fieldName": "test_BvdTFieldlabG92",
|
||||||
|
"DownloadFolder": "Downloads", //"C:\\workdir\\groenmonitor\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\
|
||||||
|
"GetCropRecordings": false,
|
||||||
|
"CrprecItem": "...", //item code of de crop recording parrent - can be found by opening the crop recording page of a field.
|
||||||
|
"GetShadowData": false,
|
||||||
|
"GetSatelliteData": true,
|
||||||
|
"SatelliteBands": [ "ndvi", "wdvi", "ci-red" ], // ["ndvi"] or ["wdvi"] or ["ci-red"] or multiple: [ "wdvi", "ndvi" ]
|
||||||
|
"StoreSatelliteStatisticsSingleImage": true,
|
||||||
|
"StoreSatelliteStatisticsCropYear": true,
|
||||||
|
"GetVanDerSatData": false,
|
||||||
|
"StoreVanDerSatStatistics": false,
|
||||||
|
"CropYear": 2022,
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ],
|
||||||
|
[ 5.567425915520115, 52.547725375100377 ],
|
||||||
|
[ 5.567917474269188, 52.540608459298582 ],
|
||||||
|
[ 5.563878143678981, 52.54048022658143 ],
|
||||||
|
[ 5.563472073408009, 52.547554398144172 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
29
FarmmapsDataDownload/DataDownloadService.cs
Normal file
29
FarmmapsDataDownload/DataDownloadService.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using FarmmapsDataDownload.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using static FarmmapsApi.Extensions;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
namespace FarmmapsDataDownload
|
||||||
|
{
|
||||||
|
public class DataDownloadService
|
||||||
|
{
|
||||||
|
private readonly ILogger<DataDownloadService> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
public DataDownloadService(ILogger<DataDownloadService> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
24
FarmmapsDataDownload/FarmmapsDataDownload.csproj
Normal file
24
FarmmapsDataDownload/FarmmapsDataDownload.csproj
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Data\**\*">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="DataDownloadInput.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="InputData-NBS.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FarmmapsApi\FarmmapsApi.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
29
FarmmapsDataDownload/Models/DataDownloadInput.cs
Normal file
29
FarmmapsDataDownload/Models/DataDownloadInput.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace FarmmapsDataDownload.Models
|
||||||
|
{
|
||||||
|
public class DataDownloadInput
|
||||||
|
{
|
||||||
|
public bool UseCreatedCropfield { get; set; }
|
||||||
|
public string File { get; set; }
|
||||||
|
public string InputVariable { get; set; }
|
||||||
|
public string OutputFileName { get; set; }
|
||||||
|
public string DownloadFolder { get; set; }
|
||||||
|
public int CropYear { get; set; }
|
||||||
|
public JObject GeometryJson { get; set; }
|
||||||
|
public string InputLayerName { get; set; }
|
||||||
|
public string fieldName { get; set; }
|
||||||
|
public bool GetSatelliteData { get; set; }
|
||||||
|
public bool GetVanDerSatData { get; set; }
|
||||||
|
public List<string> SatelliteBands { get; set; }
|
||||||
|
public bool StoreSatelliteStatisticsSingleImage { get; set; }
|
||||||
|
public bool StoreSatelliteStatisticsCropYear { get; set; }
|
||||||
|
public bool StoreVanDerSatStatistics { get; set; }
|
||||||
|
public bool GetShadowData { get; set; }
|
||||||
|
public bool GetCropRecordings { get; set; }
|
||||||
|
public string CrprecItem { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
11
FarmmapsDataDownload/Models/Settings.cs
Normal file
11
FarmmapsDataDownload/Models/Settings.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace FarmmapsDataDownload
|
||||||
|
{
|
||||||
|
public class Settings
|
||||||
|
{
|
||||||
|
public string CropfieldItemCode { get; set; }
|
||||||
|
public string SatelliteTaskCode { get; set; }
|
||||||
|
public string VanDerSatTaskCode { get; set; }
|
||||||
|
public string WatBalTaskCode { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
9
FarmmapsDataDownload/Models/TargetNData.cs
Normal file
9
FarmmapsDataDownload/Models/TargetNData.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace FarmmapsDataDownload.Models
|
||||||
|
{
|
||||||
|
public class TargetNData
|
||||||
|
{
|
||||||
|
public double TSum { get; set; }
|
||||||
|
public int TargetYield { get; set; }
|
||||||
|
public double TargetN { get; set; }
|
||||||
|
}
|
||||||
|
}
|
21
FarmmapsDataDownload/Program.cs
Normal file
21
FarmmapsDataDownload/Program.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace FarmmapsDataDownload
|
||||||
|
{
|
||||||
|
class Program : FarmmapsProgram<DataDownloadApplication>
|
||||||
|
{
|
||||||
|
private static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
await new Program().Start(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Configure(IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
serviceCollection.AddLogging()
|
||||||
|
.AddTransient<DataDownloadService>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
114
FarmmapsDataDownload/ShowGeotiff.r
Normal file
114
FarmmapsDataDownload/ShowGeotiff.r
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
# ShowGeotiff.r
|
||||||
|
# Have a look at a downloaded satellite image and check if stats are correctly calculated
|
||||||
|
# I downloaded and calculated the stats for the polygon defined in C:\git\FarmMapsApiClient_WURtest\FarmmapsDataDownload\DataDownloadInput.json
|
||||||
|
# in which I set "SatelliteBand": "wdvi" and in which in the console I requested the image for date '2022-03-08'
|
||||||
|
|
||||||
|
library(raster)
|
||||||
|
library(sf)
|
||||||
|
library(rgdal)
|
||||||
|
setwd("C:/git/FarmMapsApiClient_WURtest/FarmmapsDataDownload/bin/Debug/netcoreapp3.1/Downloads")
|
||||||
|
|
||||||
|
# FarmmapsDataDownload
|
||||||
|
fileGeotiff <- "sentinelhub_test_BvdTFieldlabG92_20220308.tif"
|
||||||
|
lenfilename <- nchar(fileGeotiff)
|
||||||
|
year <- substr(fileGeotiff,lenfilename-11,lenfilename-8)
|
||||||
|
imgdate <- substr(fileGeotiff,lenfilename-11,lenfilename-4)
|
||||||
|
|
||||||
|
stk.sentinelhub <- stack(x=fileGeotiff)
|
||||||
|
# plot(stk.sentinelhub) shows 6 plots (6 bands)
|
||||||
|
# 1. ndvi
|
||||||
|
# 2. wdvi Note wdvi-red
|
||||||
|
# 3. ci-red
|
||||||
|
# 4. natural: red
|
||||||
|
# 5. natural: green
|
||||||
|
# 6. natural: blue
|
||||||
|
names(stk.sentinelhub) <- c("ndvi","wdvired","ci-red","red","green","blue")
|
||||||
|
plot(stk.sentinelhub)
|
||||||
|
crs(stk.sentinelhub)
|
||||||
|
# CRS arguments: +proj=longlat +datum=WGS84 +no_defs
|
||||||
|
stk.sentinelhub.rd <- projectRaster(stk.sentinelhub, crs = CRS('+init=EPSG:28992'))
|
||||||
|
crs(stk.sentinelhub)
|
||||||
|
|
||||||
|
r.sentinelhub.rd.wdvi <- subset(stk.sentinelhub.rd,2)
|
||||||
|
dev.off()
|
||||||
|
plot(r.sentinelhub.rd.wdvi,main=paste("wdvi",imgdate),xlab="RDX",ylab="RDY")
|
||||||
|
cellStats(r.sentinelhub.rd.wdvi,'mean') # 0.2252725
|
||||||
|
|
||||||
|
# Convert the .rd.wdvi raster to WGS84
|
||||||
|
r.sentinelhub.wgs84.wdvi <- projectRaster(r.sentinelhub.rd.wdvi, crs = CRS('+init=EPSG:4326'))
|
||||||
|
|
||||||
|
# Draw a polygon on top of the raster
|
||||||
|
# Polygon pol from C:\git\FarmMapsApiClient_WURtest\FarmmapsDataDownload\DataDownloadInput.json
|
||||||
|
pol <- data.frame(id = 1, wkt = gsub("\n","",'POLYGON((
|
||||||
|
5.563472073408009 52.547554398144172,
|
||||||
|
5.567425915520115 52.547725375100377,
|
||||||
|
5.567917474269188 52.540608459298582,
|
||||||
|
5.563878143678981 52.54048022658143,
|
||||||
|
5.563472073408009 52.547554398144172
|
||||||
|
))'))
|
||||||
|
|
||||||
|
|
||||||
|
pol.wgs84 <- st_as_sf(pol, wkt = 'wkt', crs = CRS('+init=EPSG:4326'))
|
||||||
|
pol.rd <- st_transform(pol.wgs84, "+init=epsg:28992")
|
||||||
|
|
||||||
|
#Calculate approximate middle of polygon
|
||||||
|
res <- as.data.frame(do.call("rbind", lapply(st_geometry(pol.wgs84), st_bbox)))
|
||||||
|
res$latmid <- (res$ymax+res$ymin)/2.0
|
||||||
|
res$lonmid <- (res$xmax+res$xmin)/2.0
|
||||||
|
res
|
||||||
|
# xmin ymin xmax ymax latmid lonmid
|
||||||
|
# 1 5.563472 52.54048 5.567917 52.54773 52.5441 5.565695
|
||||||
|
|
||||||
|
# Have a look at both polygons
|
||||||
|
# wg84
|
||||||
|
dev.off()
|
||||||
|
plot(r.sentinelhub.wgs84.wdvi,main=paste("wdvi",imgdate),xlab="LON",ylab="LAT")
|
||||||
|
plot(pol.wgs84,add=TRUE, col="transparent",border="red")
|
||||||
|
# RD
|
||||||
|
dev.off()
|
||||||
|
plot(r.sentinelhub.rd.wdvi,main=paste("wdvi",imgdate),xlab="RDX",ylab="RDY")
|
||||||
|
plot(pol.rd,add=TRUE, col="transparent",border="red")
|
||||||
|
|
||||||
|
# Clip the polygon from the full rectangle figure
|
||||||
|
r.sentinelhub.rd.wdvi.pol <- mask(r.sentinelhub.rd.wdvi,pol.rd)
|
||||||
|
r.sentinelhub.wgs84.wdvi.pol <- mask(r.sentinelhub.wgs84.wdvi,pol.wgs84)
|
||||||
|
dev.off()
|
||||||
|
plot(r.sentinelhub.wgs84.wdvi.pol,main=paste("wdvi",imgdate),xlab="LON",ylab="LAT")
|
||||||
|
plot(pol.wgs84,add=TRUE, col="transparent",border="red")
|
||||||
|
#That's what we want!
|
||||||
|
|
||||||
|
# Now compare the stats
|
||||||
|
cellStats(r.sentinelhub.wgs84.wdvi,'mean') # [1] 0.2250987 # Stats from rectangle, WGS84
|
||||||
|
cellStats(r.sentinelhub.rd.wdvi,'mean') # [1] 0.2252725 # Stats from rectangle, RD. Almost but not exactly same as above
|
||||||
|
cellStats(r.sentinelhub.wgs84.wdvi.pol,'mean') # [1] 0.2275067 # Stats from raster clipped by polygon, WGS84
|
||||||
|
cellStats(r.sentinelhub.rd.wdvi.pol,'mean') # [1] 0.2275073 # Stats from raster clipped by polygon, RD. Almost but not exactly same as above
|
||||||
|
# file satelliteStats_test_BvdTFieldlabG92_20220308.csv
|
||||||
|
# "wdvi" "mean": 0.22744397204465
|
||||||
|
# Mean in csv corresponds with cellStats calculated from clipped tif!
|
||||||
|
# So while the tif returned is a non-clipped image, the downloaded statistics are from the clipped image
|
||||||
|
# Exactly as we wanted.
|
||||||
|
cellStats(r.sentinelhub.wgs84.wdvi.pol,'median') # Error in .local(x, stat, ...) : invalid 'stat'. Should be sum, min, max, sd, mean, or 'countNA'
|
||||||
|
r.sentinelhub.wgs84.wdvi.vals <- values(r.sentinelhub.wgs84.wdvi)
|
||||||
|
median(r.sentinelhub.wgs84.wdvi.vals) # [1] NA
|
||||||
|
median(r.sentinelhub.wgs84.wdvi.vals,na.rm=TRUE) # [1] 0.2318
|
||||||
|
r.sentinelhub.wgs84.wdvi.pol.vals <- values(r.sentinelhub.wgs84.wdvi.pol)
|
||||||
|
median(r.sentinelhub.wgs84.wdvi.pol.vals) # [1] NA
|
||||||
|
median(r.sentinelhub.wgs84.wdvi.pol.vals,na.rm=TRUE) # [1] 0.2338
|
||||||
|
# file satelliteStats_test_BvdTFieldlabG92_20220308.csv
|
||||||
|
# "wdvi" "mean": 0.233799993991851
|
||||||
|
# Median is same as for median(r.sentinelhub.wgs84.wdvi.pol.vals,na.rm=TRUE)
|
||||||
|
# in csv corresponds with cellStats calculated from clipped tif!
|
||||||
|
# So while the tif returned is a non-clipped image, the downloaded statistics are from the clipped image
|
||||||
|
# Exactly as we wanted.
|
||||||
|
cellStats(r.sentinelhub.wgs84.wdvi,'countNA') # [1] 27896
|
||||||
|
ncell(r.sentinelhub.wgs84.wdvi) # [1] 272718
|
||||||
|
cellStats(r.sentinelhub.wgs84.wdvi,'countNA') / ncell(r.sentinelhub.wgs84.wdvi) # [1] 0.1022888 # 10% no data? doesn't show in the plot?
|
||||||
|
cellStats(r.sentinelhub.wgs84.wdvi.pol,'countNA') # [1] 57625
|
||||||
|
summary(r.sentinelhub.wgs84.wdvi.pol.vals) # shows the same: NA's: 57625
|
||||||
|
ncell(r.sentinelhub.wgs84.wdvi.pol) # [1] 272718
|
||||||
|
populationCount = ncell(r.sentinelhub.wgs84.wdvi.pol) - cellStats(r.sentinelhub.wgs84.wdvi.pol,'countNA')
|
||||||
|
populationCount # [1] 215093
|
||||||
|
# file satelliteStats_test_BvdTFieldlabG92_20220308.csv
|
||||||
|
# "wdvi" "populationCount": 214688
|
||||||
|
# similar but not same
|
||||||
|
|
17
FarmmapsHaulmkilling/FarmmapsHaulmkilling.csproj
Normal file
17
FarmmapsHaulmkilling/FarmmapsHaulmkilling.csproj
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Data\**\*">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FarmmapsApi\FarmmapsApi.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
172
FarmmapsHaulmkilling/HaulmkillingApplication.cs
Normal file
172
FarmmapsHaulmkilling/HaulmkillingApplication.cs
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using FarmmapsHaulmkilling.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
namespace FarmmapsHaulmkilling
|
||||||
|
{
|
||||||
|
public class HaulmkillingApplication : IApplication
|
||||||
|
{
|
||||||
|
private const string DownloadFolder = "Downloads";
|
||||||
|
private const string SettingsFile = "settings.json";
|
||||||
|
|
||||||
|
private readonly ILogger<HaulmkillingApplication> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly HaulmkillingService _haulmkillingService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
private Settings _settings;
|
||||||
|
|
||||||
|
public HaulmkillingApplication(ILogger<HaulmkillingApplication> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService, HaulmkillingService haulmkillingService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
_haulmkillingService = haulmkillingService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunAsync()
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(DownloadFolder))
|
||||||
|
Directory.CreateDirectory(DownloadFolder);
|
||||||
|
|
||||||
|
LoadSettings();
|
||||||
|
|
||||||
|
// !! 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();
|
||||||
|
|
||||||
|
var myDrive = roots.SingleOrDefault(r => r.Name == "USER_FILES");
|
||||||
|
if (myDrive == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find a needed root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
|
||||||
|
if (uploadedRoot == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find a needed root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var agents = await _haulmkillingService.GetHaulmkillingAgents();
|
||||||
|
if (agents == null || agents.Count == 0)
|
||||||
|
{
|
||||||
|
_logger.LogError("No valid agents found for haulmkilling");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Item cropfieldItem;
|
||||||
|
if (string.IsNullOrEmpty(_settings.CropfieldItemCode))
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Creating cropfield");
|
||||||
|
cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDrive.Code, "Cropfield VRA Haulmkilling", 2020,
|
||||||
|
@"{""type"":""Polygon"",""coordinates"":[[[4.617786844284247,52.22533706956424],[4.618642601314543,52.225938364585989],[4.6192153806397,52.22563988897754],[4.619192414656403,52.2256242822442],[4.620306732153958,52.225031745661528],[4.620542019225217,52.22519855319158],[4.621157509147853,52.22487436515405],[4.623387917230182,52.22367660757213],[4.624563444939009,52.22304740241544],[4.624562779355982,52.223046635247019],[4.624534908813479,52.22302596787506],[4.627873021330343,52.221240670658399],[4.627504935938338,52.220104419135129],[4.627324878706837,52.22020569669098],[4.627320696113512,52.22020660117888],[4.626707169518044,52.22053923770041],[4.624700376420229,52.221619047547488],[4.623471571183885,52.22227447969577],[4.623471511010673,52.22227500174403],[4.623468838689317,52.22228052566992],[4.617786844284247,52.22533706956424]]]}");
|
||||||
|
_settings.CropfieldItemCode = cropfieldItem.Code;
|
||||||
|
SaveSettings();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Cropfield already exists trying to get");
|
||||||
|
cropfieldItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldItemCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemTaskStatus taskStatus;
|
||||||
|
if (string.IsNullOrEmpty(_settings.SatelliteTaskCode))
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Gathering satellite information for cropfield, this might take a while!");
|
||||||
|
taskStatus = await _generalService.RunAndWaitForTask(cropfieldItem, SATELLITE_TASK, null, 20);
|
||||||
|
|
||||||
|
if (taskStatus.State == ItemTaskState.Error)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Something went wrong when trying to process satellite data; {taskStatus.Message}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_settings.SatelliteTaskCode = taskStatus.Code;
|
||||||
|
SaveSettings();
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
taskStatus = await _farmmapsApiService.GetTaskStatusAsync(_settings.CropfieldItemCode, _settings.SatelliteTaskCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// find ndvi or wdvi satellite data geotiffs
|
||||||
|
var temporalItem = await _generalService.FindChildItemAsync(cropfieldItem.Code, TEMPORAL_ITEMTYPE,
|
||||||
|
"Cropfield VRA Haulmkilling, Satellite", item => item.SourceTask == SATELLITE_TASK &&
|
||||||
|
taskStatus.Finished >= item.Created &&
|
||||||
|
taskStatus.Finished <= item.Created.Value.AddHours(1));
|
||||||
|
|
||||||
|
if (temporalItem == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Temporal item not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var satelliteTiffs = await _farmmapsApiService.GetItemChildrenAsync(temporalItem.Code);
|
||||||
|
var firstSatelliteItem = satelliteTiffs.FirstOrDefault();
|
||||||
|
|
||||||
|
if (firstSatelliteItem == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Satellite item not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// must be ndvi or wdvi
|
||||||
|
var inputType = (firstSatelliteItem.Data["layers"] as JArray)?[0]["name"].ToString();
|
||||||
|
if (string.IsNullOrEmpty(inputType))
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not get the input type name from the satellite item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedAgent = agents[0];
|
||||||
|
var selectedOption = selectedAgent.ValidOptions[0];
|
||||||
|
|
||||||
|
_logger.LogInformation("Calculating application map");
|
||||||
|
var applianceMapItem = await _haulmkillingService.CalculateApplicationMapAsync(cropfieldItem,
|
||||||
|
firstSatelliteItem, inputType, selectedOption, selectedAgent);
|
||||||
|
if (applianceMapItem == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Downloading application map");
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(applianceMapItem.Code, Path.Combine(DownloadFolder,
|
||||||
|
$"{applianceMapItem.Name}_{Guid.NewGuid():N}.zip"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadSettings()
|
||||||
|
{
|
||||||
|
if (File.Exists(SettingsFile))
|
||||||
|
{
|
||||||
|
var jsonText = File.ReadAllText(SettingsFile);
|
||||||
|
_settings = JsonConvert.DeserializeObject<Settings>(jsonText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_settings = new Settings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveSettings()
|
||||||
|
{
|
||||||
|
if (_settings == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var json = JsonConvert.SerializeObject(_settings);
|
||||||
|
File.WriteAllText(SettingsFile, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
96
FarmmapsHaulmkilling/HaulmkillingService.cs
Normal file
96
FarmmapsHaulmkilling/HaulmkillingService.cs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using FarmmapsHaulmkilling.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using static FarmmapsApi.Extensions;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
namespace FarmmapsHaulmkilling
|
||||||
|
{
|
||||||
|
public class HaulmkillingService
|
||||||
|
{
|
||||||
|
private readonly ILogger<HaulmkillingService> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
public HaulmkillingService(ILogger<HaulmkillingService> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of available haulmkilling agents
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>List of haulmkilling agents</returns>
|
||||||
|
public async Task<List<HaulmkillingAgent>> GetHaulmkillingAgents()
|
||||||
|
{
|
||||||
|
var itemType = "vnd.farmmaps.itemtype.codelist.fm005";
|
||||||
|
var haulmkillingAgentItems = await _farmmapsApiService.GetItemsAsync(string.Empty, itemType);
|
||||||
|
|
||||||
|
return haulmkillingAgentItems.Select(item => item.Data.ToObject<HaulmkillingAgent>())
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an haulmkilling application map
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cropfieldItem">The context cropfield item to use</param>
|
||||||
|
/// <param name="inputItem">The geotiff item to use</param>
|
||||||
|
/// <param name="inputType">WDVI or NDVI</param>
|
||||||
|
/// <param name="agentCode">code of one of the available agents</param>
|
||||||
|
/// <param name="selectedOption">One of the available options</param>
|
||||||
|
/// <returns>Haulmkilling application map item</returns>
|
||||||
|
public async Task<Item> CalculateApplicationMapAsync(Item cropfieldItem, Item inputItem, string inputType,
|
||||||
|
string selectedOption, HaulmkillingAgent agent)
|
||||||
|
{
|
||||||
|
var taskRequest = new TaskRequest()
|
||||||
|
{
|
||||||
|
TaskType = "vnd.farmmaps.task.vrahaulmkilling"
|
||||||
|
};
|
||||||
|
taskRequest.attributes["inputCode"] = inputItem.Code;
|
||||||
|
taskRequest.attributes["inputType"] = inputType;
|
||||||
|
taskRequest.attributes["agentCode"] = agent.Code;
|
||||||
|
taskRequest.attributes["selectedOption"] = selectedOption;
|
||||||
|
taskRequest.attributes["minPercentile"] = "0.0";
|
||||||
|
|
||||||
|
var taskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskRequest);
|
||||||
|
await PollTask(TimeSpan.FromSeconds(3), async (tokenSource) =>
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Checking vrahaulmkilling task status");
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
|
||||||
|
if (itemTask.State == ItemTaskState.Error)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemName = $"VRAHaulmkilling {agent.Label}";
|
||||||
|
var applianceMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
|
||||||
|
GEOTIFF_PROCESSED_ITEMTYPE, itemName,
|
||||||
|
i => i.Updated >= itemTask.Finished &&
|
||||||
|
i.Name.ToLower().Contains(itemName.ToLower()));
|
||||||
|
|
||||||
|
if (applianceMapItem == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find the VRAHaulmkilling geotiff child item under cropfield");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return applianceMapItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
FarmmapsHaulmkilling/Models/HaulmkillingAgent.cs
Normal file
15
FarmmapsHaulmkilling/Models/HaulmkillingAgent.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace FarmmapsHaulmkilling.Models
|
||||||
|
{
|
||||||
|
public class HaulmkillingAgent
|
||||||
|
{
|
||||||
|
public string Cl { get; set; }
|
||||||
|
public string Code { get; set; }
|
||||||
|
public string Label { get; set; }
|
||||||
|
public string Options { get; set; }
|
||||||
|
|
||||||
|
public List<string> ValidOptions => Options.Split(',').ToList();
|
||||||
|
}
|
||||||
|
}
|
8
FarmmapsHaulmkilling/Models/Settings.cs
Normal file
8
FarmmapsHaulmkilling/Models/Settings.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace FarmmapsHaulmkilling.Models
|
||||||
|
{
|
||||||
|
public class Settings
|
||||||
|
{
|
||||||
|
public string CropfieldItemCode { get; set; }
|
||||||
|
public string SatelliteTaskCode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
23
FarmmapsHaulmkilling/Program.cs
Normal file
23
FarmmapsHaulmkilling/Program.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace FarmmapsHaulmkilling
|
||||||
|
{
|
||||||
|
class Program : FarmmapsProgram<HaulmkillingApplication>
|
||||||
|
{
|
||||||
|
private static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
await new Program().Start(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Configure(IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
serviceCollection.AddLogging(opts => opts
|
||||||
|
.AddConsole()
|
||||||
|
.AddFilter("System.Net.Http", LogLevel.Warning))
|
||||||
|
.AddTransient<HaulmkillingService>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,9 +6,6 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="appsettings.json">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Data\**\*">
|
<None Update="Data\**\*">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
@ -44,20 +44,20 @@ namespace FarmmapsHerbicide
|
|||||||
var agents = await _herbicideService.GetHerbicideAgents();
|
var agents = await _herbicideService.GetHerbicideAgents();
|
||||||
_liberatorTarweAgent = agents.SingleOrDefault(a => a.Name.Equals("Liberator"));
|
_liberatorTarweAgent = agents.SingleOrDefault(a => a.Name.Equals("Liberator"));
|
||||||
|
|
||||||
await SingleLutumTiffFlow(roots);
|
// await SingleLutumTiffFlow(roots);
|
||||||
await MultiVanDenBorneShapeFlow(roots);
|
await MultiVanDenBorneShapeFlow(roots);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SingleLutumTiffFlow(List<UserRoot> roots)
|
private async Task SingleLutumTiffFlow(List<UserRoot> roots)
|
||||||
{
|
{
|
||||||
var myDrive = roots.SingleOrDefault(r => r.Name == "My drive");
|
var myDrive = roots.SingleOrDefault(r => r.Name == "USER_FILES");
|
||||||
if (myDrive == null)
|
if (myDrive == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Could not find a needed root item");
|
_logger.LogError("Could not find a needed root item");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "Uploaded");
|
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
|
||||||
if (uploadedRoot == null)
|
if (uploadedRoot == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Could not find a needed root item");
|
_logger.LogError("Could not find a needed root item");
|
||||||
@ -91,20 +91,20 @@ namespace FarmmapsHerbicide
|
|||||||
|
|
||||||
private async Task MultiVanDenBorneShapeFlow(List<UserRoot> roots)
|
private async Task MultiVanDenBorneShapeFlow(List<UserRoot> roots)
|
||||||
{
|
{
|
||||||
var myDrive = roots.SingleOrDefault(r => r.Name == "My drive");
|
var myDrive = roots.SingleOrDefault(r => r.Name == "USER_FILES");
|
||||||
if (myDrive == null)
|
if (myDrive == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Could not find a needed root item");
|
_logger.LogError("Could not find a needed root item");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "Uploaded");
|
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
|
||||||
if (uploadedRoot == null)
|
if (uploadedRoot == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Could not find a needed root item");
|
_logger.LogError("Could not find a needed root item");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("Creating cropfield");
|
_logger.LogInformation("Creating cropfield");
|
||||||
var cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDrive.Code, "Cropfield VRA Herbicide van den borne", 2020,
|
var cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDrive.Code, "Cropfield VRA Herbicide van den borne", 2020,
|
||||||
@"{ ""type"": ""Polygon"", ""coordinates"": [ [ [ 5.833813406930386, 52.662044400144573 ], [ 5.835448040282574, 52.662663232992713 ], [ 5.836017878606523, 52.662878934715643 ], [ 5.836051608552347, 52.66284538659815 ], [ 5.836752490453029, 52.662168665385018 ], [ 5.837926180228544, 52.662604908046319 ], [ 5.839506445610824, 52.661074514977884 ], [ 5.839509138399547, 52.661071906335934 ], [ 5.83609382583743, 52.659780657270744 ], [ 5.834864415345847, 52.661000863063798 ], [ 5.833813406930386, 52.662044400144573 ] ] ] }");
|
@"{ ""type"": ""Polygon"", ""coordinates"": [ [ [ 5.833813406930386, 52.662044400144573 ], [ 5.835448040282574, 52.662663232992713 ], [ 5.836017878606523, 52.662878934715643 ], [ 5.836051608552347, 52.66284538659815 ], [ 5.836752490453029, 52.662168665385018 ], [ 5.837926180228544, 52.662604908046319 ], [ 5.839506445610824, 52.661074514977884 ], [ 5.839509138399547, 52.661071906335934 ], [ 5.83609382583743, 52.659780657270744 ], [ 5.834864415345847, 52.661000863063798 ], [ 5.833813406930386, 52.662044400144573 ] ] ] }");
|
||||||
@ -144,14 +144,14 @@ namespace FarmmapsHerbicide
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create appliance map
|
// create appliance map
|
||||||
_logger.LogInformation("Calculating appliance map");
|
_logger.LogInformation("Calculating application map");
|
||||||
var applianceMapItem = await _herbicideService.CalculateApplicationMapAsync(cropfieldItem, _liberatorTarweAgent, tiffInputItem, tiffInputExtraItem);
|
var applianceMapItem = await _herbicideService.CalculateApplicationMapAsync(cropfieldItem, _liberatorTarweAgent, tiffInputItem, tiffInputExtraItem);
|
||||||
if (applianceMapItem == null)
|
if (applianceMapItem == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("Downloading appliance map");
|
_logger.LogInformation("Downloading application map");
|
||||||
await _farmmapsApiService.DownloadItemAsync(applianceMapItem.Code, Path.Combine(DownloadFolder,
|
await _farmmapsApiService.DownloadItemAsync(applianceMapItem.Code, Path.Combine(DownloadFolder,
|
||||||
$"{applianceMapItem.Name}_{Guid.NewGuid():N}.zip"));
|
$"{applianceMapItem.Name}_{Guid.NewGuid():N}.zip"));
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,15 @@ namespace FarmmapsHerbicide
|
|||||||
};
|
};
|
||||||
taskRequest.attributes["inputCode"] = inputItem[0].Code;
|
taskRequest.attributes["inputCode"] = inputItem[0].Code;
|
||||||
taskRequest.attributes["agent"] = JsonConvert.SerializeObject(agent);
|
taskRequest.attributes["agent"] = JsonConvert.SerializeObject(agent);
|
||||||
|
|
||||||
|
// check for the layer name
|
||||||
|
taskRequest.attributes["inputLayerName"] = inputItem[0].Data["layers"][0]["name"].ToString();
|
||||||
|
|
||||||
if (inputItem.Length > 1)
|
if (inputItem.Length > 1)
|
||||||
|
{
|
||||||
taskRequest.attributes["extraInputCode"] = inputItem[1].Code;
|
taskRequest.attributes["extraInputCode"] = inputItem[1].Code;
|
||||||
|
taskRequest.attributes["extraInputLayerName"] = inputItem[1].Data["layers"][0]["name"].ToString();
|
||||||
|
}
|
||||||
|
|
||||||
var taskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskRequest);
|
var taskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskRequest);
|
||||||
await PollTask(TimeSpan.FromSeconds(3), async (tokenSource) =>
|
await PollTask(TimeSpan.FromSeconds(3), async (tokenSource) =>
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"Authority": "https://accounts.farmmaps.awtest.nl/",
|
|
||||||
"Endpoint": "https://farmmaps.awtest.nl/",
|
|
||||||
"BasePath": "api/v1",
|
|
||||||
"DiscoveryEndpointUrl": "https://accounts.farmmaps.awtest.nl/.well-known/openid-configuration",
|
|
||||||
"RedirectUri": "http://example.nl/api",
|
|
||||||
"ClientId": "",
|
|
||||||
"ClientSecret": "",
|
|
||||||
"Scopes": ["api"]
|
|
||||||
}
|
|
697
FarmmapsNbs/Data/Scan1_20190605_sample.json
Normal file
697
FarmmapsNbs/Data/Scan1_20190605_sample.json
Normal file
@ -0,0 +1,697 @@
|
|||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"name": "Scan_1_20190605_sample",
|
||||||
|
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
|
||||||
|
"features": [
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632010666237043, 51.965409777118658 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632082608253357, 51.965424339614621 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631300040862797, 51.967001549750549 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631196787891127, 51.96698346388041 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631159877293195, 51.966976509187006 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631122103651872, 51.966967739237141 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631085076025106, 51.966958383230711 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631046098187851, 51.966949513720984 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631006063610674, 51.966940066889208 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630968215413497, 51.966930792517452 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63093087706139, 51.966920273132438 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630893631190286, 51.966908233402968 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630857589515115, 51.96689629323334 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630822718297374, 51.966884358486894 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630785742334286, 51.966873071850813 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630749990147959, 51.966861346614202 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63092173522508, 51.96651968778518 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630364280093167, 51.966778192960227 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630398944061073, 51.966782730506807 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630432685421435, 51.966788041872078 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630466292354725, 51.966794549869846 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630499289080308, 51.966802100770551 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630532204115467, 51.966809709348624 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630564701047347, 51.966817245887519 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630598783761285, 51.966823907614867 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630262572206599, 51.966749047311851 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630283519745355, 51.966720985761285 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630304548410384, 51.96669280837235 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630326804489325, 51.966667562442957 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630349558239816, 51.966644564250878 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 17.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630372433482668, 51.966622255435055 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630395563806388, 51.966599089336441 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630418491511454, 51.966575349699973 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630448033113046, 51.966556416988652 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630476869401098, 51.96653044607239 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 17.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630505792184982, 51.966504363270154 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630533938875997, 51.966480093663954 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63056201972203, 51.966454521880948 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630590187063893, 51.966428838211975 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630617276000882, 51.966403393379643 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630643096107006, 51.966376699520417 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630668603575701, 51.966349138333207 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630692951729843, 51.966319608392638 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63071701974563, 51.966291828172757 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630740141893368, 51.966262959222597 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630762333237774, 51.966233906955324 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630783477153608, 51.966202972430544 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630900496958464, 51.966049171250837 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630926691654558, 51.966021424577221 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630952750455275, 51.965992369648113 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63097721118779, 51.965963236118206 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631001067732194, 51.965934172992284 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631023805954535, 51.96590545534535 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631042629235482, 51.965876945626057 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631059661230556, 51.965850250099386 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631076149616356, 51.965824428923327 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631089888852364, 51.965801576278089 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631100240334856, 51.965788569095068 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631112199258926, 51.965771243121416 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 17.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631157584607992, 51.965715091973181 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 17.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631160888880389, 51.965702735526136 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631172864420758, 51.965683452137199 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 17.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631199697345719, 51.965666395296779 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.6312114259468, 51.96564897864048 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631223117864331, 51.965631468955607 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631239918435618, 51.965613557205145 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631260389083833, 51.965593230804551 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631284410654336, 51.965568279368703 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631313183414724, 51.965536294712066 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631343500977401, 51.965503593406389 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631374526085172, 51.965470505603676 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631404934037055, 51.965438306124469 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631436049534021, 51.965405720148205 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631499064752424, 51.965373146511382 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631539913617539, 51.965354075585381 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631632082355162, 51.965342697711741 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631619341966687, 51.965311058942461 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631633771469954, 51.965285207841212 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631646461949604, 51.965262483367049 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631657814827253, 51.965239219614794 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631672789475205, 51.965233029356959 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63169312632789, 51.965220316276188 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631712295502603, 51.965204214017305 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631734220160585, 51.965184984889071 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631760113152819, 51.965161644517345 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631785533263169, 51.965137599601249 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631810893865079, 51.965113339142256 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631835939212403, 51.965088608987017 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631859747625065, 51.965063431626419 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631883713665021, 51.965038489113951 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631906600397608, 51.965013334244219 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631928994943112, 51.964987572948985 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631950549807836, 51.964962971367598 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631971458043838, 51.964938548311537 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63199355982561, 51.964913239000161 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632015505572917, 51.964888204740127 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632035508248395, 51.964862686257149 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63205303705455, 51.964836273363431 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632070038248862, 51.964810470080849 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632074648815943, 51.964792216788787 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63208233012088, 51.964771306323591 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632089064069232, 51.964748476870255 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632095251100534, 51.964726355146915 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632101518538311, 51.964704860747091 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632108033758102, 51.964681071003263 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632114679335852, 51.964655064729101 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632122108271587, 51.964628702997096 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632128869680566, 51.964602108009821 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632134379628159, 51.964576693634406 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632139027404113, 51.964551517292747 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632143935704694, 51.964528124802818 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632148260070644, 51.964506146180057 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632152087279736, 51.964488248345802 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632157320200565, 51.964474601861291 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632164742191119, 51.96446485126868 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632175456833743, 51.964454423592365 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632187358459544, 51.964447286975272 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632202953176948, 51.964442099992645 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632218591283241, 51.964438246470671 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632237772817979, 51.964438657232314 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632260166407019, 51.964443980499169 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632298019385736, 51.96445102052774 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63232804853283, 51.964458457618896 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632368081024315, 51.9644663341426 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632415864905083, 51.964475735777484 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632465924824645, 51.964485483313247 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63251616008388, 51.964494857678815 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632564412068048, 51.964503434159653 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632613019510041, 51.964512793998495 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632664387098681, 51.964533738166942 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632716272666014, 51.964544048739292 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632767728740356, 51.964554988228002 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632820260936416, 51.96456512027504 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632872791539648, 51.96457474242262 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632925339855262, 51.964583756551875 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632976789558299, 51.964592656442726 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633028533617896, 51.964601614249197 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633080259965109, 51.964611180073987 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633131478005686, 51.964621257391059 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633182792572288, 51.964630844113877 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633234343579832, 51.964640783108869 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633285637248405, 51.964649958051076 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633337167357913, 51.964659485265457 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633388814891483, 51.964668933666189 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633440973917341, 51.964678890373534 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633493173146433, 51.964689160742665 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633546157326342, 51.964699585553433 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633598808539285, 51.964710148686294 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633651105887228, 51.964720438360622 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633703441845586, 51.964730531797244 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633794571767939, 51.964747544652738 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633794571767939, 51.964747544652738 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 20.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633831659101048, 51.964754332120812 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 20.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633861956928186, 51.964759885648583 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633886690842941, 51.964767300057588 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633907448459317, 51.96477627621281 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63392412369433, 51.964784245311705 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63393878182235, 51.964793142461978 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633941152603049, 51.964798704781536 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633946373608926, 51.964806356650428 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633944748212168, 51.964832229572281 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633944748212168, 51.964832229572281 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633940859901807, 51.964849401964152 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633926919314516, 51.964888139414079 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633926919314516, 51.964888139414079 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633916197918003, 51.96490896131737 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633906222861894, 51.964930133900005 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633895088091945, 51.964950466801866 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633868306677693, 51.96499075446561 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633868306677693, 51.96499075446561 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633854463190307, 51.965010350584045 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633826761688805, 51.965051170638112 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633826761688805, 51.965051170638112 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.6337974855072, 51.965090152110506 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.6337974855072, 51.965090152110506 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633780915589996, 51.965109619463789 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633748451246476, 51.965151336922972 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633748451246476, 51.965151336922972 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633714273709472, 51.965197099745922 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633694930596621, 51.965220301986875 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633694930596621, 51.965220301986875 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633654949520642, 51.965266553619962 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633654949520642, 51.965266553619962 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633611849539437, 51.965312599267094 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633589783182423, 51.96533669254184 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633589783182423, 51.96533669254184 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633548727577551, 51.965384261516064 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633548727577551, 51.965384261516064 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633504084964058, 51.965432449658387 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633481312469873, 51.965456505915554 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633481312469873, 51.965456505915554 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633437435501988, 51.965504946618367 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633415603993086, 51.965528882265822 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633393777262662, 51.965554347611672 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633372479736908, 51.965579713245837 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633372479736908, 51.965579713245837 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633330688941416, 51.965630500836959 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633309843399508, 51.965656159234854 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633289332417394, 51.965682189210128 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633267367364882, 51.965707321589008 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633245444108432, 51.965733277529104 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63322428649759, 51.965759486029704 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633203069378308, 51.965785478987385 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633203069378308, 51.965785478987385 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633160189527199, 51.965839211736892 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633137172436658, 51.965866583136993 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633115157432658, 51.965894559369737 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633093237361861, 51.965921535108762 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633071399290361, 51.965949648070776 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633050798153524, 51.965978208238177 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633030275830336, 51.966006885829607 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633008006673021, 51.966035117808509 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632986916534749, 51.966064091349324 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632964766394316, 51.966092754414049 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632942009828396, 51.966121909665837 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632920726638075, 51.966151864395179 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632901304520283, 51.966181166124493 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632879389227964, 51.966209671561906 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632854356623249, 51.966238480912835 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632831046768978, 51.966266304296781 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632809242529409, 51.9662926913227 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632788284341925, 51.966319958232638 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632767129916735, 51.966347186532154 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632746602815066, 51.966374334425204 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632724525116975, 51.966401075316121 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632701720383688, 51.966427367408841 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63267930653298, 51.966453226822921 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632657581107059, 51.966479731272898 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632636407376665, 51.966507057691288 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632614977900128, 51.966534129956337 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632593548423587, 51.966561202221392 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632550547859148, 51.966597467936964 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632526967123662, 51.966622869687171 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63250279577741, 51.966648518781128 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632479723399362, 51.966674689668984 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632454741438549, 51.966699171328116 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632430927146053, 51.966724298394652 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632405711511479, 51.966747777359124 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632381100391143, 51.96677205291796 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632357464625519, 51.966796918970786 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632333787616482, 51.966821565253333 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632309217622812, 51.966845332571452 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632285142083107, 51.966868825089151 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632261066660153, 51.966893045617823 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632236936323814, 51.966917458460109 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63221360269856, 51.966941994799136 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632190653700502, 51.966966640964934 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632167677245755, 51.966991383287514 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632144906774577, 51.967015768439595 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632122493473902, 51.967040359575257 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632101549631654, 51.967063082371574 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632082239987994, 51.967083359887731 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632066968229401, 51.967100422519096 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632054594728002, 51.967117168756388 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632041383272102, 51.967133571726649 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63202950410792, 51.967149315152518 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632015770274363, 51.967163177036078 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631997571284127, 51.967171188075604 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631975333124572, 51.967174405879135 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631951720962886, 51.967175151412853 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631922970780427, 51.96717130992765 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631890030591969, 51.967164296085315 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631849534909537, 51.967153148901616 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631795742015371, 51.967137580840159 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631732429598087, 51.967119294566139 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631669446894614, 51.96710131043249 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631607769376414, 51.967084946944198 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631549457346189, 51.96706954444015 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631494661874119, 51.967054938063448 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63144799848657, 51.967042445735309 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631404508273389, 51.967030859478037 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631367487905698, 51.967020288651383 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631335728471772, 51.96700986807766 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63123997070828, 51.96698094707623 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631213668326826, 51.966980175888558 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631189174123036, 51.966978225508939 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631162921749617, 51.966974037085656 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631135859652134, 51.966967589382179 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631107108517693, 51.966960578514318 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631075787377711, 51.966953213991921 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631042379417565, 51.966944472813559 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631007202441451, 51.966935834506373 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630973432092272, 51.966927860579069 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630940890943037, 51.966918277593827 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630910978541855, 51.966907433781977 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630878430313784, 51.966897534648204 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630846301105406, 51.966889397451567 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63081698349525, 51.966881102408756 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630793297816052, 51.966874294428095 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630775626037664, 51.966867668098168 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630761295283381, 51.966859100748401 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630754031858518, 51.966848319159517 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630963652961919, 51.966540719697008 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630976306023621, 51.966544100529674 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630988190687285, 51.966552270888876 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631026321521441, 51.966567410634404 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631042736060158, 51.966567105808792 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631060730234328, 51.966566732049564 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631082419610281, 51.966567621414946 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631108724862846, 51.966572012734503 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631146761361664, 51.966580481781541 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631195457828719, 51.966593866627306 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631257533877585, 51.966611383880441 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631326230958873, 51.966630479718269 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631392414293415, 51.966649273765967 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631455534280351, 51.966666777115641 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631517527842388, 51.966683854828183 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631580414389061, 51.966701811505132 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63164457831407, 51.966719300951318 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63170805535476, 51.966736282273558 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631771999509475, 51.966753812963169 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63183752341639, 51.966772002730139 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631902841222987, 51.966789821656619 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631967856889212, 51.966807970296948 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632032020814219, 51.966825459743127 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632087544414017, 51.966840794014054 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632132710652947, 51.966853794816387 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632168357252005, 51.966863349395176 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632198027992544, 51.966868701698964 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632221901634936, 51.966871046736046 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632241502434247, 51.966867595842501 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63225725672809, 51.966861590659285 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632272928418358, 51.966854417924502 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632287006219449, 51.966844086152307 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632303061369411, 51.966829743134497 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632323593711516, 51.966810646723147 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632346158432627, 51.966788074763514 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632369025294105, 51.966765173090081 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632390463590317, 51.966742175493351 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632412108103603, 51.96672027674807 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632431445320705, 51.966700631086084 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632448406541519, 51.966683114893911 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632460519029212, 51.966666190129743 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632466010951484, 51.966650598824806 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632469566184549, 51.966635598480885 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632467544907014, 51.966622645703694 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632459919195182, 51.966608924606099 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632448886868716, 51.966594750764941 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63243181150137, 51.966585715178077 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632412827368515, 51.96658008643935 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632394104132612, 51.966573908216517 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632371562198188, 51.96656726358016 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632339377243898, 51.966558697442316 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632296752325161, 51.966546630284292 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632243302931533, 51.966531680290295 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632185787495641, 51.966515673272006 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632131349077325, 51.966500544867898 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632076141404617, 51.966485196810225 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632017458300414, 51.966468544384533 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631955052654487, 51.966451453002016 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631890298001966, 51.966433482888604 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63182237017507, 51.966414606704305 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631754332521401, 51.966396115147219 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631688712340938, 51.966377169912576 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631622927186817, 51.966357345596769 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631557293102879, 51.966337356424063 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631493266227835, 51.966317930171918 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631428126831368, 51.966299122220732 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631360391201319, 51.966279572938866 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631292600657887, 51.966260215970571 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631224947514668, 51.966241106229269 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631157019687771, 51.966222230044991 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631089380331272, 51.966203436230785 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631023622750595, 51.966184243769149 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630966807752238, 51.96616760477994 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630916229275862, 51.966153162559628 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63087249171895, 51.966140985691595 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630834757127003, 51.966130730908766 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630462852336526, 51.96654695915511 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630489203265865, 51.966523625091526 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630514801122816, 51.966501496383479 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63054022598809, 51.966479591447381 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630563654340234, 51.966457841221739 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630583956994117, 51.966436087779591 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630602053580789, 51.966419153389978 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630619912006699, 51.966409810658917 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630636901410908, 51.966408644406393 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.630654169259733, 51.966413592274293 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63066831293308, 51.966423275068536 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631189550844848, 51.965995702800917 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631210786504165, 51.965994479374025 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631236365069467, 51.965996046855174 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631268832852416, 51.965999377481282 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631305971729838, 51.966003830994957 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631359107165732, 51.966012451055974 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631426394207129, 51.966024772746614 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631497234425215, 51.966038201205251 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631565916028564, 51.966051204949387 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631631258405307, 51.966062532517611 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631730819823416, 51.966081017712632 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631799227968242, 51.966094375321745 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631867595909831, 51.966107419269122 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63193692254908, 51.966119734588453 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632006347307183, 51.966132069212996 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632075184945002, 51.96614479790577 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632144003277611, 51.966157624717397 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632213333102515, 51.966170959835658 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632281543416811, 51.966183768934911 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632349871155165, 51.966196499220501 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632418195707868, 51.966208209707176 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632486994735273, 51.966221134637664 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632554519810435, 51.966234318499929 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632612467848543, 51.966245414214391 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632661842528968, 51.966255536513195 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632704760670389, 51.966264286549574 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632739982152489, 51.966270197319297 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632767482891588, 51.966271837242786 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632792250829566, 51.966271308803293 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632812045352388, 51.966267050063301 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.6328256488306, 51.966258515698613 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632836677134983, 51.96624804781905 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632851944046488, 51.966232095032069 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632870407275325, 51.96620973884319 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632888371945773, 51.966184736630971 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632906569871515, 51.966159066891997 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632926157580727, 51.966132549508124 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632947397190867, 51.966107478230505 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632968152578052, 51.966084350024722 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632984526257552, 51.966064844061037 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632996828705473, 51.966047900337266 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63300244613758, 51.966031781576248 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633001341536287, 51.966017193915171 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632999183304134, 51.966004335375828 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632994956420676, 51.965994738842262 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632988075549742, 51.9659830913698 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632977691262306, 51.96597371018786 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632964170357274, 51.965964731038284 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632942199698628, 51.965962956169648 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632918158987141, 51.965957716494941 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632890431555351, 51.965952566783642 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632855676583825, 51.965945320960415 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632814230225179, 51.96593686050209 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632762814354073, 51.965926234675145 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63270537621543, 51.965915137367851 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63264409054354, 51.965902875376941 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632578741795494, 51.965889508210871 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632515257305631, 51.965876507843696 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632450614694753, 51.965863177695198 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63238589645588, 51.965850749921579 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632320843657217, 51.965837950570574 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632254319075777, 51.965824861641494 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632188088850892, 51.965811830628049 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632120838827081, 51.965798802800244 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632052549699138, 51.965785876276932 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631985338285736, 51.96577265221142 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63192994729746, 51.96575675104183 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631865269261824, 51.965744636929962 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63180106251524, 51.965732717462984 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.6317360933087, 51.965721565234432 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63167159379839, 51.965710097751291 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631608368240323, 51.965698371336359 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631547476636665, 51.965686696465745 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631497162563783, 51.965677204676119 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631456837308569, 51.965669780136288 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631419238483169, 51.965662484361566 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631383502323129, 51.965655045486287 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631353981482674, 51.965647096902849 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631337733665302, 51.965642169804489 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631318504596587, 51.96564029286121 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631303819545565, 51.965635764144331 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631293337802729, 51.965629900436703 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 17.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631283230813583, 51.96562335148483 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631276292074923, 51.96561447827203 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631274117455283, 51.965603511457097 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631277062046921, 51.965589988536564 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631279282071387, 51.965576536343754 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631286108923168, 51.965562772474563 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631297902973225, 51.96554715740546 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631313758876002, 51.965528758211263 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631337819769449, 51.965503361293997 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631364544447528, 51.965476269014985 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631390958635063, 51.965448116738052 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631419260973789, 51.965417392519235 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63147635897084, 51.965378374080871 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631513332951782, 51.965360676207183 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631550212587447, 51.965343280159551 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631613737124256, 51.965346324349724 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631653721639668, 51.965345120801921 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631693765472229, 51.965350349709453 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631735562510217, 51.965358063827367 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631781089657398, 51.965367021442546 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631828207604236, 51.965376699721617 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631880133374805, 51.965387323955746 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631934865981663, 51.965398704278513 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632188933255327, 51.96544805039634 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63226087527164, 51.965462612892303 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632332777084715, 51.965476861726515 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632405072966027, 51.965491697681003 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632476699727754, 51.965505790480741 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632547835895222, 51.965519786754463 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632618127603434, 51.96553341304363 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632687595750425, 51.965547081128854 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632755804471894, 51.965559380328628 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632824561703241, 51.965571481697886 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632891161912672, 51.965583668252094 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632955252828027, 51.9655961764322 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633018126113923, 51.965608139288079 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633069834748756, 51.965618313131166 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633117716748378, 51.965627734071269 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633159454277923, 51.965635232646278 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633194423199535, 51.965641909061596 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633223641719302, 51.965647250232117 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633246669194461, 51.965648315777926 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633264728032941, 51.965647180721639 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633278579101873, 51.965642567925372 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633292702036504, 51.965637091364655 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633306757498561, 51.965628849763689 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633320233995759, 51.965617334815875 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633336067129514, 51.96560057618003 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633351086450295, 51.965580701824614 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633367281604473, 51.96556054923218 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633384691202451, 51.965539922165057 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633401788731497, 51.965519845200632 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633418004783705, 51.96550010438883 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633435768246678, 51.965479750780226 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633454654405911, 51.965460942989566 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633473130377361, 51.965442665996406 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633487374304282, 51.965425696596128 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633493866841926, 51.965407202084648 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633495908606481, 51.965389054875565 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633492383273004, 51.965371748748787 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633481555157146, 51.965358407388031 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633462246832687, 51.965348799130815 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633438299461574, 51.965342049062919 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633413666851322, 51.965335673758034 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633388329696733, 51.965329771335043 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633355968188059, 51.965322792599018 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633315774883627, 51.965313661428304 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633265417421858, 51.965302836177997 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63321101937479, 51.965291827432587 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63315485678122, 51.96528098109296 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633094869145259, 51.965269891749799 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633034233287747, 51.965258471032506 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632975461688416, 51.965247417114092 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632914824238077, 51.965235486497313 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632854659669618, 51.965224260424904 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632792318774042, 51.965213217656277 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632728977384747, 51.965202079954452 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63266657698073, 51.965190821642921 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63260419428909, 51.965178955313071 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632540946240167, 51.965166307218063 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632479620365042, 51.965153731565394 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632418825287409, 51.965141566100499 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632358424278009, 51.965129987755923 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632276428889627, 51.965110865093131 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632220814805929, 51.965099820922966 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632166358843247, 51.96508910653413 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632118145469488, 51.965080333815578 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632074154392003, 51.96507341101978 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632036459040578, 51.965066605839326 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.6320017958166, 51.965057339723444 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631974438560652, 51.965045128640497 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631957784414961, 51.965031354409803 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631947704232332, 51.965018873627848 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631941704838238, 51.965006890002741 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631939837776989, 51.964993069580089 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63194477793409, 51.964979875079422 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631952721165183, 51.964967475277817 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631962028503241, 51.964952286352315 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.6319731760158, 51.96493603264615 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.631987317045396, 51.964917514242288 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632001828059538, 51.964898151379153 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632016477395772, 51.964879121482987 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632030888698236, 51.964859229415183 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632043594962642, 51.964839715296073 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632055971445729, 51.964821359297964 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632067387638335, 51.964803222028436 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632078448373115, 51.964784301400897 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632087416372907, 51.964767211199621 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632098587969149, 51.964752389073013 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632114884236533, 51.964739492497138 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63213656888534, 51.964731325122642 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632163690082934, 51.9647307501086 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632194292014876, 51.964733204036357 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632230197143286, 51.964738230143574 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632271600113045, 51.964745357141219 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632314264101145, 51.964754362923756 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632357161344535, 51.964762701179545 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632402059575369, 51.964771229301725 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632449175929382, 51.964780397681331 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632495135831395, 51.964796710767253 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632557031114427, 51.964809500370016 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632618355396726, 51.964821566123206 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632680836207215, 51.96483345175826 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63274396364643, 51.964845158867995 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632807269610968, 51.964857512606436 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63287161467964, 51.964869765040405 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63293535013717, 51.964881489862499 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632998770340113, 51.964892744988383 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63306281786658, 51.964903919707787 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63312582628891, 51.964915195731692 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633188344116983, 51.964926375229588 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633249155314168, 51.964937422776693 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633309869985329, 51.964948960918051 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63336823139687, 51.96496054563395 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633422906088116, 51.964972220313278 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633468396217712, 51.964981884065615 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633511703648885, 51.964989691523911 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633555657708788, 51.964997320456895 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633596589389489, 51.965004252809642 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633629986816647, 51.965010110442229 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63365800860499, 51.965015318069121 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633677022764186, 51.965018651498305 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633691172776859, 51.965021843228456 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633706287858495, 51.965026345928436 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633724788741281, 51.965034878063925 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633744769370974, 51.96504624927482 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633762317927406, 51.965057549636192 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633774630759939, 51.965069042858332 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63377871116589, 51.965081973840014 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633778186357114, 51.965096037074908 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633773625741519, 51.965111446513099 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63376420575788, 51.965128243950652 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633750799727613, 51.965149760650043 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633731398699146, 51.96517325724755 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633709689392779, 51.965198643779743 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633688039594853, 51.965224245854856 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63366654423857, 51.96524906297914 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633645325526462, 51.965274546037364 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633623613034441, 51.965298912770649 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633601609371521, 51.965324241387215 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633580664117935, 51.965349370580448 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633558029945842, 51.965373759804585 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.4, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633535495485423, 51.965398678233377 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633512803397712, 51.965423361814068 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633489524189721, 51.965448439462982 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633466520033076, 51.96547367314637 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633443731419342, 51.9654988473213 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633421216264131, 51.965523667631253 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63339872200695, 51.965548899721803 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63337748239681, 51.965573970999415 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633355829413233, 51.965598553275598 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633334766735592, 51.965623761282473 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633314037024913, 51.965648830967254 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633294407519637, 51.965674524789918 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633275049880059, 51.965699354848105 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633255103527371, 51.965724069075073 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633233394221003, 51.965749455607266 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633211865032788, 51.965775998667652 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633190218420514, 51.965802620541687 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633168044196399, 51.965829852026864 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63314553541249, 51.965856711934663 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633123755256605, 51.96588453054013 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633102465694982, 51.965912445671613 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633061692914298, 51.965968937090025 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633061692914298, 51.965968937090025 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633041384541194, 51.965997045273568 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633020899235584, 51.966025016727855 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.633000433235184, 51.966052890063267 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632957749621777, 51.966106661423183 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.5, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632957749621777, 51.966106661423183 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632915204330462, 51.966160765750047 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632894146431297, 51.966187503455309 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632894146431297, 51.966187503455309 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632850693986631, 51.96624000245582 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632830477361071, 51.966266090346693 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632809771734077, 51.966292591611023 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632789243039583, 51.966319229604608 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632768045225506, 51.96634512444345 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.3, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632747199683599, 51.966370782841345 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632726648498247, 51.966396499154854 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632704316646839, 51.966423495791908 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632681040624496, 51.966449593239751 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632657904517068, 51.96647653355403 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632636124361185, 51.966504352159497 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632614244493626, 51.96653164156028 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.6325922278968, 51.966559107893566 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63254847341948, 51.96659562763805 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.6, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632524233256371, 51.966620425107536 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632498564644743, 51.966645854664698 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632472717389492, 51.966670817224575 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632447598145217, 51.96669577966771 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.2, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632423220698642, 51.966721057921198 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632398898165457, 51.966746143861052 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632372570476458, 51.966773153170408 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63234680582478, 51.966799283281851 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632321700483979, 51.966825289663056 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632296691299976, 51.966851323500947 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632272369000289, 51.966877865462777 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632247648403433, 51.966904709681721 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632222680579597, 51.966931691300893 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632197300555116, 51.966957931239108 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632172703571752, 51.966984706757955 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632147378460661, 51.967010754382571 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632122369393407, 51.967037516231443 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.9, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632097319199492, 51.967064786321004 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.1, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632072447532451, 51.967091795396861 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 19.0, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632050405539252, 51.967119092476111 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.7, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.632028652133199, 51.967147199936434 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "IRMI": 18.8, "instance": 1 }, "geometry": { "type": "Point", "coordinates": [ 5.63200626687297, 51.967175334970179 ] } }
|
||||||
|
]
|
||||||
|
}
|
Binary file not shown.
@ -2,19 +2,19 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="appsettings.json">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Data\**\*">
|
<None Update="Data\**\*">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Update="NitrogenInput.json">
|
<None Update="NitrogenInput.json">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="InputData-NBS.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
10
FarmmapsNbs/FarmmapsNbs.csproj.user
Normal file
10
FarmmapsNbs/FarmmapsNbs.csproj.user
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ShowAllFiles>false</ShowAllFiles>
|
||||||
|
<ActiveDebugProfile>FarmmapsNbs</ActiveDebugProfile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
@ -5,7 +5,8 @@ namespace FarmmapsNbs.Models
|
|||||||
{
|
{
|
||||||
public class NitrogenInput
|
public class NitrogenInput
|
||||||
{
|
{
|
||||||
public string ZippedShapeFile { get; set; }
|
public bool UseCreatedCropfield { get; set; }
|
||||||
|
public string File { get; set; }
|
||||||
public string InputVariable { get; set; }
|
public string InputVariable { get; set; }
|
||||||
public string OutputFileName { get; set; }
|
public string OutputFileName { get; set; }
|
||||||
public DateTime PlantingDate { get; set; }
|
public DateTime PlantingDate { get; set; }
|
||||||
@ -13,5 +14,21 @@ namespace FarmmapsNbs.Models
|
|||||||
public string PotatoPurposeType { get; set; }
|
public string PotatoPurposeType { get; set; }
|
||||||
public int TargetYield { get; set; }
|
public int TargetYield { get; set; }
|
||||||
public JObject GeometryJson { get; set; }
|
public JObject GeometryJson { get; set; }
|
||||||
|
public string InputLayerName { get; set; }
|
||||||
|
public string fieldName{ get; set; }
|
||||||
|
public bool storeSatelliteStatistics { get; set; }
|
||||||
|
public bool GenerateTaskmap { get; set; }
|
||||||
|
public string OutputType { get; set; }
|
||||||
|
public string DdiCode { get; set; }
|
||||||
|
public string CellWidth { get; set; }
|
||||||
|
public string CellHeight { get; set; }
|
||||||
|
public string Centered { get; set; }
|
||||||
|
public JObject StartPoint { get; set; }
|
||||||
|
public JObject EndPoint { get; set; }
|
||||||
|
public string Angle { get; set; }
|
||||||
|
public string Precision { get; set; }
|
||||||
|
public string MaximumClasses { get; set; }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
9
FarmmapsNbs/Models/Settings.cs
Normal file
9
FarmmapsNbs/Models/Settings.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace FarmmapsNbs {
|
||||||
|
public class Settings {
|
||||||
|
public string CropfieldItemCode { get; set; }
|
||||||
|
public string SatelliteTaskCode { get; set; }
|
||||||
|
public string VanDerSatTaskCode { get; set; }
|
||||||
|
public string WatBalTaskCode { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -9,32 +9,33 @@ using FarmmapsApi.Services;
|
|||||||
using FarmmapsNbs.Models;
|
using FarmmapsNbs.Models;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
namespace FarmmapsNbs
|
namespace FarmmapsNbs {
|
||||||
{
|
public class NbsApplication : IApplication {
|
||||||
public class NbsApplication : IApplication
|
|
||||||
{
|
|
||||||
private const string DownloadFolder = "Downloads";
|
private const string DownloadFolder = "Downloads";
|
||||||
|
private const string SettingsFile = "settings.json";
|
||||||
|
|
||||||
private readonly ILogger<NbsApplication> _logger;
|
private readonly ILogger<NbsApplication> _logger;
|
||||||
private readonly FarmmapsApiService _farmmapsApiService;
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
private readonly NitrogenService _nitrogenService;
|
private readonly NitrogenService _nitrogenService;
|
||||||
private readonly GeneralService _generalService;
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
private Settings _settings;
|
||||||
|
|
||||||
public NbsApplication(ILogger<NbsApplication> logger, FarmmapsApiService farmmapsApiService,
|
public NbsApplication(ILogger<NbsApplication> logger, FarmmapsApiService farmmapsApiService,
|
||||||
GeneralService generalService, NitrogenService nitrogenService)
|
GeneralService generalService, NitrogenService nitrogenService) {
|
||||||
{
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_farmmapsApiService = farmmapsApiService;
|
_farmmapsApiService = farmmapsApiService;
|
||||||
_generalService = generalService;
|
_generalService = generalService;
|
||||||
_nitrogenService = nitrogenService;
|
_nitrogenService = nitrogenService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RunAsync()
|
public async Task RunAsync() {
|
||||||
{
|
|
||||||
var nitrogenInputJson = File.ReadAllText("NitrogenInput.json");
|
var nitrogenInputJson = File.ReadAllText("NitrogenInput.json");
|
||||||
List<NitrogenInput> nitrogenInputs = JsonConvert.DeserializeObject<List<NitrogenInput>>(nitrogenInputJson);
|
List<NitrogenInput> nitrogenInputs = JsonConvert.DeserializeObject<List<NitrogenInput>>(nitrogenInputJson);
|
||||||
|
|
||||||
if (!Directory.Exists(DownloadFolder))
|
if (!Directory.Exists(DownloadFolder))
|
||||||
Directory.CreateDirectory(DownloadFolder);
|
Directory.CreateDirectory(DownloadFolder);
|
||||||
|
|
||||||
@ -42,56 +43,149 @@ namespace FarmmapsNbs
|
|||||||
await _farmmapsApiService.GetCurrentUserCodeAsync();
|
await _farmmapsApiService.GetCurrentUserCodeAsync();
|
||||||
var roots = await _farmmapsApiService.GetCurrentUserRootsAsync();
|
var roots = await _farmmapsApiService.GetCurrentUserRootsAsync();
|
||||||
|
|
||||||
foreach (var input in nitrogenInputs)
|
foreach (var input in nitrogenInputs) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
await Process(roots, input);
|
await Process(roots, input);
|
||||||
}
|
} catch (Exception ex) {
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex.Message);
|
_logger.LogError(ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Process(List<UserRoot> roots, NitrogenInput input)
|
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 plantingDate = input.PlantingDate;
|
||||||
|
var FieldName = input.fieldName;
|
||||||
|
bool StoreStatistics = input.storeSatelliteStatistics;
|
||||||
var measurementDate = input.MeasurementDate;
|
var measurementDate = input.MeasurementDate;
|
||||||
|
string settingsfile = $"Settings_{FieldName}.json";
|
||||||
|
|
||||||
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "Uploaded");
|
LoadSettings(settingsfile);
|
||||||
if (uploadedRoot == null)
|
|
||||||
{
|
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
|
||||||
|
if (uploadedRoot == null) {
|
||||||
_logger.LogError("Could not find a needed root item");
|
_logger.LogError("Could not find a needed root item");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var myDriveRoot = roots.SingleOrDefault(r => r.Name == "My drive");
|
var myDriveRoot = roots.SingleOrDefault(r => r.Name == "USER_FILES");
|
||||||
if (myDriveRoot == null)
|
if (myDriveRoot == null) {
|
||||||
{
|
|
||||||
_logger.LogError("Could not find a needed root item");
|
_logger.LogError("Could not find a needed root item");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDriveRoot.Code,
|
// Use already created cropfield or create new one
|
||||||
$"VRA NBS cropfield {input.OutputFileName}", plantingDate.Year, input.GeometryJson.ToString(Formatting.None));
|
Item cropfieldItem;
|
||||||
|
if (useCreatedCropfield == false || string.IsNullOrEmpty(_settings.CropfieldItemCode)) {
|
||||||
var dataPath = Path.Combine("Data", input.ZippedShapeFile);
|
_logger.LogInformation("Creating cropfield");
|
||||||
var shapeItem =
|
cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDriveRoot.Code,
|
||||||
await _generalService.UploadZipWithShapeAsync(uploadedRoot, dataPath, Path.GetFileNameWithoutExtension(input.ZippedShapeFile));
|
$"VRA NBS cropfield {input.OutputFileName}", plantingDate.Year, input.GeometryJson.ToString(Formatting.None));
|
||||||
if (shapeItem == null)
|
_settings.CropfieldItemCode = cropfieldItem.Code;
|
||||||
{
|
SaveSettings(settingsfile);
|
||||||
_logger.LogError("Could not find shape item");
|
} else {
|
||||||
return;
|
_logger.LogInformation("Cropfield already exists, trying to get it");
|
||||||
|
cropfieldItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldItemCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation($"Converting shape to geotiff");
|
var inputItem = (Item)null;
|
||||||
var geotiffItem = await _generalService.ShapeToGeotiff(shapeItem);
|
var geotiffItem = (Item)null;
|
||||||
if (geotiffItem == null)
|
|
||||||
{
|
// If no input file is specified, use most recent satellite image
|
||||||
_logger.LogError("Something went wrong with shape to geotiff transformation");
|
if (string.IsNullOrEmpty(input.File)) {
|
||||||
return;
|
_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 satelliteItem = await _generalService.FindSatelliteItem(cropfieldItem, _settings.SatelliteTaskCode);
|
||||||
|
|
||||||
|
var satelliteBand = satelliteItem.Data["layers"][0]["name"];
|
||||||
|
var satelliteStatistics = satelliteItem.Data["layers"][0]["renderer"]["band"]["statistics"];
|
||||||
|
Console.WriteLine($"Satellite image date: {satelliteItem.DataDate}");
|
||||||
|
//Console.WriteLine($"Satellite image statistics for band {satelliteBand}: {satelliteStatistics}");
|
||||||
|
|
||||||
|
//Store data to csv
|
||||||
|
if (StoreStatistics == true) {
|
||||||
|
|
||||||
|
var SatelliteStatsFile = $"{DownloadFolder}/SatelliteDataStatistics_{FieldName}_{satelliteItem.DataDate.Value:yyyy-MM-dd}.csv";
|
||||||
|
using var w = new StreamWriter(SatelliteStatsFile);
|
||||||
|
{
|
||||||
|
foreach (var item in satelliteStatistics) {
|
||||||
|
var line = string.Format("{0}", item);
|
||||||
|
w.WriteLine(line);
|
||||||
|
w.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// must be wdvi[1]
|
||||||
|
var inputType = (satelliteItem.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)satelliteItem.DataDate;
|
||||||
|
var SatelliteDate = SatelliteImageDate.ToString("yyyyMMdd");
|
||||||
|
_logger.LogInformation("Downloading geotiff file");
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(satelliteItem.Code,
|
||||||
|
Path.Combine(DownloadFolder, $"nbs_inputSatelliteGeotiff_{input.OutputFileName}_{inputType}_{SatelliteDate}.zip"));
|
||||||
|
|
||||||
|
// overwrite measurement date by date of satellite item
|
||||||
|
measurementDate = satelliteItem.DataDate.Value;
|
||||||
|
inputItem = satelliteItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// (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);
|
||||||
|
inputItem = 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), input.GeometryJson.ToString(Formatting.None)) :
|
||||||
|
await _generalService.UploadZipWithShapeAsync(uploadedRoot, dataPath, Path.GetFileNameWithoutExtension(input.File), input.GeometryJson.ToString(Formatting.None));
|
||||||
|
|
||||||
|
if (shapeItem == null) {
|
||||||
|
_logger.LogError("Could not find item for uploaded data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inputItem = shapeItem;
|
||||||
|
////convert shape to geotiff, not necessary anymore. However can still be done
|
||||||
|
//_logger.LogInformation($"Converting shape to geotiff");
|
||||||
|
//geotiffItem = await _generalService.ShapeToGeotiff(shapeItem, 1, input.InputLayerName);
|
||||||
|
//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"));
|
||||||
|
//inputItem = geotiffItem;
|
||||||
|
////End shape to geotiff transformation
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation($"Calculating targetN with targetYield: {input.TargetYield}");
|
_logger.LogInformation($"Calculating targetN with targetYield: {input.TargetYield}");
|
||||||
@ -99,35 +193,119 @@ namespace FarmmapsNbs
|
|||||||
var targetNData = await _nitrogenService.CalculateTargetN(cropfieldItem, targetNItem, plantingDate,
|
var targetNData = await _nitrogenService.CalculateTargetN(cropfieldItem, targetNItem, plantingDate,
|
||||||
measurementDate, input.PotatoPurposeType, input.TargetYield);
|
measurementDate, input.PotatoPurposeType, input.TargetYield);
|
||||||
|
|
||||||
if (targetNData == null)
|
if (targetNData == null) {
|
||||||
{
|
|
||||||
_logger.LogError("Something went wrong with TargetN calculation");
|
_logger.LogError("Something went wrong with TargetN calculation");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation($"TargetN: {targetNData.TargetN}");
|
_logger.LogInformation($"TargetN: {targetNData.TargetN}");
|
||||||
|
|
||||||
var targetNDataPath = Path.Combine(DownloadFolder, $"{input.OutputFileName}.targetn.json");
|
var targetNDataPath = Path.Combine(DownloadFolder, $"{input.OutputFileName}.targetn.json");
|
||||||
|
|
||||||
await File.WriteAllTextAsync(targetNDataPath, JsonConvert.SerializeObject(targetNData, Formatting.Indented));
|
await File.WriteAllTextAsync(targetNDataPath, JsonConvert.SerializeObject(targetNData, Formatting.Indented));
|
||||||
|
|
||||||
_logger.LogInformation("Calculating uptake map");
|
_logger.LogInformation("Calculating uptake map");
|
||||||
var uptakeMapItem =
|
var uptakeMapItem =
|
||||||
await _nitrogenService.CalculateUptakeMap(cropfieldItem, geotiffItem, plantingDate,
|
await _nitrogenService.CalculateUptakeMap(cropfieldItem, inputItem, plantingDate,
|
||||||
measurementDate, input.InputVariable);
|
measurementDate, input.InputVariable, input.InputLayerName);
|
||||||
|
if (uptakeMapItem == null) {
|
||||||
|
_logger.LogError("Something went wrong with creating the uptakeMap");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_logger.LogInformation("Downloading uptake map");
|
_logger.LogInformation("Downloading uptake map");
|
||||||
await _farmmapsApiService.DownloadItemAsync(uptakeMapItem.Code,
|
await _farmmapsApiService.DownloadItemAsync(uptakeMapItem.Code,
|
||||||
Path.Combine(DownloadFolder, $"{input.OutputFileName}.uptake.zip"));
|
Path.Combine(DownloadFolder, $"{input.OutputFileName}.uptake.zip"));
|
||||||
|
_logger.LogInformation("UptakeMap downloaded");
|
||||||
|
|
||||||
_logger.LogInformation("Calculating application map");
|
_logger.LogInformation("Calculating application map");
|
||||||
var applicationMapItem =
|
var applianceMapItem =
|
||||||
await _nitrogenService.CalculateApplicationMap(cropfieldItem, geotiffItem, plantingDate,
|
await _nitrogenService.CalculateApplicationMap(cropfieldItem, inputItem, plantingDate,
|
||||||
measurementDate,
|
measurementDate, input.InputVariable, targetNData.TargetN, input.InputLayerName);
|
||||||
input.InputVariable, targetNData.TargetN);
|
|
||||||
|
|
||||||
|
if (applianceMapItem == null) {
|
||||||
|
_logger.LogError("Something went wrong with creating the applicationMap");
|
||||||
|
return;
|
||||||
|
}
|
||||||
_logger.LogInformation("Downloading application map");
|
_logger.LogInformation("Downloading application map");
|
||||||
await _farmmapsApiService.DownloadItemAsync(applicationMapItem.Code,
|
await _farmmapsApiService.DownloadItemAsync(applianceMapItem.Code,
|
||||||
Path.Combine(DownloadFolder, $"{input.OutputFileName}.application.zip"));
|
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 = applianceMapItem;
|
||||||
|
|
||||||
|
if (tiffItem == null) {
|
||||||
|
_logger.LogError("Could not find item for uploaded data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ApplicationMap (GEOTIFF) To Taskmap
|
||||||
|
if (input.GenerateTaskmap) {
|
||||||
|
//GEOTIFF TO Taskmap
|
||||||
|
_logger.LogInformation($"Converting geotiff to taskmap");
|
||||||
|
|
||||||
|
var taskmap = (Item)null;
|
||||||
|
if (input.OutputType == "isoxml") {
|
||||||
|
|
||||||
|
if (input.DdiCode == null) {
|
||||||
|
_logger.LogInformation("DDi not given. Using expected identifiers");
|
||||||
|
input.DdiCode = input.DdiCode = "0006";
|
||||||
|
|
||||||
|
}
|
||||||
|
taskmap = await _generalService.CreateTaskmap(cropfieldItem: cropfieldItem, tiffItem: applianceMapItem, outputType: input.OutputType, cellWidth: input.CellWidth,
|
||||||
|
cellHeight: input.CellHeight, startPoint: input.StartPoint.ToString(Formatting.None), inputLayerName: input.InputLayerName, ddiCode: input.DdiCode, centered: input.Centered,
|
||||||
|
endPoint: input.EndPoint.ToString(Formatting.None), angle: input.Angle, precision: input.Precision,
|
||||||
|
cropTypeName: null, costumerName: null, ProductGroupName: null, productName: null, resolution: null, unitScale: null, maximumClasses: input.MaximumClasses);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
taskmap = await _generalService.CreateTaskmap(cropfieldItem: cropfieldItem, tiffItem: applianceMapItem, outputType: input.OutputType, cellWidth: input.CellWidth,
|
||||||
|
cellHeight: input.CellHeight, startPoint: input.StartPoint.ToString(Formatting.None), inputLayerName: input.InputLayerName, centered: input.Centered,
|
||||||
|
endPoint: input.EndPoint.ToString(Formatting.None), angle: input.Angle, precision: input.Precision, maximumClasses: input.MaximumClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (taskmap == null) {
|
||||||
|
_logger.LogError("Something went wrong with geotiff to taskmap 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,126 +1,59 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"zippedShapeFile": "Scan_1_20190605.zip",
|
"UseCreatedCropfield": true,
|
||||||
"inputVariable": "irmi",
|
"file": "Scan1_20190605_sample.json",
|
||||||
"outputFileName": "vranbs1",
|
"inputVariable": "irmi",
|
||||||
|
"inputLayerName": "irmi",
|
||||||
|
"outputFileName": "vranbs_sample",
|
||||||
|
"fieldName": "sampleJson_irmi-usertest",
|
||||||
|
"storeSatelliteStatistics": true,
|
||||||
"plantingDate": "2019-04-18",
|
"plantingDate": "2019-04-18",
|
||||||
"measurementDate": "2019-06-05",
|
"measurementDate": "2019-06-05",
|
||||||
"potatoPurposeType": "consumption",
|
"potatoPurposeType": "consumption",
|
||||||
"targetYield": 45,
|
"targetYield": 45,
|
||||||
"geometryJson": { "type": "Polygon", "coordinates": [ [ [ 3.40843828875524, 50.638966444680605 ], [ 3.408953272886064, 50.639197789621612 ], [ 3.409242951459603, 50.639469958681836 ], [ 3.409328782148028, 50.639612846807708 ], [ 3.409457528180712, 50.639789755314411 ], [ 3.409639918393741, 50.640014292074966 ], [ 3.409833037442765, 50.640211611372706 ], [ 3.410069071836049, 50.640395321698435 ], [ 3.410380208081761, 50.640572227259661 ], [ 3.410605513638958, 50.640715112034222 ], [ 3.411925160474145, 50.641177783561204 ], [ 3.411935889310142, 50.640728720085136 ], [ 3.412590348309737, 50.63948356709389 ], [ 3.413244807309242, 50.638224772339846 ], [ 3.413400375432099, 50.637901562841307 ], [ 3.413539850300779, 50.637449065809889 ], [ 3.413475477284437, 50.637418445552932 ], [ 3.40999396998362, 50.637449065810451 ], [ 3.409940325803365, 50.638102293212661 ], [ 3.409575545377398, 50.638483338338325 ], [ 3.409060561246574, 50.638707881340494 ], [ 3.40843828875524, 50.638966444680605 ] ] ] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"zippedShapeFile": "Scan_1_20190605.zip",
|
|
||||||
"inputVariable": "irmi",
|
|
||||||
"outputFileName": "vranbs2",
|
|
||||||
"plantingDate": "2019-04-18",
|
|
||||||
"measurementDate": "2019-06-05",
|
|
||||||
"potatoPurposeType": "starch",
|
|
||||||
"targetYield": 45,
|
|
||||||
"geometryJson": {
|
"geometryJson": {
|
||||||
"type": "Polygon",
|
"type": "Polygon",
|
||||||
"coordinates": [
|
"coordinates": [
|
||||||
[
|
[
|
||||||
[ 3.40843828875524, 50.638966444680605 ],
|
[ 5.63217247936348731, 51.96438066944019596 ],
|
||||||
[ 3.408953272886064, 50.639197789621612 ],
|
[ 5.6321047379532132, 51.96445630006819982 ],
|
||||||
[ 3.409242951459603, 50.639469958681836 ],
|
[ 5.63206782435562925, 51.96450152306518078 ],
|
||||||
[ 3.409328782148028, 50.639612846807708 ],
|
[ 5.63189463337882312, 51.96471369141583807 ],
|
||||||
[ 3.409457528180712, 50.639789755314411 ],
|
[ 5.63125445938590019, 51.96545230717740793 ],
|
||||||
[ 3.409639918393741, 50.640014292074966 ],
|
[ 5.63038475519850046, 51.96645153536461237 ],
|
||||||
[ 3.409833037442765, 50.640211611372706 ],
|
[ 5.6302190722686376, 51.96664178312045124 ],
|
||||||
[ 3.410069071836049, 50.640395321698435 ],
|
[ 5.63010295472675626, 51.96676711160860407 ],
|
||||||
[ 3.410380208081761, 50.640572227259661 ],
|
[ 5.63204023224759265, 51.96725135278578023 ],
|
||||||
[ 3.410605513638958, 50.640715112034222 ],
|
[ 5.63281523134503814, 51.96638856753320823 ],
|
||||||
[ 3.411925160474145, 50.641177783561204 ],
|
[ 5.63281527471734655, 51.96638851620966904 ],
|
||||||
[ 3.411935889310142, 50.640728720085136 ],
|
[ 5.63366926331355611, 51.96542171716968284 ],
|
||||||
[ 3.412590348309737, 50.63948356709389 ],
|
[ 5.63397637358524683, 51.96498159324188748 ],
|
||||||
[ 3.413244807309242, 50.638224772339846 ],
|
[ 5.6341135965418534, 51.96474743038492505 ],
|
||||||
[ 3.413400375432099, 50.637901562841307 ],
|
[ 5.63219031197733688, 51.96438405049333653 ],
|
||||||
[ 3.413539850300779, 50.637449065809889 ],
|
[ 5.63217541872332195, 51.96438123226843686 ],
|
||||||
[ 3.413475477284437, 50.637418445552932 ],
|
[ 5.63217247936348731, 51.96438066944019596 ]
|
||||||
[ 3.40999396998362, 50.637449065810451 ],
|
|
||||||
[ 3.409940325803365, 50.638102293212661 ],
|
|
||||||
[ 3.409575545377398, 50.638483338338325 ],
|
|
||||||
[ 3.409060561246574, 50.638707881340494 ],
|
|
||||||
[ 3.40843828875524, 50.638966444680605 ]
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
},
|
"GenerateTaskmap": false
|
||||||
{
|
|
||||||
"zippedShapeFile": "Scan_1_20190605.zip",
|
|
||||||
"inputVariable": "irmi",
|
|
||||||
"outputFileName": "vranbs3",
|
|
||||||
"plantingDate": "2019-04-18",
|
|
||||||
"measurementDate": "2019-06-20",
|
|
||||||
"potatoPurposeType": "starch",
|
|
||||||
"targetYield": 45,
|
|
||||||
"geometryJson": {
|
|
||||||
"type": "Polygon",
|
|
||||||
"coordinates": [
|
|
||||||
[
|
|
||||||
[ 3.40843828875524, 50.638966444680605 ],
|
|
||||||
[ 3.408953272886064, 50.639197789621612 ],
|
|
||||||
[ 3.409242951459603, 50.639469958681836 ],
|
|
||||||
[ 3.409328782148028, 50.639612846807708 ],
|
|
||||||
[ 3.409457528180712, 50.639789755314411 ],
|
|
||||||
[ 3.409639918393741, 50.640014292074966 ],
|
|
||||||
[ 3.409833037442765, 50.640211611372706 ],
|
|
||||||
[ 3.410069071836049, 50.640395321698435 ],
|
|
||||||
[ 3.410380208081761, 50.640572227259661 ],
|
|
||||||
[ 3.410605513638958, 50.640715112034222 ],
|
|
||||||
[ 3.411925160474145, 50.641177783561204 ],
|
|
||||||
[ 3.411935889310142, 50.640728720085136 ],
|
|
||||||
[ 3.412590348309737, 50.63948356709389 ],
|
|
||||||
[ 3.413244807309242, 50.638224772339846 ],
|
|
||||||
[ 3.413400375432099, 50.637901562841307 ],
|
|
||||||
[ 3.413539850300779, 50.637449065809889 ],
|
|
||||||
[ 3.413475477284437, 50.637418445552932 ],
|
|
||||||
[ 3.40999396998362, 50.637449065810451 ],
|
|
||||||
[ 3.409940325803365, 50.638102293212661 ],
|
|
||||||
[ 3.409575545377398, 50.638483338338325 ],
|
|
||||||
[ 3.409060561246574, 50.638707881340494 ],
|
|
||||||
[ 3.40843828875524, 50.638966444680605 ]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"zippedShapeFile": "Scan_1_20190605.zip",
|
|
||||||
"inputVariable": "irmi",
|
|
||||||
"outputFileName": "vranbs4",
|
|
||||||
"plantingDate": "2019-04-18",
|
|
||||||
"measurementDate": "2019-07-03",
|
|
||||||
"potatoPurposeType": "starch",
|
|
||||||
"targetYield": 45,
|
|
||||||
"geometryJson": {
|
|
||||||
"type": "Polygon",
|
|
||||||
"coordinates": [
|
|
||||||
[
|
|
||||||
[ 3.40843828875524, 50.638966444680605 ],
|
|
||||||
[ 3.408953272886064, 50.639197789621612 ],
|
|
||||||
[ 3.409242951459603, 50.639469958681836 ],
|
|
||||||
[ 3.409328782148028, 50.639612846807708 ],
|
|
||||||
[ 3.409457528180712, 50.639789755314411 ],
|
|
||||||
[ 3.409639918393741, 50.640014292074966 ],
|
|
||||||
[ 3.409833037442765, 50.640211611372706 ],
|
|
||||||
[ 3.410069071836049, 50.640395321698435 ],
|
|
||||||
[ 3.410380208081761, 50.640572227259661 ],
|
|
||||||
[ 3.410605513638958, 50.640715112034222 ],
|
|
||||||
[ 3.411925160474145, 50.641177783561204 ],
|
|
||||||
[ 3.411935889310142, 50.640728720085136 ],
|
|
||||||
[ 3.412590348309737, 50.63948356709389 ],
|
|
||||||
[ 3.413244807309242, 50.638224772339846 ],
|
|
||||||
[ 3.413400375432099, 50.637901562841307 ],
|
|
||||||
[ 3.413539850300779, 50.637449065809889 ],
|
|
||||||
[ 3.413475477284437, 50.637418445552932 ],
|
|
||||||
[ 3.40999396998362, 50.637449065810451 ],
|
|
||||||
[ 3.409940325803365, 50.638102293212661 ],
|
|
||||||
[ 3.409575545377398, 50.638483338338325 ],
|
|
||||||
[ 3.409060561246574, 50.638707881340494 ],
|
|
||||||
[ 3.40843828875524, 50.638966444680605 ]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// "GenerateTaskmap": true,
|
||||||
|
// "OutputType": "shape", // "shape" or "isoxml" if isoxml also add ddiCode
|
||||||
|
// "Precision": "0",
|
||||||
|
// "MaximumClasses": "4",
|
||||||
|
// "DdiCode": "0006",
|
||||||
|
// "CellWidth": "27",
|
||||||
|
// "CellHeight": "10",
|
||||||
|
// "Centered": "false",
|
||||||
|
// "StartPoint": {
|
||||||
|
// "type": "Point",
|
||||||
|
// "coordinates": [ 5.6322, 51.9644 ]
|
||||||
|
// },
|
||||||
|
// "EndPoint": { // if no angle
|
||||||
|
// "type": "Point",
|
||||||
|
// "coordinates": [ 5.6341, 51.9647 ]
|
||||||
|
// }
|
||||||
|
// //"Angle": "317.0" // if no endpoint
|
||||||
|
|
||||||
|
//}
|
||||||
]
|
]
|
@ -51,8 +51,8 @@ namespace FarmmapsNbs
|
|||||||
var nbsTargetNRequest = new TaskRequest {TaskType = VRANBS_TASK};
|
var nbsTargetNRequest = new TaskRequest {TaskType = VRANBS_TASK};
|
||||||
nbsTargetNRequest.attributes["operation"] = "targetn";
|
nbsTargetNRequest.attributes["operation"] = "targetn";
|
||||||
nbsTargetNRequest.attributes["inputCode"] = targetNItem.Code;
|
nbsTargetNRequest.attributes["inputCode"] = targetNItem.Code;
|
||||||
nbsTargetNRequest.attributes["plantingDate"] = plantingDate.ToString();
|
nbsTargetNRequest.attributes["plantingDate"] = plantingDate.ToString("o");
|
||||||
nbsTargetNRequest.attributes["measurementDate"] = measurementDate.ToString();
|
nbsTargetNRequest.attributes["measurementDate"] = measurementDate.ToString("o");
|
||||||
nbsTargetNRequest.attributes["purposeType"] = purposeType.ToLower();
|
nbsTargetNRequest.attributes["purposeType"] = purposeType.ToLower();
|
||||||
nbsTargetNRequest.attributes["targetYield"] = targetYield.ToString();
|
nbsTargetNRequest.attributes["targetYield"] = targetYield.ToString();
|
||||||
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsTargetNRequest);
|
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsTargetNRequest);
|
||||||
@ -74,7 +74,7 @@ namespace FarmmapsNbs
|
|||||||
var item = await _farmmapsApiService.GetItemAsync(targetNItem.Code);
|
var item = await _farmmapsApiService.GetItemAsync(targetNItem.Code);
|
||||||
return item.Data.ToObject<TargetNData>();
|
return item.Data.ToObject<TargetNData>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the uptake map based on the given inputs
|
/// Calculates the uptake map based on the given inputs
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -82,28 +82,35 @@ namespace FarmmapsNbs
|
|||||||
/// <param name="inputItem"></param>
|
/// <param name="inputItem"></param>
|
||||||
/// <param name="plantingDate">The date the crop is planted</param>
|
/// <param name="plantingDate">The date the crop is planted</param>
|
||||||
/// <param name="measurementDate">The date the measurements are taken</param>
|
/// <param name="measurementDate">The date the measurements are taken</param>
|
||||||
|
/// <param name="inputType">Data type, could be yara, ci, irmi or wdvi</param>
|
||||||
|
/// <param name="inputLayerName">Column name in which the sensor value is stored</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<Item> CalculateUptakeMap(Item cropfieldItem, Item inputItem, DateTime plantingDate,
|
public async Task<Item> CalculateUptakeMap(Item cropfieldItem, Item inputItem, DateTime plantingDate,
|
||||||
DateTime measurementDate, string inputType)
|
DateTime measurementDate, string inputType, string inputLayerName)
|
||||||
{
|
{
|
||||||
var nbsUptakeMapRequest = new TaskRequest {TaskType = VRANBS_TASK};
|
var nbsUptakeMapRequest = new TaskRequest {TaskType = VRANBS_TASK};
|
||||||
nbsUptakeMapRequest.attributes["operation"] = "uptake";
|
nbsUptakeMapRequest.attributes["operation"] = "uptake";
|
||||||
nbsUptakeMapRequest.attributes["inputCode"] = inputItem.Code;
|
nbsUptakeMapRequest.attributes["inputCode"] = inputItem.Code;
|
||||||
nbsUptakeMapRequest.attributes["plantingDate"] = plantingDate.ToString();
|
nbsUptakeMapRequest.attributes["plantingDate"] = plantingDate.ToString("o");
|
||||||
nbsUptakeMapRequest.attributes["measurementDate"] = measurementDate.ToString();
|
nbsUptakeMapRequest.attributes["measurementDate"] = measurementDate.ToString("o");
|
||||||
nbsUptakeMapRequest.attributes["inputType"] = inputType.ToLower();
|
nbsUptakeMapRequest.attributes["inputType"] = inputType.ToLower();
|
||||||
|
if (!(string.IsNullOrEmpty(inputLayerName))) nbsUptakeMapRequest.attributes["inputLayerName"] = inputLayerName;
|
||||||
|
//toevoeging FS. Kolom IRMI hernoemd als IMI. Deze wordt niet automatisch herkend. En moet dus gespecificeerd worden.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsUptakeMapRequest);
|
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsUptakeMapRequest);
|
||||||
|
|
||||||
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) =>
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) =>
|
||||||
{
|
{
|
||||||
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
_logger.LogInformation($"Calculating uptake map; status: {itemTaskStatus.State}");
|
||||||
if (itemTaskStatus.IsFinished)
|
if (itemTaskStatus.IsFinished)
|
||||||
tokenSource.Cancel();
|
tokenSource.Cancel();
|
||||||
});
|
});
|
||||||
|
|
||||||
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
if(itemTask.State == ItemTaskState.Error)
|
if (itemTask.State == ItemTaskState.Error)
|
||||||
{
|
{
|
||||||
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
|
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
|
||||||
return null;
|
return null;
|
||||||
@ -111,9 +118,10 @@ namespace FarmmapsNbs
|
|||||||
|
|
||||||
var itemName = "VRANbs uptake";
|
var itemName = "VRANbs uptake";
|
||||||
var uptakeMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
|
var uptakeMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
|
||||||
GEOTIFF_PROCESSED_ITEMTYPE, itemName,
|
GEOTIFF_PROCESSED_ITEMTYPE, itemName,
|
||||||
i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) &&
|
i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) &&
|
||||||
i.Name.ToLower().Contains(itemName.ToLower()));
|
i.Name.ToLower().Contains(itemName.ToLower()));
|
||||||
|
|
||||||
if (uptakeMapItem == null)
|
if (uptakeMapItem == null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Could not find the uptake geotiff child item under cropfield");
|
_logger.LogError("Could not find the uptake geotiff child item under cropfield");
|
||||||
@ -131,30 +139,34 @@ namespace FarmmapsNbs
|
|||||||
/// <param name="inputItem">The farmmaps item containing the geotiff data</param>
|
/// <param name="inputItem">The farmmaps item containing the geotiff data</param>
|
||||||
/// <param name="plantingDate">The date the crop is planted</param>
|
/// <param name="plantingDate">The date the crop is planted</param>
|
||||||
/// <param name="measurementDate">The date the measurements are taken</param>
|
/// <param name="measurementDate">The date the measurements are taken</param>
|
||||||
/// <param name="inputType">The inputtype to use</param>
|
/// <param name="inputType">The inputtype to use, could be yara, ci, irmi or wdvi</param>
|
||||||
/// <param name="targetN">The target nitrogen to use for the calculations</param>
|
/// <param name="targetN">The target nitrogen to use for the calculations</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<Item> CalculateApplicationMap(Item cropfieldItem, Item inputItem, DateTime plantingDate,
|
public async Task<Item> CalculateApplicationMap(Item cropfieldItem, Item inputItem, DateTime plantingDate,
|
||||||
DateTime measurementDate, string inputType, double targetN)
|
DateTime measurementDate, string inputType, double targetN, string inputLayerName)
|
||||||
{
|
{
|
||||||
var nbsApplicationMapRequest = new TaskRequest {TaskType = VRANBS_TASK};
|
var nbsApplicationMapRequest = new TaskRequest {TaskType = VRANBS_TASK};
|
||||||
nbsApplicationMapRequest.attributes["operation"] = "application";
|
nbsApplicationMapRequest.attributes["operation"] = "application";
|
||||||
nbsApplicationMapRequest.attributes["inputCode"] = inputItem.Code;
|
nbsApplicationMapRequest.attributes["inputCode"] = inputItem.Code;
|
||||||
nbsApplicationMapRequest.attributes["plantingDate"] = plantingDate.ToString();
|
nbsApplicationMapRequest.attributes["plantingDate"] = plantingDate.ToString("o");
|
||||||
nbsApplicationMapRequest.attributes["measurementDate"] = measurementDate.ToString();
|
nbsApplicationMapRequest.attributes["measurementDate"] = measurementDate.ToString("o");
|
||||||
nbsApplicationMapRequest.attributes["inputCode"] = inputItem.Code;
|
nbsApplicationMapRequest.attributes["inputCode"] = inputItem.Code;
|
||||||
nbsApplicationMapRequest.attributes["inputType"] = inputType.ToLower();
|
nbsApplicationMapRequest.attributes["inputType"] = inputType.ToLower();
|
||||||
nbsApplicationMapRequest.attributes["targetN"] = targetN.ToString(CultureInfo.InvariantCulture);
|
nbsApplicationMapRequest.attributes["targetN"] = targetN.ToString(CultureInfo.InvariantCulture);
|
||||||
|
if (!(string.IsNullOrEmpty(inputLayerName))) nbsApplicationMapRequest.attributes["inputLayerName"] = inputLayerName;
|
||||||
|
|
||||||
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsApplicationMapRequest);
|
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsApplicationMapRequest);
|
||||||
|
|
||||||
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) =>
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) =>
|
||||||
{
|
{
|
||||||
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
|
_logger.LogInformation($"Calculating application map; status: {itemTaskStatus.State}");
|
||||||
if (itemTaskStatus.IsFinished)
|
if (itemTaskStatus.IsFinished)
|
||||||
tokenSource.Cancel();
|
tokenSource.Cancel();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
|
||||||
if(itemTask.State == ItemTaskState.Error)
|
if(itemTask.State == ItemTaskState.Error)
|
||||||
{
|
{
|
||||||
@ -164,7 +176,7 @@ namespace FarmmapsNbs
|
|||||||
|
|
||||||
var itemName = $"VRANbs application";
|
var itemName = $"VRANbs application";
|
||||||
var applicationMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
|
var applicationMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
|
||||||
GEOTIFF_PROCESSED_ITEMTYPE, itemName,
|
GEOTIFF_PROCESSED_ITEMTYPE, itemName,
|
||||||
i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) &&
|
i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) &&
|
||||||
i.Name.ToLower().Contains(itemName.ToLower()));
|
i.Name.ToLower().Contains(itemName.ToLower()));
|
||||||
if (applicationMapItem == null)
|
if (applicationMapItem == null)
|
||||||
|
@ -14,9 +14,7 @@ namespace FarmmapsNbs
|
|||||||
|
|
||||||
protected override void Configure(IServiceCollection serviceCollection)
|
protected override void Configure(IServiceCollection serviceCollection)
|
||||||
{
|
{
|
||||||
serviceCollection.AddLogging(opts => opts
|
serviceCollection.AddLogging()
|
||||||
.AddConsole()
|
|
||||||
.AddFilter("System.Net.Http", LogLevel.Warning))
|
|
||||||
.AddTransient<NitrogenService>();
|
.AddTransient<NitrogenService>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"Authority": "https://accounts.farmmaps.awtest.nl/",
|
|
||||||
"Endpoint": "https://farmmaps.awtest.nl/",
|
|
||||||
"BasePath": "api/v1",
|
|
||||||
"DiscoveryEndpointUrl": "https://accounts.farmmaps.awtest.nl/.well-known/openid-configuration",
|
|
||||||
"RedirectUri": "http://example.nl/api",
|
|
||||||
"ClientId": "",
|
|
||||||
"ClientSecret": "",
|
|
||||||
"Scopes": ["api"]
|
|
||||||
}
|
|
BIN
FarmmapsPoten/Data/PlantingSampleDataLutum.zip
Normal file
BIN
FarmmapsPoten/Data/PlantingSampleDataLutum.zip
Normal file
Binary file not shown.
302
FarmmapsPoten/Data/PlantingSampleDataLutumJSON.json
Normal file
302
FarmmapsPoten/Data/PlantingSampleDataLutumJSON.json
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"name": "PlantingSampleDataLutum",
|
||||||
|
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
|
||||||
|
"features": [
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669006678383711, 52.529290221274948 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 13 }, "geometry": { "type": "Point", "coordinates": [ 5.669006104248043, 52.529200349555097 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 13 }, "geometry": { "type": "Point", "coordinates": [ 5.669005530115061, 52.529110477833399 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669004955984766, 52.529020606109889 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 13 }, "geometry": { "type": "Point", "coordinates": [ 5.669004381857157, 52.528930734384545 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.669003807732236, 52.528840862657354 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 12 }, "geometry": { "type": "Point", "coordinates": [ 5.66900323361, 52.528750990928309 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.669002659490453, 52.528661119197444 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 14 }, "geometry": { "type": "Point", "coordinates": [ 5.669002085373592, 52.528571247464789 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669001511259415, 52.528481375730252 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669000937147927, 52.528391503993873 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.669000363039124, 52.52830163225569 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669154039708354, 52.529289871032709 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669153465272641, 52.529199999313761 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669152890839613, 52.529110127592965 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 13 }, "geometry": { "type": "Point", "coordinates": [ 5.669152316409275, 52.529020255870378 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 14 }, "geometry": { "type": "Point", "coordinates": [ 5.669151741981626, 52.528930384145944 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.669151167556664, 52.528840512419642 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 13 }, "geometry": { "type": "Point", "coordinates": [ 5.66915059313439, 52.528750640691563 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 14 }, "geometry": { "type": "Point", "coordinates": [ 5.669150018714802, 52.528660768961629 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 13 }, "geometry": { "type": "Point", "coordinates": [ 5.669149444297904, 52.528570897229841 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 13 }, "geometry": { "type": "Point", "coordinates": [ 5.669148869883696, 52.528481025496269 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 14 }, "geometry": { "type": "Point", "coordinates": [ 5.669148295472175, 52.528391153760822 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.66914772106334, 52.528301282023527 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.669147146657193, 52.528211410284435 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 14 }, "geometry": { "type": "Point", "coordinates": [ 5.669146572253736, 52.528121538543502 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669145997852967, 52.528031666800764 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669145423454884, 52.527941795056144 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669301401030309, 52.529289520607428 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.66930082629455, 52.52919964888941 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669300251561478, 52.529109777169573 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669299676831097, 52.529019905447882 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.669299102103404, 52.528930033724393 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.669298527378404, 52.528840161999021 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669297952656091, 52.528750290271873 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669297377936467, 52.528660418542835 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 14 }, "geometry": { "type": "Point", "coordinates": [ 5.669296803219534, 52.528570546811963 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 14 }, "geometry": { "type": "Point", "coordinates": [ 5.669296228505289, 52.528480675079251 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.669295653793735, 52.528390803344763 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.669295079084868, 52.52830093160842 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.669294504378692, 52.528211059870216 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 14 }, "geometry": { "type": "Point", "coordinates": [ 5.669293929675204, 52.528121188130193 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669293354974407, 52.528031316388351 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669292780276298, 52.527941444644689 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669448762349575, 52.529289169999203 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669448187313771, 52.529199298282116 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669447612280653, 52.529109426563181 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.669447037250229, 52.529019554842385 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669446462222496, 52.52892968311982 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669445887197454, 52.528839811395386 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669445312175103, 52.528749939669105 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.669444737155444, 52.528660067941011 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669444162138473, 52.528570196211071 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 15 }, "geometry": { "type": "Point", "coordinates": [ 5.669443587124193, 52.528480324479311 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669443012112604, 52.528390452745711 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669442437103707, 52.528300581010306 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669441862097501, 52.528210709273012 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669441287093983, 52.52812083753394 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669440712093158, 52.528030965793008 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 16 }, "geometry": { "type": "Point", "coordinates": [ 5.669440137095023, 52.527941094050242 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669596123666151, 52.529288819207963 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.6695955483303, 52.5291989474918 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669594972997138, 52.529109075773768 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669594397666672, 52.529019204053945 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669593822338896, 52.52892933233224 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.669593247013813, 52.528839460608751 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669592671691423, 52.528749588883372 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669592096371725, 52.528659717156224 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.66959152105472, 52.528569845427207 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669590945740404, 52.528479973696371 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669590370428786, 52.528390101963666 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669589795119855, 52.528300230229171 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669589219813616, 52.528210358492849 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669588644510072, 52.528120486754638 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669588069209219, 52.52803061501465 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.669587493911057, 52.527940743272772 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669743484980033, 52.52928846823373 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.669742909344135, 52.529198596518491 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669742333710931, 52.529108724801389 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669741758080422, 52.529018853082476 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669741182452603, 52.528928981361695 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.669740606827482, 52.528839109639122 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.669740031205053, 52.528749237914688 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.669739455585318, 52.528659366188421 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669738879968274, 52.528569494460349 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669738304353925, 52.528479622730416 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 17 }, "geometry": { "type": "Point", "coordinates": [ 5.66973772874227, 52.528389750998656 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.66973715313331, 52.528299879265084 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669736577527043, 52.528210007529651 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.669736001923469, 52.528120135792392 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669735426322587, 52.528030264053307 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669890846291222, 52.529288117076518 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.669890270355278, 52.529198245362174 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.669889694422031, 52.529108373646018 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669889118491477, 52.529018501928007 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.669888542563618, 52.528928630208178 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 22 }, "geometry": { "type": "Point", "coordinates": [ 5.669887966638455, 52.528838758486494 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 22 }, "geometry": { "type": "Point", "coordinates": [ 5.669887390715987, 52.528748886762969 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 22 }, "geometry": { "type": "Point", "coordinates": [ 5.669886814796213, 52.528659015037654 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669886238879136, 52.528569143310477 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669885662964753, 52.528479271581489 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669885087053065, 52.528389399850646 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669884511144072, 52.528299528117998 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.669883935237774, 52.528209656383481 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.66988335933417, 52.528119784647131 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 18 }, "geometry": { "type": "Point", "coordinates": [ 5.669882783433263, 52.528029912908977 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.670038207599717, 52.529287765736285 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.670037631363726, 52.529197894022879 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670037055130432, 52.529108022307639 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.670036478899838, 52.529018150590574 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.670035902671936, 52.528928278871632 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.670035326446734, 52.528838407150914 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.670034750224229, 52.528748535428306 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.670034174004417, 52.528658663703865 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.670033597787302, 52.528568791977627 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.670033021572887, 52.528478920249526 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670032445361164, 52.528389048519642 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.670031869152139, 52.528299176787897 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 22 }, "geometry": { "type": "Point", "coordinates": [ 5.670031292945811, 52.528209305054318 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 22 }, "geometry": { "type": "Point", "coordinates": [ 5.670030716742176, 52.528119433318885 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 19 }, "geometry": { "type": "Point", "coordinates": [ 5.670030140541242, 52.52802956158164 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.670186145444245, 52.529377285923772 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.670185568905514, 52.52928741421308 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.670184992369477, 52.52919754250059 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 22 }, "geometry": { "type": "Point", "coordinates": [ 5.670184415836139, 52.529107670786267 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.670183839305502, 52.529017799070111 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.670183262777561, 52.528927927352115 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 22 }, "geometry": { "type": "Point", "coordinates": [ 5.670182686252317, 52.528838055632299 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.670182109729772, 52.528748183910643 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.670181533209922, 52.52865831218714 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670180956692772, 52.528568440461825 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.670180380178322, 52.528478568734663 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670179803666567, 52.52838869700566 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670179227157511, 52.528298825274803 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 22 }, "geometry": { "type": "Point", "coordinates": [ 5.670178650651151, 52.528208953542183 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 20 }, "geometry": { "type": "Point", "coordinates": [ 5.67017807414749, 52.528119081807688 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 22 }, "geometry": { "type": "Point", "coordinates": [ 5.670177497646527, 52.528029210071367 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.670333507047393, 52.529376934216629 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670332930208612, 52.529287062506896 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670332353372531, 52.529197190795308 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670331776539151, 52.52910731908193 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 21 }, "geometry": { "type": "Point", "coordinates": [ 5.670331199708469, 52.529017447366684 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670330622880485, 52.528927575649611 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670330046055202, 52.528837703930698 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670329469232617, 52.528747832209973 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670328892412731, 52.528657960487401 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670328315595544, 52.528568088762988 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.67032773878106, 52.528478217036756 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670327161969271, 52.528388345308677 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670326585160184, 52.528298473578765 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670326008353794, 52.52820860184702 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 22 }, "geometry": { "type": "Point", "coordinates": [ 5.670325431550103, 52.528118730113469 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670324854749113, 52.528028858378079 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.67048086864784, 52.529376582326506 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670480291509012, 52.529286710617704 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670479714372884, 52.529196838907055 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670479137239461, 52.529106967194558 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670478560108735, 52.529017095480263 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 22 }, "geometry": { "type": "Point", "coordinates": [ 5.670477982980711, 52.5289272237641 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670477405855387, 52.528837352046096 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670476828732764, 52.528747480326295 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.67047625161284, 52.528657608604661 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670475674495618, 52.528567736881193 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670475097381098, 52.528477865155843 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670474520269277, 52.528387993428701 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670473943160156, 52.528298121699713 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670473366053738, 52.52820824996892 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670472788950019, 52.528118378236279 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670472211849, 52.528028506501805 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.670628230245586, 52.529376230253412 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.670627652806711, 52.529286358545527 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670627075370538, 52.529196486835779 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670626497937069, 52.529106615124242 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670625920506301, 52.52901674341085 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670625343078235, 52.528926871695603 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.670624765652872, 52.528836999978552 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670624188230208, 52.528747128259667 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670623610810248, 52.528657256538921 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.670623033392991, 52.528567384816377 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.670622455978436, 52.528477513091964 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 23 }, "geometry": { "type": "Point", "coordinates": [ 5.670621878566583, 52.528387641365747 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670621301157429, 52.52829776963771 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.67062072375098, 52.528207897907812 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670620146347232, 52.528118026176088 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670619568946186, 52.528028154442524 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670775591840631, 52.529375877997303 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670775014101707, 52.529286006290334 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670774436365489, 52.529196134581525 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670773858631976, 52.529106262870911 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.670773280901165, 52.52901639115845 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670772703173058, 52.52892651944412 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670772125447654, 52.528836647727985 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.670771547724952, 52.528746776010017 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670770970004954, 52.528656904290216 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670770392287662, 52.528567032568581 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.670769814573072, 52.528477160845142 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 24 }, "geometry": { "type": "Point", "coordinates": [ 5.670769236861187, 52.528387289119834 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670768659152, 52.528297417392693 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670768081445522, 52.528207545663754 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670767503741745, 52.528117673932925 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670766926040671, 52.528027802200249 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.67092295343297, 52.529375525558216 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.670922375394001, 52.52928565385217 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.670921797357738, 52.529195782144292 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.670921219324179, 52.529105910434581 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.670920641293326, 52.529016038723007 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670920063265176, 52.528926167009637 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.670919485239732, 52.528836295294447 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670918907216992, 52.52874642357736 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670918329196958, 52.528656551858511 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670917751179629, 52.528566680137807 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.670917173165005, 52.52847680841527 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670916595153083, 52.528386936690872 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.67091601714387, 52.528297064964669 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 25 }, "geometry": { "type": "Point", "coordinates": [ 5.670915439137358, 52.528207193236646 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.670914861133554, 52.528117321506784 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.670914283132454, 52.528027449775095 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.671070315022605, 52.529375172936099 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.671069736683591, 52.529285301230992 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.671069158347279, 52.529195429524037 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.671068580013677, 52.529105557815264 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.671068001682782, 52.529015686104621 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.671067423354591, 52.52892581439216 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.671066845029107, 52.528835942677908 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.67106626670633, 52.528746070961773 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.671065688386258, 52.528656199243834 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.671065110068891, 52.528566327524032 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.671064531754232, 52.528476455802441 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.67106395344228, 52.528386584078959 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.671063375133032, 52.528296712353679 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.671062796826493, 52.528206840626574 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.671062218522659, 52.528116968897628 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 26 }, "geometry": { "type": "Point", "coordinates": [ 5.671061640221531, 52.528027097166849 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.671217676609535, 52.529374820131018 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671217097970472, 52.52928494842682 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.671216519334117, 52.529195076720818 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671215940700469, 52.529105205012932 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.67121536206953, 52.529015333303256 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.671214783441298, 52.52892546159174 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671214204815774, 52.528835589878348 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.67121362619296, 52.528745718163179 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.671213047572849, 52.528655846446135 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671212468955447, 52.528565974727286 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.671211890340752, 52.528476103006554 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671211311728769, 52.52838623128406 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 27 }, "geometry": { "type": "Point", "coordinates": [ 5.67121073311949, 52.528296359559697 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671210154512919, 52.528206487833543 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.671209575909057, 52.528116616105528 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671208997307901, 52.528026744375651 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.671365038193755, 52.529374467142929 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.671364459254646, 52.529284595439655 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.671363880318245, 52.529194723734562 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 32 }, "geometry": { "type": "Point", "coordinates": [ 5.671363301384553, 52.529104852027658 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.671362722453573, 52.529014980318877 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 28 }, "geometry": { "type": "Point", "coordinates": [ 5.671362143525299, 52.528925108608256 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671361564599734, 52.528835236895866 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671360985676879, 52.528745365181578 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 32 }, "geometry": { "type": "Point", "coordinates": [ 5.671360406756732, 52.528655493465472 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.671359827839296, 52.528565621747525 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 32 }, "geometry": { "type": "Point", "coordinates": [ 5.671359248924568, 52.528475750027788 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 32 }, "geometry": { "type": "Point", "coordinates": [ 5.671358670012548, 52.528385878306167 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.671358091103239, 52.528296006582757 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.671357512196637, 52.528206134857442 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671356933292747, 52.528116263130357 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.671512399775269, 52.529374113971883 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.671511820536112, 52.529284242269519 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671511241299665, 52.529194370565364 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.67151066206593, 52.52910449885934 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.671510082834905, 52.529014627151504 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 32 }, "geometry": { "type": "Point", "coordinates": [ 5.67150950360659, 52.528924755441842 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 32 }, "geometry": { "type": "Point", "coordinates": [ 5.671508924380984, 52.528834883730326 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.671508345158092, 52.528745012016955 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671507765937908, 52.528655140301815 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 32 }, "geometry": { "type": "Point", "coordinates": [ 5.671507186720435, 52.528565268584806 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 33 }, "geometry": { "type": "Point", "coordinates": [ 5.671506607505673, 52.528475396865979 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 33 }, "geometry": { "type": "Point", "coordinates": [ 5.671506028293621, 52.528385525145282 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.67150544908428, 52.528295653422774 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 29 }, "geometry": { "type": "Point", "coordinates": [ 5.671504869877649, 52.52820578169846 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 33 }, "geometry": { "type": "Point", "coordinates": [ 5.671504290673729, 52.528115909972264 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.671658602278375, 52.52919401721315 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 32 }, "geometry": { "type": "Point", "coordinates": [ 5.671658022744594, 52.529104145508029 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 32 }, "geometry": { "type": "Point", "coordinates": [ 5.671657443213525, 52.529014273801138 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.67165686368517, 52.528924402092414 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.671656284159525, 52.52883453038185 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 34 }, "geometry": { "type": "Point", "coordinates": [ 5.671655704636593, 52.528744658669403 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 34 }, "geometry": { "type": "Point", "coordinates": [ 5.671655125116374, 52.528654786955173 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671654545598865, 52.528564915239095 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 31 }, "geometry": { "type": "Point", "coordinates": [ 5.671653966084067, 52.528475043521155 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 30 }, "geometry": { "type": "Point", "coordinates": [ 5.671653386571983, 52.528385171801425 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 32 }, "geometry": { "type": "Point", "coordinates": [ 5.67165280706261, 52.528295300079861 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 32 }, "geometry": { "type": "Point", "coordinates": [ 5.67165222755595, 52.528205428356415 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 33 }, "geometry": { "type": "Point", "coordinates": [ 5.671651648051999, 52.528115556631185 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 34 }, "geometry": { "type": "Point", "coordinates": [ 5.671800165038228, 52.528294946553906 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 33 }, "geometry": { "type": "Point", "coordinates": [ 5.671799585231536, 52.528205074831419 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "lutum": 34 }, "geometry": { "type": "Point", "coordinates": [ 5.671799005427561, 52.528115203107113 ] } }
|
||||||
|
]
|
||||||
|
}
|
21
FarmmapsPoten/FarmmapsPoten.csproj
Normal file
21
FarmmapsPoten/FarmmapsPoten.csproj
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Data\**\*">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="PotenInput.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FarmmapsApi\FarmmapsApi.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
33
FarmmapsPoten/Models/PotenInput.cs
Normal file
33
FarmmapsPoten/Models/PotenInput.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace FarmmapsPoten.Models
|
||||||
|
{
|
||||||
|
public class PotenInput
|
||||||
|
{
|
||||||
|
|
||||||
|
public string File { get; set; }
|
||||||
|
public string InputLayerName { get; set; }
|
||||||
|
public string OutputFileName { get; set; }
|
||||||
|
public string FieldName { get; set; }
|
||||||
|
public int PlantingYear { get; set; }
|
||||||
|
public string MeanDensity { get; set; }
|
||||||
|
public string Variation { get; set; }
|
||||||
|
public bool UseShadow { get; set; }
|
||||||
|
public bool CountPerArea { get; set; }
|
||||||
|
public JObject GeometryJson { get; set; }
|
||||||
|
|
||||||
|
public bool GenerateTaskmap { get; set; }
|
||||||
|
public string OutputType { get; set; }
|
||||||
|
public string DdiCode { get; set; }
|
||||||
|
public string CellWidth { get; set; }
|
||||||
|
public string CellHeight { get; set; }
|
||||||
|
public string Centered { get; set; }
|
||||||
|
public JObject StartPoint { get; set; }
|
||||||
|
public JObject EndPoint { get; set; }
|
||||||
|
public string Angle { get; set; }
|
||||||
|
public string Precision { get; set; }
|
||||||
|
public string MaximumClasses { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
225
FarmmapsPoten/PotenApplication.cs
Normal file
225
FarmmapsPoten/PotenApplication.cs
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
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 FarmmapsPoten.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
|
||||||
|
namespace FarmmapsVRApoten
|
||||||
|
{
|
||||||
|
public class PotenApplication : IApplication {
|
||||||
|
private const string DownloadFolder = "Downloads";
|
||||||
|
|
||||||
|
private readonly ILogger<PotenApplication> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly PotenService _potenService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
|
||||||
|
public PotenApplication(ILogger<PotenApplication> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService, PotenService potenService) {
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
_potenService = potenService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunAsync() {
|
||||||
|
// read field data from separate json file
|
||||||
|
var VRAPotenInputJson = File.ReadAllText("PotenInput.json");
|
||||||
|
List<PotenInput> potenInputs = JsonConvert.DeserializeObject<List<PotenInput>>(VRAPotenInputJson);
|
||||||
|
|
||||||
|
|
||||||
|
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 potenInputs) {
|
||||||
|
try {
|
||||||
|
await Process(roots, input);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
_logger.LogError(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Process(List<UserRoot> roots, PotenInput input) {
|
||||||
|
var meanDensity = input.MeanDensity;
|
||||||
|
var variation = input.Variation;
|
||||||
|
var fieldName = input.FieldName;
|
||||||
|
bool useShadow = input.UseShadow;
|
||||||
|
bool countPerArea = input.CountPerArea;
|
||||||
|
var inputLayerName = input.InputLayerName;
|
||||||
|
|
||||||
|
var myDrive = roots.SingleOrDefault(r => r.Name == "USER_FILES");
|
||||||
|
if (myDrive == null) {
|
||||||
|
_logger.LogError("Could not find a needed root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
|
||||||
|
if (uploadedRoot == null) {
|
||||||
|
_logger.LogError("Could not find a needed root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Creating cropfield");
|
||||||
|
|
||||||
|
var cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDrive.Code,
|
||||||
|
$"VRA Poten cropfield {input.OutputFileName}", input.PlantingYear,
|
||||||
|
input.GeometryJson.ToString(Formatting.None));
|
||||||
|
|
||||||
|
_logger.LogInformation($"CropfielditemCode: {cropfieldItem.Code}");
|
||||||
|
|
||||||
|
|
||||||
|
//Downloading shadowMap for own interpretation
|
||||||
|
if (useShadow) {
|
||||||
|
_logger.LogInformation("Calculate shadow map for field");
|
||||||
|
var shadowItem = await _generalService.RunShadowTask(cropfieldItem);
|
||||||
|
if (shadowItem == null) {
|
||||||
|
_logger.LogError("Something went wrong while obtaining the shadow map");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Downloading shadow map");
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(shadowItem.Code,
|
||||||
|
Path.Combine(DownloadFolder, $"{input.OutputFileName}.shadow.zip"));
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Looking for local data to use");
|
||||||
|
var localDataAvailable = input.File;
|
||||||
|
var geotiffItem = (Item)null;
|
||||||
|
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(localDataAvailable)) {
|
||||||
|
_logger.LogInformation("Could not find item for uploaded data, using BOFEK");
|
||||||
|
|
||||||
|
//Retreiving BOFEK
|
||||||
|
_logger.LogInformation("Get BOFEK for field");
|
||||||
|
var bofekItem = await _generalService.RunBofekTask(cropfieldItem);
|
||||||
|
if (bofekItem == null) {
|
||||||
|
_logger.LogError("Something went wrong while obtaining the BOFEK data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Downloading Bofek map");
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(bofekItem.Code,
|
||||||
|
Path.Combine(DownloadFolder, $"{input.OutputFileName}.BOFEK.zip"));
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
} 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), input.GeometryJson.ToString(Formatting.None));
|
||||||
|
|
||||||
|
if (shapeItem == null) {
|
||||||
|
_logger.LogError("Something went wrong while searching for the shape file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// transform shape to geotiff as VRA poten only supports tiff input item
|
||||||
|
_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($"ShapeToGeotiff_GeotiffItemcode: {geotiffItem.Code}");
|
||||||
|
|
||||||
|
_logger.LogInformation("Downloading geotiff file");
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(geotiffItem.Code,
|
||||||
|
Path.Combine(DownloadFolder, $"VRApoten_inputGeotiff_{input.OutputFileName}.zip"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// create appliance map
|
||||||
|
_logger.LogInformation("Calculating application map");
|
||||||
|
|
||||||
|
// INPUT IS NEEDED as GEOTIFF
|
||||||
|
var applianceMapItem =
|
||||||
|
await _potenService.CalculateApplicationMapAsync(cropfieldItem, geotiffItem, meanDensity, variation, countPerArea, useShadow, inputLayerName);
|
||||||
|
|
||||||
|
if (applianceMapItem == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Downloading application map");
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(applianceMapItem.Code,
|
||||||
|
Path.Combine(DownloadFolder, $"VRApoten_appliancemap_{input.OutputFileName}.zip"));
|
||||||
|
|
||||||
|
string finalOutput = Path.Combine(DownloadFolder, $"VRApoten_appliancemap_{input.OutputFileName}.zip");
|
||||||
|
_logger.LogInformation(File.Exists(finalOutput)
|
||||||
|
? "Download application map completed."
|
||||||
|
: "Something went wrong while downloading.");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(input.GenerateTaskmap) {
|
||||||
|
//GEOTIFF TO Taskmap
|
||||||
|
_logger.LogInformation($"Converting geotiff to taskmap");
|
||||||
|
|
||||||
|
var taskmap = (Item)null;
|
||||||
|
if (input.OutputType == "isoxml")
|
||||||
|
{
|
||||||
|
|
||||||
|
if (input.DdiCode == null)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("DDi not given. Using expected identifiers");
|
||||||
|
if (countPerArea == true) {input.DdiCode = input.DdiCode = "0011";}
|
||||||
|
else { input.DdiCode = "0016"; };
|
||||||
|
}
|
||||||
|
taskmap = await _generalService.CreateTaskmap(cropfieldItem: cropfieldItem, tiffItem: applianceMapItem, outputType: input.OutputType, cellWidth: input.CellWidth,
|
||||||
|
cellHeight: input.CellHeight, startPoint: input.StartPoint.ToString(Formatting.None), ddiCode: input.DdiCode, centered: input.Centered,
|
||||||
|
endPoint: input.EndPoint.ToString(Formatting.None), angle: input.Angle, precision: input.Precision,
|
||||||
|
cropTypeName: null, costumerName: null, ProductGroupName: null, productName : null, resolution: "3", unitScale: null, maximumClasses: input.MaximumClasses);
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
taskmap = await _generalService.CreateTaskmap(cropfieldItem: cropfieldItem, tiffItem: applianceMapItem, outputType: input.OutputType, cellWidth: input.CellWidth,
|
||||||
|
cellHeight: input.CellHeight, startPoint: input.StartPoint.ToString(Formatting.None), centered: input.Centered,
|
||||||
|
endPoint: input.EndPoint.ToString(Formatting.None), angle: input.Angle, precision: input.Precision, maximumClasses: input.MaximumClasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (taskmap == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Something went wrong with geotiff to taskmap transformation");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Downloading taskmap");
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(taskmap.Code,
|
||||||
|
Path.Combine(DownloadFolder, $"VRApoten_taskmap_{input.OutputFileName}_isoxml.zip"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
FarmmapsPoten/PotenInput.json
Normal file
53
FarmmapsPoten/PotenInput.json
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
[
|
||||||
|
|
||||||
|
{
|
||||||
|
"File": "PlantingSampleDataLutum.zip",
|
||||||
|
//"InputLayerName": "EC0-60",
|
||||||
|
"OutputFileName": "2021.06.09_vraPoten_SampleData",
|
||||||
|
"FieldName": "lutum",
|
||||||
|
"PlantingYear": 2021,
|
||||||
|
"MeanDensity": "30",
|
||||||
|
"Variation": "20",
|
||||||
|
"UseShadow": false,
|
||||||
|
"CountPerArea": true, // don't forget to change ddi if isoxml is created
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.66886041703652044, 52.52929999060298627 ],
|
||||||
|
[ 5.6716230923214912, 52.52946316399909676 ],
|
||||||
|
[ 5.67185376229668581, 52.5280565894154563 ],
|
||||||
|
[ 5.66903207841337231, 52.52790646510525363 ],
|
||||||
|
[ 5.66886041703652044, 52.52929999060298627 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"GenerateTaskmap": true,
|
||||||
|
"OutputType": "shape", // "shape" or "isoxml" if isoxml also add ddiCode
|
||||||
|
"Precision": "2",
|
||||||
|
"MaximumClasses": "5",
|
||||||
|
"DdiCode": "0016", // DDI 0011 for count per area; DDI 0016 for distance (CM)
|
||||||
|
"CellWidth": "3",
|
||||||
|
"CellHeight": "10",
|
||||||
|
"Centered": "true",
|
||||||
|
"StartPoint": {
|
||||||
|
"type": "Point",
|
||||||
|
//"coordinates": [ 5.66886041703652044, 52.52929999060298627 ] // 1
|
||||||
|
//"coordinates": [ 5.6716230923214912, 52.52946316399909676 ] // 2
|
||||||
|
//"coordinates": [ 5.67185376229668581, 52.5280565894154563 ] // 3
|
||||||
|
"coordinates": [ 5.66903207841337231, 52.52790646510525363 ] // 4
|
||||||
|
},
|
||||||
|
"EndPoint": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [ 5.66886041703652044, 52.52929999060298627 ] // 1
|
||||||
|
//"coordinates": [ 5.6716230923214912, 52.52946316399909676 ] // 2
|
||||||
|
//"coordinates": [ 5.67185376229668581, 52.5280565894154563 ] // 3
|
||||||
|
//"coordinates": [ 5.66903207841337231, 52.52790646510525363 ] // 4
|
||||||
|
} // if no angle
|
||||||
|
|
||||||
|
//"Angle": "317.0" // if no endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
]
|
79
FarmmapsPoten/PotenService.cs
Normal file
79
FarmmapsPoten/PotenService.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using static FarmmapsApi.Extensions;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
|
||||||
|
namespace FarmmapsVRApoten
|
||||||
|
{
|
||||||
|
public class PotenService
|
||||||
|
{
|
||||||
|
private readonly ILogger<PotenService> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
public PotenService(ILogger<PotenService> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Item> CalculateApplicationMapAsync(Item cropfieldItem, Item inputItem, string meanDensity, string variation, bool countPerArea, bool useShadow, string inputLayerName = null)
|
||||||
|
{
|
||||||
|
var potenApplicationMapRequest = new TaskRequest() { TaskType = VRAPLANTING_TASK };
|
||||||
|
if (inputItem != null) {potenApplicationMapRequest.attributes["inputCode"] = inputItem.Code; }
|
||||||
|
potenApplicationMapRequest.attributes["meanDensity"] = meanDensity;
|
||||||
|
potenApplicationMapRequest.attributes["variation"] = variation;
|
||||||
|
potenApplicationMapRequest.attributes["variation"] = variation;
|
||||||
|
potenApplicationMapRequest.attributes["countPerArea"] = countPerArea.ToString();
|
||||||
|
potenApplicationMapRequest.attributes["useShadow"] = useShadow.ToString();
|
||||||
|
potenApplicationMapRequest.attributes["inputLayerName"] = inputLayerName;
|
||||||
|
|
||||||
|
var taskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, potenApplicationMapRequest);
|
||||||
|
_logger.LogInformation($"itemTaskCode: {taskCode}");
|
||||||
|
_logger.LogInformation($"potenTaskmapRequest: {potenApplicationMapRequest}");
|
||||||
|
_logger.LogInformation($"potenTaskmapRequest type: {potenApplicationMapRequest.TaskType}");
|
||||||
|
_logger.LogInformation($"cropfieldItemCode: {cropfieldItem.Code}");
|
||||||
|
|
||||||
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) => {
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
|
||||||
|
_logger.LogInformation($"Waiting on calculation of application map; Status: {itemTaskStatus.State}");
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
|
||||||
|
if (itemTask.State == ItemTaskState.Error)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemName = $"VRAPoten";
|
||||||
|
var applianceMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
|
||||||
|
GEOTIFF_PROCESSED_ITEMTYPE, itemName,
|
||||||
|
i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) &&
|
||||||
|
i.Name.ToLower().Contains(itemName.ToLower()));
|
||||||
|
|
||||||
|
if (applianceMapItem == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find the VRAPoten geotiff child item under cropfield");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return applianceMapItem;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
21
FarmmapsPoten/Program.cs
Normal file
21
FarmmapsPoten/Program.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace FarmmapsVRApoten
|
||||||
|
{
|
||||||
|
class Program : FarmmapsProgram<PotenApplication>
|
||||||
|
{
|
||||||
|
private static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
await new Program().Start(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Configure(IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
serviceCollection.AddLogging()
|
||||||
|
.AddTransient<PotenService>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
FarmmapsZonering/Data/Points.json
Normal file
45
FarmmapsZonering/Data/Points.json
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"name": "Points",
|
||||||
|
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
|
||||||
|
"features": [
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 9, "Data_decimal": 0.1 }, "geometry": { "type": "Point", "coordinates": [ 5.670697160803186, 52.529191329839897 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 3, "Data_decimal": 0.97 }, "geometry": { "type": "Point", "coordinates": [ 5.671065563240634, 52.529190448643625 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 9, "Data_decimal": 0.09 }, "geometry": { "type": "Point", "coordinates": [ 5.671433965661168, 52.5291895663036 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 1, "Data_decimal": 0.29 }, "geometry": { "type": "Point", "coordinates": [ 5.669222114450619, 52.528970163883578 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 10, "Data_decimal": 0.05 }, "geometry": { "type": "Point", "coordinates": [ 5.669590515080236, 52.528969287267856 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 3, "Data_decimal": 0.35 }, "geometry": { "type": "Point", "coordinates": [ 5.669958915693023, 52.528968409508401 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 2, "Data_decimal": 0.59 }, "geometry": { "type": "Point", "coordinates": [ 5.670327316288964, 52.528967530605286 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 1, "Data_decimal": 0.16 }, "geometry": { "type": "Point", "coordinates": [ 5.670695716868035, 52.528966650558438 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 7, "Data_decimal": 0.57 }, "geometry": { "type": "Point", "coordinates": [ 5.671064117430213, 52.528965769367922 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 6, "Data_decimal": 0.4 }, "geometry": { "type": "Point", "coordinates": [ 5.671432517975476, 52.528964887033666 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 2, "Data_decimal": 0.32 }, "geometry": { "type": "Point", "coordinates": [ 5.669220678033353, 52.528745484567601 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 1, "Data_decimal": 0.16 }, "geometry": { "type": "Point", "coordinates": [ 5.669589076787721, 52.528744607957577 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 7, "Data_decimal": 0.36 }, "geometry": { "type": "Point", "coordinates": [ 5.669957475525263, 52.528743730203921 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 3, "Data_decimal": 0.33 }, "geometry": { "type": "Point", "coordinates": [ 5.670325874245955, 52.528742851306561 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 1, "Data_decimal": 0.86 }, "geometry": { "type": "Point", "coordinates": [ 5.670694272949777, 52.528741971265497 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 6, "Data_decimal": 0.61 }, "geometry": { "type": "Point", "coordinates": [ 5.671062671636706, 52.528741090080729 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 9, "Data_decimal": 0.7 }, "geometry": { "type": "Point", "coordinates": [ 5.671431070306722, 52.528740207752286 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 4, "Data_decimal": 0.73 }, "geometry": { "type": "Point", "coordinates": [ 5.669219241632893, 52.528520805240142 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 5, "Data_decimal": 0.54 }, "geometry": { "type": "Point", "coordinates": [ 5.669587638512033, 52.528519928635895 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 1, "Data_decimal": 0.11 }, "geometry": { "type": "Point", "coordinates": [ 5.669956035374347, 52.528519050887994 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 10, "Data_decimal": 0.41 }, "geometry": { "type": "Point", "coordinates": [ 5.670324432219813, 52.528518171996353 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 3, "Data_decimal": 0.17 }, "geometry": { "type": "Point", "coordinates": [ 5.670692829048409, 52.52851729196108 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 5, "Data_decimal": 0.8 }, "geometry": { "type": "Point", "coordinates": [ 5.671061225860114, 52.528516410782132 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 4, "Data_decimal": 0.11 }, "geometry": { "type": "Point", "coordinates": [ 5.671429622654903, 52.528515528459451 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 3, "Data_decimal": 0.31 }, "geometry": { "type": "Point", "coordinates": [ 5.669217805249236, 52.528296125901214 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 9, "Data_decimal": 0.07 }, "geometry": { "type": "Point", "coordinates": [ 5.669586200253172, 52.528295249302751 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 10, "Data_decimal": 0.54 }, "geometry": { "type": "Point", "coordinates": [ 5.669954595240281, 52.528294371560584 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 8, "Data_decimal": 0.82 }, "geometry": { "type": "Point", "coordinates": [ 5.670322990210543, 52.528293492674734 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 7, "Data_decimal": 0.54 }, "geometry": { "type": "Point", "coordinates": [ 5.670691385163935, 52.528292612645224 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 2, "Data_decimal": 0.35 }, "geometry": { "type": "Point", "coordinates": [ 5.671059780100435, 52.528291731472009 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 1, "Data_decimal": 0.35 }, "geometry": { "type": "Point", "coordinates": [ 5.671428175020021, 52.528290849155169 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 8, "Data_decimal": 0.13 }, "geometry": { "type": "Point", "coordinates": [ 5.669216368882385, 52.528071446550889 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 10, "Data_decimal": 0.51 }, "geometry": { "type": "Point", "coordinates": [ 5.669584762011135, 52.528070569958146 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 7, "Data_decimal": 0.52 }, "geometry": { "type": "Point", "coordinates": [ 5.669953155123062, 52.528069692221734 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 8, "Data_decimal": 0.86 }, "geometry": { "type": "Point", "coordinates": [ 5.670321548218141, 52.528068813341662 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 10, "Data_decimal": 0.54 }, "geometry": { "type": "Point", "coordinates": [ 5.670689941296351, 52.528067933317907 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 7, "Data_decimal": 0.54 }, "geometry": { "type": "Point", "coordinates": [ 5.671058334357669, 52.528067052150526 ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 10, "Data_decimal": 0.33 }, "geometry": { "type": "Point", "coordinates": [ 5.671426727402074, 52.528066169839413 ] } }
|
||||||
|
]
|
||||||
|
}
|
40
FarmmapsZonering/Data/Polygons.json
Normal file
40
FarmmapsZonering/Data/Polygons.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"name": "Polygons",
|
||||||
|
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
|
||||||
|
"features": [
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 4, "Data_decimal": 0.17 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670445415146707, 52.529088625025459 ], [ 5.670436500109911, 52.529205353741368 ], [ 5.67100275425158, 52.529226856274043 ], [ 5.670445415146707, 52.529088625025459 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 3, "Data_decimal": 0.17 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670474664765167, 52.528705646190737 ], [ 5.670509421984359, 52.528695389390876 ], [ 5.670475899473076, 52.528689479586824 ], [ 5.670474664765167, 52.528705646190737 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 8, "Data_decimal": 0.66 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670529486595214, 52.527987838516857 ], [ 5.670513853610409, 52.528192528445118 ], [ 5.671080652223759, 52.528222889234513 ], [ 5.671037195788521, 52.52802077466923 ], [ 5.670529486595214, 52.527987838516857 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 6, "Data_decimal": 0.87 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.671088061587392, 52.528257349960555 ], [ 5.670500031678031, 52.528373505423083 ], [ 5.670475899473076, 52.528689479586824 ], [ 5.670509421984359, 52.528695389390876 ], [ 5.67114210124075, 52.528508686753064 ], [ 5.671088061587392, 52.528257349960555 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 2, "Data_decimal": 0.97 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.671208751860665, 52.528818676769426 ], [ 5.671298932270745, 52.529238103127824 ], [ 5.671622542615743, 52.529250391677266 ], [ 5.671678791037005, 52.528901541665995 ], [ 5.671208751860665, 52.528818676769426 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 8, "Data_decimal": 0.34 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.671805511114944, 52.528115629819482 ], [ 5.671223720783484, 52.528230552757869 ], [ 5.671782157848563, 52.528260465657667 ], [ 5.671805511114944, 52.528115629819482 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 2, "Data_decimal": 0.93 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.671223720783484, 52.528230552757869 ], [ 5.671088061587392, 52.528257349960555 ], [ 5.67114210124075, 52.528508686753064 ], [ 5.671772111651965, 52.528322771687201 ], [ 5.671782157848563, 52.528260465657667 ], [ 5.671223720783484, 52.528230552757869 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 9, "Data_decimal": 0.88 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.669598765293697, 52.528964122725455 ], [ 5.669756159705026, 52.52891767588612 ], [ 5.66960263338403, 52.528879598286942 ], [ 5.669598765293697, 52.528964122725455 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 3, "Data_decimal": 0.65 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.66964340911196, 52.528542716867584 ], [ 5.669617818752811, 52.528547771814544 ], [ 5.66960263338403, 52.528879598286942 ], [ 5.669756159705026, 52.52891767588612 ], [ 5.670010186520852, 52.528842712978594 ], [ 5.670075070608809, 52.528618816025038 ], [ 5.66964340911196, 52.528542716867584 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 2, "Data_decimal": 0.12 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.669646065617165, 52.527930529158823 ], [ 5.669636227085067, 52.52814551803705 ], [ 5.670203425137223, 52.528175900222543 ], [ 5.670262935417118, 52.527970546787003 ], [ 5.669646065617165, 52.527930529158823 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 4, "Data_decimal": 0.36 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670124673219705, 52.528447651201468 ], [ 5.66964340911196, 52.528542716867584 ], [ 5.670075070608809, 52.528618816025038 ], [ 5.670124673219705, 52.528447651201468 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 1, "Data_decimal": 0.25 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.66997288555807, 52.528971428233667 ], [ 5.669910879416426, 52.5291853941944 ], [ 5.670436500109911, 52.529205353741368 ], [ 5.670445415146707, 52.529088625025459 ], [ 5.66997288555807, 52.528971428233667 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 4, "Data_decimal": 0.32 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670010186520852, 52.528842712978594 ], [ 5.670474664765167, 52.528705646190737 ], [ 5.670475899473076, 52.528689479586824 ], [ 5.670075070608809, 52.528618816025038 ], [ 5.670010186520852, 52.528842712978594 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 5, "Data_decimal": 0.41 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670262935417118, 52.527970546787003 ], [ 5.670203425137223, 52.528175900222543 ], [ 5.670513853610409, 52.528192528445118 ], [ 5.670529486595214, 52.527987838516857 ], [ 5.670262935417118, 52.527970546787003 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 7, "Data_decimal": 0.8 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670500031678031, 52.528373505423083 ], [ 5.670124673219705, 52.528447651201468 ], [ 5.670075070608809, 52.528618816025038 ], [ 5.670475899473076, 52.528689479586824 ], [ 5.670500031678031, 52.528373505423083 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 9, "Data_decimal": 0.35 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.668970013365158, 52.529149666415094 ], [ 5.669598765293697, 52.528964122725455 ], [ 5.66960263338403, 52.528879598286942 ], [ 5.668980939909752, 52.528725405867227 ], [ 5.668923420100609, 52.52914789711555 ], [ 5.668970013365158, 52.529149666415094 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 4, "Data_decimal": 0.69 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.669617818752811, 52.528547771814544 ], [ 5.668988191186747, 52.528672144197635 ], [ 5.668980939909752, 52.528725405867227 ], [ 5.66960263338403, 52.528879598286942 ], [ 5.669617818752811, 52.528547771814544 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 3, "Data_decimal": 0.43 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.669636227085067, 52.52814551803705 ], [ 5.669646065617165, 52.527930529158823 ], [ 5.669094033437861, 52.527894717682074 ], [ 5.669064060973, 52.528114869735482 ], [ 5.669636227085067, 52.52814551803705 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 6, "Data_decimal": 0.6 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.669618253034461, 52.528538282012228 ], [ 5.669636227085067, 52.52814551803705 ], [ 5.669064060973, 52.528114869735482 ], [ 5.669020756513456, 52.528432947202063 ], [ 5.669618253034461, 52.528538282012228 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 3, "Data_decimal": 0.39 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670509421984359, 52.528695389390876 ], [ 5.670474664765167, 52.528705646190737 ], [ 5.670445415146707, 52.529088625025459 ], [ 5.67100275425158, 52.529226856274043 ], [ 5.671298932270745, 52.529238103127824 ], [ 5.671208751860665, 52.528818676769426 ], [ 5.670509421984359, 52.528695389390876 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 3, "Data_decimal": 0.93 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.67114210124075, 52.528508686753064 ], [ 5.670509421984359, 52.528695389390876 ], [ 5.671208751860665, 52.528818676769426 ], [ 5.67114210124075, 52.528508686753064 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 5, "Data_decimal": 0.2 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.671772111651965, 52.528322771687201 ], [ 5.67114210124075, 52.528508686753064 ], [ 5.671208751860665, 52.528818676769426 ], [ 5.671678791037005, 52.528901541665995 ], [ 5.671772111651965, 52.528322771687201 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 6, "Data_decimal": 0.64 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.669756159705026, 52.52891767588612 ], [ 5.669598765293697, 52.528964122725455 ], [ 5.669589198259692, 52.529173178902582 ], [ 5.669910879416426, 52.5291853941944 ], [ 5.66997288555807, 52.528971428233667 ], [ 5.669756159705026, 52.52891767588612 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 7, "Data_decimal": 0.2 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670010186520852, 52.528842712978594 ], [ 5.669756159705026, 52.52891767588612 ], [ 5.66997288555807, 52.528971428233667 ], [ 5.670010186520852, 52.528842712978594 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 10, "Data_decimal": 0.66 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670474664765167, 52.528705646190737 ], [ 5.670010186520852, 52.528842712978594 ], [ 5.66997288555807, 52.528971428233667 ], [ 5.670445415146707, 52.529088625025459 ], [ 5.670474664765167, 52.528705646190737 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 2, "Data_decimal": 0.06 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.669598765293697, 52.528964122725455 ], [ 5.668970013365158, 52.529149666415094 ], [ 5.669589198259692, 52.529173178902582 ], [ 5.669598765293697, 52.528964122725455 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 1, "Data_decimal": 0.62 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670500031678031, 52.528373505423083 ], [ 5.671088061587392, 52.528257349960555 ], [ 5.671080652223759, 52.528222889234513 ], [ 5.670513853610409, 52.528192528445118 ], [ 5.670500031678031, 52.528373505423083 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 1, "Data_decimal": 0.58 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.671223720783484, 52.528230552757869 ], [ 5.671805511114944, 52.528115629819482 ], [ 5.671812693849701, 52.528071082842963 ], [ 5.671037195788521, 52.52802077466923 ], [ 5.671080652223759, 52.528222889234513 ], [ 5.671223720783484, 52.528230552757869 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 2, "Data_decimal": 0.83 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.671088061587392, 52.528257349960555 ], [ 5.671223720783484, 52.528230552757869 ], [ 5.671080652223759, 52.528222889234513 ], [ 5.671088061587392, 52.528257349960555 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 5, "Data_decimal": 0.45 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.669617818752811, 52.528547771814544 ], [ 5.66964340911196, 52.528542716867584 ], [ 5.669618253034461, 52.528538282012228 ], [ 5.669617818752811, 52.528547771814544 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 4, "Data_decimal": 0.34 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.66964340911196, 52.528542716867584 ], [ 5.670124673219705, 52.528447651201468 ], [ 5.670203425137223, 52.528175900222543 ], [ 5.669636227085067, 52.52814551803705 ], [ 5.669618253034461, 52.528538282012228 ], [ 5.66964340911196, 52.528542716867584 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 10, "Data_decimal": 0.68 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670124673219705, 52.528447651201468 ], [ 5.670500031678031, 52.528373505423083 ], [ 5.670513853610409, 52.528192528445118 ], [ 5.670203425137223, 52.528175900222543 ], [ 5.670124673219705, 52.528447651201468 ] ] ] } },
|
||||||
|
{ "type": "Feature", "properties": { "Data_whole": 9, "Data_decimal": 0.97 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.668988191186747, 52.528672144197635 ], [ 5.669617818752811, 52.528547771814544 ], [ 5.669618253034461, 52.528538282012228 ], [ 5.669020756513456, 52.528432947202063 ], [ 5.668988191186747, 52.528672144197635 ] ] ] } }
|
||||||
|
]
|
||||||
|
}
|
Binary file not shown.
BIN
FarmmapsZonering/Data/data_9001.tif
Normal file
BIN
FarmmapsZonering/Data/data_9001.tif
Normal file
Binary file not shown.
BIN
FarmmapsZonering/Data/data_lowres_9001.tiff
Normal file
BIN
FarmmapsZonering/Data/data_lowres_9001.tiff
Normal file
Binary file not shown.
BIN
FarmmapsZonering/Data/data_times_two_4326.tiff
Normal file
BIN
FarmmapsZonering/Data/data_times_two_4326.tiff
Normal file
Binary file not shown.
8
FarmmapsZonering/Data/pg.json
Normal file
8
FarmmapsZonering/Data/pg.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"name": "neo_pg",
|
||||||
|
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
|
||||||
|
"features": [
|
||||||
|
{ "type": "Feature", "properties": { "id": 1 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 5.670991253771027, 52.796788997702613 ], [ 5.671526456638633, 52.797291618546666 ], [ 5.671275936147413, 52.797422436717852 ], [ 5.671959173850738, 52.798269302728798 ], [ 5.670649634919365, 52.798778791408822 ], [ 5.671503682048522, 52.799591206957416 ], [ 5.675159003761311, 52.798193567415474 ], [ 5.673029579585948, 52.796024727480535 ], [ 5.670991253771027, 52.796788997702613 ] ] ] } }
|
||||||
|
]
|
||||||
|
}
|
BIN
FarmmapsZonering/Data/pg.zip
Normal file
BIN
FarmmapsZonering/Data/pg.zip
Normal file
Binary file not shown.
BIN
FarmmapsZonering/Data/sentinel2_L2A_B04.tiff
Normal file
BIN
FarmmapsZonering/Data/sentinel2_L2A_B04.tiff
Normal file
Binary file not shown.
BIN
FarmmapsZonering/Data/sentinel2_L2A_B08.tiff
Normal file
BIN
FarmmapsZonering/Data/sentinel2_L2A_B08.tiff
Normal file
Binary file not shown.
21
FarmmapsZonering/FarmmapsZonering.csproj
Normal file
21
FarmmapsZonering/FarmmapsZonering.csproj
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Data\**\*">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="ZoneringInput.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\FarmmapsApi\FarmmapsApi.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
8
FarmmapsZonering/Models/InputParameter.cs
Normal file
8
FarmmapsZonering/Models/InputParameter.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace FarmmapsZonering.Models
|
||||||
|
{
|
||||||
|
public class InputParameter
|
||||||
|
{
|
||||||
|
public string ItemCode { get; set; }
|
||||||
|
public string LayerName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
9
FarmmapsZonering/Models/Output.cs
Normal file
9
FarmmapsZonering/Models/Output.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace FarmmapsZonering.Models
|
||||||
|
{
|
||||||
|
public class Output
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Quantity { get; set; }
|
||||||
|
public string Unit { get; set; }
|
||||||
|
}
|
||||||
|
}
|
11
FarmmapsZonering/Models/Settings.cs
Normal file
11
FarmmapsZonering/Models/Settings.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace FarmmapsHaulmkilling.Models
|
||||||
|
{
|
||||||
|
public class Settings
|
||||||
|
{
|
||||||
|
public string CropfieldItemCode { get; set; }
|
||||||
|
public string CropfieldName { get; set; }
|
||||||
|
public string SatelliteTaskCode { get; set; }
|
||||||
|
public string VanDerSatTaskCode { get; set; }
|
||||||
|
public string WatBalTaskCode { get; set; }
|
||||||
|
}
|
||||||
|
}
|
24
FarmmapsZonering/Models/ZoneringInput.cs
Normal file
24
FarmmapsZonering/Models/ZoneringInput.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace FarmmapsZonering.Models
|
||||||
|
{
|
||||||
|
public class ZoneringInput
|
||||||
|
{
|
||||||
|
public string InputItemOne { get; set; }
|
||||||
|
public string InputItemTwo { get; set; }
|
||||||
|
public string Formula { get; set; }
|
||||||
|
public string OutputFileName { get; set; }
|
||||||
|
public string CropFieldName { get; set; }
|
||||||
|
public string CalculatedLayerName { get; set; }
|
||||||
|
public string CalculatedQuantity { get; set; }
|
||||||
|
public string CalculatedUnit { get; set; }
|
||||||
|
public bool CreateNewCropfield { get; set; }
|
||||||
|
public int CropYear { get; set; }
|
||||||
|
public JObject GeometryJson { get; set; }
|
||||||
|
public bool GetWatBal { get; set; }
|
||||||
|
public bool GetVanDerSat { get; set; }
|
||||||
|
public bool storeVanDerSatStatistics { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
24
FarmmapsZonering/Program.cs
Normal file
24
FarmmapsZonering/Program.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi;
|
||||||
|
using FarmmapsZonering.Services;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace FarmmapsZonering
|
||||||
|
{
|
||||||
|
class Program : FarmmapsProgram<ZoneringApplication>
|
||||||
|
{
|
||||||
|
private static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
await new Program().Start(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Configure(IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
serviceCollection.AddLogging(opts => opts
|
||||||
|
.AddConsole()
|
||||||
|
.AddFilter("System.Net.Http", LogLevel.Warning))
|
||||||
|
.AddTransient<ZoneringService>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
FarmmapsZonering/Services/ZoneringService.cs
Normal file
66
FarmmapsZonering/Services/ZoneringService.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FarmmapsApi.Models;
|
||||||
|
using FarmmapsApi.Services;
|
||||||
|
using FarmmapsHaulmkilling.Models;
|
||||||
|
using FarmmapsZonering.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using static FarmmapsApi.Extensions;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
namespace FarmmapsZonering.Services
|
||||||
|
{
|
||||||
|
public class ZoneringService
|
||||||
|
{
|
||||||
|
private readonly ILogger<ZoneringService> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
|
||||||
|
public ZoneringService(ILogger<ZoneringService> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Item> CreateApplicationMapAsync(Item cropfieldItem, string formula, Output output, params InputParameter[] inputItemCodes)
|
||||||
|
{
|
||||||
|
var zoneringTaskRequest = new TaskRequest() {TaskType = VRAZONERING_TASK};
|
||||||
|
zoneringTaskRequest.attributes["formula"] = formula;
|
||||||
|
zoneringTaskRequest.attributes["output"] = JsonConvert.SerializeObject(output);
|
||||||
|
zoneringTaskRequest.attributes["inputs"] = JsonConvert.SerializeObject(inputItemCodes);
|
||||||
|
|
||||||
|
var taskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, zoneringTaskRequest);
|
||||||
|
|
||||||
|
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) =>
|
||||||
|
{
|
||||||
|
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
|
||||||
|
_logger.LogInformation($"Waiting on calculation of application map; Status: {itemTaskStatus.State}");
|
||||||
|
if (itemTaskStatus.IsFinished)
|
||||||
|
tokenSource.Cancel();
|
||||||
|
});
|
||||||
|
|
||||||
|
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
|
||||||
|
if (itemTask.State == ItemTaskState.Error)
|
||||||
|
{
|
||||||
|
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var applianceMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
|
||||||
|
GEOTIFF_PROCESSED_ITEMTYPE, output.Name,
|
||||||
|
i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) &&
|
||||||
|
i.Name.ToLower().Contains(output.Name.ToLower()));
|
||||||
|
|
||||||
|
if (applianceMapItem == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find the VRAZonering geotiff child item under cropfield");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return applianceMapItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
213
FarmmapsZonering/ZoneringApplication.cs
Normal file
213
FarmmapsZonering/ZoneringApplication.cs
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
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 FarmmapsHaulmkilling.Models;
|
||||||
|
using FarmmapsZonering.Models;
|
||||||
|
using FarmmapsZonering.Services;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using static FarmmapsApiSamples.Constants;
|
||||||
|
|
||||||
|
namespace FarmmapsZonering
|
||||||
|
{
|
||||||
|
public class ZoneringApplication : IApplication
|
||||||
|
{
|
||||||
|
private const string DownloadFolder = "Downloads";
|
||||||
|
private const string SettingsFile = "settings.json";
|
||||||
|
|
||||||
|
private readonly ILogger<ZoneringApplication> _logger;
|
||||||
|
private readonly FarmmapsApiService _farmmapsApiService;
|
||||||
|
private readonly GeneralService _generalService;
|
||||||
|
private readonly ZoneringService _zoneringService;
|
||||||
|
|
||||||
|
private Settings _settings;
|
||||||
|
|
||||||
|
public ZoneringApplication(ILogger<ZoneringApplication> logger, FarmmapsApiService farmmapsApiService,
|
||||||
|
GeneralService generalService, ZoneringService zoneringService)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_farmmapsApiService = farmmapsApiService;
|
||||||
|
_generalService = generalService;
|
||||||
|
_zoneringService = zoneringService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunAsync()
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(DownloadFolder))
|
||||||
|
Directory.CreateDirectory(DownloadFolder);
|
||||||
|
|
||||||
|
// Read input data from separate file
|
||||||
|
var zoneringInputJson = File.ReadAllText("ZoneringInput.json");
|
||||||
|
List<ZoneringInput> zoneringInputs = JsonConvert.DeserializeObject<List<ZoneringInput>>(zoneringInputJson);
|
||||||
|
|
||||||
|
// !! 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 zoneringInputs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await ZoningAsync(roots, input);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ZoningAsync(List<UserRoot> roots, ZoneringInput input)
|
||||||
|
{
|
||||||
|
var myDrive = roots.SingleOrDefault(r => r.Name == "USER_FILES");
|
||||||
|
if (myDrive == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find a needed root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useCreatedCropfield = false;
|
||||||
|
bool GetWatBal = input.GetWatBal;
|
||||||
|
bool getVanDerSat = input.GetVanDerSat;
|
||||||
|
bool StoreVanDerSatStatistics = input.storeVanDerSatStatistics;
|
||||||
|
var FieldName = input.CropFieldName;
|
||||||
|
string settingsfile = $"Settings_{FieldName}.json";
|
||||||
|
|
||||||
|
// Load settings from previous cropfield
|
||||||
|
LoadSettings(settingsfile);
|
||||||
|
|
||||||
|
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
|
||||||
|
if (uploadedRoot == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find a needed root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Item cropfieldItem;
|
||||||
|
if (input.CreateNewCropfield == true) // || string.IsNullOrEmpty(_settings.CropfieldItemCode) ## CHECK IT!!
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Creating cropfield");
|
||||||
|
|
||||||
|
|
||||||
|
cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDrive.Code, input.CropFieldName, input.CropYear,
|
||||||
|
input.GeometryJson.ToString(Formatting.None));
|
||||||
|
|
||||||
|
_settings.CropfieldName = cropfieldItem.Name;
|
||||||
|
_settings.CropfieldItemCode = cropfieldItem.Code;
|
||||||
|
SaveSettings(settingsfile);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Cropfield already exists trying to get");
|
||||||
|
cropfieldItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldItemCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetWatBal==true) {
|
||||||
|
////Run watbal
|
||||||
|
//if (useCreatedCropfield == false || string.IsNullOrEmpty(_settings.WatBalTaskCode)) {
|
||||||
|
// var WatBalTaskCode = await _generalService.RunWatBalTask(cropfieldItem);
|
||||||
|
// _settings.WatBalTaskCode = WatBalTaskCode;
|
||||||
|
// SaveSettings(settingsfile);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//// Get watbal data
|
||||||
|
//Item WatBalItem = await _generalService.FindWatBalItem(cropfieldItem, _settings.WatBalTaskCode, FieldName, StoreStatistics);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getVanDerSat==true) {
|
||||||
|
// 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, StoreVanDerSatStatistics);
|
||||||
|
|
||||||
|
|
||||||
|
// download the geotiff
|
||||||
|
_logger.LogInformation("Downloading geotiff file");
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(VanDerSatItem.Code,
|
||||||
|
Path.Combine(DownloadFolder, $"nbs_VanDerSatGeotiff_{input.OutputFileName}.zip"));
|
||||||
|
}
|
||||||
|
|
||||||
|
var inputOneItem = await _generalService.UploadDataAsync(uploadedRoot, GEOTIFF_PROCESSED_ITEMTYPE,
|
||||||
|
Path.Combine("Data", $"{input.InputItemOne}"), Path.GetFileNameWithoutExtension($"{input.InputItemOne}"));
|
||||||
|
|
||||||
|
if (inputOneItem == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Could not find item for uploaded data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//var inputTwoItem = await _generalService.UploadDataAsync(uploadedRoot, GEOTIFF_PROCESSED_ITEMTYPE,
|
||||||
|
// Path.Combine("Data", $"{input.InputItemTwo}"), Path.GetFileNameWithoutExtension($"{input.InputItemTwo}"));
|
||||||
|
|
||||||
|
//if (inputTwoItem == null) {
|
||||||
|
// _logger.LogError("Could not find item for uploaded data");
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
var outputItem = await _zoneringService.CreateApplicationMapAsync(cropfieldItem, input.Formula, new Output()
|
||||||
|
{
|
||||||
|
Name = input.CalculatedLayerName,
|
||||||
|
Quantity = input.CalculatedQuantity,
|
||||||
|
Unit = input.CalculatedUnit,
|
||||||
|
|
||||||
|
|
||||||
|
}, new InputParameter()
|
||||||
|
{
|
||||||
|
ItemCode = inputOneItem.Code,
|
||||||
|
LayerName = inputOneItem.Data["layers"][0]["name"].ToString()
|
||||||
|
//},
|
||||||
|
//new InputParameter()
|
||||||
|
//{
|
||||||
|
// ItemCode = inputTwoItem.Code,
|
||||||
|
// LayerName = inputTwoItem.Data["layers"][0]["name"].ToString()
|
||||||
|
});
|
||||||
|
|
||||||
|
_logger.LogInformation("Downloading output");
|
||||||
|
_logger.LogInformation($"outputitem: {outputItem} with code {outputItem.Code} and date {outputItem.DataDate}");
|
||||||
|
|
||||||
|
await _farmmapsApiService.DownloadItemAsync(outputItem.Code,
|
||||||
|
|
||||||
|
Path.Combine(DownloadFolder, $"{input.OutputFileName}.zoning.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
99
FarmmapsZonering/ZoneringInput.json
Normal file
99
FarmmapsZonering/ZoneringInput.json
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
[
|
||||||
|
|
||||||
|
//Formule kan meerdere inputs aan
|
||||||
|
// Met blokhaken en een nummer specificeer je een input:
|
||||||
|
//[0], [10]. etc...
|
||||||
|
// Aan de hand van de volgorde van input wordt momenteel bepaald welk nummer bij welk input hoort.
|
||||||
|
//[0] is dus de eerst tiff opgegeven.Als het goed is maakt het nummer nu niks uit, dus als er 2 inputs zijn en in de formule staan[0] en[10] dan zal die nog steeds werken.
|
||||||
|
//De volgorde van de tiff kun je verslepen, bij de formule inputs kun je de input van het ene[0] slot naar het andere slepen[10]
|
||||||
|
//Functies: abs, min en max
|
||||||
|
//Constanten: pi en e
|
||||||
|
|
||||||
|
//if ([0] -[1])/ ([0] +[1]) < 0 then 0
|
||||||
|
//else if ([0] -[1])/ ([0] +[1]) > 1 then 1
|
||||||
|
//else ([0] -[1]) / ([0] +[1])
|
||||||
|
|
||||||
|
//{
|
||||||
|
// "InputItemOne": "20201106_Sentinel2_L2A_B04.tiff",
|
||||||
|
// "InputItemTwo": "20201106_Sentinel2_L2A_B08.tiff",
|
||||||
|
// "Formula": "([1]-[0])/([1]+[0])",
|
||||||
|
// "CreatedLayerName": "Biomassa",
|
||||||
|
// "CalculatedQuantity": "NDVI",
|
||||||
|
// "CalculatedUnit": "ndviValue",
|
||||||
|
|
||||||
|
// "OutputFileName": "FullField_NDVI",
|
||||||
|
// "CropFieldName": "FullField",
|
||||||
|
// "CreateNewCropfield": false,
|
||||||
|
// "CropYear": 2020,
|
||||||
|
// "geometryJson": {
|
||||||
|
// "type": "Polygon",
|
||||||
|
// "coordinates": [
|
||||||
|
|
||||||
|
// [
|
||||||
|
// [ 4.9593709, 52.8014339 ],
|
||||||
|
// [ 4.9675488, 52.7943149 ],
|
||||||
|
// [ 4.9735195, 52.7968665 ],
|
||||||
|
// [ 4.9667833, 52.8030414 ],
|
||||||
|
// [ 4.9593709, 52.8014339 ]
|
||||||
|
// ]
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
//,
|
||||||
|
//{
|
||||||
|
// "InputItemOne": "data_9001.tif",
|
||||||
|
// "InputItemTwo": "data_times_two_4326.tiff",
|
||||||
|
// "Formula": "if [0] >= 1.28 then [1] else 0",
|
||||||
|
// "CreatedLayerName": "Biomassa",
|
||||||
|
// "CalculatedQuantity": "NDVI",
|
||||||
|
// "CalculatedUnit": "ndviValue",
|
||||||
|
// "OutputFileName": "Zoning",
|
||||||
|
// "CropFieldName": "Data_whole",
|
||||||
|
// "UseShadow": false,
|
||||||
|
// "GetWatBal": false,
|
||||||
|
// "GetVanDerSat": false,
|
||||||
|
// "storeVanDerSatStatistics": false,
|
||||||
|
// "CropYear": 2020,
|
||||||
|
// "geometryJson": {
|
||||||
|
// "type": "Polygon",
|
||||||
|
// "coordinates": [
|
||||||
|
// [
|
||||||
|
// [ 5.66886041703652044, 52.52929999060298627 ],
|
||||||
|
// [ 5.6716230923214912, 52.52946316399909676 ],
|
||||||
|
// [ 5.67185376229668581, 52.5280565894154563 ],
|
||||||
|
// [ 5.66903207841337231, 52.52790646510525363 ],
|
||||||
|
// [ 5.66886041703652044, 52.52929999060298627 ]
|
||||||
|
// ]
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
//},
|
||||||
|
{
|
||||||
|
"InputItemOne": "VRApoten_appliancemap_20210215_vraPoten_SampleData_CovertArea.tif",
|
||||||
|
//"InputItemTwo": "",
|
||||||
|
"Formula": "((100/[0])/0.75)",
|
||||||
|
"LayerName": "CountPerAreaConversion",
|
||||||
|
"CalculatedQuantity": "CountPerArea",
|
||||||
|
"CalculatedUnit": "#/m2",
|
||||||
|
"OutputFileName": "CountPerAreaConversionOutput",
|
||||||
|
"CropFieldName": "ZoningCpA",
|
||||||
|
"CreateNewCropfield": true,
|
||||||
|
"UseShadow": false,
|
||||||
|
"GetWatBal": false,
|
||||||
|
"GetVanDerSat": false,
|
||||||
|
"storeVanDerSatStatistics": false,
|
||||||
|
"CropYear": 2020,
|
||||||
|
"geometryJson": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[ 5.66886041703652044, 52.52929999060298627 ],
|
||||||
|
[ 5.6716230923214912, 52.52946316399909676 ],
|
||||||
|
[ 5.67185376229668581, 52.5280565894154563 ],
|
||||||
|
[ 5.66903207841337231, 52.52790646510525363 ],
|
||||||
|
[ 5.66886041703652044, 52.52929999060298627 ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
22
README.MD
22
README.MD
@ -1,6 +1,26 @@
|
|||||||
##### NOT PRODUCTION READY CODE, JUST AN EXAMPLE
|
##### NOT PRODUCTION READY CODE, JUST AN EXAMPLE
|
||||||
|
|
||||||
Put your clientId and clientSecret in the appsettings.json.
|
Put your clientId and clientSecret or your Farmmaps-account data (username and password) in a newly created appsettings.secrets.json file inside the root of the Secrets project.
|
||||||
|
|
||||||
|
**appsettings.secrets.json**
|
||||||
|
```
|
||||||
|
{
|
||||||
|
//API credential sign-in
|
||||||
|
"ClientId": "<clientId>",
|
||||||
|
"ClientSecret": "<clientSecret>"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or when using a Farmmaps account to sing-in
|
||||||
|
|
||||||
|
**appsettings.secrets.json**
|
||||||
|
```
|
||||||
|
{
|
||||||
|
//Sign-in using farmmaps account
|
||||||
|
"Username": "",
|
||||||
|
"Password": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
* Isn't 100% complete.
|
* Isn't 100% complete.
|
||||||
* Needs proper testing of all public api methods.
|
* Needs proper testing of all public api methods.
|
||||||
|
18
Secrets/Secrets.csproj
Normal file
18
Secrets/Secrets.csproj
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard1.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="appsettings.json" />
|
||||||
|
<Content Include="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<None Remove="appsettings.secrets.json" />
|
||||||
|
<Content Include="appsettings.secrets.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
6
Secrets/Secrets.csproj.user
Normal file
6
Secrets/Secrets.csproj.user
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ShowAllFiles>true</ShowAllFiles>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
28
Secrets/appsettings.json
Normal file
28
Secrets/appsettings.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
//There are three farmmaps environments, uncomment the environemnt you want to use with this sample client
|
||||||
|
|
||||||
|
//test environment
|
||||||
|
"Authority": "https://accounts.test.farmmaps.eu/",
|
||||||
|
"Endpoint": "https://test.farmmaps.eu/",
|
||||||
|
"BasePath": "api/v1",
|
||||||
|
"DiscoveryEndpointUrl": "https://accounts.test.farmmaps.eu/.well-known/openid-configuration",
|
||||||
|
"GrantClientId": "farmmapstesteu",
|
||||||
|
|
||||||
|
////acceptance environment
|
||||||
|
//"Authority": "https://accounts.acc.farmmaps.eu/",
|
||||||
|
//"Endpoint": "https://acc.farmmaps.eu/",
|
||||||
|
//"BasePath": "api/v1",
|
||||||
|
//"DiscoveryEndpointUrl": "https://accounts.acc.farmmaps.eu/.well-known/openid-configuration",
|
||||||
|
//"GrantClientId": "farmmapsacceu",
|
||||||
|
|
||||||
|
////production environment
|
||||||
|
//"authority": "https://accounts.farmmaps.eu/",
|
||||||
|
//"endpoint": "https://farmmaps.eu/",
|
||||||
|
//"basepath": "api/v1",
|
||||||
|
//"discoveryendpointurl": "https://accounts.farmmaps.eu/.well-known/openid-configuration",
|
||||||
|
//"GrantClientId": "farmmaps",
|
||||||
|
|
||||||
|
//overige info
|
||||||
|
"RedirectUri": "http://example.nl/api",
|
||||||
|
"Scopes": [ "api" ]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user