Compare commits

..

146 Commits

Author SHA1 Message Date
56b337aebf Merge pull request 'master' (#16) from abel/FarmMapsApiClient_KB34_MAST:master into master
Reviewed-on: #16
2025-01-10 15:39:26 +00:00
c6e4f7368f Delete the FarmmapsCleanUpApplication 2025-01-10 12:50:49 +01:00
fd44f99c98 Merge remote-tracking branch 'upstream/master'
And updated ShowGeotiff.r using new 'r' 'terra' packages
And added comment for the DataDownloadApplication and for the BulkSatDownloadApplication:
    //To run this app, first go to farmmaps datastore at https://farmmaps.eu/en/editor/plan (or on test)
    //goto 'Apps and Data', goto 'Data', buy (or get for free?): 'SATELLITE'
2025-01-10 12:44:14 +01:00
fb92fa0d1c KPI ammonia emissions is now fully functional (including in the example input file) 2024-08-26 10:35:58 +02:00
67e5cb6bb4 Added KPI G1 ammonia emissions (only on test servers)
- Ammonia emissions from fertilizers not yet fully functional
2024-07-04 13:35:33 +02:00
da82c232e3 Added CL104 2024-06-28 11:27:24 +02:00
752b538780 changed explanation of optional inputs for green manure. 2024-06-05 14:06:13 +02:00
178ba1ea5b //added a duplicate counter to deal with calculations where there is more 1 duplicate. 2024-05-28 10:06:48 +02:00
c2e4f9d861 commented out the totalNfertiliserInput = totalNferiliserCropfield check 2024-05-27 15:35:25 +02:00
6d6b5b1b7a removed incorrect duplicate KPIs 2024-05-27 13:52:15 +02:00
fcf6b2af51 Merge branch 'master' of https://git.akkerweb.nl/abel/FarmMapsApiClient_KB34_MAST 2024-05-16 10:05:04 +02:00
24feeba58e throw warning instead of error 2024-05-16 10:04:48 +02:00
a98a81776d calculate KPI's for all example fields instead of one field 2024-05-15 16:06:19 +02:00
e05bb5a8f7 added code for checking if multiple runs give same KPI output
(should be but is not, so where is it going wrong?)
2024-05-15 15:45:53 +02:00
6faa5104c8 added example with greenmanure 2024-05-02 15:57:32 +02:00
efb4d6833f Included relevant codelist for dataOperations operationCode and status. 2024-04-11 11:31:56 +02:00
0a9a83a5a6 updated KPIdefinitions and todolist 2024-04-10 10:29:30 +02:00
fe2bd98589 added target and threshold definitions + changed productionPurposeCode to be functional 2024-03-12 11:42:16 +01:00
ffbb45894a write A1 yield & strawYield to output
update definitions
update TODO.txt
2024-03-11 14:35:03 +01:00
67014e20f5 updated names of output KPI B1 and B2 + added yieldStraw to output (non functional) 2024-03-07 10:37:27 +01:00
84f27db16e DataCropfieldCharacteristics as an array containing cropyield and possibly strawyield. If no strawyield is filled in then straw remains in field. 2024-02-27 15:44:07 +01:00
d756f08b4c typos 2024-02-27 13:58:09 +01:00
77532fee9f add codelist 265. Empty result? 2024-02-27 13:55:51 +01:00
5d2789a806 updated KPI definitions 2024-02-19 15:07:26 +01:00
dea4f102f5 C1 defs 2024-02-16 15:28:15 +01:00
39ee3263a7 bit of code simplification 2024-02-16 14:52:48 +01:00
619cb5e92c small updates on KPIdefinitions.csv & TODO.txt 2024-02-16 14:36:10 +01:00
5399fd66df added detailed output for KPI C1 effective organic matter supply 2024-02-16 12:58:00 +01:00
5d02370f56 details about N & P balance written to output file 2024-02-12 15:43:00 +01:00
e4087adc77 add miliebelastingspunten (mbp) and checks on whether KPI task is finished or not yet (if not yet then wait and call again) 2023-11-28 15:16:44 +01:00
4761166472 new Task<Configuration> GetConfiguration 2023-11-28 15:12:51 +01:00
9d691dfed1 read & write KPI "E1" = milieu belastingspunten ("mbp") 2023-11-22 16:16:59 +01:00
d616fd3dfc in KPIApplication add bofek to cropfield, because KPI E1 (milieubelastingspunten) only calculated if soil is known 2023-11-21 14:03:14 +01:00
3f66676914 specify how many seconds to wait for the KPItask to be completed 2023-11-15 16:49:46 +01:00
aa18393102 two example inputs for testing garden pea (doperwt) for whole year of part of growing period 2023-11-08 13:51:30 +01:00
0b0ec8f767 StartDate & EndDate of cropfield. Is relevant for N fixation by leguminose crops where currently N fixation depends on day between these two dates. If not provided a whole year is assumed which leads to high N fixation 2023-11-08 13:50:37 +01:00
aef8c7c446 update KPIdefinitions.csv & TODO.txt 2023-11-08 13:48:01 +01:00
bb4e795abc Merge pull request 'master' (#15) from jits/FarmMapsApiClient_WURtest:master into master
Reviewed-on: #15
2023-11-02 11:01:02 +00:00
788c071739 Merge remote-tracking branch 'remote/master' 2023-11-02 12:00:12 +01:00
f1707c432f More testing & demo's in KPIInput.json:
* pesticide
* effect of soiltype: yes, different target & threshold for nitrogen (OK)
* effect of productionpurpose: none?
* effect of location: different nitrogen balance due to different atmospheric deposition (OK)

And update TODO.txt
2023-11-01 13:05:49 +01:00
cfba86cf75 Get polygon area from geometry and give to operations if operation was on whole field
Time tracker for how much time the KPI calculations take
2023-11-01 13:02:54 +01:00
da808362c3 Added codelist CL251: Codering teeltdoelen (CropProductionPurposeCode) 2023-11-01 12:32:05 +01:00
847ff75845 download codelist CL405, soil types 2023-10-24 13:47:58 +02:00
6d903c3e9b error catching and console input to ask which KPIinput file to use 2023-10-24 13:06:36 +02:00
6eb36b2b4f remove author name from code 2023-10-23 12:48:28 +02:00
7f3b87ae38 and of course also add & commit this one ... 2023-10-18 17:35:34 +02:00
90f285a0d1 update todo list 2023-10-18 17:33:55 +02:00
546ce131e4 also commit this file 2023-10-18 17:33:32 +02:00
d8c2ecb88b new project to download latest version of editeelt codelists 2023-10-18 17:32:38 +02:00
2d588026e2 also write totalNapplied to csv file with KPI outputs per cropfield 2023-10-16 15:34:07 +02:00
1a9d5af5f6 don't write duplicate KPIOutput items to output csv 2023-10-16 13:55:12 +02:00
8771e47b28 TODO 2023-10-13 16:38:27 +02:00
4102ed628e farmmapsKPI receives minimum necessary input and writes relevant KPI output 2023-10-13 16:37:50 +02:00
1cc36422a4 start & end date & geometry added to operations item and to cropfield characteristics item 2023-10-11 17:00:25 +02:00
fedd363075 in KPIApplication possible to (1) add an operation, e.g. applying fertilizer and (2) add a cropfield characteristic containing cropyield. 2023-10-04 17:21:05 +02:00
f04cc239d5 Extra note to Clone the git repository to a local drive. DON'T clone to a network drive like "My Documents". Latter may cause authentication problems. 2023-10-04 10:43:44 +02:00
aace4a32f8 added a comment about failed test to download stats for multi-annual timeseries for a given field 2023-08-01 15:22:20 +02:00
166fd1f66d fix BulkSatDownloadApplication: fire a number of calls awaiting satellite task, until number of images returned no longer increases 2023-08-01 11:03:40 +02:00
8a770a1762 handles existing cropfielditemcode 2023-06-27 14:08:27 +02:00
b99191b7b1 niewste versie 2023-06-27 12:58:36 +02:00
9c65d3c6c6 Fix utc datetime 2023-06-19 09:18:39 +02:00
5a4a04a3ec Fix datetime 2023-06-19 09:06:59 +02:00
9be9eb3145 update TargetFramework of all projects to netcoreapp3.1. Except FarmmapsAPi & Secrets which remain 2.1 2023-06-13 12:05:30 +02:00
641e09f833 Merge branch 'master' of https://git.akkerweb.nl/abel/FarmMapsApiClient_KB34_MAST 2023-05-02 10:55:43 +02:00
8c5a0aed95 de niet verplichte inputs verwijderd van de input file. Wel wordt er dus de input file gebruikt die in de C:\Users\hoeve065\Documents\hoofdmap_werk\project_KB34MAST nutrienten DB\API04.03\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\KPIInput.json staat, en niet bij het KPI programma. 2023-05-02 10:55:24 +02:00
59f9ef4743 nu kan er van de gegeven input een cropfield wordern gemaakt, en hier kunnen vervolgens KPIs over berekend worden. Volgende stap is het strippen van de KPIinput om te kijken wat het minimale is dat nodig is om de kpis te berekenen. verder nu eem aantal inputs die niet nodig waren verwijdertInput aangepast, 2023-04-25 16:33:57 +02:00
8bb5c6f581 Input aangepast, nu kan er van de gegeven input een cropfield wordern gemaakt, en hier kunnen vervolgens KPIs over berekend worden. Volgende stap is het strippen van de KPIinput om te kijken wat het minimale is dat nodig is om de kpis te berekenen. 2023-04-25 16:14:43 +02:00
7149086ce2 KPI items opslaan werkt. alle KPI items worden nu naar een JSON file in de dowload folder geschreven 2023-04-25 12:00:08 +02:00
55f00da9d0 KPI items ophalen voor een cropfield werkt nu. wel dus een bestaand cropfield ingeven bij de settings in de BIN. Alle KPIs worden opgehaald na een minuut wachten. 2023-04-07 14:33:49 +02:00
3d7bf186e7 de properties voor de KPI task worden nu correct doorgegeven denk ik 2023-04-06 16:11:37 +02:00
8f8f857bf0 ook in in de andere KPIinout toegevoegd 2023-04-03 13:05:00 +02:00
b7bedf182c aggegrate KPI = false toegevoegd aan inputs 2023-04-03 13:03:10 +02:00
be22d631bc geupdate runKPIitemtask, helaas nog geen KPI data gevonden als child item 2023-03-31 11:13:51 +02:00
7dda21dd77 probeersel om een runKPItask te maken 2023-03-31 11:02:06 +02:00
c79e0d062c Merge branch 'master' of https://git.akkerweb.nl/abel/FarmMapsApiClient_KB34_MAST 2023-03-22 14:48:34 +01:00
32138bef80 blah test 2023-03-22 14:48:13 +01:00
e66820bd87 test 2023-03-22 14:41:41 +01:00
cb999caf46 Merge pull request 'Update 'FarmmapsApi/Constants.cs'' (#14) from fedde-patch-1 into master
Reviewed-on: #14
2022-05-25 08:18:42 +00:00
721b33b4e5 Update 'FarmmapsApi/Constants.cs' 2022-04-25 14:44:57 +00:00
334d890f13 update DataDownloadApplication 2022-03-11 15:10:33 +01:00
f8a412be64 with doDB clearer choice on whether to read fields for which to download satellite stats from csv or database 2022-03-07 13:36:20 +01:00
3da2b71d62 Merge pull request 'Update 'README.MD'' (#13) from fedde-patch-1 into master
Reviewed-on: #13
Reviewed-by: Mark van der Wal <mark.vanderwal@akkerweb.nl>
2022-02-28 13:54:46 +00:00
b7b669bcfd Update 'README.MD' 2022-02-28 13:50:44 +00:00
0f9fe0a433 Updated receiving of root items 2022-02-28 14:29:56 +01:00
5c38ff99dc Merge pull request 'UserInput' (#12) from UserInput into master
Reviewed-on: #12
Reviewed-by: Mark van der Wal <mark.vanderwal@akkerweb.nl>
2022-02-28 13:28:24 +00:00
Fedde Sijbrandij
c29f996d23 small update 2022-02-28 13:28:24 +00:00
44cde0fe15 added download of all crop recordings of 1 field - using a manual croprecording itemcode 2022-02-28 13:28:24 +00:00
0767b3fff8 Merge pull request 'NBSInput' (#11) from NBSInput into master
Reviewed-on: #11
Reviewed-by: Mark van der Wal <mark.vanderwal@akkerweb.nl>
2022-02-24 15:49:06 +00:00
f2bd127554 nog een kleine update 2022-02-23 20:41:32 +01:00
73e09f79f4 Update NBS input 2022-02-23 20:37:30 +01:00
706352170a update inputdata NBS 2022-02-23 20:22:14 +01:00
e07fb2de7a AW-3569 Added posibility to login with username/password 2022-02-23 10:33:59 +01:00
2790beaa88 Merge pull request 'Update appsettings, included the three environments test, acceptance and production. + update the NBS sample code to the newest flow (backwards compatible' (#10) from NBS_update into master
Reviewed-on: #10
Reviewed-by: Mark van der Wal <mark.vanderwal@akkerweb.nl>
2022-02-11 12:31:20 +00:00
694d7ce90b Update appsettings, included the three environments test, acceptance and production. + update the NBS sample code to the newest flow (backwards compatible 2022-02-11 13:14:26 +01:00
8cebe9f2c2 AW-2834 2021-12-16 12:05:35 +01:00
a1696c38c7 fix uploading 2021-07-08 17:18:12 +02:00
c2515281d1 attribute pass fix for shapetogeotiff 2021-07-02 10:34:30 +02:00
fa2075cbc6 added inputLayerName to CreateTaskmap 2021-07-01 12:54:06 +02:00
6a3baeb8ad improved shapetogeotiff method 2021-07-01 12:47:04 +02:00
61985f9079 Merge pull request 'Veranderingen jits, fedde en pepijn.' (#9) from jits/FarmMapsApiClient_WURtest:master into master
Reviewed-on: #9
2021-06-10 08:25:24 +00:00
7c5bbf0fbe small update for finding shape taskmap 2021-06-09 11:53:14 +02:00
915df2ac6b new project FarmmapsCleanUp to clean up cropfielditems and satellitetaskcodes used only once 2021-06-07 16:38:42 +02:00
d1747427bc also logging satellitetaskcode to cropfieldtable in database 2021-05-29 12:50:33 +02:00
111b4e576f solved issue where sometimes satelliteItem contains only 2 layers
Normally 3 layers 0: ndvi, 1: wdvi, 2: natural. In some cases only 2 layers: 0: wdvi, 1: natural. Which caused error when requesting statistics.
This happened for example for cropfieldItem.Code ‘e08d71bd92334dbab9e645ad6e72da63’
2021-05-28 17:25:31 +02:00
1bc326cfd2 Projects FarmmapsBulkSatDownload and FarmmapsDataDownload fully updated and tested
Added some extra Tasks to /FarmmapsApi/Services/GeneralService.cs
Added class SatelliteStatistics.cs to /FarmmapsApi/Models
2021-05-26 10:16:29 +02:00
c673f8ddc4 Merge remote-tracking branch 'upstream/master' 2021-05-20 09:13:57 +02:00
407ef09d21 Added project FarmmapsBulkSatDownload
Merge branch 'master' of https://git.akkerweb.nl/jits/FarmMapsApiClient_WURtest

# Conflicts:
#	FarmmapsApi/Services/GeneralService.cs
2021-05-18 18:35:11 +02:00
250020be78 Added project FarmmapsBulkSatDownload 2021-05-18 18:19:28 +02:00
Riepma
a8efaf93c2 added appsettings.json 2021-05-12 13:29:53 +02:00
5da74c2db0 small update on DataDownload and GenerelServices 2021-05-12 13:05:17 +02:00
Riepma
245e82adbc Added rest of the modified files 2021-05-12 08:06:30 +02:00
Riepma
bea4d207d0 added project to only download some data 2021-05-11 15:03:08 +02:00
Riepma
462e66baea Merge remote-tracking branch 'upstream/master' 2021-04-21 10:17:24 +02:00
e0aae4afaf small change of date notation in a filename of a csv 2021-04-21 09:03:25 +02:00
bd846e9f0d update NBS 2021-04-21 08:59:54 +02:00
Riepma
1ddafc6d87 added layer specification VRApoten 2021-04-14 20:53:26 +02:00
Riepma
7baf16db74 fixed to store statistics of satellite images 2021-04-13 10:54:04 +02:00
Riepma
89d2af5944 updated poten&nbs, both work properly again 2021-04-12 17:01:17 +02:00
Riepma
c7ab62c911 Added option to generate ISOXML taskmap, added missing Nbs data 2021-04-12 14:22:24 +02:00
Riepma
4459a4e76d solved merging in poten app 2021-04-09 13:48:03 +02:00
Riepma
766674c731 ISOXML to taskmap 2021-04-07 10:38:42 +02:00
d5f715ef92 merged 2021-04-02 16:30:49 +02:00
760f3fad64 added field polygon to data upload 2021-04-02 16:15:44 +02:00
Riepma
93469b605c Update NBS taskmap generator 2021-03-22 10:35:55 +01:00
b758913693 update poten serice, foutje hersteld 2021-03-09 14:18:54 +01:00
f71f072be7 update poten; schaduw moet nu als attribute worden meegegeven 2021-03-09 14:15:32 +01:00
Riepma
761221d936 Merge branch 'master' of https://git.akkerweb.nl/jits/FarmMapsApiClient_WURtest 2021-03-01 16:38:55 +01:00
Riepma
39a2024718 update poten app with centered and countPerArea 2021-03-01 16:31:31 +01:00
6d14299852 update Blight 2021-03-01 15:56:15 +01:00
cf5ac33b3f added updaten zoning input 2021-03-01 14:33:29 +01:00
6debe82085 Updated Blight and Zonering 2021-03-01 14:04:18 +01:00
Riepma
3ad594d83f Created separate project for areaConversion VRA poten
Updated VRA poten sample code
2021-02-16 09:46:50 +01:00
Riepma
101b683daa Update zonering to find the right output files
Added taskmap creator to NBS
2021-02-15 17:06:09 +01:00
Riepma
c02b232837 Added Taskmap sample code to potenAPI 2021-02-12 17:10:25 +01:00
a29b973268 adjusted zoning 2021-01-28 16:34:39 +01:00
c33a8c8a11 some adjustments to zoning, included vandersat among others 2021-01-28 15:29:11 +01:00
bb14c4e4b0 added vandersat data to sample code 2021-01-28 15:08:32 +01:00
jits
693c82db2e update zonering testData 2020-12-18 14:03:35 +01:00
Riepma
79cc135bbd solved conflicts 2020-12-18 10:39:21 +01:00
Riepma
764df7ce91 "Inputfile created for zonering" 2020-12-18 10:22:23 +01:00
Fedde Sijbrandij
ab9a23221f kleine update zonering 2020-12-16 10:23:24 +01:00
Fedde Sijbrandij
59bde76903 added zoninginput, file and data 2020-12-16 10:09:24 +01:00
751b154bb9 added settings-file to NBS 2020-12-16 09:34:11 +01:00
Fedde Sijbrandij
ad49bafa07 update blight 2020-12-15 17:10:42 +01:00
Fedde Sijbrandij
f3a2b33810 update Blight 2020-12-15 16:28:19 +01:00
Riepma
02708ba01d Eerdere aanpassingen NBS en zonering verwerkt 2020-12-11 14:02:01 +01:00
84 changed files with 6404 additions and 1341 deletions

3
.gitignore vendored
View File

@@ -2,4 +2,5 @@
.vs/
bin/
obj/
appsettings.secrets.json
appsettings.secrets.json
FarmmapsBulkSatDownload/DBsettings.secrets.json

View File

@@ -44,14 +44,14 @@ namespace FarmMapsBlight
await _farmmapsApiService.GetCurrentUserCodeAsync();
var roots = await _farmmapsApiService.GetCurrentUserRootsAsync();
var myDrive = roots.SingleOrDefault(r => r.Name == "My drive");
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 == "Uploaded");
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
if (uploadedRoot == null)
{
_logger.LogError("Could not find a needed root item");
@@ -62,8 +62,10 @@ namespace FarmMapsBlight
if (string.IsNullOrEmpty(_settings.CropfieldItemCode))
{
_logger.LogInformation("Creating cropfield");
string cropFieldData = "{\"area\":0,\"code\":\"0552ef068b0e4e6590c317a4c662faea\",\"name\":null,\"polygon\":null,\"soilCode\":\"60\",\"soilName\":null,\"fieldCode\":null,\"schemeUrl\":null,\"externalId\":null,\"schemeCode\":null,\"varietyCode\":\"11113\",\"varietyName\":\"Bintje\",\"cropTypeCode\":\"1010101\",\"cropTypeName\":\"Consumptieaardappelen\",\"productionTypeCode\":\"1\",\"productionPurposeCode\":null,\"productionPurposeName\":null,\"productionSequenceCode\":\"HFDTLT\"}";
cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDrive.Code, "Cropfield Blight", 2020,
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();
@@ -74,11 +76,7 @@ namespace FarmMapsBlight
cropfieldItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldItemCode);
}
DateTime adviceDate = DateTime.Now.Date;
DateTime plantingDate = new DateTime(2020, 3, 20);
DateTime emergeDate = new DateTime(2020, 5, 20);
var blightItem = await _blightService.CreateAdvice(cropfieldItem, adviceDate, plantingDate, emergeDate);
var blightItem = await _blightService.CreateAdvice(cropfieldItem);
if (blightItem == null)
{
return;

View File

@@ -25,17 +25,13 @@ namespace FarmMapsBlight
_generalService = generalService;
}
public async Task<Item> CreateAdvice(Item cropfieldItem, DateTime adviceDate, DateTime plantingDate, DateTime emergeDate)
public async Task<Item> CreateAdvice(Item cropfieldItem)
{
var taskRequest = new TaskRequest()
{
TaskType = "vnd.farmmaps.task.blight"
};
taskRequest.attributes["d"] = DateTime.Now.Date.ToString("o");
taskRequest.attributes["plantingDate"] = plantingDate.ToUniversalTime().ToString("o");
taskRequest.attributes["emergeDate"] = emergeDate.ToUniversalTime().ToString("o");
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\"}";
@@ -45,15 +41,11 @@ namespace FarmMapsBlight
taskRequest.attributes["sprays"] = JsonConvert.SerializeObject(sprays);
List<Irrigation> irrigations = new List<Irrigation>();
irrigations.Add(new Irrigation() { startTime = new DateTime(2020, 7, 1, 2, 0, 0), endTime = new DateTime(2020, 7, 1, 14, 0, 0) });
taskRequest.attributes["irrigations"] = JsonConvert.SerializeObject(irrigations);
var taskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskRequest);
await PollTask(TimeSpan.FromSeconds(3), async (tokenSource) =>
{
_logger.LogInformation("Checking blight task status");
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
_logger.LogInformation($"Checking blight task status: { itemTaskStatus.State}");
if (itemTaskStatus.IsFinished)
tokenSource.Cancel();
});

View 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>

View File

@@ -8,20 +8,31 @@ namespace FarmmapsApiSamples
public const string GEOTIFF_PROCESSED_ITEMTYPE = "vnd.farmmaps.itemtype.geotiff.processed";
public const string CROPFIELD_ITEMTYPE = "vnd.farmmaps.itemtype.cropfield";
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 GEOJSON_ITEMTYPE = "vnd.farmmaps.itemtype.geojson";
public const string BLIGHT_ITEMTYPE = "vnd.farmmaps.itemtype.blight";
public const string CROPREC_ITEMTYPE = "vnd.farmmaps.itemtype.crprec";
public const string CROPOP_ITEMTYPE = "vnd.farmmaps.itemtype.crprec.operation";
public const string CROPCHAR_ITEMTYPE = "vnd.farmmaps.itemtype.edicrop.characteristic";
public const string CROPSCHEME_ITEMTYPE = "vnd.farmmaps.itemtype.croppingscheme"; // deze toegevoegd, misschien is het type van de KPI task wel een croppingscheme
//public const string KPI_ITEM = "vnd.farmmaps.itemtype.kpi.data"; //PO20231004: originally with .data
public const string KPICONTAINER_ITEM = "vnd.farmmaps.itemtype.kpi.data.container"; //PO20231004: originally without .container
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.satellite";
public const string SATELLITE_TASK = "vnd.farmmaps.task.sentinelhub";
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 CROPREC_TASK = "vnd.farmmaps.task.crprec";
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";
public const string KPI_TASK = "vnd.farmmaps.task.kpi"; // dus nieuwe taak om de KPIs te berekenen
}
}

View File

@@ -2,6 +2,8 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>

View File

@@ -7,8 +7,11 @@
public string BasePath { get; set; }
public string DiscoveryEndpointUrl { get; set; }
public string RedirectUri { get; set; }
public string GrantClientId { get; set; }
public string ClientId { get; set; }
public string ClientSecret { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string[] Scopes { get; set; }
}
}

View 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;
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
@@ -45,6 +46,10 @@ namespace FarmmapsApi.Services
}
}
public async Task<Configuration> GetConfiguration()
{
return _configuration;
}
public async Task AuthenticateAsync()
{
if (_httpClient.DefaultRequestHeaders.Authorization != null &&
@@ -53,9 +58,16 @@ namespace FarmmapsApi.Services
throw new AuthenticationException("Already seems to be authenticated");
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)
throw new AuthenticationException(token.Error);
@@ -88,7 +100,19 @@ namespace FarmmapsApi.Services
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)
@@ -314,7 +338,6 @@ namespace FarmmapsApi.Services
farmmapsUploader.UploadSessionData += data => location = data.UploadUri;
var progress = await farmmapsUploader.UploadAsync();
return new UploadResults(progress, location);
}

View File

@@ -68,10 +68,7 @@ namespace FarmmapsApi.Services
contentStream.ThrowIfNull(nameof(contentStream));
_streamLength = ContentStream.CanSeek ? ContentStream.Length : UnknownSize;
var twoMB = 2 * 0x100000;
ChunkSize = twoMB;
body.ChunkSize = ChunkSize;
ChunkSize = 2 * 0x100000;
Body = body;
Path = path;

View File

@@ -12,28 +12,30 @@ using static FarmmapsApiSamples.Constants;
namespace FarmmapsApi.Services
{
public class GeneralService
{
public class GeneralService {
private readonly ILogger<GeneralService> _logger;
private readonly FarmmapsApiService _farmmapsApiService;
public GeneralService(ILogger<GeneralService> logger, FarmmapsApiService farmmapsApiService)
{
public GeneralService(ILogger<GeneralService> logger, FarmmapsApiService farmmapsApiService) {
_logger = logger;
_farmmapsApiService = farmmapsApiService;
}
public async Task<Item> CreateCropfieldItemAsync(string parentItemCode, string name, int year,
string fieldGeomJson, string data = "{}")
string fieldGeomJson, string data = "{}", DateTime startDate = new DateTime(), DateTime endDate = new DateTime() )
{
var currentYear = new DateTime(year, 1, 1);
var cropfieldItemRequest = new ItemRequest()
//If user provides no startDate or endDate, then set startDate and endDate to full year provided through 'year'
if (startDate == new DateTime() || endDate == new DateTime())
{
startDate = new DateTime(year, 1, 1);
endDate = new DateTime(year, 12, 31);
}
var cropfieldItemRequest = new ItemRequest() {
ParentCode = parentItemCode,
ItemType = CROPFIELD_ITEMTYPE,
Name = name,
DataDate = currentYear,
DataEndDate = currentYear.AddYears(1).AddDays(-1),
DataDate = startDate,
DataEndDate = endDate,
Data = JObject.Parse(data),
Geometry = JObject.Parse(fieldGeomJson)
};
@@ -41,11 +43,67 @@ namespace FarmmapsApi.Services
return await _farmmapsApiService.CreateItemAsync(cropfieldItemRequest);
}
public async Task<Item> CreateOperationItemAsync(string cropRecordingItemCode, int year,
string fieldGeomJson, string data = "{}", DateTime startDate = new DateTime(), DateTime endDate = new DateTime())
{
//If user provides no startDate or endDate, then set startDate and endDate to full year provided through 'year'
if (startDate == new DateTime() || endDate == new DateTime())
{
startDate = new DateTime(year, 1, 1);
endDate = new DateTime(year, 12, 31);
}
JObject jdata = JObject.Parse(data);
string name = string.Format($"CrpRec Operation, {jdata.GetValue("name")}");
ItemRequest operationItemRequest = new ItemRequest()
{
ParentCode = cropRecordingItemCode,
ItemType = CROPOP_ITEMTYPE,
Name = name,
DataDate = startDate,
DataEndDate = endDate,
Data = jdata,
Geometry = JObject.Parse(fieldGeomJson)
};
return await _farmmapsApiService.CreateItemAsync(operationItemRequest);
}
public async Task<Item> CreateCropfieldCharacteristicItemAsync(string cropfieldItemCode, int year,
string fieldGeomJson, string data = "{}", DateTime startDate = new DateTime(), DateTime endDate = new DateTime())
{
//If user provides no startDate or endDate, then set startDate and endDate to full year provided through 'year'
if (startDate == new DateTime() || endDate == new DateTime())
{
startDate = new DateTime(year, 1, 1);
endDate = new DateTime(year, 12, 31);
}
// not sure if here we also need to specify DataDate, DataEndDate & Geometry. Do it just in case
string name = "Cropfield characteristic";
ItemRequest cropfieldCharactericsticItemRequest = new ItemRequest()
{
ParentCode = cropfieldItemCode,
ItemType = CROPCHAR_ITEMTYPE,
Name = name,
DataDate = startDate,
DataEndDate = endDate,
Data = JObject.Parse(data),
Geometry = JObject.Parse(fieldGeomJson)
};
return await _farmmapsApiService.CreateItemAsync(cropfieldCharactericsticItemRequest);
}
public async Task<Item> UploadDataAsync(UserRoot root, string itemType, string filePath, string itemName, string geoJsonString = null)
{
var startUpload = DateTime.UtcNow.AddSeconds(-3);
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)
return null;
@@ -66,13 +124,21 @@ namespace FarmmapsApi.Services
return await FindChildItemAsync(root.Code, SHAPE_PROCESSED_ITEMTYPE, itemName,
i => i.Created >= startUpload &&
i.Name.ToLower().Contains(itemName.ToLower()));;
i.Name.ToLower().Contains(itemName.ToLower())); ;
}
public async Task<Item> ShapeToGeotiff(Item shapeItem)
public async Task<Item> ShapeToGeotiff(Item shapeItem, int resolution = 1, params string[] inputLayerNames)
{
var startUpload = DateTime.UtcNow.AddSeconds(-3);
await RunAndWaitForTask(shapeItem, "vnd.farmmaps.task.shapetogeotiff");
var taskStatus = await RunAndWaitForTask(shapeItem, "vnd.farmmaps.task.shapetogeotiff", request =>
{
request.attributes["resolution"] = resolution.ToString();
if(inputLayerNames.Length > 0)
request.attributes["inputLayers"] = $"[{string.Join(",", inputLayerNames.Select(v => $"\"{v}\""))}]";
});
if (taskStatus.State == ItemTaskState.Error)
return null;
return await FindChildItemAsync(shapeItem.ParentCode, GEOTIFF_PROCESSED_ITEMTYPE, shapeItem.Name,
i => i.Created >= startUpload &&
@@ -89,8 +155,7 @@ namespace FarmmapsApi.Services
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(tiffItem.Code, taskmapRequest);
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) =>
{
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)
@@ -98,6 +163,65 @@ namespace FarmmapsApi.Services
});
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 taskmap is a child of the input tiff *** Update feb 2021: it is a child of the cropfield.
var itemName = "Taskmap";
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}");
@@ -106,11 +230,25 @@ namespace FarmmapsApi.Services
//the taskmap is a child of the input tiff
var itemName = "Taskmap";
var taskMapItem = await FindChildItemAsync(tiffItem.ParentCode,
SHAPE_PROCESSED_ITEMTYPE, itemName);
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 taskmap as a child item under the input");
_logger.LogError("Could not find the shape/isoxml taskmap as a child item under the cropfield");
return null;
}
@@ -119,18 +257,15 @@ namespace FarmmapsApi.Services
public async Task<ItemTaskStatus> RunAndWaitForTask(Item subjectItem, string taskIdentifier,
Action<TaskRequest> configureCallback = null, int retrySeconds = 3)
{
var taskRequest = new TaskRequest()
{
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) =>
{
await PollTask(TimeSpan.FromSeconds(retrySeconds), async (tokenSource) => {
_logger.LogInformation($"Checking {taskIdentifier} task status");
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(subjectItem.Code, taskCode);
if (itemTaskStatus.IsFinished)
@@ -143,26 +278,22 @@ namespace FarmmapsApi.Services
}
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;
int tries = 0;
await PollTask(TimeSpan.FromSeconds(3), async source =>
{
await PollTask(TimeSpan.FromSeconds(3), async source => {
_logger.LogInformation($"Trying to get {containsName} data");
var uploadedFilesChildren = await _farmmapsApiService.GetItemChildrenAsync(parentCode, itemType);
Func<Item, bool> func = filter ?? (i => i.Name.ToLower().Contains(containsName.ToLower()));
dataItem = uploadedFilesChildren.FirstOrDefault(func);
if (dataItem != null || tries == maxTries)
{
if (dataItem != null || tries == maxTries) {
source.Cancel();
}
}
tries++;
});
if (dataItem == null)
{
if (dataItem == null) {
_logger.LogError("dataItem not found");
return null;
}
@@ -171,16 +302,15 @@ namespace FarmmapsApi.Services
return dataItem;
}
public async Task<Item> RunBofekTask(Item cropfieldItem)
public async Task<Item> RunCropRecordingTask(Item cropfieldItem)
{
var taskmapRequest = new TaskRequest {TaskType = BOFEK_TASK};
var cropRecordingRequest = new TaskRequest { TaskType = CROPREC_TASK };
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskmapRequest);
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, cropRecordingRequest);
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) =>
{
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}");
_logger.LogInformation($"Waiting on RunCropRecordingTask; status: {itemTaskStatus.State}");
if (itemTaskStatus.IsFinished)
tokenSource.Cancel();
});
@@ -192,12 +322,42 @@ namespace FarmmapsApi.Services
return null;
}
//the CropRecording data is a child of the cropfield
var itemName = "Crprec";
var cropRecordingItem = await FindChildItemAsync(cropfieldItem.Code,
CROPREC_ITEMTYPE, itemName);
if (cropRecordingItem == null)
{
_logger.LogError("Could not find the CropRecording data as a child item under the cropfield");
return null;
}
return cropRecordingItem;
}
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)
{
if (bofekItem == null) {
_logger.LogError("Could not find the BOFEK data as a child item under the cropfield");
return null;
}
@@ -205,16 +365,19 @@ namespace FarmmapsApi.Services
return bofekItem;
}
public async Task<Item> RunAhnTask(Item cropfieldItem)
public async Task<List<Item>> GetKpiItemsForCropField(Item cropfieldItem, int waitsecs = 6)
{
var taskmapRequest = new TaskRequest {TaskType = AHN_TASK};
TaskRequest kpiRequest = new TaskRequest { TaskType = KPI_TASK };
kpiRequest.attributes["processAggregateKpi"] = "false";
int year = cropfieldItem.DataDate.Value.Year;
kpiRequest.attributes["year"] = year.ToString();
int ms = waitsecs * 1000;
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, taskmapRequest);
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, kpiRequest);
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) =>
{
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}");
_logger.LogInformation($"Waiting on retreiving KPI data; status: {itemTaskStatus.State}");
if (itemTaskStatus.IsFinished)
tokenSource.Cancel();
});
@@ -225,13 +388,51 @@ namespace FarmmapsApi.Services
_logger.LogError($"Something went wrong with task execution: {itemTask.Message}");
return null;
}
_logger.LogInformation($"Taking {waitsecs} seconds to look up all KPI items. The longer we wait the more KPI's we get ..." +
$"");
await Task.Delay(ms); // wait 60000ms = 60 secs for task to be completed
//After the task is completed we have 1 kpiContainerItem with a code and with no data
//Because the data are in the children of this kpiContainerItem. The container will have a list of children each with an "id" aand data,
//The ids' are "a1", "b1", "b2", "c1","d1","d3","d5"
//with following meanings:
//| A1 | Opbrengst | Yield |
//| B1 | Stikstofoverschot | Nitrogen surplus |
//| B2 | Fosfaatoverschot | Phosphate surplus |
//| C1 | Effectieve Organischestof aanvoer| Effective Organic Matter supply |
//| D1 | Gebruik bestrijdingsmiddelen | Use of pesticides|
//| D3 | Gewasdiversiteit(randdichtheid) | Crop diversity(edge density) |
//| D5 | Percentage rustgewassen | Percentage of rest crops |
List <Item> kpiContainerItem = await _farmmapsApiService.GetItemChildrenAsync(cropfieldItem.Code, KPICONTAINER_ITEM);
string kpiContainerItemCode = kpiContainerItem[0].Code;
List<Item> kpiItems = await _farmmapsApiService.GetItemChildrenAsync(kpiContainerItemCode);
return kpiItems;
}
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)
{
if (ahnItem == null) {
_logger.LogError("Could not find the AHN data as a child item under the cropfield");
return null;
}
@@ -239,14 +440,12 @@ namespace FarmmapsApi.Services
return ahnItem;
}
public async Task<Item> RunShadowTask(Item cropfieldItem)
{
var taskmapRequest = new TaskRequest {TaskType = SHADOW_TASK};
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) =>
{
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)
@@ -254,8 +453,7 @@ namespace FarmmapsApi.Services
});
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}");
return null;
}
@@ -264,13 +462,359 @@ namespace FarmmapsApi.Services
var itemName = "shadow";
var shadowItem = await FindChildItemAsync(cropfieldItem.Code,
GEOTIFF_PROCESSED_ITEMTYPE, itemName);
if (shadowItem == null)
{
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;
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Net.Http;
using System.Threading.Tasks;
using FarmmapsApi.Models;
using IdentityModel;
using IdentityModel.Client;
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)
{
return await _httpClient.RequestRefreshTokenAsync(new RefreshTokenRequest()

View File

@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30320.27
# Visual Studio Version 17
VisualStudioVersion = 17.4.33122.133
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsNbs", "FarmmapsNbs\FarmmapsNbs.csproj", "{E08EF7E9-F09E-42D8-825C-164E458C78F4}"
EndProject
@@ -19,50 +19,124 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsHaulmkilling", "Far
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsPoten", "FarmmapsPoten\FarmmapsPoten.csproj", "{AAFAB03A-6F5C-4D91-991F-867B7898F981}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FarmMapsBlight", "FarmMapsBlight\FarmMapsBlight.csproj", "{892E0932-5D11-4A37-979E-CEDB39C2E181}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmMapsBlight", "FarmMapsBlight\FarmMapsBlight.csproj", "{892E0932-5D11-4A37-979E-CEDB39C2E181}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FarmmapsZonering", "FarmmapsZonering\FarmmapsZonering.csproj", "{91A58C4A-4A80-4079-B43D-9B851206194F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsZonering", "FarmmapsZonering\FarmmapsZonering.csproj", "{91A58C4A-4A80-4079-B43D-9B851206194F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Secrets", "Secrets\Secrets.csproj", "{C4EE5ECA-253A-4B71-9F67-D231AC4517D6}"
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}") = "FarmmapsKPI", "FarmmapsKPI\FarmmapsKPI.csproj", "{14575235-9867-4CE5-A22F-3F9FE002FF42}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsDownloadCL", "FarmmapsDownloadCL\FarmmapsDownloadCL.csproj", "{63E69101-D804-4DBC-B2E4-A33771CD5C5F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E08EF7E9-F09E-42D8-825C-164E458C78F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E08EF7E9-F09E-42D8-825C-164E458C78F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E08EF7E9-F09E-42D8-825C-164E458C78F4}.Debug|x64.ActiveCfg = Debug|Any CPU
{E08EF7E9-F09E-42D8-825C-164E458C78F4}.Debug|x64.Build.0 = Debug|Any CPU
{E08EF7E9-F09E-42D8-825C-164E458C78F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E08EF7E9-F09E-42D8-825C-164E458C78F4}.Release|Any CPU.Build.0 = Release|Any CPU
{E08EF7E9-F09E-42D8-825C-164E458C78F4}.Release|x64.ActiveCfg = Release|Any CPU
{E08EF7E9-F09E-42D8-825C-164E458C78F4}.Release|x64.Build.0 = Release|Any CPU
{1FA9E50B-F45E-4534-953A-37C783D03C74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1FA9E50B-F45E-4534-953A-37C783D03C74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1FA9E50B-F45E-4534-953A-37C783D03C74}.Debug|x64.ActiveCfg = Debug|x64
{1FA9E50B-F45E-4534-953A-37C783D03C74}.Debug|x64.Build.0 = Debug|x64
{1FA9E50B-F45E-4534-953A-37C783D03C74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1FA9E50B-F45E-4534-953A-37C783D03C74}.Release|Any CPU.Build.0 = Release|Any CPU
{1FA9E50B-F45E-4534-953A-37C783D03C74}.Release|x64.ActiveCfg = Release|x64
{1FA9E50B-F45E-4534-953A-37C783D03C74}.Release|x64.Build.0 = Release|x64
{731A88CD-9DC4-4969-86F2-2315830A6998}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{731A88CD-9DC4-4969-86F2-2315830A6998}.Debug|Any CPU.Build.0 = Debug|Any CPU
{731A88CD-9DC4-4969-86F2-2315830A6998}.Debug|x64.ActiveCfg = Debug|Any CPU
{731A88CD-9DC4-4969-86F2-2315830A6998}.Debug|x64.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.Build.0 = Release|Any CPU
{731A88CD-9DC4-4969-86F2-2315830A6998}.Release|x64.ActiveCfg = Release|Any CPU
{731A88CD-9DC4-4969-86F2-2315830A6998}.Release|x64.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}.Debug|x64.ActiveCfg = Debug|Any CPU
{DFA89D0B-5400-4374-B824-8367B76B4B6E}.Debug|x64.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
{DFA89D0B-5400-4374-B824-8367B76B4B6E}.Release|x64.ActiveCfg = Release|Any CPU
{DFA89D0B-5400-4374-B824-8367B76B4B6E}.Release|x64.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}.Debug|x64.ActiveCfg = Debug|Any CPU
{AAFAB03A-6F5C-4D91-991F-867B7898F981}.Debug|x64.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
{AAFAB03A-6F5C-4D91-991F-867B7898F981}.Release|x64.ActiveCfg = Release|Any CPU
{AAFAB03A-6F5C-4D91-991F-867B7898F981}.Release|x64.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}.Debug|x64.ActiveCfg = Debug|Any CPU
{892E0932-5D11-4A37-979E-CEDB39C2E181}.Debug|x64.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
{892E0932-5D11-4A37-979E-CEDB39C2E181}.Release|x64.ActiveCfg = Release|Any CPU
{892E0932-5D11-4A37-979E-CEDB39C2E181}.Release|x64.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}.Debug|x64.ActiveCfg = Debug|Any CPU
{91A58C4A-4A80-4079-B43D-9B851206194F}.Debug|x64.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
{91A58C4A-4A80-4079-B43D-9B851206194F}.Release|x64.ActiveCfg = Release|Any CPU
{91A58C4A-4A80-4079-B43D-9B851206194F}.Release|x64.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}.Debug|x64.ActiveCfg = Debug|Any CPU
{32ED9500-AAAB-4030-9C7A-F611A85DF890}.Debug|x64.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
{32ED9500-AAAB-4030-9C7A-F611A85DF890}.Release|x64.ActiveCfg = Release|Any CPU
{32ED9500-AAAB-4030-9C7A-F611A85DF890}.Release|x64.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}.Debug|x64.ActiveCfg = Debug|Any CPU
{772DBDCD-9FAA-40A7-8551-2C1620C4AB67}.Debug|x64.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
{772DBDCD-9FAA-40A7-8551-2C1620C4AB67}.Release|x64.ActiveCfg = Release|Any CPU
{772DBDCD-9FAA-40A7-8551-2C1620C4AB67}.Release|x64.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}.Debug|x64.ActiveCfg = Debug|x64
{C4EE5ECA-253A-4B71-9F67-D231AC4517D6}.Debug|x64.Build.0 = Debug|x64
{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
{C4EE5ECA-253A-4B71-9F67-D231AC4517D6}.Release|x64.ActiveCfg = Release|x64
{C4EE5ECA-253A-4B71-9F67-D231AC4517D6}.Release|x64.Build.0 = Release|x64
{14575235-9867-4CE5-A22F-3F9FE002FF42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14575235-9867-4CE5-A22F-3F9FE002FF42}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14575235-9867-4CE5-A22F-3F9FE002FF42}.Debug|x64.ActiveCfg = Debug|x64
{14575235-9867-4CE5-A22F-3F9FE002FF42}.Debug|x64.Build.0 = Debug|x64
{14575235-9867-4CE5-A22F-3F9FE002FF42}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14575235-9867-4CE5-A22F-3F9FE002FF42}.Release|Any CPU.Build.0 = Release|Any CPU
{14575235-9867-4CE5-A22F-3F9FE002FF42}.Release|x64.ActiveCfg = Release|x64
{14575235-9867-4CE5-A22F-3F9FE002FF42}.Release|x64.Build.0 = Release|x64
{63E69101-D804-4DBC-B2E4-A33771CD5C5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63E69101-D804-4DBC-B2E4-A33771CD5C5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63E69101-D804-4DBC-B2E4-A33771CD5C5F}.Debug|x64.ActiveCfg = Debug|x64
{63E69101-D804-4DBC-B2E4-A33771CD5C5F}.Debug|x64.Build.0 = Debug|x64
{63E69101-D804-4DBC-B2E4-A33771CD5C5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63E69101-D804-4DBC-B2E4-A33771CD5C5F}.Release|Any CPU.Build.0 = Release|Any CPU
{63E69101-D804-4DBC-B2E4-A33771CD5C5F}.Release|x64.ActiveCfg = Release|x64
{63E69101-D804-4DBC-B2E4-A33771CD5C5F}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -0,0 +1,604 @@
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
{
//To run this app, first go to farmmaps datastore at https://farmmaps.eu/en/editor/plan (or on test)
//goto 'Apps and Data', goto 'Data', buy (or get for free?): 'SATELLITE'
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);
}
}
}

