forked from FarmMaps/FarmMapsApiClient
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'
This commit is contained in:
@@ -17,6 +17,8 @@ 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;
|
||||
@@ -25,6 +27,7 @@ namespace FarmmapsBulkSatDownload
|
||||
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,
|
||||
@@ -51,96 +54,104 @@ namespace FarmmapsBulkSatDownload
|
||||
DateTime lastdownloadedimagedate;
|
||||
int cropYear;
|
||||
|
||||
// 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))
|
||||
//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)
|
||||
{
|
||||
connection.Open();
|
||||
// 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"
|
||||
|
||||
// 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())
|
||||
// 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))
|
||||
{
|
||||
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.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();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 = bulkSatDownloadInputListDB; //bulkSatDownloadInputListDB; //bulkSatDownloadInputListCsv;
|
||||
|
||||
// Whichever option (database or json/csv), continue here
|
||||
// Delete the settingsfile
|
||||
// File.Delete(settingsfile);
|
||||
|
||||
// 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();
|
||||
@@ -191,6 +202,33 @@ LIMIT 5;", schemaname, parceltablename, groenmonitorlatestviewname); //LIMIT x
|
||||
|
||||
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;
|
||||
@@ -222,6 +260,10 @@ LIMIT 5;", schemaname, parceltablename, groenmonitorlatestviewname); //LIMIT x
|
||||
DateTime lastDownloadedSatelliteDate = input.lastdownloadedimagedate;
|
||||
cropfielditemcode = input.cropfielditemcode;
|
||||
satellitetaskcode = input.satellitetaskcode;
|
||||
int satelliteItemsCropYearCntPrev;
|
||||
int satelliteItemsCropYearCnt;
|
||||
int callCnt;
|
||||
int sleepSecsSum;
|
||||
|
||||
LoadSettings(settingsfile);
|
||||
|
||||
@@ -309,23 +351,80 @@ LIMIT 5;", schemaname, parceltablename, groenmonitorlatestviewname); //LIMIT x
|
||||
// TODO also log satellitetaskcode to settings, how?
|
||||
// SaveSettings(settingsfile);
|
||||
|
||||
// Getting satellite items
|
||||
_logger.LogInformation(string.Format($"Running FindSatelliteItems for cropfieldItem.Code '{cropfieldItem.Code}', SatelliteTaskCode '{satellitetaskcode}'"));
|
||||
satelliteItemsCropYear = await _generalService.FindSatelliteItems(cropfieldItem, satellitetaskcode);
|
||||
// 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($"No satellite tiffs found for fieldName '{fieldName}', cropYear {cropYear}, cropfielditemcode '{cropfielditemcode}'");
|
||||
_logger.LogInformation($"// FarmmapsBulkSatDownload: No satellite tiffs found for fieldName '{fieldName}', cropYear {cropYear}, cropfielditemcode '{cropfielditemcode}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (satelliteItemsCropYear.Count == 0)
|
||||
{
|
||||
satelliteItemsAvailable = false;
|
||||
_logger.LogInformation($"No satellite tiffs found for fieldName '{fieldName}', cropYear {cropYear}, cropfielditemcode '{cropfielditemcode}'");
|
||||
_logger.LogInformation($"// FarmmapsBulkSatDownload: No satellite tiffs found for fieldName '{fieldName}', cropYear {cropYear}, cropfielditemcode '{cropfielditemcode}'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,10 +434,10 @@ LIMIT 5;", schemaname, parceltablename, groenmonitorlatestviewname); //LIMIT x
|
||||
// Download statistics to a single csv file
|
||||
if (satelliteItemsAvailable && downloadFolder != null && fileNameStats != null)
|
||||
{
|
||||
// Write statistics for all images for all fieldNane and cropYear to a single csv file, fileNameStats
|
||||
// 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 thee single large csv file
|
||||
// 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);
|
||||
|
||||
Reference in New Issue
Block a user