View 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
}
]

View 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;
}
}
}

View File

@@ -0,0 +1,6 @@
{
"User": "",
"Password": "",
"Database": "",
"Host": ""
}

View 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>

View 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; }
}
}

View 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;
}
}
}

View File

@@ -0,0 +1,10 @@
using System.Collections.Generic;
using FarmmapsApi.Models;
namespace FarmmapsBulkSatDownload
{
public class Settings
{
public List<Item> cropFieldItems { get; set; }
}
}

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

View File

@@ -0,0 +1,363 @@
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
{
//To run this app, first go to farmmaps datastore at https://farmmaps.eu/en/editor/plan (or on test)
//goto 'Apps and Data', goto 'Data', buy (or get for free?): 'SATELLITE'
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);
}
}
}

View 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 ]
]
]
}
}
]

View 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;
}
}
}

View 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>

View 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; }
}
}

View 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; }
}
}

View 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; }
}
}

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

View File

@@ -0,0 +1,82 @@
# ShowGeotiff.r
# Have a look at a downloaded satellite image and check if stats are correctly calculated
# downloaded and calculated the stats for the polygon defined in C:\git\FarmMapsApiClient\FarmmapsDataDownload\DataDownloadInput.json
# and in which in the console I requested the image for date '2022-08-25'
library(terra)
setwd("C:/git/FarmMapsApiClient/FarmmapsDataDownload/bin/Debug/netcoreapp3.1/Downloads")
# FarmmapsDataDownload
fileGeotiff <- "sentinelhub_test_BvdTFieldlabG92_20220825.tif"
lenfilename <- nchar(fileGeotiff)
year <- substr(fileGeotiff,lenfilename-11,lenfilename-8)
imgdate <- substr(fileGeotiff,lenfilename-11,lenfilename-4)
r.sentinelhub <- rast(x=fileGeotiff)
# plot(r.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(r.sentinelhub) <- c("ndvi","wdvired","ci-red","red","green","blue")
# crs(r.sentinelhub)
# CRS arguments: +proj=longlat +datum=WGS84 +no_defs
r.sentinelhub.rd <- project(r.sentinelhub,'+init=EPSG:28992')
# crs(r.sentinelhub.rd)
r.sentinelhub.rd.wdvi <- subset(r.sentinelhub.rd,2)
# dev.off()
plot(r.sentinelhub.rd.wdvi,main=paste("wdvi",imgdate),xlab="RDX",ylab="RDY")
global(r.sentinelhub.rd.wdvi, fun="mean")
# Convert the .rd.wdvi raster to WGS84
r.sentinelhub.wgs84.wdvi <- project(r.sentinelhub.rd.wdvi, '+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 <- vect(pol$wkt,crs='+init=EPSG:4326')
pol.rd <- project(pol.wgs84, "+init=epsg:28992")
# Have a look at both polygons
# wg84
plot(r.sentinelhub.wgs84.wdvi,main=paste("wdvi",imgdate),xlab="LON",ylab="LAT")
plot(pol.wgs84,add=TRUE, col="transparent",border="red")
# RD
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)
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
global(r.sentinelhub.wgs84.wdvi,'mean') # [1] 0.1733634 # Stats from rectangle, WGS84
global(r.sentinelhub.rd.wdvi,'mean') # [1] 0.173531 # Stats from rectangle, RD. Almost but not exactly same as above
global(r.sentinelhub.wgs84.wdvi.pol,'mean',na.rm=TRUE) # [1] 0.1740224 # Stats from raster clipped by polygon, WGS84
global(r.sentinelhub.rd.wdvi.pol,'mean',na.rm=TRUE) # [1] 0.1738386 # Stats from raster clipped by polygon, RD. Almost but not exactly same as above
# file satelliteStats_test_BvdTFieldlabG92_20220825.csv
# "wdvi" "mean": 0.173905644768987
# 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.
global(r.sentinelhub.wgs84.wdvi.pol,'median', na.rm=TRUE) # Error in fun(values(x[[i]]), ...) : could not find function "fun"
r.sentinelhub.wgs84.wdvi.vals <- values(r.sentinelhub.wgs84.wdvi)
median(r.sentinelhub.wgs84.wdvi.vals) # [1] 0.1459627
median(r.sentinelhub.wgs84.wdvi.vals,na.rm=TRUE) # [1] 0.1459627
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.1453323

View File

@@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using FarmmapsApi;
using FarmmapsApi.Models;
using FarmmapsApi.Services;
using FarmmapsDownloadCL.Models;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using static FarmmapsApiSamples.Constants;
namespace FarmmapsDownloadCL
{
public class DownloadCLApplication : IApplication
{
private readonly ILogger<DownloadCLApplication> _logger;
private readonly FarmmapsApiService _farmmapsApiService;
private readonly DownloadCLService _DownloadCLService;
private readonly GeneralService _generalService;
public readonly Dictionary<string, List<string>> _dictCl;
string _itemcode;
public DownloadCLApplication(ILogger<DownloadCLApplication> logger, FarmmapsApiService farmmapsApiService,
GeneralService generalService, DownloadCLService DownloadCLService)
{
_logger = logger;
_farmmapsApiService = farmmapsApiService;
_generalService = generalService;
_DownloadCLService = DownloadCLService;
CodelistsClasses clc = new CodelistsClasses();
_itemcode = clc.itemcode;
_dictCl = clc.dictCl;
}
public async Task RunAsync()
{
var fieldsInputJson = File.ReadAllText("DownloadCLInput.json");
DownloadCLInput clInput = JsonConvert.DeserializeObject<DownloadCLInput>(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();
//Where to write the output
string downloadFolder = clInput.DownloadFolder;
if (string.IsNullOrEmpty(downloadFolder))
{
downloadFolder = "Downloads";
}
if (!Directory.Exists(downloadFolder))
Directory.CreateDirectory(downloadFolder);
//Get the most recent codelists
foreach (string codelist in clInput.codelists)
{
try
{
await Process(roots, codelist, downloadFolder);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
}
private async Task Process(List<UserRoot> roots, string codelistname, string downloadFolder)
{
List<Item> codelist;
string itemtype;
string className;
string body;
string header;
string value;
string[] aboutArray = null;
string[] headerArray = null;
PropertyInfo[] props;
PropertyInfo prop;
List<string> dataList;
string clJson = Path.Combine(downloadFolder, $"{codelistname}.json");
string clCsv = Path.Combine(downloadFolder, $"{codelistname}.csv");
try
{
itemtype = _dictCl[codelistname][0];
className = _dictCl[codelistname][1];
codelist = await _farmmapsApiService.GetItemChildrenAsync(_itemcode, itemtype);
//Write full codelist in json format to clJson.
body = JsonConvert.SerializeObject(codelist);
File.WriteAllText(clJson, body);
_logger.LogInformation($"Downloaded file {clJson}");
//Write full list in csv format to clCsv.
StreamWriter sw = new StreamWriter(clCsv);
//Write metadata in top: when downloaded
sw.WriteLine($"Editeelt codelist {codelistname} downloaded on {DateTime.Now} with the FarmmapsDownloadCL application");
//Generic, for any Codelist as long as it is also defined in FarmmapsDownloadCL.Models in
string typerequest = "FarmmapsDownloadCL.Models." + className + ", FarmmapsDownloadCL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
Type objType = Type.GetType(typerequest);
object clitem = Activator.CreateInstance(objType);
props = clitem.GetType().GetProperties();
//Lookup about info and write to top
foreach (PropertyInfo pi in props)
{
if (pi.Name == "about")
{
aboutArray = (string[])pi.GetValue(clitem);
foreach (string about in aboutArray)
{
//Add quotes
value = "\"" + about + "\"";
//Write each about to a separate line in the csv file
sw.WriteLine(value);
}
}
}
//Write an empty line
sw.WriteLine();
//Look up the headerArray and write the header comma separated
int i = 0;
while (headerArray == null)
{
prop = props[i];
if (prop.Name == "headers")
{
headerArray = (string[])prop.GetValue(clitem);
}
i++;
}
header = string.Join(",", headerArray);
sw.WriteLine(header);
//Add quotes because a value for field 'description' could be '21% Cl, 16.5%CaO, 1330 g/l' and without the quotes that
//would show up as separate columns. So per definition we will add quotes, except if we have a fieldname in the listNotToQuote, then value for that fieldname will not be given quotes
//e.g. not code "3" but code 3.
List<string> listNotToQuote = new List<string>() { "code", "n", "p", "k", "quantity", "cropGroupCode", "cultivationGroupCode" };
//Loop through all items in the codelist
foreach (Item item in codelist)
{
dataList = new List<string> { };
clitem = JsonConvert.DeserializeObject(item.Data.ToString(), objType);
//Add values of the cLitem to the dataList in the same order as the header
foreach (string h in headerArray)
{
value = (string)clitem.GetType().GetProperty(h).GetValue(clitem, null);
if(listNotToQuote.Contains(h) == false)
value = "\"" +value + "\"";
dataList.Add(value);
}
string dataLine = string.Join(",", dataList);
sw.WriteLine(string.Join(",", dataList));
}
sw.Close();
_logger.LogInformation($"Downloaded file {clCsv}");
}
catch
{
_logger.LogWarning($"Missing lookup information on codelist {codelistname}");
}
}
}
}

View File

@@ -0,0 +1,5 @@
{
"codeLists": [ "CL022", "CL127", "CL263", "CL265", "CL405", "CL251", "CL104" ]
//"codeLists": [ "CL263", "CL265"]
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Globalization;
using System.Threading.Tasks;
using FarmmapsApi.Models;
using FarmmapsApi.Services;
using FarmmapsDownloadCL.Models;
using Microsoft.Extensions.Logging;
using static FarmmapsApi.Extensions;
using static FarmmapsApiSamples.Constants;
namespace FarmmapsDownloadCL
{
public class DownloadCLService
{
private readonly ILogger<DownloadCLService> _logger;
private readonly FarmmapsApiService _farmmapsApiService;
private readonly GeneralService _generalService;
public DownloadCLService(ILogger<DownloadCLService> logger, FarmmapsApiService farmmapsApiService,
GeneralService generalService)
{
_logger = logger;
_farmmapsApiService = farmmapsApiService;
_generalService = generalService;
}
}
}

View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Collections" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FarmmapsApi\FarmmapsApi.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="DownloadCLInput.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace FarmmapsDownloadCL.Models
{
public class CodelistsClasses
{
public CodelistsClasses()
{
this.itemcode = "938c0aec4efc46e88783fd029f17309e%3ASYSTEM_DATA";
this.dictCl = new Dictionary<string, List<string>>();
//Add here once you have defined a new CLxxxitem below
//To add a new item, look it up in https://test.farmmaps.eu/swagger/index.html. Download the item you are interested in (like "vnd.farmmaps.itemtype.codelist.cl263")
//do this under Items <- get/api/v1/items, use the it field. Depending on the size of the list retrieving the list can take a few minutes.
//then below create a new CLxxxitem with fieldnames as you see them in the just downloaded new codelist
this.dictCl.Add("CL022", new List<string> { "vnd.farmmaps.itemtype.codelist.cl022", "CL022item" });
this.dictCl.Add("CL104", new List<string> { "vnd.farmmaps.itemtype.codelist.cl104", "CL104item" });
this.dictCl.Add("CL127", new List<string> { "vnd.farmmaps.itemtype.codelist.cl127", "CL127item" });
this.dictCl.Add("CL251", new List<string> { "vnd.farmmaps.itemtype.codelist.cl251", "CL251item" });
this.dictCl.Add("CL263", new List<string> { "vnd.farmmaps.itemtype.codelist.cl263", "CL263item" });
this.dictCl.Add("CL265", new List<string> { "vnd.farmmaps.itemtype.codelist.cl265", "CL265item" });
this.dictCl.Add("CL405", new List<string> { "vnd.farmmaps.itemtype.codelist.cl405", "CL405item" });
}
public string itemcode;
//Define here the codelist names, their item type and the class defining the contents of the data type (and defined in the Models.CodelistsClasses)
public Dictionary<string, List<string>> dictCl;
}
public class CL022item
{
public CL022item()
{
this.headers = new string[] { "codelist", "code", "description", "type", "n", "p", "k", "composition" };
this.codelist = "CL022";
this.about = new string[] { "EDI-Crop, coderingslijst meststoffen", "type MOR = organische meststof; MAN = anorganische meststof" };
}
public string[] headers { get; }
public string codelist { get; }
public string[] about { get; }
public string k { get; set; }
public string n { get; set; }
public string p { get; set; }
public string code { get; set; }
public string type { get; set; }
public string composition { get; set; }
public string description { get; set; }
}
public class CL104item
{
public CL104item()
{
this.headers = new string[] { "codelist", "code", "description" };
this.codelist = "CL104";
this.about = new string[] { "EDI-crop, coderingslijst groenbemesters" };
}
public string[] headers { get; }
public string codelist { get; }
public string[] about { get; }
public string code { get; set; }
public string description { get; set; }
}
public class CL127item
{
public CL127item()
{
this.headers = new string[] { "codelist", "code", "description", "description_nl", "culturalPracticeLevel1", "culturalPracticeLevel2" };
this.codelist = "CL127";
}
public string[] headers { get; }
public string codelist { get; }
public string code { get; set; }
public string description { get; set; }
public string description_nl { get; set; }
public string culturalPracticeLevel1 { get; set; }
public string culturalPracticeLevel2 { get; set; }
}
public class CL251item
{
public CL251item()
{
this.headers = new string[] { "codelist", "code", "rvo", "active", "primary", "description", "description_fr", "description_nl" };
this.codelist = "CL251";
this.about = new string[] { "Codering teeltdoelen (CropProductionPurposeCode)", "primary: 1 = primary; 2 = secondary", "rvo: 1 = yes; 0 = no" };
}
public string[] headers { get; }
public string codelist { get; }
public string[] about { get; }
public string code { get; set; }
public string rvo { get; set; }
public string active { get; set; }
public string primary { get; set; }
public string description { get; set; }
public string description_nl { get; set; }
public string description_fr { get; set; }
}
public class CL263item
{
public CL263item()
{
this.headers = new string[] { "codelist", "code", "eppoCode", "botanicName", "description", "description_fr", "description_nl", "cropGroupCode", "cropGroupName", "subCropGroupCode", "subCropGroupName", "cultivationGroupCode", "cultivationGroupName" };
this.codelist = "CL263";
this.about = new string[] { "EDI-Crop, coderingslijst gewassoorten" };
}
public string[] headers { get; }
public string codelist { get; }
public string[] about { get; }
public string code { get; set; }
public string eppoCode { get; set; }
public string botanicName { get; set; }
public string description { get; set; }
public string description_nl { get; set; }
public string description_fr { get; set; }
public string cropGroupCode { get; set; }
public string cropGroupName { get; set; }
public string subCropGroupCode { get; set; }
public string subCropGroupName { get; set; }
public string cultivationGroupCode { get; set; }
public string cultivationGroupName { get; set; }
public string composition { get; set; } //?
}
public class CL265item
{
public CL265item()
{
this.headers = new string[] { "Code", "Formaat", "Eenheid", "Waarde" };
this.codelist = "CL265";
this.about = new string[] { "EDI-Crop CL265: FarmCharacterictics, FieldCharacteristics, CropFieldCharacteristics, TreatmentCharacteristics",
"Betreft codelijst eigenschappen teelt en teelthandelingen CL265.Daar waar in kolom 'Waarde' wordt verwezen naar CL.., wordt de codelijst bedoeld die onder het betreffende nummer bekend is.",
"In het EDI-Crop bericht wordt de code gebruikt onder resp. CropFieldCharacteristic c.q.TreatmentCharacteristic middels de dataelementen PropertyVariableCode (invullen vanuit CL265) en PropertyVariableValue(voor de waarde)"};
}
public string[] headers { get; }
public string codelist { get; }
public string[] about { get; }
public string Code { get; set; }
public string Formaat { get; set; }
public string Eenheid { get; set; }
public string Waarde { get; set; }
}
public class CL405item
{
public CL405item()
{
this.headers = new string[] { "codelist", "code", "description", "description_fr", "description_nl", "hoofdgroep" };
this.codelist = "CL405";
this.about = new string[] { };
}
public string[] headers { get; }
public string codelist { get; }
public string[] about { get; }
public string code { get; set; }
public string hoofdgroep { get; set; }
public string description { get; set; }
public string description_fr { get; set; }
public string description_nl { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
using System;
using Newtonsoft.Json.Linq;
namespace FarmmapsDownloadCL.Models
{
public class DownloadCLInput
{
public string[] codelists { get; set; }
public string DownloadFolder { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using System.Threading.Tasks;
using FarmmapsApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace FarmmapsDownloadCL
{
class Program : FarmmapsProgram<DownloadCLApplication>
{
private static async Task Main(string[] args)
{
await new Program().Start(args);
}
protected override void Configure(IServiceCollection serviceCollection)
{
serviceCollection.AddLogging()
.AddTransient<DownloadCLService>();
}
}
}

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>

View File

@@ -45,14 +45,14 @@ namespace FarmmapsHaulmkilling
await _farmmapsApiService.GetCurrentUserCodeAsync();
var roots = await _farmmapsApiService.GetCurrentUserRootsAsync();
var myDrive = roots.SingleOrDefault(r => r.Name == "My drive");
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 == "Uploaded");
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
if (uploadedRoot == null)
{
_logger.LogError("Could not find a needed root item");

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
@@ -25,7 +26,7 @@ namespace FarmmapsHaulmkilling
_farmmapsApiService = farmmapsApiService;
_generalService = generalService;
}
/// <summary>
/// Gets the list of available haulmkilling agents
/// </summary>
@@ -38,7 +39,7 @@ namespace FarmmapsHaulmkilling
return haulmkillingAgentItems.Select(item => item.Data.ToObject<HaulmkillingAgent>())
.ToList();
}
/// <summary>
/// Creates an haulmkilling application map
/// </summary>
@@ -69,7 +70,7 @@ namespace FarmmapsHaulmkilling
if (itemTaskStatus.IsFinished)
tokenSource.Cancel();
});
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
if (itemTask.State == ItemTaskState.Error)
{
@@ -79,10 +80,10 @@ namespace FarmmapsHaulmkilling
var itemName = $"VRAHaulmkilling {agent.Label}";
var applianceMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
GEOTIFF_PROCESSED_ITEMTYPE, itemName,
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");
@@ -92,4 +93,4 @@ namespace FarmmapsHaulmkilling
return applianceMapItem;
}
}
}
}

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>

View File

@@ -50,14 +50,14 @@ namespace FarmmapsHerbicide
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)
{
_logger.LogError("Could not find a needed root item");
return;
}
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "Uploaded");
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
if (uploadedRoot == null)
{
_logger.LogError("Could not find a needed root item");
@@ -91,14 +91,14 @@ namespace FarmmapsHerbicide
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)
{
_logger.LogError("Could not find a needed root item");
return;
}
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "Uploaded");
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
if (uploadedRoot == null)
{
_logger.LogError("Could not find a needed root item");

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\FarmmapsApi\FarmmapsApi.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="KPIInput.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,895 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using System.Transactions;
using FarmmapsApi;
using FarmmapsApi.Models;
using FarmmapsApi.Services;
using FarmmapsKPI.Models;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using static FarmmapsApiSamples.Constants;
namespace FarmmapsKPI
{
public class KPIApplication : IApplication
{
//private const string DownloadFolder = "Downloads";
private const string SettingsFile = "settings.json";
private readonly ILogger<KPIApplication> _logger;
private readonly FarmmapsApiService _farmmapsApiService;
private readonly KPIService _kpiService;
private readonly GeneralService _generalService;
private Settings _settings;
public KPIApplication(ILogger<KPIApplication> logger, FarmmapsApiService farmmapsApiService,
GeneralService generalService, KPIService kpiService)
{
_logger = logger;
_farmmapsApiService = farmmapsApiService;
_generalService = generalService;
_kpiService = kpiService;
}
public async Task RunAsync()
{
KPIInput input;
string fnKPIinput;
//Console.WriteLine("Type name of input json file. Example: KPIinput.json (in same directory as FarmmapsKPI.exe) or for example like this: C:/temp/KPIinputChemieTmp.json");
//fnKPIinput = Console.ReadLine();
//if (string.IsNullOrEmpty(fnKPIinput))
//{
//fnKPIinput = "KPIinput.json";
fnKPIinput = "C:\\git\\FarmMapsApiClient_KB34_MAST\\FarmmapsKPI\\KPIinput.json";
//}
var fieldsInputJson = File.ReadAllText(fnKPIinput);
List<KPIInput> fieldsInputs = JsonConvert.DeserializeObject<List<KPIInput>>(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();
//Where to write the output
string downloadFolder = fieldsInputs[0].DownloadFolder;
if (string.IsNullOrEmpty(downloadFolder))
{
downloadFolder = "Downloads";
}
if (!Directory.Exists(downloadFolder))
Directory.CreateDirectory(downloadFolder);
//Write the same info to a single csv file. Note this means existing file will be overwritten!
StreamWriter sw;
string KPIItemCsv = Path.GetFileNameWithoutExtension(fnKPIinput) + "_Items.csv";
string KPIItemPathCsv = Path.Combine(downloadFolder, KPIItemCsv);
List<string> headerList = new List<string> { "run","parentName", "cropfieldcode", "area_ha", "cropTypeCode", "cropTypeName", "KPIid", "KPIvariable", "KPIvalue", "KPIunit", "KPItargetvalue", "KPIthresholdValue",
"mbp_productCode","mbp_productName","mbp_quantity","mbp_unitCode","mbp_date","mbp_KPIvariable","mbp_KPIvalue"};
//Create a new csv file. Means if existing then overwritten !!!
sw = new StreamWriter(KPIItemPathCsv);
Configuration cf = await _farmmapsApiService.GetConfiguration();
string endPoint = cf.Endpoint;
sw.WriteLine($"Using FarmmapsKPI application in FarmmapsApSamples.sln. Input file: '{fnKPIinput}'. Download DateTime: '{DateTime.Now}'. Calculations on: '{endPoint}'");
sw.WriteLine();
sw.WriteLine(string.Join(",", headerList));
// For each input download all KPI's. Keep track to time, important when doing bulk calculations
var watch = System.Diagnostics.Stopwatch.StartNew();
TimeSpan tsSofar = new TimeSpan();
TimeSpan tsRemaining;
TimeSpan tsTotalEstimated;
//Per default just 1 run per field. For debugging check if when we run multiple times do we get (should be) always the same output?
int nrun = 1;
for (int run = 1; run <= nrun; run++) {
for (int i = 0; i < fieldsInputs.Count; i++)
//for (int i = 3; i < 4; i++) // for testing
{
watch.Restart();
input = fieldsInputs[i];
_logger.LogInformation(string.Format($"// FarmmapsKPI: Run {run}: Downloading KPI's for field {i + 1} out of {fieldsInputs.Count} to single csv file {KPIItemPathCsv}"));
try
{
await Process(roots, input, sw, run);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
watch.Stop();
tsSofar = tsSofar + watch.Elapsed;
tsTotalEstimated = tsSofar / (i + 1) * fieldsInputs.Count;
tsRemaining = tsTotalEstimated - tsSofar;
_logger.LogInformation(string.Format($"// Time (hh:mm:ss): this field: {strTime(watch.Elapsed)}. Sofar: {strTime(tsSofar)}. Estimated total: {strTime(tsTotalEstimated)}. Remaining: {strTime(tsRemaining)}"));
}
}
//Close the csv file, write message to screen
sw.Close();
_logger.LogInformation(string.Format($"// FarmmapsKPI:"));
_logger.LogInformation($"Done! Written all KPI for all fields in '{fnKPIinput}' to output file '{KPIItemPathCsv}'");
}
private async Task Process(List<UserRoot> roots, KPIInput input, StreamWriter sw, int run)
{
List<Item> cropfieldChildren;
List<Item> crprecChildren;
KPIOutput kpio;
KPIOutput kpioPrevious = new KPIOutput(); //creates a new empty
//If KPI E1 is calculated, write these sub kpi's to output
string[] mbp_KPIvariables = new string[] { "aquaticLife", "groundWater", "soilLife" };
string mbp_KPIvalue;
int targetKPIitemsCount; //if we know we should be getting 8 KPI items (A1,B1,B2,C1,D1,E1,F1,F2)
int maxtries = 5; // but don't keep on trying forever; there is a maximum number of tries
int trycnt;
//double totalNferiliserInput = 0;
//double totalNferiliserCropfield = 0;
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 useExistingCropfieldWithChildren = input.UseExistingCropfieldWithChildren;
int cropYear = input.CropYear;
string fieldName = input.fieldName;
string fieldGeom = input.GeometryJson.ToString(Formatting.None);
//Settings
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, added a Data input, with field specific data for the KPI calculation
Item cropfieldItem;
//1 useExistingCropfieldWithChildren = false -> create new
//2 useExistingCropfieldWithChildren = true && input.CropfieldItemCode = "" or absent -> read from settings json
//3 useExistingCropfieldWithChildren = true && input.CropfieldItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> use this one
if (useExistingCropfieldWithChildren == false)
{
_logger.LogInformation($"Creating cropfield with name '{fieldName}'");
cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDriveRoot.Code,
$"{fieldName}", cropYear, input.GeometryJson.ToString(Formatting.None), input.DataCropfield.ToString(Formatting.None), input.StartDate, input.EndDate);
_settings.CropfieldItemCode = cropfieldItem.Code;
SaveSettings(settingsfile);
}
else if (string.IsNullOrEmpty(input.CropfieldItemCode))
{
_logger.LogInformation("reading CropfieldItemCode from settings file");
cropfieldItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldItemCode);
}
else
{
_logger.LogInformation("reading CropfieldItemCode from KPIinput json");
cropfieldItem = await _farmmapsApiService.GetItemAsync(input.CropfieldItemCode);
SaveSettings(settingsfile);
}
// The cropfieldCharacteristicItem is used to enter crop yields and/or straw yields
Item cropfieldCharacteristicItem;
string dataCropfieldCharacteristic;
//1 useExistingCropfieldWithChildren = false -> create new
//2 useExistingCropfieldWithChildren = true && input.CropfieldCharacteristicItemCode = "" or absent -> read from settings json
//3 useExistingCropfieldWithChildren = true && input.CropfieldCharacteristicItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> use this one
if (useExistingCropfieldWithChildren == false)
{
for (int i = 0; i < input.DataCropfieldCharacteristics.Length; i++)
{
dataCropfieldCharacteristic = input.DataCropfieldCharacteristics[i].ToString(Formatting.None);
dynamic data = JObject.Parse(dataCropfieldCharacteristic);
_logger.LogInformation($"CreateCropfieldCharacteristicItemAsync ... for cropfieldCharacteristic {i}: '{data.label}', value '{data.value}'");
cropfieldCharacteristicItem = await _generalService.CreateCropfieldCharacteristicItemAsync(cropfieldItem.Code, cropYear, fieldGeom, dataCropfieldCharacteristic);
_settings.CropfieldCharacteristicItemCode = cropfieldCharacteristicItem.Code;
SaveSettings(settingsfile);
}
}
else if (string.IsNullOrEmpty(input.CropfieldItemCode))
{
_logger.LogInformation("reading CropfieldCharacteristicItemCode from settings file");
cropfieldCharacteristicItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldCharacteristicItemCode);
}
else
{
_logger.LogInformation("reading CropfieldCharacteristicItemCode from KPIinput json");
cropfieldCharacteristicItem = await _farmmapsApiService.GetItemAsync(input.CropfieldCharacteristicItemCode);
SaveSettings(settingsfile);
}
// Now we can do a first KPI calculation and get the polygon area from the KPI output (where it is based on geometry)
// We need that because for operations, you need to provide the area on which the operation was applied
// And if we put that to the crop area, then we neatly get everything on a per ha basis
_logger.LogInformation($"Getting polygon area (ha))");
List<Item> KPIItemsArea = await _generalService.GetKpiItemsForCropField(cropfieldItem, 3);
trycnt = 1;
targetKPIitemsCount = 3; // here for the area we need at least 3, but not more than that
while (KPIItemsArea.Count < targetKPIitemsCount & trycnt < maxtries)
{
KPIItemsArea = await _generalService.GetKpiItemsForCropField(cropfieldItem,3);
_logger.LogInformation($"Found {KPIItemsArea.Count} KPI items");
trycnt++;
}
kpio = JsonConvert.DeserializeObject<KPIOutput>(KPIItemsArea[0].Data.ToString());
string area_ha = kpio.data.area;
// turn the area into a JObject for later merging with operation data;
string strJarea = JsonConvert.SerializeObject(new { area = area_ha });
JObject Jarea = JObject.Parse(strJarea);
if (useExistingCropfieldWithChildren == false)
{
//Retreiving BOFEK. A cropfield has 1 soil
//Have a look at the cropfieldChildren before and after running this task, see one child (i.e. soil) has been added)
//cropfieldChildren = await _farmmapsApiService.GetItemChildrenAsync(cropfieldItem.Code);
_logger.LogInformation("Get BOFEK for field");
Item bofekItem = await _generalService.RunBofekTask(cropfieldItem);
if (bofekItem == null)
{
_logger.LogError("Something went wrong while obtaining the BOFEK data");
return;
}
//cropfieldChildren = await _farmmapsApiService.GetItemChildrenAsync(cropfieldItem.Code);
}
else
{
_logger.LogInformation("For existing cropfield we assume it already has BOFEK soil data");
}
// A cropfield has 1 crop recording and the crop recording has 0:many operations
//So first at the crop recording
Item crprecItem;
//1 useExistingCropfieldWithChildren = false -> create new
//2 useExistingCropfieldWithChildren = true && input.CropRecordingItemCode = "" or absent -> read from settings json
//3 useExistingCropfieldWithChildren = true && input.CropRecordingItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> use this one
if (useExistingCropfieldWithChildren == false)
{
_logger.LogInformation("RunCropRecordingTask ...");
crprecItem = await _generalService.RunCropRecordingTask(cropfieldItem);
_settings.CropRecordingItemCode = crprecItem.Code;
SaveSettings(settingsfile);
}
else if (string.IsNullOrEmpty(input.CropfieldItemCode))
{
_logger.LogInformation("reading CropRecordingItemCode from settings file");
crprecItem = await _farmmapsApiService.GetItemAsync(_settings.CropRecordingItemCode);
}
else
{
_logger.LogInformation("reading CropRecordingItemCode from KPIinput json");
crprecItem = await _farmmapsApiService.GetItemAsync(input.CropRecordingItemCode);
SaveSettings(settingsfile);
}
// Now add the operations
List<Item> crpOperationItems = new List<Item> { };
List<string> crpOperationItemCodes = new List<string> { };
Item crpOperationItem;
string dataOperation;
string codeOperation;
//1 useExistingCropfieldWithChildren = false -> create new
//2 useExistingCropfieldWithChildren = true && input.OperationItemCode = "" or absent -> read from settings json
//3 useExistingCropfieldWithChildren = true && input.OperationItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> use this one
if (useExistingCropfieldWithChildren == false)
{
for (int i = 0; i < input.DataOperations.Length; i++)
{
dataOperation = input.DataOperations[i].ToString(Formatting.None);
dynamic data = JObject.Parse(dataOperation);
_logger.LogInformation($"CreateOperationItemAsync ... for operation {i}: '{data.name}', on date '{data.from}'");
// Now check if the operation has a field called area
string? opArea = data["area"];
if (string.IsNullOrEmpty(opArea))
{
// if not having field area: add it to dataOperation ...
input.DataOperations[i].Merge(Jarea);
// ... and update the string
dataOperation = input.DataOperations[i].ToString(Formatting.None);
}
else
{
// if yes having field area: compare with polygon area. If not the same, throw warning
if (data.area != area_ha)
{
double differencePercent = 100.0*(Convert.ToDouble(area_ha) / Convert.ToDouble(data.area) - 1.0);
_logger.LogWarning($"cropfield has area {area_ha}, but in your KPIinput.json or file like that, you have an operation with area {data.area}" +
$" Difference is {area_ha} / {data.area} - 100% = {differencePercent}%." +
$" Is that correct? Example if operation was applied in part of field, e.g. in case of variable rate (VRA) application." +
$" Or did you accidentally fill in area in the KPIinput json? To use cropfield area, omit field 'area' from json" +
$" then the KPI applicataion will fill in area calculated from geometry");
}
}
//Now after optionally adding the area, add the Operation to the crop recording
crpOperationItem = await _generalService.CreateOperationItemAsync(crprecItem.Code, cropYear, fieldGeom, dataOperation);
crpOperationItems.Add(crpOperationItem);
crpOperationItemCodes.Add(crpOperationItem.Code);
//Keep track of totalNferiliserInput
//totalNferiliserInput = totalNferiliserInput + (double)data.n; / this causes a problem if N content of the fertilizer is missing. As this check is no longer needed I just commented it out
}
_settings.OperationItemCodes = crpOperationItemCodes.ToArray();
SaveSettings(settingsfile);
}
else if (string.IsNullOrEmpty(input.CropfieldItemCode))
{
_logger.LogInformation("reading OperationItemCode from settings file");
for (int i = 0; i < _settings.OperationItemCodes.Length; i++)
{
codeOperation = _settings.OperationItemCodes[i];
crpOperationItem = await _farmmapsApiService.GetItemAsync(codeOperation);
crpOperationItems.Add(crpOperationItem);
crpOperationItemCodes.Add(crpOperationItem.Code);
}
}
else
{
_logger.LogInformation("reading OperationItemCodes from KPIinput json");
for (int i = 0; i < input.OperationItemCodes.Length; i++)
{
codeOperation = input.OperationItemCodes[i];
crpOperationItem = await _farmmapsApiService.GetItemAsync(codeOperation);
crpOperationItems.Add(crpOperationItem);
crpOperationItemCodes.Add(crpOperationItem.Code);
}
_settings.OperationItemCodes = crpOperationItemCodes.ToArray();
SaveSettings(settingsfile);
}
// Inspect the children and grandchildren. If all is well, cropfield will have:
// one crprec, with 0-many operations as children. And the Data of an operation will have specification of how much fertilizer / cropprotection agent was applied
// one edicrop.characteristic (with yield in the data)
cropfieldChildren = await _farmmapsApiService.GetItemChildrenAsync(cropfieldItem.Code);
crprecChildren = await _farmmapsApiService.GetItemChildrenAsync(crprecItem.Code);
//Check total operations
int nOperationsInput = input.DataOperations.Length;
int nOperationsCropfield = crprecChildren.Count;
if (nOperationsInput != nOperationsCropfield)
{
_logger.LogWarning(String.Format($"1. run {run}: nOperationsInput != nOperationsCropfield?!"));
//throw new Exception(String.Format($"run {run}: nOperationsInput != nOperationsCropfield?!"));
}
//Check totalNfertiliser input and Cropfield,
//for (int o = 0; o < crprecChildren.Count; o++)
//{
// dynamic data = JObject.Parse(crprecChildren[o].Data.ToString());
// totalNferiliserCropfield = totalNferiliserCropfield + (double)data.n;
//}
//if (totalNferiliserInput != totalNferiliserCropfield)
//{
// _logger.LogWarning(String.Format($"2. run {run}: totalNferiliserInput != totalNferiliserCropfield?!"));
// //throw new Exception(String.Format($"run {run}: totalNferiliserInput != totalNferiliserCropfield?!"));
//}
//Now get the KPIs for this cropfield, mounted with operations & cropyield
List<Item> KPIItems = await _generalService.GetKpiItemsForCropField(cropfieldItem, 3);
_logger.LogInformation($"GetKpiItemsForCropField('{cropfieldItem.Code}')");
//Pesticide KPI's D1 and E1 are retreived from API's of CTBG and CLM and may take a bit longer to retrieve
targetKPIitemsCount = 8; //if we know we should be getting 8 KPI items (A1,B1,B2,C1,D1,E1,F1,F2)
trycnt = 0;
bool boolAquaticLife = false;
_logger.LogInformation($"Firing calls GetKpiItemsForCropField() until we have {targetKPIitemsCount} KPIitems, but don't keep firing forever, stop after {maxtries} calls");
_logger.LogInformation($"Before we start:");
//_logger.LogInformation($"* KPIItems.Count = {KPIItems.Count}");
_logger.LogInformation($"* trycnt = {trycnt}");
_logger.LogInformation($"* boolAquaticLife = {boolAquaticLife}");
//additional criterion for while loop: check if it really contains the E1 mbp elements.
//while (trycnt == 0 || ((KPIItems.Count < targetKPIitemsCount || boolAquaticLife == false) & trycnt < maxtries))
targetKPIitemsCount = 8; //if we know we should be getting 8 KPI items (A1,B1,B2,C1,D1,E1,F1,F2)
while (trycnt == 0 || (KPIItems.Count < targetKPIitemsCount & trycnt < maxtries))
{
_logger.LogInformation($"Call nr {trycnt + 1}");
KPIItems = await _generalService.GetKpiItemsForCropField(cropfieldItem, 30); //number after comma is how many seconds per try, should be between 30 seconds and 5 minutes
_logger.LogInformation($"Found {KPIItems.Count} KPI items");
//boolAquaticLife = GetBoolAquaticLife(KPIItems);
trycnt ++;
}
if (KPIItems.Count < targetKPIitemsCount) {
_logger.LogWarning($"Found {KPIItems.Count} KPIItems while you were aiming for {targetKPIitemsCount} KPIItems");
}
//Download KPI's into a json output file for this specific cropfield (with unique cropfieldItem.Code)
string KPIItemPathJson = Path.Combine(downloadFolder, $"KPIItems_{cropfieldItem.Code}.json");
var count = 0;
foreach (Item item in KPIItems)
{
//Console.WriteLine($"KPI item #{count}: {item.Name}");
File.AppendAllText(KPIItemPathJson, item.Data + Environment.NewLine);
count++;
}
_logger.LogInformation($"Downloaded file {KPIItemPathJson}");
_logger.LogInformation($"");
//Remove duplicate KPI items
List<Item> KPIItemsClean = new List<Item>();
Item itemi;
string id, idNext;
double value, valueNext;
int DuplicateCounter;
value = 0;
id = "";
DuplicateCounter = 1;
for (int i = 0; i < KPIItems.Count; i++)
{
itemi = KPIItems[i];
idNext = JsonConvert.DeserializeObject<KPIOutput>(itemi.Data.ToString()).id;
valueNext = Convert.ToDouble(JsonConvert.DeserializeObject<KPIOutput>(itemi.Data.ToString()).value);
if (idNext != null)
{
if (id != idNext)
{
KPIItemsClean.Add(itemi);
}
else
{
if (valueNext >= value)
{
//Remove the previous element from this list with same id but wrong value (valueNext > value) or duplicate value (valueNext == value). Presumes list is always sorted by kpiid, e.g. we may havce "
KPIItemsClean.RemoveAt(i - DuplicateCounter); //added a duplicate counter to deal with calculations where there is more 1 duplicate.
KPIItemsClean.Add(itemi);
DuplicateCounter = DuplicateCounter + 1;
}
else
{
//Previous element was correct and already added so do nothing here
}
}
id = idNext;
value = valueNext;
}
}
////Order again from A zo Z.
//List<Item> KPIItemsCleanSorted = new List<Item>();
//for (int i = KPIItemsClean.Count - 1; i >= 0; i--)
//{
// KPIItemsCleanSorted.Add(KPIItemsClean[i]);
//}
//Write to the csv file that collects all KPI's for all the crop fields
List<string> dataList;
foreach (Item item in KPIItemsClean)
{
kpio = JsonConvert.DeserializeObject<KPIOutput>(item.Data.ToString());
if (kpio.id != null)
{
KPIelementsOfBalance kPIelementsOfBalance = kpio.data.values;
if (kpio.id == "A1") //TtD
{
//Make a new dataList = new line to be written
//Fill the datalist with this kpi
dataList = new List<string>
{
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id,
kpio.quantity, // in KPI output quantity is what we call KPIvariable in headerlist of csv file
kpio.value,
kpio.unit,
kpio.targetValue,
kpio.thresholdValue
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
foreach (string elementName in kpio.A1elements)
{
// get A1element from the element called values
// TtD 20240311: note elements of A1 are in the data structure elements of kpio.data and not as below for B1, B2, etc as kpio.data.values
string elementValue = (string)kpio.data.GetType().GetProperty(elementName).GetValue(kpio.data, null);
dataList = new List<string>
{
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id,
elementName, // specific output variable name for A1 element
elementValue, // specific output value name for A1 element
kpio.unit,
"",
""
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
}
}
else if (kpio.id == "B1")
{
//Make a new dataList = new line to be written
//Fill the datalist with this kpi
dataList = new List<string>
{
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id,
kpio.quantity, // in KPI output quantity is what we call KPIvariable in headerlist of csv file
kpio.value,
kpio.unit,
kpio.targetValue,
kpio.thresholdValue
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
foreach (string elementName in kpio.B1elements)
{
// get B1element from the element called values
string elementValue = (string)kPIelementsOfBalance.GetType().GetProperty(elementName).GetValue(kPIelementsOfBalance, null);
dataList = new List<string>
{
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id,
elementName, // specific output variable name for B1 element
elementValue, // specific output value name for B1 element
kpio.unit,
"",
""
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
//Check if totalNferiliserInput is equal to what comes out of the KPI calculation
//if (elementName == "nFertilizerNKgHa")
//{
// if (totalNferiliserInput != Convert.ToDouble(elementValue))
// {
// _logger.LogWarning(String.Format($"3. run {run}: totalNferiliserInput != nFertilizerNKgHa"));
// //throw new Exception(String.Format($"run {run}: totalNferiliserInput != nFertilizerNKgHa"));
// }
//}
}
}
else if (kpio.id == "B2")
{
//Make a new dataList = new line to be written
dataList = new List<string>
{
//Fill the datalist with this kpi
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id,
kpio.quantity, // in KPI output quantity is what we call KPIvariable in headerlist of csv file
kpio.value,
kpio.unit,
kpio.targetValue,
kpio.thresholdValue
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
foreach (string elementName in kpio.B2elements)
{
// get B1element from the element called values
string elementValue = (string)kPIelementsOfBalance.GetType().GetProperty(elementName).GetValue(kPIelementsOfBalance, null);
dataList = new List<string>
{
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id,
elementName, // specific output variable name for B2 element
elementValue, // specific output value name for B2 element
kpio.unit,
"",
""
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
}
}
else if (kpio.id == "C1") //TtD
{
//Make a new dataList = new line to be written
dataList = new List<string>
{
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id,
kpio.quantity, // in KPI output quantity is what we call KPIvariable in headerlist of csv file
kpio.value,
kpio.unit,
kpio.targetValue,
kpio.thresholdValue
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
foreach (string elementName in kpio.C1elements)
{
// get C1element from the element called values
string elementValue = (string)kPIelementsOfBalance.GetType().GetProperty(elementName).GetValue(kPIelementsOfBalance, null);
dataList = new List<string>
{
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id,
elementName, // specific output variable name for C1 element
elementValue, // specific output value name for C1 element
kpio.unit,
"",
""
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
}
}
else if (kpio.id == "E1")
{
//for E1, environmentMeasureData is an array of elements with 1 per pesticide. Inside each element there are multiple mbp_KPIvariables to be written
foreach (KPIenvironmentMeasureData e in kpio.data.environmentMeasureData)
{
foreach (string mbp_KPIvariable in mbp_KPIvariables)
{
if (mbp_KPIvariable == "aquaticLife") { mbp_KPIvalue = e.aquaticLife; } else if (mbp_KPIvariable == "groundWater") { mbp_KPIvalue = e.groundWater; } else if (mbp_KPIvariable == "soilLife") { mbp_KPIvalue = e.soilLife; } else { mbp_KPIvalue = ""; }
//Make a new dataList = new line to be written
dataList = new List<string>
{
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id, //"E1"
kpio.quantity, // "mbp"
"", // not here the value
"", // not here KPIunit for this indicator
"", // not here KPItargetvalue for this indicator
"", // not here KPIthresholdValue for this indicator
e.productCode,
e.productName,
e.quantity,
e.unitCode,
e.date,
mbp_KPIvariable,
mbp_KPIvalue
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
}
}
}
else if (kpio.id == "G1") //TtD
{
//Make a new dataList = new line to be written
dataList = new List<string>
{
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id,
kpio.quantity, // in KPI output quantity is what we call KPIvariable in headerlist of csv file
kpio.value,
kpio.unit,
kpio.targetValue,
kpio.thresholdValue
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
foreach (string elementName in kpio.G1elements)
{
// get G1element from the element called values
string elementValue = (string)kPIelementsOfBalance.GetType().GetProperty(elementName).GetValue(kPIelementsOfBalance, null);
dataList = new List<string>
{
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id,
elementName, // specific output variable name for G1 element
elementValue, // specific output value name for G1 element
kpio.unit,
"",
""
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
}
}
else
{
//Any other KPI, (D1, F1, and F2), with just 1 record to write
dataList = new List<string>
{
run.ToString(),
kpio.parentName,
cropfieldItem.Code,
kpio.data.area,
kpio.data.cropTypeCode,
kpio.data.cropTypeName,
kpio.id,
kpio.quantity,
kpio.value,
kpio.unit,
kpio.targetValue,
kpio.thresholdValue
};
//Write the datalist to a line to the streamwrieter sw for the output csv file
sw.WriteLine(string.Join(",", dataList));
}
}
}
////Total N applied from input
//double totalNapplied = 0.0;
//double operationNapplied;
//for (int i = 0; i < crpOperationItemCodes.Count; i++)
//{
// codeOperation = crpOperationItemCodes[i];
// crpOperationItem = await _farmmapsApiService.GetItemAsync(codeOperation);
// dynamic data = JObject.Parse(crpOperationItem.Data.ToString(Formatting.None));
// if (data.n != null)
// {
// operationNapplied = crpOperationItem.Data.GetValue("n").ToObject<double>();
// totalNapplied = totalNapplied + operationNapplied;
// }
//}
////Also add totalNapplied to the csv
//dataList = new List<string> { };
//dataList.Add(kpioPrevious.parentName);
//dataList.Add(cropfieldItem.Code);
//try { dataList.Add(kpioPrevious.data.area); } catch { dataList.Add(""); };
//try { dataList.Add(kpioPrevious.data.cropTypeCode); } catch { dataList.Add(""); };
//try { dataList.Add(kpioPrevious.data.cropTypeName); } catch { dataList.Add(""); };
//dataList.Add("");
//dataList.Add("totalNapplied");
//dataList.Add(totalNapplied.ToString());
//dataList.Add("kg/ha");
//dataList.Add("");
//dataList.Add("");
//sw.WriteLine(string.Join(",", dataList));
//Clean up. Only newly created fields
//Look up instruction in Swagger / api / v1 / items /{ code}
if (useExistingCropfieldWithChildren == false && input.DeleteNewlyCreatedAfterCalc == true)
{
// Tested and found that if I delete the parent (cropfieldItem) then
// automatically deletes children (crprecItem, cropfieldCharacteristicItem, KPIcontainer)
// and automatically deletes grand children (crprecItem: operations, KPIcontainer: KPI items)
await _farmmapsApiService.DeleteItemAsync(cropfieldItem.Code);
//Do we need to wait here for the task to be completed? Or does it continue in the background?
//await Task.Delay(60000); // wait 60 secs for task to be completed
//Before the GetItem you will see cropfieldItem, crprecItem etc exist (with data).
//After the GetItem these cropfieldItem, crprecItem etc are null which means they have been succesfully deleted.
//// Check if below works, i.e. is item really deleted?
//cropfieldItem = await _farmmapsApiService.GetItemAsync(cropfieldItem.Code);
//// Check if croprecording has also been deleted. If not also delete it
//crprecItem = await _farmmapsApiService.GetItemAsync(crprecItem.Code);
//// Check if 1 operation has also been deleted. If not also delete it
//crpOperationItem = await _farmmapsApiService.GetItemAsync(crpOperationItemCodes[0]);
//// Check if 1 cropfieldCharacteristicItem has also been deleted. If not also delete it
//cropfieldCharacteristicItem = await _farmmapsApiService.GetItemAsync(cropfieldCharacteristicItem.Code);
}
}
// 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);
}
private string strTime(TimeSpan ts)
{
return String.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds);
}
private bool GetBoolAquaticLife(List<Item> KPIItems)
{
bool found = false;
foreach (Item item in KPIItems)
{
KPIOutput kpio = JsonConvert.DeserializeObject<KPIOutput>(item.Data.ToString());
if (kpio.id == "E1")
{
try
{
foreach (KPIenvironmentMeasureData e in kpio.data.environmentMeasureData)
{
if (e.aquaticLife != null)
{
found = true;
_logger.LogInformation($"Found e.aquaticLife = {e.aquaticLife}");
_logger.LogInformation("");
}
}
}
catch (Exception ex)
{
_logger.LogWarning($"NOT Found e.aquaticLife");
_logger.LogError(ex.Message);
}
}
}
return found;
}
}
}

891
FarmmapsKPI/KPIInput.json Normal file
View File

@@ -0,0 +1,891 @@
[
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "test_Potato_ZeroFertilizer_Consumption_Sand",
//Note when you run the FarmmapsKPI project, somewhere to your C:\git\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\ directory, files named like this are written:
//'Settings_aardappelveld_test_Potato_ZeroFertilizer.json', where 'aardappelveld_test_Potato_ZeroFertilizer.json' is your fieldName (see below)
//1 useExistingCropfieldWithChildren = false -> create new
//2 useExistingCropfieldWithChildren = true && CropfieldItemCode = "" or absent -> read fieldName (see below) -> read all codes from settings json file
//3 useExistingCropfieldWithChildren = true && CropfieldItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> if you have in your account already an existing cropfield then use that
"CropfieldItemCode": "", // could contain for example this: "abae97f89f3c4ac08953b1b8bea9f076" if this is an exisiting CropfieldItemCode in your account.
//And then if useExistingCropfieldWithChildren = true, this would be used.
"dataCropfield": {
//"area": 4.22, //Leave empty, KPI app will calculate it from geometry
"final": true, //always true
"soilCode": "1", //From codelist CL405. Can be no longer be omitted
"soilName": "Sand",
"cropTypeCode": "1010101", //From codelist CL263
"cropTypeName": "Potato", //From codelist CL263
"productionPurposeCode": "003", //From codelist CL251. For testing, see case with consumption & starch potato
"productionPurposeName": "consumption" //From codelist CL251
},
"CropRecordingItemCode": "", // could contain for example this: "314aa1b6480b493ba28a5f55039a01d4" if this is the CropRecordingItemCode of the provided CropfieldItemCode. And then if useExistingCropfieldWithChildren = true, this would be used
"OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used
"dataOperations": [], //leaving the operations empty means no fertilizer is applied
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
//PO20231029: not different yields from different parts of fields?
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "48.01"
}
],
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\Downloads\
"CropYear": 2022,
//geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North)
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "test_Potato_ZeroFertilizer_Consumption_Clay",
//Note when you run the FarmmapsKPI project, somewhere to your C:\git\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\ directory, files named like this are written:
//'Settings_aardappelveld_test_Potato_ZeroFertilizer.json', where 'aardappelveld_test_Potato_ZeroFertilizer.json' is your fieldName (see below)
//1 useExistingCropfieldWithChildren = false -> create new
//2 useExistingCropfieldWithChildren = true && CropfieldItemCode = "" or absent -> read fieldName (see below) -> read all codes from settings json file
//3 useExistingCropfieldWithChildren = true && CropfieldItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> if you have in your account already an existing cropfield then use that
"CropfieldItemCode": "", // could contain for example this: "abae97f89f3c4ac08953b1b8bea9f076" if this is an exisiting CropfieldItemCode in your account.
//And then if useExistingCropfieldWithChildren = true, this would be used.
"dataCropfield": {
//"area": 4.22, //Leave empty, KPI app will calculate it from geometry
"final": true, //always true
"soilCode": "7", //From codelist CL405. Can no longer be omitted
"soilName": "Clay", //From codelist CL405
"cropTypeCode": "1010101", //From codelist CL263
"cropTypeName": "Potato", //From codelist CL263
"productionPurposeCode": "003", //From codelist CL251. For testing, see case with consumption & starch potato
"productionPurposeName": "consumption" //From codelist CL251
},
"CropRecordingItemCode": "", // could contain for example this: "314aa1b6480b493ba28a5f55039a01d4" if this is the CropRecordingItemCode of the provided CropfieldItemCode. And then if useExistingCropfieldWithChildren = true, this would be used
"OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used
"dataOperations": [], //leaving the operations empty means no fertilizer is applied
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
//PO20231029: not different yields from different parts of fields?
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "48.01"
}
],
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\Downloads\
"CropYear": 2022,
//geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North)
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "test_Potato_ZeroFertilizer_Starch_Sand",
//Note when you run the FarmmapsKPI project, somewhere to your C:\git\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\ directory, files named like this are written:
//'Settings_aardappelveld_test_Potato_ZeroFertilizer.json', where 'aardappelveld_test_Potato_ZeroFertilizer.json' is your fieldName (see below)
//1 useExistingCropfieldWithChildren = false -> create new
//2 useExistingCropfieldWithChildren = true && CropfieldItemCode = "" or absent -> read fieldName (see below) -> read all codes from settings json file
//3 useExistingCropfieldWithChildren = true && CropfieldItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> if you have in your account already an existing cropfield then use that
"CropfieldItemCode": "", // could contain for example this: "abae97f89f3c4ac08953b1b8bea9f076" if this is an exisiting CropfieldItemCode in your account.
//And then if useExistingCropfieldWithChildren = true, this would be used.
"dataCropfield": {
//"area": 4.22, //Leave empty, KPI app will calculate it from geometry
"final": true, //always true
"soilCode": "1", //From codelist CL405. Can be no longer be omitted
"soilName": "Sand",
"cropTypeCode": "1010101", //From codelist CL263
"cropTypeName": "Potato", //From codelist CL263
"productionPurposeCode": "002", //From codelist CL251. For testing, see case with consumption & starch potato
"productionPurposeName": "starch" //From codelist CL251
},
"CropRecordingItemCode": "", // could contain for example this: "314aa1b6480b493ba28a5f55039a01d4" if this is the CropRecordingItemCode of the provided CropfieldItemCode. And then if useExistingCropfieldWithChildren = true, this would be used
"OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used
"dataOperations": [], //leaving the operations empty means no fertilizer is applied
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
//PO20231029: not different yields from different parts of fields?
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "48.01"
}
],
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\Downloads\
"CropYear": 2022,
//geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North)
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "aardappelveld_test_Potato_cattlemanure144kgnha_plusUrea92kgNha",
"CropfieldItemCode": "",
"dataCropfield": {
//"area": 4.22, //Leave empty, KPI app will calculate it from geometry
"final": true, //always true
"soilCode": "5", //From codelist CL405. Can be no longer be omitted
"soilName": "Loam", //From codelist CL405.
"cropTypeCode": "1010101", //From codelist CL263
"cropTypeName": "Potato", //From codelist CL263
//"rootDepthMax": 45, //not needed for KPI calculation, but shown here to know this is a possible property
//"emergenceDate": "2022-05-16T00:00:00", //not needed for KPI calculation, but shown here to know this is a possible property
"productionPurposeCode": "003", //From codelist CL251. Can be omitted if unknown
"productionPurposeName": "consumption" //From codelist CL251. Can be omitted if unknown
},
"CropRecordingItemCode": "",
"OperationItemCodes": [],
"dataOperations": [
{
//"area": "0.08", //if leave empty then write code to fill in value from geometry (operation applied to whole field). Fill in different value if operation applied to part of the field (e.g. in case of variable rate application, VRA)
"contractor": false,
"designator": "Kunstmest strooien", //refers to codelist CL127 with operation methods
"from": "2022-05-23T11:34:00",
"method": "70400", //refers to codelist CL127 with operation methods
"n": "92", //refers to codelist CL022 with fertilizer types & npk contents
"name": "Kunstmest strooien", //refers to codelist CL127 with operation methods
"product": "7360", //refers to codelist CL022 with fertilizer types
//"type": "MAN", //indicates wether the fertilization is anorganic (MAN) or organic (MOR)
"quantity": "200",
//"status": "3", // refers to codelist CL256. where 3 stand for completed. The status does not matter and is not used in the KPI calculations
"operationCode": "7", // refers to codelist CL018 consisting of main catergorie of operations. Code 7 stands for fertilization
"to": "2022-05-23T12:34:00",
"unit": "kg/ha",
"unitCode": "KGMHAR"
},
{
"k": "201.6",
"n": "144",
"p": "60.8",
"to": "2022-04-19T09:19:00",
//"area": "0.08", //if leave empty then write code to fill in value from geometry (operation applied to whole field). Fill in different value if operation applied to part of the field (e.g. in case of variable rate application, VRA)
"from": "2022-04-19T08:19:00",
"name": "Injecteren", //refers to codelist CL127 with operation methods
"unit": "kg/ha",
"method": "70700", //refers to codelist CL127 with operation methods
//"status": "3", // refers to codelist CL256. where 3 stand for completed. The status does not matter and is not used in the KPI calculations
"operationCode": "7", // refers to codelist CL018 consisting of main catergorie of operations. Code 7 stands for fertilization
"product": "2329", //refers to codelist CL022 with fertilizer types
//"type": "MAN",//indicates wether the fertilization is anorganic (MAN) or organic (MOR)
"quantity": "32000",
"unitCode": "KGMHAR",
"contractor": false,
"designator": "Injecteren"
}
],
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "48.01"
}
],
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\
"CropYear": 2022,
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "aardappelveld_test_Potato_Urea92kgNha",
"CropfieldItemCode": "",
"dataCropfield": {
//"area": 4.22, //Leave empty, KPI app will calculate it from geometry
"final": true, //always true
"soilCode": "5", //From codelist CL405. Can be no longer be omitted
"soilName": "Loam", //From codelist CL405.
"cropTypeCode": "1010101", //From codelist CL263
"cropTypeName": "Potato", //From codelist CL263
//"rootDepthMax": 45, //not needed for KPI calculation, but shown here to know this is a possible property
//"emergenceDate": "2022-05-16T00:00:00", //not needed for KPI calculation, but shown here to know this is a possible property
"productionPurposeCode": "003", //From codelist CL251. Can be omitted if unknown
"productionPurposeName": "consumption" //From codelist CL251. Can be omitted if unknown
},
"CropRecordingItemCode": "",
"OperationItemCodes": [],
"dataOperations": [
{
//"area": "0.08", //if leave empty then write code to fill in value from geometry (operation applied to whole field). Fill in different value if operation applied to part of the field (e.g. in case of variable rate application, VRA)
"contractor": false,
"designator": "Kunstmest strooien", //refers to codelist CL127 with operation methods
"from": "2022-05-23T11:34:00",
"method": "70400", //refers to codelist CL127 with operation methods
"n": "92",
"name": "Kunstmest strooien", //refers to codelist CL127 with operation methods
"product": "7360", //refers to codelist CL022 with fertilizer types
"quantity": "200",
//"status": "3", // refers to codelist CL256. where 3 stand for completed. The status does not matter and is not used in the KPI calculations
"operationCode": "7", // refers to codelist CL018 consisting of main catergorie of operations. Code 7 stands for fertilization
"to": "2022-05-23T12:34:00",
"unit": "kg/ha",
"unitCode": "KGMHAR"
}
],
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "48.01"
}
],
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\
"CropYear": 2022,
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "aardappelveld_test_Potato_Urea92kgNha_ZuidLimburg",
"CropfieldItemCode": "",
"dataCropfield": {
//"area": 4.22, //Leave empty, KPI app will calculate it from geometry
"final": true, //always true
"soilCode": "5", //From codelist CL405. Can be no longer be omitted
"soilName": "Loam", //From codelist CL405.
"cropTypeCode": "1010101", //From codelist CL263
"cropTypeName": "Potato", //From codelist CL263
//"rootDepthMax": 45, //not needed for KPI calculation, but shown here to know this is a possible property
//"emergenceDate": "2022-05-16T00:00:00", //not needed for KPI calculation, but shown here to know this is a possible property
"productionPurposeCode": "003", //From codelist CL251. Can be omitted if unknown
"productionPurposeName": "consumption" //From codelist CL251. Can be omitted if unknown
},
"CropRecordingItemCode": "",
"OperationItemCodes": [],
"dataOperations": [
{
//"area": "0.08", //if leave empty then write code to fill in value from geometry (operation applied to whole field). Fill in different value if operation applied to part of the field (e.g. in case of variable rate application, VRA)
"contractor": false,
"designator": "Kunstmest strooien", //refers to codelist CL127 with operation methods
"from": "2022-05-23T11:34:00",
"method": "70400", //refers to codelist CL127 with operation methods
"n": "92",
"name": "Kunstmest strooien", //refers to codelist CL127 with operation methods
//"status": "3", // refers to codelist CL256. where 3 stand for completed. The status does not matter and is not used in the KPI calculations
"operationCode": "7", // refers to codelist CL018 consisting of main catergorie of operations. Code 7 stands for fertilization
"product": "7360", //refers to codelist CL022 with fertilizer types
"quantity": "200",
"to": "2022-05-23T12:34:00",
"unit": "kg/ha",
"unitCode": "KGMHAR"
}
],
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "48.01"
}
],
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\
"CropYear": 2022,
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.900,
50.800
],
[
5.901,
50.800
],
[
5.901,
50.801
],
[
5.900,
50.801
],
[
5.900,
50.800
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "caseQuoteNnotProvidedInDataOperations",
"CropfieldItemCode": "",
"dataCropfield": {
"soilCode": "1", //From codelist CL405. Can be no longer be omitted
"soilName": "Sand",
//"area": 4.22, //Leave empty, KPI app will calculate it from geometry
"final": true, //always true
"cropTypeCode": "1010101", //From codelist CL263
"cropTypeName": "Potato", //From codelist CL263
//"rootDepthMax": 45, //not needed for KPI calculation, but shown here to know this is a possible property
//"emergenceDate": "2022-05-16T00:00:00", //not needed for KPI calculation, but shown here to know this is a possible property
"productionPurposeCode": "003", //From codelist CL251. Can be omitted if unknown
"productionPurposeName": "consumption" //From codelist CL251. Can be omitted if unknown
},
"CropRecordingItemCode": "",
"OperationItemCodes": [],
"dataOperations": [
{
//"area": "0.08", //if leave empty then write code to fill in value from geometry (operation applied to whole field). Fill in different value if operation applied to part of the field (e.g. in case of variable rate application, VRA)
"contractor": false,
"designator": "Kunstmest strooien", //refers to codelist CL127 with operation methods
"from": "2022-05-23T11:34:00",
"method": "70400", //refers to codelist CL127 with operation methods
//"n": "92",
"name": "Kunstmest strooien", //refers to codelist CL127 with operation methods
//"status": "3", // refers to codelist CL256. where 3 stand for completed. The status does not matter and is not used in the KPI calculations
"operationCode": "7", // refers to codelist CL018 consisting of main catergorie of operations. Code 7 stands for fertilization
"product": "7360", //refers to codelist CL022 with fertilizer types
"quantity": "200",
"to": "2022-05-23T12:34:00",
"unit": "kg/ha",
"unitCode": "KGMHAR"
}
],
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "48.01"
}
],
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\
"CropYear": 2022,
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "examplePesticide_11767N",
"CropfieldItemCode": "", // could contain for example this: "abae97f89f3c4ac08953b1b8bea9f076" if this is an exisiting CropfieldItemCode in your account.
"dataCropfield": {
"soilCode": "1", //From codelist CL405. Can be no longer be omitted
"soilName": "Sand",
"final": true, //always true
"cropTypeCode": "1010101", //From codelist CL263
"cropTypeName": "Potato", //From codelist CL263
"productionPurposeCode": "003", //From codelist CL251. Can be omitted if unknown
"productionPurposeName": "consumption" //From codelist CL251. Can be omitted if unknown
},
"CropRecordingItemCode": "", // could contain for example this: "314aa1b6480b493ba28a5f55039a01d4" if this is the CropRecordingItemCode of the provided CropfieldItemCode. And then if useExistingCropfieldWithChildren = true, this would be used
"OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used
"dataOperations": [
{
"to": "2022-07-13T17:27:00",
"from": "2022-07-13T16:27:00",
"name": "Volveld spuiten (3/3)", //refers to codelist CL127 with operation methods
"method": "80200", //refers to codelist CL127 with operation methods
//"status": "3", // refers to codelist CL256. where 3 stand for completed. The status does not matter and is not used in the KPI calculations
"operationCode": "8", // refers to codelist CL018 consisting of main catergorie of operations. Code 8 stands for crop protection
"products": [
{
"product": "11767 N", //CTBG code, lookup via CTBG API. Important: with space N",
"quantity": "1.25",
"unitCode": "LTRHAR"
//"designator": "Amistar"
}
]
}
],
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
"code": "860619",
"label": "cropyield",
"value": "48.01"
}
],
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\Downloads\
"CropYear": 2022,
//geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North)
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "doperwt_heleJaar",
"CropfieldItemCode": "",
"dataCropfield": {
"soilCode": "1", //From codelist CL405. Can be no longer be omitted
"soilName": "Sand",
"final": true, //always true
"cropTypeCode": "1030101", //From codelist CL263
"cropTypeName": "Garden pea" //From codelist CL263
},
"CropRecordingItemCode": "",
"OperationItemCodes": [],
"dataOperations": [],
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "9.58" //CBS: https://www.cbs.nl/nl-nl/cijfers/detail/37738, 2022: 40.4 Mkg / 4216 ha = 40400 / 4216
}
],
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\
"CropYear": 2022,
//"StartDate": "2022-04-15", //PO20231108: StartDate & EndDate important for legumes, where Nitrogen fixation depends on number of days from start to end. More days = more N fixation
//"EndDate": "2022-07-30", // if StartDate & EndDate left empty then whole year from cropYear
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "doperwt_groeiperiode",
"CropfieldItemCode": "",
"dataCropfield": {
"soilCode": "1", //From codelist CL405. Can be no longer be omitted
"soilName": "Sand",
"final": true, //always true
"cropTypeCode": "1030101", //From codelist CL263
"cropTypeName": "Garden pea" //From codelist CL263
},
"CropRecordingItemCode": "",
"OperationItemCodes": [],
"dataOperations": [],
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "9.58" //CBS: https://www.cbs.nl/nl-nl/cijfers/detail/37738, 2022: 40.4 Mkg / 4216 ha = 40400 / 4216
}
],
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\
"CropYear": 2022,
"StartDate": "2022-04-15", //PO20231108: StartDate & EndDate important for legumes, where Nitrogen fixation depends on number of days from start to end. More days = more N fixation
"EndDate": "2022-07-30", // if StartDate & EndDate left empty then whole year from cropYear
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "test_WinterWheat_DefaultStrawRemainsInField",
//Note when you run the FarmmapsKPI project, somewhere to your C:\git\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\ directory, files named like this are written:
//'Settings_aardappelveld_test_Potato_ZeroFertilizer.json', where 'aardappelveld_test_Potato_ZeroFertilizer.json' is your fieldName (see below)
//1 useExistingCropfieldWithChildren = false -> create new
//2 useExistingCropfieldWithChildren = true && CropfieldItemCode = "" or absent -> read fieldName (see below) -> read all codes from settings json file
//3 useExistingCropfieldWithChildren = true && CropfieldItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> if you have in your account already an existing cropfield then use that
"CropfieldItemCode": "", // could contain for example this: "abae97f89f3c4ac08953b1b8bea9f076" if this is an exisiting CropfieldItemCode in your account.
//And then if useExistingCropfieldWithChildren = true, this would be used.
"dataCropfield": {
//"area": 4.22, //Leave empty, KPI app will calculate it from geometry
"final": true, //always true
"soilCode": "1", //From codelist CL405. Can be no longer be omitted
"soilName": "Sand",
"cropTypeCode": "1020101", //From codelist CL263
"cropTypeName": "Winter wheat" //From codelist CL263
},
"CropRecordingItemCode": "", // could contain for example this: "314aa1b6480b493ba28a5f55039a01d4" if this is the CropRecordingItemCode of the provided CropfieldItemCode. And then if useExistingCropfieldWithChildren = true, this would be used
"OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used
"dataOperations": [], //leaving the operations empty means no fertilizer is applied
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
//PO20231029: not different yields from different parts of fields?
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "10.0"
}
],
//"DownloadFolder": "Downloads", //"C:\\hugoschrererdir\\kpidir\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\Downloads\
"CropYear": 2022,
//geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North)
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "test_WinterWheat_StrawRemovedFromField",
//Note when you run the FarmmapsKPI project, somewhere to your C:\git\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\ directory, files named like this are written:
//'Settings_aardappelveld_test_Potato_ZeroFertilizer.json', where 'aardappelveld_test_Potato_ZeroFertilizer.json' is your fieldName (see below)
//1 useExistingCropfieldWithChildren = false -> create new
//2 useExistingCropfieldWithChildren = true && CropfieldItemCode = "" or absent -> read fieldName (see below) -> read all codes from settings json file
//3 useExistingCropfieldWithChildren = true && CropfieldItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> if you have in your account already an existing cropfield then use that
"CropfieldItemCode": "", // could contain for example this: "abae97f89f3c4ac08953b1b8bea9f076" if this is an exisiting CropfieldItemCode in your account.
//And then if useExistingCropfieldWithChildren = true, this would be used.
"dataCropfield": {
//"area": 4.22, //Leave empty, KPI app will calculate it from geometry
"final": true, //always true
"soilCode": "1", //From codelist CL405. Can be no longer be omitted
"soilName": "Sand",
"cropTypeCode": "1020101", //From codelist CL263
"cropTypeName": "Winter wheat" //From codelist CL263
},
"CropRecordingItemCode": "", // could contain for example this: "314aa1b6480b493ba28a5f55039a01d4" if this is the CropRecordingItemCode of the provided CropfieldItemCode. And then if useExistingCropfieldWithChildren = true, this would be used
"OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used
"dataOperations": [], //leaving the operations empty means no fertilizer is applied
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
//PO20231029: not different yields from different parts of fields?
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "10.0"
},
{
"code": "fm009", //TODO: which codelist?
"label": "strawyield",
"value": "6.8"
}
],
"CropYear": 2022,
//geometryJson = polygon of location of the cropfield, coordinates in LON,LAT (LON: decimal degrees East, LAT: decimal degrees North)
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
},
{
"useExistingCropfieldWithChildren": false,
"deleteNewlyCreatedAfterCalc": true,
"fieldName": "test_WinterWheat_greenmanure",
//Note when you run the FarmmapsKPI project, somewhere to your C:\git\FarmMapsApiClient_KB34_MAST\FarmmapsKPI\bin\Debug\netcoreapp3.1\ directory, files named like this are written:
//'Settings_aardappelveld_test_Potato_ZeroFertilizer.json', where 'aardappelveld_test_Potato_ZeroFertilizer.json' is your fieldName (see below)
//1 useExistingCropfieldWithChildren = false -> create new
//2 useExistingCropfieldWithChildren = true && CropfieldItemCode = "" or absent -> read fieldName (see below) -> read all codes from settings json file
//3 useExistingCropfieldWithChildren = true && CropfieldItemCode like "deb48a74c5b54299bb852f17288010e9" in KPIinput -> if you have in your account already an existing cropfield then use that
"CropfieldItemCode": "", // could contain for example this: "abae97f89f3c4ac08953b1b8bea9f076" if this is an exisiting CropfieldItemCode in your account.
//And then if useExistingCropfieldWithChildren = true, this would be used.
"dataCropfield": {
//"area": 4.22, //Leave empty, KPI app will calculate it from geometry
"final": true, //always true
"soilCode": "1", //From codelist CL405. Can be no longer be omitted
"soilName": "Sand",
"cropTypeCode": "1020101", //From codelist CL263
"cropTypeName": "Winter wheat" //From codelist CL263
},
"CropRecordingItemCode": "", // could contain for example this: "314aa1b6480b493ba28a5f55039a01d4" if this is the CropRecordingItemCode of the provided CropfieldItemCode. And then if useExistingCropfieldWithChildren = true, this would be used
"OperationItemCodes": [], // could contain for example this: ["4d1a6f28ea3f414180663baa4b08c60f"] or ["4d1a6f28ea3f414180663baa4b08c60f","21e08386f0454ad79acfebf78649d59b"] if these are the operations of the provided CropRecordingItemCode. And then if useExistingCropfieldWithChildren = true, these would be used
"dataOperations": [],
"CropfieldCharacteristicItemCode": "",
"DataCropfieldCharacteristics": [
{
"code": "860619", //From codelist CL265. 860619 refers to cropyield in ton/ha
"label": "cropyield",
"value": "10"
},
{
"code": "501505", //From codelist CL265. 501505 refers to green manure after main crop.
"label": "cropgreenmanureaftercultivation",
"value": "1040102", // Code is from CL263. You can put any CL263 crop here. However, the KPI app only works with a limited selection of greenmanure crops, see CL104 for the names.
//"cropHeight": 100, //optional input. Height of greemmanure in cm.
//"plantingDate": "2022-08-01T12:34:00" // optional input. Plantingsdate of greenmanure. required layout "2022-07-23T12:34:00".
}
],
"CropYear": 2022,
"geometryJson": {
"type": "Polygon",
"coordinates": [
[
[
5.5945257993548765,
52.57080744107003
],
[
5.598645994070678,
52.571540800206236
],
[
5.599381743127071,
52.57012773140724
],
[
5.595408698222548,
52.56968054825188
],
[
5.5945257993548765,
52.57080744107003
]
]
]
}
}
]

27
FarmmapsKPI/KPIService.cs Normal file
View File

@@ -0,0 +1,27 @@
using System;
using System.Globalization;
using System.Threading.Tasks;
using FarmmapsApi.Models;
using FarmmapsApi.Services;
using FarmmapsKPI.Models;
using Microsoft.Extensions.Logging;
using static FarmmapsApi.Extensions;
using static FarmmapsApiSamples.Constants;
namespace FarmmapsKPI
{
public class KPIService
{
private readonly ILogger<KPIService> _logger;
private readonly FarmmapsApiService _farmmapsApiService;
private readonly GeneralService _generalService;
public KPIService(ILogger<KPIService> logger, FarmmapsApiService farmmapsApiService,
GeneralService generalService)
{
_logger = logger;
_farmmapsApiService = farmmapsApiService;
_generalService = generalService;
}
}
}

View File

@@ -0,0 +1,28 @@
KPIid,KPIvariable,Description,Calculated,KPItargetvalue,KPIthresholdValue
A1,yield,observed yield,User input,target value as in benchmark value for same crop in same region. E.g. cropyield target is from Central Bureau of Statistics (CBS) for same crop in region in which the cropfield (geometry) is located.,No threshold for this KPI.
A1,strawYield,straw yield; value 0 or not filled in = straw remains in field; value > 0 means straw was exported,User input,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
B1,nitrogen,Nitrogen surplus = N artifical fertilizer + N manure+ N atmospheric deposition + N fixation by crop + N from seed potatoes - N removal through harvested product. ,Calculated KPI internal model & parameters and from user input: yield and fertilizer/manure applications.,The target value depends on the soil type. To calculate the threshold and target values data from CBS and RIVM are used. The same calculation method is also used in biodiversiteitsmonitoring akkerbouw (https://www.bo-akkerbouw.nl/kennis-en-innovatie/pps-biodiversiteitsmonitor-akkerbouw).,The threshold value depends on soil type and groundwater levels. To calculate the threshold and target values data from CBS and RIVM are used. The same calculation method is also used in biodiversiteitsmonitoring akkerbouw (https://www.bo-akkerbouw.nl/kennis-en-innovatie/pps-biodiversiteitsmonitor-akkerbouw).
B1,nHarvestedKgHa, N removal through harvested product. ,Calculated KPI internal model & parameters and from user input: yield.,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
B1,nHarvestedStrawKgHa, N removal through harvested product. ,Calculated KPI internal model & parameters and from user input: yieldStraw.,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
B1,nFixationNKgHa, N fixated by crop (legumes only). ,Calculated KPI internal model & parameters and from user input: planting date,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
B1,nDepositionNKgHa, N deposition,Based on RIVM maps. Value depens on location,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
B1,nFertilizerNKgHa, N from artifical fertilizers and manure.,KPI internal model & parameters and from user input: fertilizer/manure applications.,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
B1,sowPlantingNKgHa, N from seed potatoes (potatoes only). ,Calculated KPI internal model & parameters and from user input: amount of planted seed potatoes,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
B2,phosphate,Phosphate surplus = P fertilizer + P from seed potatoes - P removal through harvested product. ,Calculated KPI internal model & parameters and from user input: yield and fertilizer applications ,The phosphate target value is set at 20 kg/ha ,No threshold for this KPI.
B2,pHarvestedKgHa, P2O5 removal through harvested product. ,Calculated KPI internal model & parameters and from user input: yield,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
B2,pHarvestedStrawKgHa, P2O5 removal through harvested product. ,Calculated KPI internal model & parameters and from user input: yieldStraw,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
B2,pFertillizerPKgHa, P2O5 from artifical fertilizers and manure.,Calculated KPI internal model & parameters and from user input: fertilizer/manure applications.,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
B2,sowPlantingPKgHa, P2O5 from seeds potatoes (potatoes only). ,Calculated KPI internal model & parameters and from user input: amount of planted seed potatoes,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
C1,effective organic matter supply,"Organic matter supply = Organic matter from manure + Crop residues to soil + organic matter from green manure. ""Effective"" means netto, after correction for carbon respiration by soil microbial activity",Calculated KPI internal model & parameters and from user input: yield and manure applications.,The target value for this KPI is the amount of EOM that companies with Goede Landbouwpraktijk supply (2500 kg EOM/ha/year). ,The threshold value is 2000 kg EOM/ha/year. This value comes from van Doorn et al. (2022) which states that on average 2000 kg of EOM/ha degrades on Dutch agricultural land. This is the also the threshold value from biodiversiteitsmonitoring akkerbouw (https://www.bo-akkerbouw.nl/kennis-en-innovatie/pps-biodiversiteitsmonitor-akkerbouw)
C1,fertilizerEom,"Effective organic matter added through fertilizer (animal manure, compost, etc). ",Calculated KPI internal model & parameters and from user input: manure applications.,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
C1,greenManureEom,Effective organic matter added through green manure (also called cover crop). ,Calculated KPI internal model & parameters and from user input: cover crop.,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
C1,cropLeftoversEom,Effective organic matter added through crop residues of main product and (when relevant) straw.,Calculated KPI internal model & parameters.,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
D1,pesticides,"kg/ha of active ingredient. Sum over kg a.i. of the different crop protection agents applied, with concentration (kg a.i. / kg or litre) of crop protection agents ",Retrieved from CTBG,The target value fort his KPI is to reduce pesticide use to 50% of the amount used in the Netherlands during 2020. Data for 2020 is obtained from CBS statline ,No threshold for this KPI.
E1,mpb,"milieubelastingspunten. For each pesticide applied show 3 sub-mbp's: aquaticLife, groundWater, soilLife",Retrieved from CTBG,"0 applications with exceedances of either the target MBP or risks. MBP's consist of three categories (groundwater, soil life, and aquatic life). An value of <100 in either or these categories counts as exceedance. Each application of pesticides cannot have more then one exceedance for MBP. Risks consist of two categories (natural enemies and pollinators), a value of B or C in either category counts as exceedance. Each application of pesticides cannot have more then one exceedance for risks. Values and methodology come from Environmental Yardstick for Pesticides (https://www.milieumeetlat.nl/). The same calculation method is also used in biodiversiteitsmonitoring akkerbouw (https://www.bo-akkerbouw.nl/kennis-en-innovatie/pps-biodiversiteitsmonitor-akkerbouw).","0 applications with exceedances of either the target MBP or risks. MBP's consist of three categories (groundwater, soil life, and aquatic life). An value of <10 in either or these categories counts as exceedance. Each application of pesticides cannot have more then one exceedance for MBP. Risks consist of two categories (natural enemies and pollinators), a value of B or C in either category counts as exceedance. Each application of pesticides cannot have more then one exceedance for risks. Values and methodology come from Environmental Yardstick for Pesticides (https://www.milieumeetlat.nl/). The same calculation method is also used in biodiversiteitsmonitoring akkerbouw (https://www.bo-akkerbouw.nl/kennis-en-innovatie/pps-biodiversiteitsmonitor-akkerbouw)."
F1,greenness,time of year that the field was covered. ,Based on NDVI data from AgroDataCube.,Target value is 75%.,Threshold value is 25%.
F2,rotationindex,index of diversity of crops over time. ,Calculated in AgroDataCube,Target value is 75%.,Threshold value is 25%.
G1,ammonia emissions,"ammonia emissions from crop residues, green manure, artificial fertilizers and organic fertilizers.",Calculated KPI internal model & parameters and from user input: fertilizer/manure applications.,There is not target value yet for this KPI. Currently has a dummy value of 9999.,There is not target value yet for this KPI. Currently has a dummy value of 9999.
G1,Manure,ammonia emissions from manure.,Calculated KPI internal model & parameters and from user input: manure applications.,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
G1,GreenManure,ammonia emissions from green manure (also called cover crop). ,Calculated KPI internal model & parameters.,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
G1,CropResidues,ammonia emissions from crop residues. ,Calculated KPI internal model & parameters.,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
G1,ArtificialFertilize,ammonia emissions from artificial fertilizers ,Calculated KPI internal model & parameters and from user input: artificial fertilizer applications.,there are no target values for individual compenets of KPI's,there are no threshold values for individual compenets of KPI's
1 KPIid KPIvariable Description Calculated KPItargetvalue KPIthresholdValue
2 A1 yield observed yield User input target value as in benchmark value for same crop in same region. E.g. cropyield target is from Central Bureau of Statistics (CBS) for same crop in region in which the cropfield (geometry) is located. No threshold for this KPI.
3 A1 strawYield straw yield; value 0 or not filled in = straw remains in field; value > 0 means straw was exported User input there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
4 B1 nitrogen Nitrogen surplus = N artifical fertilizer + N manure+ N atmospheric deposition + N fixation by crop + N from seed potatoes - N removal through harvested product. Calculated KPI internal model & parameters and from user input: yield and fertilizer/manure applications. The target value depends on the soil type. To calculate the threshold and target values data from CBS and RIVM are used. The same calculation method is also used in biodiversiteitsmonitoring akkerbouw (https://www.bo-akkerbouw.nl/kennis-en-innovatie/pps-biodiversiteitsmonitor-akkerbouw). The threshold value depends on soil type and groundwater levels. To calculate the threshold and target values data from CBS and RIVM are used. The same calculation method is also used in biodiversiteitsmonitoring akkerbouw (https://www.bo-akkerbouw.nl/kennis-en-innovatie/pps-biodiversiteitsmonitor-akkerbouw).
5 B1 nHarvestedKgHa N removal through harvested product. Calculated KPI internal model & parameters and from user input: yield. there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
6 B1 nHarvestedStrawKgHa N removal through harvested product. Calculated KPI internal model & parameters and from user input: yieldStraw. there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
7 B1 nFixationNKgHa N fixated by crop (legumes only). Calculated KPI internal model & parameters and from user input: planting date there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
8 B1 nDepositionNKgHa N deposition Based on RIVM maps. Value depens on location there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
9 B1 nFertilizerNKgHa N from artifical fertilizers and manure. KPI internal model & parameters and from user input: fertilizer/manure applications. there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
10 B1 sowPlantingNKgHa N from seed potatoes (potatoes only). Calculated KPI internal model & parameters and from user input: amount of planted seed potatoes there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
11 B2 phosphate Phosphate surplus = P fertilizer + P from seed potatoes - P removal through harvested product. Calculated KPI internal model & parameters and from user input: yield and fertilizer applications The phosphate target value is set at 20 kg/ha  No threshold for this KPI.
12 B2 pHarvestedKgHa P2O5 removal through harvested product. Calculated KPI internal model & parameters and from user input: yield there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
13 B2 pHarvestedStrawKgHa P2O5 removal through harvested product. Calculated KPI internal model & parameters and from user input: yieldStraw there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
14 B2 pFertillizerPKgHa P2O5 from artifical fertilizers and manure. Calculated KPI internal model & parameters and from user input: fertilizer/manure applications. there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
15 B2 sowPlantingPKgHa P2O5 from seeds potatoes (potatoes only). Calculated KPI internal model & parameters and from user input: amount of planted seed potatoes there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
16 C1 effective organic matter supply Organic matter supply = Organic matter from manure + Crop residues to soil + organic matter from green manure. "Effective" means netto, after correction for carbon respiration by soil microbial activity Calculated KPI internal model & parameters and from user input: yield and manure applications. The target value for this KPI is the amount of EOM that companies with ‘ Goede Landbouwpraktijk’ supply (2500 kg EOM/ha/year). The threshold value is 2000 kg EOM/ha/year. This value comes from van Doorn et al. (2022) which states that on average 2000 kg of EOM/ha degrades on Dutch agricultural land. This is the also the threshold value from biodiversiteitsmonitoring akkerbouw (https://www.bo-akkerbouw.nl/kennis-en-innovatie/pps-biodiversiteitsmonitor-akkerbouw)
17 C1 fertilizerEom Effective organic matter added through fertilizer (animal manure, compost, etc). Calculated KPI internal model & parameters and from user input: manure applications. there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
18 C1 greenManureEom Effective organic matter added through green manure (also called cover crop). Calculated KPI internal model & parameters and from user input: cover crop. there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
19 C1 cropLeftoversEom Effective organic matter added through crop residues of main product and (when relevant) straw. Calculated KPI internal model & parameters. there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
20 D1 pesticides kg/ha of active ingredient. Sum over kg a.i. of the different crop protection agents applied, with concentration (kg a.i. / kg or litre) of crop protection agents Retrieved from CTBG The target value fort his KPI is to reduce pesticide use to 50% of the amount used in the Netherlands during 2020. Data for 2020 is obtained from CBS statline No threshold for this KPI.
21 E1 mpb milieubelastingspunten. For each pesticide applied show 3 sub-mbp's: aquaticLife, groundWater, soilLife Retrieved from CTBG 0 applications with exceedances of either the target MBP or risks. MBP's consist of three categories (groundwater, soil life, and aquatic life). An value of <100 in either or these categories counts as exceedance. Each application of pesticides cannot have more then one exceedance for MBP. Risks consist of two categories (natural enemies and pollinators), a value of B or C in either category counts as exceedance. Each application of pesticides cannot have more then one exceedance for risks. Values and methodology come from Environmental Yardstick for Pesticides (https://www.milieumeetlat.nl/). The same calculation method is also used in biodiversiteitsmonitoring akkerbouw (https://www.bo-akkerbouw.nl/kennis-en-innovatie/pps-biodiversiteitsmonitor-akkerbouw). 0 applications with exceedances of either the target MBP or risks. MBP's consist of three categories (groundwater, soil life, and aquatic life). An value of <10 in either or these categories counts as exceedance. Each application of pesticides cannot have more then one exceedance for MBP. Risks consist of two categories (natural enemies and pollinators), a value of B or C in either category counts as exceedance. Each application of pesticides cannot have more then one exceedance for risks. Values and methodology come from Environmental Yardstick for Pesticides (https://www.milieumeetlat.nl/). The same calculation method is also used in biodiversiteitsmonitoring akkerbouw (https://www.bo-akkerbouw.nl/kennis-en-innovatie/pps-biodiversiteitsmonitor-akkerbouw).
22 F1 greenness time of year that the field was covered. Based on NDVI data from AgroDataCube. Target value is 75%. Threshold value is 25%.
23 F2 rotationindex index of diversity of crops over time. Calculated in AgroDataCube Target value is 75%. Threshold value is 25%.
24 G1 ammonia emissions ammonia emissions from crop residues, green manure, artificial fertilizers and organic fertilizers. Calculated KPI internal model & parameters and from user input: fertilizer/manure applications. There is not target value yet for this KPI. Currently has a dummy value of 9999. There is not target value yet for this KPI. Currently has a dummy value of 9999.
25 G1 Manure ammonia emissions from manure. Calculated KPI internal model & parameters and from user input: manure applications. there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
26 G1 GreenManure ammonia emissions from green manure (also called cover crop). Calculated KPI internal model & parameters. there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
27 G1 CropResidues ammonia emissions from crop residues. Calculated KPI internal model & parameters. there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's
28 G1 ArtificialFertilize ammonia emissions from artificial fertilizers Calculated KPI internal model & parameters and from user input: artificial fertilizer applications. there are no target values for individual compenets of KPI's there are no threshold values for individual compenets of KPI's

View File

@@ -0,0 +1,26 @@
using System;
using Newtonsoft.Json.Linq;
namespace FarmmapsKPI.Models
{
public class KPIInput
{
public bool UseExistingCropfieldWithChildren { get; set; }
public bool DeleteNewlyCreatedAfterCalc { get; set; }
public string fieldName { get; set; }
public string CropfieldItemCode { get; set; }
public JObject DataCropfield { get; set; }
public string CropRecordingItemCode { get; set; }
public JObject DataCropRecording { get; set; }
public string[] OperationItemCodes { get; set; }
public JObject[] DataOperations { get; set; }
public string CropfieldCharacteristicItemCode { get; set; }
public JObject[] DataCropfieldCharacteristics { get; set; }
public string DownloadFolder { get; set; }
public int CropYear { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public JObject GeometryJson { get; set; }
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
namespace FarmmapsKPI.Models
{
public class KPIOutput
{
public string id { get; set; }
public KPIOutputData data { get; set; }
public string type { get; set; }
public string unit { get; set; }
public string value { get; set; }
public string duration { get; set; }
public string quantity { get; set; }
public string parentName { get; set; }
public string targetValue { get; set; }
public string thresholdValue { get; set; }
public List<string> A1elements; //TtD
public List<string> B1elements;
public List<string> B2elements;
public List<string> C1elements;
public List<string> G1elements; //TtD
public KPIOutput()
{
this.A1elements = new List<string>() { "yield", "strawYield" }; //TtD
this.B1elements = new List<string>() { "nHarvestedKgHa", "nHarvestedStrawKgHa", "nFixationNKgHa", "nDepositionNKgHa","nFertilizerNKgHa","sowPlantingNKgHa" }; //TtD
this.B2elements = new List<string>() { "pHarvestedKgHa", "pHarvestedStrawKgHa", "pFertillizerPKgHa", "sowPlantingPKgHa" }; //TtD
this.C1elements = new List<string>() { "fertilizerEom", "greenManureEom", "cropLeftoversEom" }; //TtD to do rename
this.G1elements = new List<string>() { "Manure", "GreenManure", "CropResidues", "ArtificialFertilize" }; //TtD
}
}
public class KPIOutputData
{
public string area { get; set; }
public string cropTypeCode { get; set; }
public string cropTypeName { get; set; }
public string yield { get; set; }
public string strawYield { get; set; }
public KPIelementsOfBalance values { get; set; }
public KPIenvironmentMeasureData[] environmentMeasureData { get; set; }
}
public class KPIenvironmentMeasureData
{
public string date { get; set; }
public string productCode { get; set; }
public string productName { get; set; }
public string quantity { get; set; }
public string unitCode { get; set; }
public string soilLife { get; set; }
public string aquaticLife { get; set; }
public string groundWater { get; set; }
}
public class KPIelementsOfBalance
{
public string yield { get; set; } //TtD
public string strawYield { get; set; } //TtD
public string nHarvestedKgHa { get; set; } //TtD
public string nHarvestedStrawKgHa { get; set; } //TtD
public string nFixationNKgHa { get; set; }
public string nDepositionNKgHa { get; set; }
public string nFertilizerNKgHa { get; set; }
public string sowPlantingNKgHa { get; set; }
public string pHarvestedKgHa { get; set; } //TtD
public string pHarvestedStrawKgHa { get; set; } //TtD
public string pFertillizerPKgHa { get; set; } //TtD
public string sowPlantingPKgHa { get; set; } //TtD
public string fertilizerEom { get; set; } //TtD
public string greenManureEom { get; set; } //TtD
public string cropLeftoversEom { get; set; } //TtD tamara: rename
public string Manure { get; set; } //TtD
public string GreenManure { get; set; } //TtD
public string CropResidues { get; set; } //TtD
public string ArtificialFertilize { get; set; } //TtD
}
}

View File

@@ -0,0 +1,11 @@
namespace FarmmapsKPI
{
public class Settings
{
public string CropfieldItemCode { get; set; }
public string CropRecordingItemCode { get; set; }
public string[] OperationItemCodes { get; set; }
public string CropfieldCharacteristicItemCode { get; set; }
}
}

21
FarmmapsKPI/Program.cs Normal file
View File

@@ -0,0 +1,21 @@
using System.Threading.Tasks;
using FarmmapsApi;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace FarmmapsKPI
{
class Program : FarmmapsProgram<KPIApplication>
{
private static async Task Main(string[] args)
{
await new Program().Start(args);
}
protected override void Configure(IServiceCollection serviceCollection)
{
serviceCollection.AddLogging()
.AddTransient<KPIService>();
}
}
}

66
FarmmapsKPI/TODO.txt Normal file
View File

@@ -0,0 +1,66 @@
TODO.txt
###################################################################################################
# 1. DONE
###################################################################################################
Laat de farmmapsKPI zelf maar uitzoeken wat de n-p gehaltes zijn:
a. We willen als input opgeven we hebben 400 kg/ha urea gegeven, of 32000 kg/ha runderdrijfmest.
Daarvoor wel de juiste gewas code opgeven -> zie onder, FarmmapsEditeeltList 263 gewassen
Daarvoor wel de juiste meststof code opgeven -> zie onder, FarmmapsEditeeltList 022 meststoffen
b. Check of de operation data een element <20>n<EFBFBD> bevat. Zoniet of als waarde 0, dan
i. Zoek onder de motorkap op: de omreken factor (bijv 200 kg/ha urea met 46% n -> 200*0.46 = 92 kg N/ha)
ii. Voeg die 92 toe aan de operation data ("n": 92)
c. Reken N surplus uit (KPI item id b1)
GEPARKEERD:
Want voor veel meststoffen is geen content bekend -> automatisch opzoeken zal in veel gevallen niet goed werken
Laat de gebruiker zelf maar de codelist CL022 raadplegen en omrekenen.
Nieuw project: FarmmapsEditeeltLists DONE
a. Why? Because
i. This is (1) so that we can at any time retrieve the most recent up-to-date list
ii. so that you can look up crops and fertilizer types and fill in KPIinput.json correctly
b. Download full list of items from vnd.farmmaps.itemtype.codelist.cl263 DONE
c. Write them to a csv file DONE
d. In any case following lists: 127 operations DONE; 022 meststoffen (fertilizer products) DONE; 263 gewassen DONE; 405 soilcode DONE
in which list the productionPurposeCode 251 DONE
Testing:
Effect of soiltype (e.g. different N concents in crop depending on soiltype? (CL405))
DONE (using KPIinput.json): same N balance, different target & threshold
Effect of location (e.g. different atmospheric N deposition).
DONE (using KPIinput.json): slightly different N balance
"DataCropfieldCharacteristic": {
"code": "860619", //PO20231004: so what does this code mean? Can we see the code list somewhere? COMPLETED code comes from codelist CL265. 860619 refers to cropyield in ton/ha
productionPurposeCode: different result depending on starch or consumption potato (different N contents in tubers)?
nContentFactor seems not to be adjusted by productionPurposeCode. Tamara check with Francisco
idem for pContentFactor
DONE (using KPIinput.json): surprisingly no effect?, format of the productionPurposeCode was wrong i.e was '002' instead of '2'. Format has been adjusted.
dataOperations: "operationCode": "7" & "8": DONE
a. which codelist? What does it mean? this refers to CL018 (bewerkinghoofdcaterogie), which contains information about the caterogie of the crop operations.
7 stands for fertilization while 8 refers to crop protection
b. using KPIinput.json: does it have an effect on KPI outcomes? YES
dataOperations: "status": "3": DONE
a. which codelist? What does it mean? this refers to CL256 (statusBewerking), which contains information about a crop operation has been planned, completed, cancelled etc. 3 refers to completed
b. using KPIinput.json: does it have an effect on KPI outcomes? NO, even without the status the crop operations is included in the KPI calculation.
As the status has no effect on the KPI calculations I have changed the lines about the status in the KPIinput.json file to comment
KPIelementsOfBalance: Tamara
a. define elements for C1 organic matter supply
b. for nitrogen B1 rename disposal to nHarvestedNKgHa COMPLETED
c. for phosporous B2 rename disposal to pHarvestedPKgHa COMPLETED
d. for phosporous B2 rename from pFertilizerNKgHa to pFertilizerPKgHa COMPLETED
e. idem sowPlantingNKgHa COMPLETED
f. add straw for N & P in output COMPLETED
g. add 2 examples in KPIinput.json: straw yes/no removed. Bijv. nStrawLeftInField EN nStrawRemoved COMPLETED
h. add amount of removed straw in A1 COMPLETED
i. update KPIdefinitions.csv COMPLETED
###################################################################################################
# 2. Pending
###################################################################################################
Testing:
KPIelementsOfBalance: Tamara
j. for C1 rename 'cropLeftoversEom' to 'cropResiduesEom' GEPARKEERD

View 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 ] } }
]
}

View File

@@ -1,819 +0,0 @@
{
"type": "FeatureCollection",
"name": "Scan_1_20190605",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4111546, 50.6406962 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.411151, 50.6406838 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4111456, 50.6406706 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4111371, 50.6406588 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4111243, 50.6406488 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4111111, 50.6406409 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4110933, 50.640633 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.411066, 50.6406243 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4110331, 50.6406135 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4109925, 50.640599 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4109546, 50.6405849 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4109156, 50.6405696 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4108766, 50.6405543 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4108366, 50.6405393 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.410795, 50.6405224 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.410755, 50.6405059 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4107166, 50.6404895 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4106803, 50.6404725 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4106436, 50.6404562 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4106086, 50.640439 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4105746, 50.64042 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4105415, 50.6404011 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4105085, 50.6403818 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4104761, 50.6403628 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4104435, 50.6403418 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4104118, 50.6403205 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4103781, 50.640299 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4103436, 50.6402766 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4103111, 50.6402551 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4102795, 50.6402326 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4102485, 50.6402087 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4102186, 50.6401853 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4101898, 50.6401623 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4101588, 50.6401392 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4101291, 50.6401161 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4100998, 50.640092 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4100715, 50.640068 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4100458, 50.6400443 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4100213, 50.6400205 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4099976, 50.6399958 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.409975, 50.6399706 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4099525, 50.6399454 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4099303, 50.6399205 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4099063, 50.6398954 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4098826, 50.6398705 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4098586, 50.639845 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4098345, 50.6398194 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4098135, 50.6397931 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4097948, 50.6397667 ] } },
{ "type": "Feature", "properties": { "IRMI": 17.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4097768, 50.6397403 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.409758, 50.6397135 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4097386, 50.6396868 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.40972, 50.6396595 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4097015, 50.6396328 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4096806, 50.639603 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4096585, 50.6395711 ] } },
{ "type": "Feature", "properties": { "IRMI": 17.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4096363, 50.6395391 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4096158, 50.6395081 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.409594, 50.639477 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4095721, 50.6394458 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4095503, 50.6394157 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4095271, 50.6393867 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.409503, 50.6393579 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4094768, 50.63933 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4094523, 50.6393026 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4094266, 50.639276 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4094006, 50.6392503 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4093726, 50.6392254 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4093451, 50.6392005 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4093161, 50.6391757 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4092858, 50.6391511 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4092555, 50.6391281 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4092253, 50.6391057 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4091955, 50.6390844 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4091661, 50.639067 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4091386, 50.6390513 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.409112, 50.6390361 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4090885, 50.6390235 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.409075, 50.6390138 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4090683, 50.6390033 ] } },
{ "type": "Feature", "properties": { "IRMI": 17.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4090598, 50.6389923 ] } },
{ "type": "Feature", "properties": { "IRMI": 17.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4090576, 50.6389797 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4090626, 50.6389676 ] } },
{ "type": "Feature", "properties": { "IRMI": 17.7 }, "geometry": { "type": "Point", "coordinates": [ 3.409074, 50.6389562 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4090913, 50.6389443 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4091086, 50.6389323 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4091308, 50.6389218 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4091573, 50.6389104 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4091888, 50.638896 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4092273, 50.6388768 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4092675, 50.6388575 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4093085, 50.6388381 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4093486, 50.6388193 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4093895, 50.6388004 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4094286, 50.6387822 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4094698, 50.6387639 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4095108, 50.638745 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4095525, 50.6387256 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4095948, 50.6387066 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4096373, 50.6386874 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4096791, 50.638668 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.409721, 50.6386485 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4097631, 50.6386295 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4098056, 50.6386101 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.409848, 50.6385913 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4098863, 50.6385746 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4099128, 50.6385614 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4099361, 50.6385498 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4099586, 50.638537 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4099801, 50.6385231 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4099976, 50.6385067 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4100133, 50.6384872 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4100311, 50.6384641 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.410052, 50.6384362 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4100723, 50.6384077 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4100925, 50.638379 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4101123, 50.6383499 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4101308, 50.6383206 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4101495, 50.6382915 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4101671, 50.6382624 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4101841, 50.6382328 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4102005, 50.6382045 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4102163, 50.6381765 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4102331, 50.6381474 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4102498, 50.6381186 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4102645, 50.6380897 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4102766, 50.6380604 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4102883, 50.6380318 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4102893, 50.638013 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4102928, 50.637991 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.410295, 50.6379673 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4102968, 50.6379444 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4102988, 50.6379221 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4103006, 50.6378975 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4103021, 50.6378707 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4103043, 50.6378434 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4103058, 50.637816 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4103063, 50.63779 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.410306, 50.6377644 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4103063, 50.6377405 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4103063, 50.6377181 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4103066, 50.6376998 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4103091, 50.6376854 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4103145, 50.6376744 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.410323, 50.6376621 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4103333, 50.6376528 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4103476, 50.6376447 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4103622, 50.6376379 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4103811, 50.6376346 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4104041, 50.6376355 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4104426, 50.6376351 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4104735, 50.6376366 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4105143, 50.6376366 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.410563, 50.6376366 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.410614, 50.6376365 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4106651, 50.637636 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4107141, 50.6376351 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4107636, 50.6376349 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.410814, 50.6376345 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4108653, 50.6376345 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.410916, 50.6376349 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4109668, 50.6376354 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4110163, 50.6376354 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4110671, 50.6376346 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.41112, 50.6376345 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4111715, 50.6376345 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4112225, 50.6376345 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4112741, 50.6376349 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4113266, 50.6376353 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4113795, 50.6376354 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4114321, 50.6376362 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4114856, 50.637636 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.411539, 50.6376353 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4115923, 50.637634 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4116445, 50.6376328 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.411697, 50.6376316 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4117496, 50.637631 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4118018, 50.637631 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.7 }, "geometry": { "type": "Point", "coordinates": [ 3.411854, 50.6376305 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4119065, 50.6376303 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4119586, 50.6376294 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.412011, 50.6376288 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4120635, 50.6376281 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4121166, 50.6376278 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4121698, 50.6376278 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4122238, 50.6376278 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4122775, 50.637628 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4123308, 50.637628 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4123841, 50.6376278 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4124768, 50.6376269 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4124768, 50.6376269 ] } },
{ "type": "Feature", "properties": { "IRMI": 20.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4125145, 50.6376264 ] } },
{ "type": "Feature", "properties": { "IRMI": 20.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4125453, 50.637626 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.9 }, "geometry": { "type": "Point", "coordinates": [ 3.412571, 50.6376285 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4125931, 50.6376333 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.412611, 50.6376379 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4126271, 50.6376438 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4126305, 50.6376488 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4126371, 50.6376553 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4126405, 50.637681 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4126405, 50.637681 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.41264, 50.6376986 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4126338, 50.6377393 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4126338, 50.6377393 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4126273, 50.6377618 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4126216, 50.6377845 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4126146, 50.6378066 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4125961, 50.6378513 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4125961, 50.6378513 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4125863, 50.6378732 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.412567, 50.6379186 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.412567, 50.6379186 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4125458, 50.6379625 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4125458, 50.6379625 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4125333, 50.6379848 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4125095, 50.638032 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4125095, 50.638032 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4124848, 50.6380835 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4124703, 50.63811 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4124703, 50.63811 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.41244, 50.6381631 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.41244, 50.6381631 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4124066, 50.6382166 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4123896, 50.6382445 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4123896, 50.6382445 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4123585, 50.6382991 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4123585, 50.6382991 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.412324, 50.638355 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4123063, 50.638383 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4123063, 50.638383 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4122726, 50.638439 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4122558, 50.6384667 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4122393, 50.6384959 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4122233, 50.6385249 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4122233, 50.6385249 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4121921, 50.6385828 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4121766, 50.638612 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4121615, 50.6386415 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4121448, 50.6386704 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4121283, 50.6387001 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4121126, 50.6387299 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4120968, 50.6387595 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4120968, 50.6387595 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4120651, 50.6388205 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4120478, 50.6388518 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4120316, 50.6388835 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4120153, 50.6389142 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4119993, 50.638946 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4119846, 50.638978 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.41197, 50.6390101 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4119536, 50.6390421 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4119385, 50.6390746 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4119223, 50.639107 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4119056, 50.63914 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4118905, 50.6391735 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4118771, 50.639206 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4118611, 50.6392382 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4118421, 50.6392713 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4118246, 50.6393031 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4118083, 50.6393332 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.411793, 50.639364 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4117775, 50.6393948 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4117626, 50.6394254 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4117461, 50.6394559 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4117288, 50.6394861 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4117118, 50.6395158 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4116956, 50.639546 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4116801, 50.6395769 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4116643, 50.6396076 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4116485, 50.6396383 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.411633, 50.6396692 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4116173, 50.6397001 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4116011, 50.6397314 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4115861, 50.6397629 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4115688, 50.6397933 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4115528, 50.639824 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.411535, 50.6398535 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.411518, 50.6398836 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4115021, 50.639914 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4114861, 50.6399442 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.411469, 50.6399738 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4114523, 50.640003 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4114358, 50.6400329 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4114193, 50.640063 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4114036, 50.640093 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4113883, 50.640123 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.411373, 50.6401531 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4113578, 50.6401828 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.411343, 50.6402126 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4113291, 50.6402402 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4113161, 50.640265 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4113061, 50.6402856 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4112988, 50.6403051 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4112906, 50.6403245 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4112835, 50.6403429 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4112741, 50.64036 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4112588, 50.6403727 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4112383, 50.6403819 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4112158, 50.6403891 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4111871, 50.6403933 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4111535, 50.6403956 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4111115, 50.640396 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4110555, 50.6403958 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4109896, 50.6403956 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4109241, 50.6403956 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4108603, 50.6403968 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4108, 50.640398 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4107433, 50.640399 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.410695, 50.6403998 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.41065, 50.6404006 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4106115, 50.6404006 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4105781, 50.6403993 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.41055, 50.640394 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4105255, 50.6403844 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4105031, 50.6403743 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4104798, 50.6403615 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4104565, 50.6403463 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4104318, 50.64033 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4104048, 50.6403125 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4103763, 50.640293 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4103461, 50.640273 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.410317, 50.6402541 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4102896, 50.6402341 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4102651, 50.6402138 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4102378, 50.6401935 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4102103, 50.640175 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4101855, 50.6401573 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4101655, 50.6401429 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4101511, 50.6401307 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4101405, 50.6401178 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4101373, 50.6401052 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4101358, 50.6400928 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.410139, 50.6400801 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.410147, 50.6400681 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4101591, 50.6400588 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4101748, 50.640054 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.410192, 50.6400487 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4102131, 50.6400436 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4102396, 50.6400406 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4102785, 50.6400383 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.410329, 50.6400378 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4103935, 50.6400376 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4104648, 50.6400371 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4105336, 50.640037 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4105991, 50.6400365 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4106634, 50.6400359 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4107288, 50.6400359 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4107953, 50.6400351 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.410861, 50.640034 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4109273, 50.6400333 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4109953, 50.6400328 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.411063, 50.640032 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4111305, 50.6400316 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.411197, 50.6400308 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4112546, 50.6400303 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4113016, 50.6400304 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4113385, 50.6400298 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4113685, 50.6400268 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4113921, 50.6400225 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.41141, 50.6400138 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4114235, 50.6400037 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4114366, 50.6399925 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4114473, 50.6399787 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4114588, 50.6399605 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4114733, 50.6399365 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4114888, 50.6399086 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4115045, 50.6398803 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4115188, 50.6398523 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4115336, 50.6398253 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4115468, 50.6398011 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4115583, 50.6397796 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4115653, 50.63976 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4115663, 50.6397435 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4115656, 50.6397281 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4115601, 50.6397162 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.411549, 50.6397051 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4115345, 50.6396945 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4115156, 50.6396905 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4114958, 50.6396903 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4114761, 50.6396895 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4114526, 50.6396893 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4114193, 50.6396899 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.411375, 50.63969 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4113195, 50.6396903 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4112598, 50.6396907 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4112033, 50.6396911 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.411146, 50.6396915 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.411085, 50.6396916 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4110203, 50.6396923 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4109531, 50.6396928 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4108826, 50.6396933 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4108121, 50.6396942 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4107438, 50.639694 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4106751, 50.639693 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4106065, 50.6396918 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4105396, 50.6396907 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4104718, 50.6396905 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4104013, 50.6396903 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4103308, 50.6396903 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4102605, 50.6396905 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.41019, 50.639691 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4101198, 50.6396915 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4100513, 50.6396911 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4099921, 50.6396907 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4099395, 50.6396907 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4098941, 50.639691 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.409855, 50.6396915 ] } },
{ "type": "Feature", "properties": { "IRMI": 17.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4098208, 50.6396915 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4097925, 50.6396887 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4097696, 50.6396852 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4097505, 50.6396776 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.409736, 50.6396666 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.409722, 50.6396547 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.2 }, "geometry": { "type": "Point", "coordinates": [ 3.409707, 50.6396377 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4096915, 50.6396145 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4096731, 50.6395871 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4096533, 50.639558 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4096346, 50.6395298 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4096161, 50.6395018 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4095975, 50.6394758 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4095785, 50.6394529 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.409564, 50.6394328 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.409557, 50.6394139 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.409558, 50.6393969 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4095651, 50.6393804 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4095765, 50.6393676 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.409593, 50.6393585 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4096136, 50.6393532 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.409639, 50.6393498 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4096715, 50.6393468 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4097088, 50.639344 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4097626, 50.6393422 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.409831, 50.6393413 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4099031, 50.6393408 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.409973, 50.6393403 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4100393, 50.6393388 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4101025, 50.6393378 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4101683, 50.6393366 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4102341, 50.639336 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4103003, 50.6393353 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.410368, 50.6393343 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4104356, 50.6393342 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4105036, 50.6393342 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4105721, 50.639334 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.41064, 50.639334 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4107093, 50.6393337 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.410779, 50.6393336 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4108486, 50.6393332 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.410919, 50.6393319 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4109895, 50.6393306 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4110595, 50.6393298 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4111295, 50.6393291 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4112001, 50.6393288 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4112695, 50.6393282 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.411339, 50.6393275 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4114083, 50.6393258 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4114783, 50.6393252 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4115471, 50.6393251 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4116061, 50.6393248 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4116565, 50.6393252 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4117003, 50.6393255 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.411736, 50.6393245 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4117633, 50.6393208 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4117875, 50.6393155 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4118061, 50.6393075 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4118178, 50.6392965 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4118266, 50.6392841 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4118385, 50.6392655 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4118523, 50.63924 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4118651, 50.639212 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.411878, 50.6391833 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4118921, 50.6391535 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4119081, 50.6391248 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.411924, 50.6390981 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4119363, 50.6390758 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4119451, 50.6390568 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4119475, 50.6390399 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4119436, 50.6390258 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.411939, 50.6390136 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.411933, 50.639005 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.411924, 50.6389949 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.411912, 50.6389877 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.411897, 50.6389815 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4118751, 50.638984 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4118505, 50.6389835 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4118223, 50.6389838 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4117868, 50.6389834 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4117445, 50.6389831 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.411692, 50.6389826 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4116335, 50.6389828 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.411571, 50.6389826 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4115043, 50.6389821 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4114395, 50.6389816 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4113735, 50.638981 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4113076, 50.6389813 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4112413, 50.6389813 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4111735, 50.6389813 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.411106, 50.6389813 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4110375, 50.6389815 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.410968, 50.638982 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4108995, 50.638982 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4108321, 50.638982 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4107641, 50.638982 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4106953, 50.6389821 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4106271, 50.6389821 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4105588, 50.6389825 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4104913, 50.6389821 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4104236, 50.6389822 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4103563, 50.6389828 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4102893, 50.6389822 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4102218, 50.6389825 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4101546, 50.6389838 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4100885, 50.6389843 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4100216, 50.6389851 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4099555, 50.6389851 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.409889, 50.6389852 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4098226, 50.6389859 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4097568, 50.6389865 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4096915, 50.6389872 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4096256, 50.6389888 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4095601, 50.63899 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4094958, 50.6389907 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4094338, 50.638991 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4093826, 50.6389914 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4093416, 50.6389919 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4093033, 50.638992 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4092668, 50.6389916 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4092363, 50.6389895 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4092113, 50.6389843 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4091941, 50.6389755 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4091821, 50.6389659 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4091745, 50.6389566 ] } },
{ "type": "Feature", "properties": { "IRMI": 17.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4091675, 50.6389468 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4091643, 50.638936 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4091663, 50.638925 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.409174, 50.6389135 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.2 }, "geometry": { "type": "Point", "coordinates": [ 3.409181, 50.6389018 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4091924, 50.6388915 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4092091, 50.6388813 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4092306, 50.63887 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4092623, 50.6388552 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4092971, 50.6388398 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.409332, 50.6388233 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4093696, 50.6388051 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4094058, 50.638787 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4094431, 50.63877 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4094803, 50.6387533 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4095171, 50.6387353 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.409555, 50.6387176 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.409593, 50.6387006 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.409632, 50.6386836 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4096698, 50.6386663 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4097081, 50.6386495 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4097458, 50.6386366 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4097848, 50.6386277 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4098251, 50.6386251 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4098676, 50.6386246 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.409914, 50.6386246 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4099621, 50.638625 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4100151, 50.6386254 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.410071, 50.638626 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4101288, 50.6386259 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4101883, 50.6386259 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4102481, 50.6386263 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4103091, 50.6386265 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4103685, 50.6386259 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4104288, 50.6386254 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4104898, 50.6386256 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4105513, 50.6386254 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4106123, 50.6386256 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4106753, 50.6386256 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.410743, 50.6386259 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4108153, 50.6386254 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4108886, 50.6386253 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.410962, 50.6386245 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4110366, 50.6386242 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.41111, 50.6386246 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4111833, 50.6386247 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4112571, 50.6386253 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4113301, 50.6386253 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4114026, 50.6386253 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4114742, 50.6386251 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.411545, 50.6386251 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4116143, 50.638624 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4116841, 50.6386226 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4117518, 50.6386217 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4118171, 50.6386216 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4118811, 50.6386212 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4119338, 50.6386212 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4119826, 50.6386212 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.412025, 50.6386205 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4120606, 50.6386203 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4120903, 50.6386199 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4121131, 50.6386165 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4121306, 50.6386119 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4121433, 50.6386047 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4121561, 50.6385966 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4121683, 50.6385858 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4121793, 50.6385719 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4121916, 50.6385524 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4122025, 50.63853 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4122145, 50.6385071 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4122276, 50.6384835 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4122405, 50.6384605 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4122526, 50.638438 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4122661, 50.6384146 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.412281, 50.6383925 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4122956, 50.638371 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4123063, 50.6383516 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4123091, 50.6383322 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4123076, 50.638314 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4123008, 50.6382977 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4122876, 50.6382867 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4122668, 50.638281 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.412242, 50.638279 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4122166, 50.6382775 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4121906, 50.6382766 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4121575, 50.638276 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4121163, 50.6382748 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4120648, 50.6382739 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4120093, 50.6382736 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4119521, 50.6382738 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4118911, 50.6382745 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4118294, 50.638275 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4117696, 50.6382755 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4117078, 50.6382755 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4116466, 50.6382761 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4115833, 50.6382773 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.411519, 50.6382786 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4114556, 50.6382796 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4113921, 50.63828 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4113276, 50.6382798 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.411265, 50.6382793 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.411203, 50.6382791 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4111415, 50.6382794 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4110803, 50.6382805 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4110198, 50.6382807 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.41096, 50.6382811 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4109001, 50.6382815 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4108408, 50.6382823 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.410782, 50.6382829 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4107233, 50.6382837 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4106645, 50.6382853 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.410606, 50.6382865 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4105488, 50.6382867 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4104921, 50.6382866 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4104366, 50.6382866 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4103876, 50.6382873 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4103431, 50.638289 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4103048, 50.6382896 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.410269, 50.6382872 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4102398, 50.6382805 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4102208, 50.6382702 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4102085, 50.6382599 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4102003, 50.6382493 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4101958, 50.6382361 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4101981, 50.6382222 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4102035, 50.6382085 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4102097, 50.6381918 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4102175, 50.6381737 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4102278, 50.6381528 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4102383, 50.638131 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.410249, 50.6381095 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4102593, 50.6380872 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.410268, 50.6380656 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4102766, 50.6380452 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4102843, 50.6380252 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4102915, 50.6380045 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.410297, 50.637986 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4103051, 50.6379693 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4103186, 50.6379535 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4103383, 50.6379413 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4103648, 50.6379355 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4103953, 50.637932 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4104315, 50.63793 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4104735, 50.637929 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4105171, 50.6379296 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4105608, 50.6379295 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4106065, 50.6379292 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4106545, 50.6379291 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4107066, 50.6379285 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.410759, 50.6379278 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4108115, 50.6379276 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4108666, 50.6379273 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.410921, 50.6379276 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4109755, 50.6379278 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4110305, 50.6379278 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4110883, 50.6379273 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4111476, 50.6379266 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4112113, 50.637926 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4112745, 50.6379266 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.411337, 50.6379266 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4114006, 50.6379262 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4114648, 50.6379255 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4115293, 50.6379254 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4115948, 50.637925 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4116596, 50.6379242 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.411724, 50.637923 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.411789, 50.6379216 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.411853, 50.6379205 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4119165, 50.6379194 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4119783, 50.6379185 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4120401, 50.6379181 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4120996, 50.6379182 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4121555, 50.6379191 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.412202, 50.6379198 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.412246, 50.6379191 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4122906, 50.6379181 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4123321, 50.637917 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.412366, 50.6379163 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4123945, 50.637916 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4124138, 50.6379156 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4124283, 50.637916 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.412444, 50.6379175 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4124638, 50.6379223 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4124856, 50.6379296 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.412505, 50.6379373 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4125193, 50.6379462 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4125258, 50.6379581 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.412528, 50.637972 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4125265, 50.637988 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4125205, 50.6380063 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4125115, 50.63803 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.412497, 50.6380568 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4124806, 50.6380859 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4124643, 50.6381152 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.412448, 50.6381437 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4124321, 50.6381728 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.6 }, "geometry": { "type": "Point", "coordinates": [ 3.4124155, 50.6382009 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4123988, 50.63823 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4123831, 50.6382587 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4123656, 50.638287 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4123483, 50.6383158 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4123308, 50.6383444 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4123128, 50.6383735 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4122951, 50.6384027 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4122776, 50.6384318 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4122603, 50.6384605 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4122431, 50.6384896 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4122271, 50.6385183 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4122106, 50.6385466 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4121948, 50.6385754 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4121793, 50.638604 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.412165, 50.638633 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4121508, 50.6386611 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.412136, 50.6386892 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4121196, 50.6387183 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4121036, 50.6387485 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4120875, 50.6387788 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.412071, 50.6388098 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4120541, 50.6388405 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4120381, 50.638872 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4120226, 50.6389035 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4119935, 50.6389668 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4119935, 50.6389668 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.411979, 50.6389983 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4119643, 50.6390297 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4119496, 50.639061 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4119181, 50.639122 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.4119181, 50.639122 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4118868, 50.6391833 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4118713, 50.6392136 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4118713, 50.6392136 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4118388, 50.6392735 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.411824, 50.639303 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4118088, 50.639333 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4117938, 50.6393631 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.411778, 50.6393926 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4117625, 50.6394218 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4117473, 50.639451 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4117306, 50.6394818 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.4117128, 50.6395119 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4116953, 50.6395428 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4116793, 50.6395743 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4116631, 50.6396053 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4116468, 50.6396365 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4116305, 50.639668 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.6 }, "geometry": { "type": "Point", "coordinates": [ 3.411614, 50.6396985 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4115963, 50.63973 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4115783, 50.6397611 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.411561, 50.639792 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.2 }, "geometry": { "type": "Point", "coordinates": [ 3.4115445, 50.639823 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.411528, 50.6398538 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4115101, 50.639887 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4114925, 50.6399192 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4114755, 50.6399511 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4114586, 50.639983 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4114425, 50.6400152 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4114261, 50.6400478 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4114095, 50.6400806 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4113923, 50.6401128 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.411376, 50.6401453 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4113588, 50.6401773 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4113421, 50.6402099 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4113255, 50.640243 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.1 }, "geometry": { "type": "Point", "coordinates": [ 3.411309, 50.6402758 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4112953, 50.6403081 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4112821, 50.6403411 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4112683, 50.6403743 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4112541, 50.6404071 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4112426, 50.6404395 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.41123, 50.6404736 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.8 }, "geometry": { "type": "Point", "coordinates": [ 3.4112198, 50.6405063 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4112111, 50.6405385 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4112028, 50.6405687 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.0 }, "geometry": { "type": "Point", "coordinates": [ 3.4111971, 50.6405928 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.4111928, 50.6406145 ] } },
{ "type": "Feature", "properties": { "IRMI": 18.9 }, "geometry": { "type": "Point", "coordinates": [ 3.411189, 50.6406321 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.4 }, "geometry": { "type": "Point", "coordinates": [ 3.4111843, 50.6406476 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.5 }, "geometry": { "type": "Point", "coordinates": [ 3.41118, 50.6406615 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.7 }, "geometry": { "type": "Point", "coordinates": [ 3.4111751, 50.6406735 ] } },
{ "type": "Feature", "properties": { "IRMI": 19.3 }, "geometry": { "type": "Point", "coordinates": [ 3.4111692, 50.6406854 ] } }
]
}

Binary file not shown.

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
@@ -12,6 +12,9 @@
<None Update="NitrogenInput.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="InputData-NBS.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>

View File

@@ -5,6 +5,7 @@ namespace FarmmapsNbs.Models
{
public class NitrogenInput
{
public bool UseCreatedCropfield { get; set; }
public string File { get; set; }
public string InputVariable { get; set; }
public string OutputFileName { get; set; }
@@ -13,5 +14,21 @@ namespace FarmmapsNbs.Models
public string PotatoPurposeType { get; set; }
public int TargetYield { 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; }
}
}

View 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; }
}
}

View File

@@ -9,34 +9,33 @@ using FarmmapsApi.Services;
using FarmmapsNbs.Models;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using static FarmmapsApiSamples.Constants;
namespace FarmmapsNbs
{
public class NbsApplication : IApplication
{
namespace FarmmapsNbs {
public class NbsApplication : IApplication {
private const string DownloadFolder = "Downloads";
private const string SettingsFile = "settings.json";
private readonly ILogger<NbsApplication> _logger;
private readonly FarmmapsApiService _farmmapsApiService;
private readonly NitrogenService _nitrogenService;
private readonly GeneralService _generalService;
private Settings _settings;
public NbsApplication(ILogger<NbsApplication> logger, FarmmapsApiService farmmapsApiService,
GeneralService generalService, NitrogenService nitrogenService)
{
GeneralService generalService, NitrogenService nitrogenService) {
_logger = logger;
_farmmapsApiService = farmmapsApiService;
_generalService = generalService;
_nitrogenService = nitrogenService;
}
public async Task RunAsync()
{
public async Task RunAsync() {
var nitrogenInputJson = File.ReadAllText("NitrogenInput.json");
//var nitrogenInputJson = File.ReadAllText("fivefieldsinput.json");
List<NitrogenInput> nitrogenInputs = JsonConvert.DeserializeObject<List<NitrogenInput>>(nitrogenInputJson);
if (!Directory.Exists(DownloadFolder))
Directory.CreateDirectory(DownloadFolder);
@@ -44,77 +43,149 @@ namespace FarmmapsNbs
await _farmmapsApiService.GetCurrentUserCodeAsync();
var roots = await _farmmapsApiService.GetCurrentUserRootsAsync();
foreach (var input in nitrogenInputs)
{
try
{
foreach (var input in nitrogenInputs) {
try {
await Process(roots, input);
}
catch (Exception ex)
{
} catch (Exception ex) {
_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 FieldName = input.fieldName;
bool StoreStatistics = input.storeSatelliteStatistics;
var measurementDate = input.MeasurementDate;
string settingsfile = $"Settings_{FieldName}.json";
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "Uploaded");
if (uploadedRoot == null)
{
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 == "My drive");
if (myDriveRoot == null)
{
var myDriveRoot = roots.SingleOrDefault(r => r.Name == "USER_FILES");
if (myDriveRoot == null) {
_logger.LogError("Could not find a needed root item");
return;
}
var cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDriveRoot.Code,
$"VRA NBS cropfield {input.OutputFileName}", plantingDate.Year, input.GeometryJson.ToString(Formatting.None));
// Use already created cropfield or create new one
Item cropfieldItem;
if (useCreatedCropfield == false || string.IsNullOrEmpty(_settings.CropfieldItemCode)) {
_logger.LogInformation("Creating cropfield");
cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDriveRoot.Code,
$"VRA NBS cropfield {input.OutputFileName}", plantingDate.Year, input.GeometryJson.ToString(Formatting.None));
_settings.CropfieldItemCode = cropfieldItem.Code;
SaveSettings(settingsfile);
} else {
_logger.LogInformation("Cropfield already exists, trying to get it");
cropfieldItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldItemCode);
}
var inputItem = (Item)null;
var geotiffItem = (Item)null;
if (input.File.Contains(".tif") || input.File.Contains(".geotiff")) {
// If no input file is specified, use most recent satellite image
if (string.IsNullOrEmpty(input.File)) {
_logger.LogInformation("No specific data given, retrieving most recent satellite image");
// check if satellite task not yet done, do here and save taskcode
if (useCreatedCropfield == false || string.IsNullOrEmpty(_settings.SatelliteTaskCode)) {
var satelliteTaskCode = await _generalService.RunSatelliteTask(cropfieldItem);
_settings.SatelliteTaskCode = satelliteTaskCode;
SaveSettings(settingsfile);
}
// Select a particular satellite item from satelliteTask
Item 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);
geotiffItem = await _generalService.UploadDataAsync(uploadedRoot, GEOTIFF_PROCESSED_ITEMTYPE, dataPath,
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)) :
await _generalService.UploadZipWithShapeAsync(uploadedRoot, dataPath, Path.GetFileNameWithoutExtension(input.File));
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($"Converting shape to geotiff");
geotiffItem = await _generalService.ShapeToGeotiff(shapeItem);
if (geotiffItem == null) {
_logger.LogError("Something went wrong with shape to geotiff transformation");
return;
}
_logger.LogInformation("Downloading geotiff file");
await _farmmapsApiService.DownloadItemAsync(geotiffItem.Code,
Path.Combine(DownloadFolder, $"{input.OutputFileName}.input_geotiff.zip"));
//_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}");
@@ -122,72 +193,119 @@ namespace FarmmapsNbs
var targetNData = await _nitrogenService.CalculateTargetN(cropfieldItem, targetNItem, plantingDate,
measurementDate, input.PotatoPurposeType, input.TargetYield);
if (targetNData == null)
{
if (targetNData == null) {
_logger.LogError("Something went wrong with TargetN calculation");
return;
}
_logger.LogInformation($"TargetN: {targetNData.TargetN}");
////Option to manually adjust the Target N, for test purposes only!
//targetNData.TargetN = 225;
//_logger.LogInformation($"TargetN adjusted: {targetNData.TargetN}");
var targetNDataPath = Path.Combine(DownloadFolder, $"{input.OutputFileName}.targetn.json");
await File.WriteAllTextAsync(targetNDataPath, JsonConvert.SerializeObject(targetNData, Formatting.Indented));
_logger.LogInformation("Calculating uptake map");
var uptakeMapItem =
await _nitrogenService.CalculateUptakeMap(cropfieldItem, geotiffItem, plantingDate,
measurementDate, input.InputVariable);
if (uptakeMapItem == null)
{
await _nitrogenService.CalculateUptakeMap(cropfieldItem, inputItem, plantingDate,
measurementDate, input.InputVariable, input.InputLayerName);
if (uptakeMapItem == null) {
_logger.LogError("Something went wrong with creating the uptakeMap");
return;
}
_logger.LogInformation("Downloading uptake map");
await _farmmapsApiService.DownloadItemAsync(uptakeMapItem.Code,
Path.Combine(DownloadFolder, $"{input.OutputFileName}.uptake.zip"));
_logger.LogInformation("UptakeMap downloaded to {0}", Path.Combine(DownloadFolder, $"{input.OutputFileName}.uptake.zip"));
_logger.LogInformation("UptakeMap downloaded");
_logger.LogInformation("Calculating application map");
var applicationMapItem =
await _nitrogenService.CalculateApplicationMap(cropfieldItem, geotiffItem, plantingDate,
measurementDate,
input.InputVariable, targetNData.TargetN);
var applianceMapItem =
await _nitrogenService.CalculateApplicationMap(cropfieldItem, inputItem, plantingDate,
measurementDate, input.InputVariable, targetNData.TargetN, input.InputLayerName);
if (applicationMapItem == null)
{
if (applianceMapItem == null) {
_logger.LogError("Something went wrong with creating the applicationMap");
return;
}
_logger.LogInformation("Downloading application map");
await _farmmapsApiService.DownloadItemAsync(applicationMapItem.Code,
await _farmmapsApiService.DownloadItemAsync(applianceMapItem.Code,
Path.Combine(DownloadFolder, $"{input.OutputFileName}.application.zip"));
_logger.LogInformation("Application map can be found in {0}", Path.Combine(DownloadFolder, $"{input.OutputFileName}.application.zip"));
//transforming tiff to shape
var tiffItem = applicationMapItem;
var tiffItem = applianceMapItem;
if (tiffItem == null)
{
if (tiffItem == null) {
_logger.LogError("Could not find item for uploaded data");
return;
}
_logger.LogInformation($"Converting geotiff to shape");
var taskmap = await _generalService.GeotiffToShape(tiffItem);
if (taskmap == null)
{
_logger.LogError("Something went wrong with geotiff to shape transformation");
return;
//ApplicationMap (GEOTIFF) To Taskmap
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"));
}
_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);
}
}
}
}

View File

@@ -1,126 +1,59 @@
[
{
"file": "Scan_1_20190605.json",
"inputVariable": "irmi",
"outputFileName": "vranbs1",
"UseCreatedCropfield": true,
"file": "Scan1_20190605_sample.json",
"inputVariable": "irmi",
"inputLayerName": "irmi",
"outputFileName": "vranbs_sample",
"fieldName": "sampleJson_irmi-usertest",
"storeSatelliteStatistics": true,
"plantingDate": "2019-04-18",
"measurementDate": "2019-06-05",
"potatoPurposeType": "consumption",
"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 ] ] ] }
},
{
"file": "Scan_1_20190605.zip",
"inputVariable": "irmi",
"outputFileName": "vranbs2",
"plantingDate": "2019-04-18",
"measurementDate": "2019-06-05",
"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 ]
[ 5.63217247936348731, 51.96438066944019596 ],
[ 5.6321047379532132, 51.96445630006819982 ],
[ 5.63206782435562925, 51.96450152306518078 ],
[ 5.63189463337882312, 51.96471369141583807 ],
[ 5.63125445938590019, 51.96545230717740793 ],
[ 5.63038475519850046, 51.96645153536461237 ],
[ 5.6302190722686376, 51.96664178312045124 ],
[ 5.63010295472675626, 51.96676711160860407 ],
[ 5.63204023224759265, 51.96725135278578023 ],
[ 5.63281523134503814, 51.96638856753320823 ],
[ 5.63281527471734655, 51.96638851620966904 ],
[ 5.63366926331355611, 51.96542171716968284 ],
[ 5.63397637358524683, 51.96498159324188748 ],
[ 5.6341135965418534, 51.96474743038492505 ],
[ 5.63219031197733688, 51.96438405049333653 ],
[ 5.63217541872332195, 51.96438123226843686 ],
[ 5.63217247936348731, 51.96438066944019596 ]
]
]
}
},
{
"file": "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 ]
]
]
}
},
{
"file": "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": false
}
// "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
//}
]

View File

@@ -74,7 +74,7 @@ namespace FarmmapsNbs
var item = await _farmmapsApiService.GetItemAsync(targetNItem.Code);
return item.Data.ToObject<TargetNData>();
}
/// <summary>
/// Calculates the uptake map based on the given inputs
/// </summary>
@@ -82,9 +82,11 @@ namespace FarmmapsNbs
/// <param name="inputItem"></param>
/// <param name="plantingDate">The date the crop is planted</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>
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};
nbsUptakeMapRequest.attributes["operation"] = "uptake";
@@ -92,10 +94,9 @@ namespace FarmmapsNbs
nbsUptakeMapRequest.attributes["plantingDate"] = plantingDate.ToString("o");
nbsUptakeMapRequest.attributes["measurementDate"] = measurementDate.ToString("o");
nbsUptakeMapRequest.attributes["inputType"] = inputType.ToLower();
nbsUptakeMapRequest.attributes["inputLayerName"] = "IRMI"; //toevoeging FS. Kolom IRMI hernoemd als IMI. Deze wordt niet automatisch herkend. En moet dus gespecificeerd worden.
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.
//var layers = inputItem.Data["layers"]; //toevoeging FS, check welke data lagen worden omgezet
//_logger.LogInformation($"DataLayers: {layers}"); //toevoeging FS check welke data lagen worden omgezet
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsUptakeMapRequest);
@@ -103,12 +104,13 @@ namespace FarmmapsNbs
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) =>
{
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
_logger.LogInformation($"Calculating uptake map; status: {itemTaskStatus.State}");
if (itemTaskStatus.IsFinished)
tokenSource.Cancel();
tokenSource.Cancel();
});
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}");
return null;
@@ -116,9 +118,10 @@ namespace FarmmapsNbs
var itemName = "VRANbs uptake";
var uptakeMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
GEOTIFF_PROCESSED_ITEMTYPE, itemName,
GEOTIFF_PROCESSED_ITEMTYPE, itemName,
i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) &&
i.Name.ToLower().Contains(itemName.ToLower()));
i.Name.ToLower().Contains(itemName.ToLower()));
if (uptakeMapItem == null)
{
_logger.LogError("Could not find the uptake geotiff child item under cropfield");
@@ -136,11 +139,11 @@ namespace FarmmapsNbs
/// <param name="inputItem">The farmmaps item containing the geotiff data</param>
/// <param name="plantingDate">The date the crop is planted</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>
/// <returns></returns>
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};
nbsApplicationMapRequest.attributes["operation"] = "application";
@@ -150,13 +153,14 @@ namespace FarmmapsNbs
nbsApplicationMapRequest.attributes["inputCode"] = inputItem.Code;
nbsApplicationMapRequest.attributes["inputType"] = inputType.ToLower();
nbsApplicationMapRequest.attributes["targetN"] = targetN.ToString(CultureInfo.InvariantCulture);
if (!(string.IsNullOrEmpty(inputLayerName))) nbsApplicationMapRequest.attributes["inputLayerName"] = inputLayerName;
string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsApplicationMapRequest);
await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) =>
{
var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, itemTaskCode);
_logger.LogInformation($"Calculating application map; status: {itemTaskStatus.State}");
if (itemTaskStatus.IsFinished)
tokenSource.Cancel();
});
@@ -172,7 +176,7 @@ namespace FarmmapsNbs
var itemName = $"VRANbs application";
var applicationMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code,
GEOTIFF_PROCESSED_ITEMTYPE, itemName,
GEOTIFF_PROCESSED_ITEMTYPE, itemName,
i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) &&
i.Name.ToLower().Contains(itemName.ToLower()));
if (applicationMapItem == null)

View File

@@ -14,9 +14,7 @@ namespace FarmmapsNbs
protected override void Configure(IServiceCollection serviceCollection)
{
serviceCollection.AddLogging(opts => opts
.AddConsole()
.AddFilter("System.Net.Http", LogLevel.Warning))
serviceCollection.AddLogging()
.AddTransient<NitrogenService>();
}
}

View File

@@ -10,7 +10,7 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="PotenInput.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

View File

@@ -5,14 +5,29 @@ namespace FarmmapsPoten.Models
{
public class PotenInput
{
public bool UseShadow { get; set; }
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; }
}
}

View File

@@ -14,9 +14,7 @@ using static FarmmapsApiSamples.Constants;
namespace FarmmapsVRApoten
{
public class PotenApplication : IApplication
{
public class PotenApplication : IApplication {
private const string DownloadFolder = "Downloads";
private readonly ILogger<PotenApplication> _logger;
@@ -26,16 +24,14 @@ namespace FarmmapsVRApoten
public PotenApplication(ILogger<PotenApplication> logger, FarmmapsApiService farmmapsApiService,
GeneralService generalService, PotenService potenService)
{
GeneralService generalService, PotenService potenService) {
_logger = logger;
_farmmapsApiService = farmmapsApiService;
_generalService = generalService;
_potenService = potenService;
}
public async Task RunAsync()
{
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);
@@ -48,36 +44,31 @@ namespace FarmmapsVRApoten
await _farmmapsApiService.GetCurrentUserCodeAsync();
var roots = await _farmmapsApiService.GetCurrentUserRootsAsync();
foreach (var input in potenInputs)
{
try
{
foreach (var input in potenInputs) {
try {
await Process(roots, input);
}
catch (Exception ex)
{
} catch (Exception ex) {
_logger.LogError(ex.Message);
}
}
}
private async Task Process(List<UserRoot> roots, PotenInput input)
{
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 == "My drive");
if (myDrive == null)
{
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 == "Uploaded");
if (uploadedRoot == null)
{
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN");
if (uploadedRoot == null) {
_logger.LogError("Could not find a needed root item");
return;
}
@@ -88,13 +79,14 @@ namespace FarmmapsVRApoten
$"VRA Poten cropfield {input.OutputFileName}", input.PlantingYear,
input.GeometryJson.ToString(Formatting.None));
//Calculating shadow map
if (useShadow)
{
_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)
{
if (shadowItem == null) {
_logger.LogError("Something went wrong while obtaining the shadow map");
return;
}
@@ -104,21 +96,18 @@ namespace FarmmapsVRApoten
Path.Combine(DownloadFolder, $"{input.OutputFileName}.shadow.zip"));
}
_logger.LogInformation("Looking for local data to use");
var localDataAvailable = input.File;
var geotiffItem = (Item) null;
var geotiffItem = (Item)null;
if (String.IsNullOrEmpty(localDataAvailable))
{
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)
{
if (bofekItem == null) {
_logger.LogError("Something went wrong while obtaining the BOFEK data");
return;
}
@@ -126,10 +115,7 @@ namespace FarmmapsVRApoten
_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")) {
} 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,
@@ -139,20 +125,16 @@ namespace FarmmapsVRApoten
_logger.LogError("Could not find item for uploaded data");
return;
}
}
else
{
} 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));
Path.GetFileNameWithoutExtension(input.File), input.GeometryJson.ToString(Formatting.None));
if (shapeItem == null)
{
if (shapeItem == null) {
_logger.LogError("Something went wrong while searching for the shape file");
return;
}
@@ -161,26 +143,28 @@ namespace FarmmapsVRApoten
_logger.LogInformation($"Converting shape to geotiff");
geotiffItem = await _generalService.ShapeToGeotiff(shapeItem);
if (geotiffItem == null)
{
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);
await _potenService.CalculateApplicationMapAsync(cropfieldItem, geotiffItem, meanDensity, variation, countPerArea, useShadow, inputLayerName);
if (applianceMapItem == null)
{
if (applianceMapItem == null) {
return;
}
@@ -192,18 +176,50 @@ namespace FarmmapsVRApoten
_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);
}
_logger.LogInformation($"Converting geotiff to shape");
var taskmap = await _generalService.GeotiffToShape(applianceMapItem);
if (taskmap == null)
{
_logger.LogError("Something went wrong with geotiff to shape transformation");
_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}.zip"));
Path.Combine(DownloadFolder, $"VRApoten_taskmap_{input.OutputFileName}_isoxml.zip"));
}
}
}
}

View File

@@ -1,13 +1,15 @@
[
{
"File": "PlantingSampleDataLutum.zip",
//"File": "Lutum_SampleDataPlanting.zip",
"OutputFileName": "vraPoten_SampleData",
//"InputLayerName": "EC0-60",
"OutputFileName": "2021.06.09_vraPoten_SampleData",
"FieldName": "lutum",
"PlantingYear": 2020,
"PlantingYear": 2021,
"MeanDensity": "30",
"Variation": "20",
"UseShadow": false,
"CountPerArea": true, // don't forget to change ddi if isoxml is created
"geometryJson": {
"type": "Polygon",
"coordinates": [
@@ -19,6 +21,33 @@
[ 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
}
]

View File

@@ -25,24 +25,16 @@ namespace FarmmapsVRApoten
_generalService = generalService;
}
public async Task<Item> CalculateApplicationMapAsync(Item cropfieldItem, Item inputItem,string meanDensity, string variation)
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;
//var taskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, potenApplicationMapRequest);
//await PollTask(TimeSpan.FromSeconds(3), async (tokenSource) =>
//{
// _logger.LogInformation("Checking VRAPoten task status");
// var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
// // Code
// if (itemTaskStatus.IsFinished)
// tokenSource.Cancel();
//});
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}");
@@ -50,8 +42,6 @@ namespace FarmmapsVRApoten
_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}");
@@ -60,7 +50,6 @@ namespace FarmmapsVRApoten
});
var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode);
if (itemTask.State == ItemTaskState.Error)
{
@@ -82,10 +71,9 @@ namespace FarmmapsVRApoten
return applianceMapItem;
}
}
}
}
}

View 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 ] } }
]
}

View 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.

Binary file not shown.

View File

@@ -1,14 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<None Update="Data\**\*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ZoneringInput.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>

View File

@@ -1,4 +1,4 @@
namespace FarmmapsHaulmkilling.Models
namespace FarmmapsZonering.Models
{
public class InputParameter
{

View File

@@ -3,5 +3,9 @@ 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; }
}
}

View 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; }
}
}

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -40,92 +41,49 @@ namespace FarmmapsZonering
if (!Directory.Exists(DownloadFolder))
Directory.CreateDirectory(DownloadFolder);
LoadSettings();
// 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();
// await SimpleAdditionAsync(roots);
await ZoningAsync(roots);
}
private async Task SimpleAdditionAsync(List<UserRoot> roots)
{
var myDrive = roots.SingleOrDefault(r => r.Name == "My drive");
if (myDrive == null)
{
_logger.LogError("Could not find a needed root item");
return;
}
var uploadedRoot = roots.SingleOrDefault(r => r.Name == "Uploaded");
if (uploadedRoot == null)
{
_logger.LogError("Could not find a needed root item");
return;
}
Item cropfieldItem;
if (string.IsNullOrEmpty(_settings.CropfieldItemCode))
{
_logger.LogInformation("Creating cropfield");
cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDrive.Code, "Cropfield VRA Zonering", 2020,
@"{ ""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 ] ] ] }");
_settings.CropfieldItemCode = cropfieldItem.Code;
SaveSettings();
}
else
{
_logger.LogInformation("Cropfield already exists trying to get");
cropfieldItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldItemCode);
}
var inputOneItem = await _generalService.UploadDataAsync(uploadedRoot, GEOTIFF_PROCESSED_ITEMTYPE,
Path.Combine("Data", "data_9001.tif"),"data_9001");
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", "data_times_two_4326.tiff"), "data_times_two_4326");
if (inputTwoItem == null) {
_logger.LogError("Could not find item for uploaded data");
return;
foreach (var input in zoneringInputs)
{
try
{
await ZoningAsync(roots, input);
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
var outputItem = await _zoneringService.CreateApplicationMapAsync(cropfieldItem, "[0] + [1]", new Output()
{
Name = "add",
Unit = "n/kg",
Quantity = "Nitrogen"
}, 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");
await _farmmapsApiService.DownloadItemAsync(outputItem.Code,
Path.Combine(DownloadFolder, $"times_2_zonering.zip"));
}
private async Task ZoningAsync(List<UserRoot> roots)
private async Task ZoningAsync(List<UserRoot> roots, ZoneringInput input)
{
var myDrive = roots.SingleOrDefault(r => r.Name == "My drive");
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 == "Uploaded");
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");
@@ -133,75 +91,123 @@ namespace FarmmapsZonering
}
Item cropfieldItem;
if (string.IsNullOrEmpty(_settings.CropfieldItemCode))
if (input.CreateNewCropfield == true) // || string.IsNullOrEmpty(_settings.CropfieldItemCode) ## CHECK IT!!
{
_logger.LogInformation("Creating cropfield");
cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDrive.Code, "Cropfield VRA Zonering", 2020,
@"{ ""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 ] ] ] }");
cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDrive.Code, input.CropFieldName, input.CropYear,
input.GeometryJson.ToString(Formatting.None));
_settings.CropfieldName = cropfieldItem.Name;
_settings.CropfieldItemCode = cropfieldItem.Code;
SaveSettings();
}
SaveSettings(settingsfile);
}
else
{
_logger.LogInformation("Cropfield already exists trying to get");
cropfieldItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldItemCode);
}
var inputOneItem = await _generalService.UploadDataAsync(uploadedRoot, GEOTIFF_PROCESSED_ITEMTYPE,
Path.Combine("Data", "data_9001.tif"),"data_9001");
if (inputOneItem == null) {
_logger.LogError("Could not find item for uploaded data");
return;
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);
}
var inputTwoItem = await _generalService.UploadDataAsync(uploadedRoot, GEOTIFF_PROCESSED_ITEMTYPE,
Path.Combine("Data", "data_times_two_4326.tiff"), "data_times_two_4326");
if (inputTwoItem == null) {
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 outputItem = await _zoneringService.CreateApplicationMapAsync(cropfieldItem, "if [0] >= 1.28 then [1] else 0", new Output()
//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 = "Remove",
Unit = "m&m",
Quantity = "Nonsense"
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()
//},
//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, $"NonsenseRemove.zip"));
Path.Combine(DownloadFolder, $"{input.OutputFileName}.zoning.zip"));
}
private void LoadSettings()
{
if (File.Exists(SettingsFile))
{
var jsonText = File.ReadAllText(SettingsFile);
// 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
{
} else {
_settings = new Settings();
}
}
private void SaveSettings()
{
private void SaveSettings(string file) {
if (_settings == null)
return;
var json = JsonConvert.SerializeObject(_settings);
File.WriteAllText(SettingsFile, json);
File.WriteAllText(file, json);
}
private void SaveInfo(string file) {
if (_settings == null)
return;
var json = JsonConvert.SerializeObject(_settings);
File.WriteAllText(file, json);
}
}
}
}

View 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 ]
]
]
}
}
]

View File

@@ -1,15 +1,28 @@
##### NOT PRODUCTION READY CODE, JUST AN EXAMPLE
Put your clientId and clientSecret in a newly created appsettings.secrets.json file inside the root of the Secrets project.
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.
Clone the git repository to a local drive. DON'T clone to a network drive like "My Documents". Latter may cause authentication problems.
**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.
* Needs proper testing of all public api methods.
* Needs documentation of all public api methods.

View File

@@ -1,18 +1,19 @@
<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>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Platforms>AnyCPU;x64</Platforms>
</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>

View 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>

View File

@@ -1,8 +1,28 @@
{
"Authority": "https://accounts.test.farmmaps.eu/",
"Endpoint": "https://test.farmmaps.eu/",
"BasePath": "api/v1",
"DiscoveryEndpointUrl": "https://accounts.test.farmmaps.eu/.well-known/openid-configuration",
//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"]
"Scopes": [ "api" ]
}