public float[][] ReadRegionAcrossFiles(int xOffset, int yOffset, int xSize, int ySize) { int nPixPerTile = xSize * ySize; float[][] tileData = new float[m_FileDates.Count][]; int fileNum = 0; foreach (var t in m_FileDates) { var newshape = GDAL_Operations.GetRasterShape(t.Value); if (newshape.Item1 != Shape.Item1 || newshape.Item2 != Shape.Item2) { throw new ArgumentException("Raster shapes don't match"); } var newGT = GDAL_Operations.GetGeoTransform(t.Value); if (!GeoTransform.SequenceEqual(newGT)) { throw new ArgumentException("Raster geotransforms don't match"); } var newNDV = GDAL_Operations.GetNoDataValue(t.Value); if (newNDV != NoDataValue) { throw new ArgumentException("Raster nodata values don't match"); } var newProj = GDAL_Operations.GetProjection(t.Value); if (newProj != Projection) { throw new ArgumentException("Raster projections don't match"); } tileData[fileNum] = GDAL_Operations.ReadGDALRasterBandsToFlatArray( t.Value, xSize, ySize, xOffset, yOffset, 1); fileNum += 1; } return(tileData); }
static float[] TestReadTileAcrossTime(int column, int row, int xSize = 512, int ySize = 512) { int xOff = column * xSize; int yOff = row * ySize; string fileWildCard = "F:\\MOD11A2_Gapfilled_Output\\LST_Day\\Output_Final_30k_2030pc\\*Data.tif"; IFilenameDateParser modisFileParse = new FilenameDateParser_MODIS8DayRaw(); var details = GetFilenamesAndDates(fileWildCard, modisFileParse); string firstFileName = details[0].Item1; double[] overallGT = GDAL_Operations.GetGeoTransform(firstFileName); var shape = GDAL_Operations.GetRasterShape(firstFileName); if (yOff > shape.Item1 || xOff > shape.Item2) { throw new ArgumentException("you specified a column or row greater than the number of tiles available"); } if (yOff + ySize > shape.Item1) { ySize = shape.Item1 - yOff; } if (xOff + xSize > shape.Item2) { xSize = shape.Item2 - xOff; } int nPix = xSize * ySize; float[] tileData = new float[nPix * details.Count]; for (int t = 0; t < details.Count; t++) { int pxStart = nPix * t; string filename = details[t].Item1; DateTime filedate = details[t].Item2; var newshape = GDAL_Operations.GetRasterShape(filename); if (newshape.Item1 != shape.Item1 || newshape.Item2 != shape.Item2) { throw new ArgumentException("Raster shapes don't match"); } var bandarr = GDAL_Operations.ReadGDALRasterBandsToFlatArray(filename, xSize, ySize, xOff, yOff, 1); Array.Copy(bandarr, 0, tileData, pxStart, bandarr.Length); // tileData[pxStart : pxStart+nPix] = arr; } return(tileData); }
public float[][] ReadRegionAcrossFiles_MP(int xOffset, int yOffset, int xSize, int ySize) { int nPixPerTile = xSize * ySize; float[][] tileData = new float[m_FileDates.Count][]; ParallelOptions b = new ParallelOptions(); b.MaxDegreeOfParallelism = 6; var keys = m_FileDates.Keys; Parallel.For(0, keys.Count, b, c => { var fDate = keys[c]; var fName = m_FileDates[fDate]; var newshape = GDAL_Operations.GetRasterShape(fName); if (newshape.Item1 != Shape.Item1 || newshape.Item2 != Shape.Item2) { throw new ArgumentException("Raster shapes don't match"); } var newGT = GDAL_Operations.GetGeoTransform(fName); if (!GeoTransform.SequenceEqual(newGT)) { throw new ArgumentException("Raster geotransforms don't match"); } var newNDV = GDAL_Operations.GetNoDataValue(fName); if (newNDV != NoDataValue) { throw new ArgumentException("Raster nodata values don't match"); } var newProj = GDAL_Operations.GetProjection(fName); if (newProj != Projection) { throw new ArgumentException("Raster projections don't match"); } tileData[c] = GDAL_Operations.ReadGDALRasterBandsToFlatArray( fName, xSize, ySize, xOffset, yOffset, 1); }); return(tileData); }
static void Main(string [] args) { Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";C:\\Users\\zool1301.NDPH\\Documents\\Code_General\\temp-suitability\\TempSuitability_CSharp\\packages\\GDAL.Native.1.11.1\\gdal\\x64"); //string testFile = "G:\\DataPrep\\ts_global\\TempSuitability.Pf.AnnualInfectiousDays.1k.2010.global.tif"; string testFile = "F:\\MOD11A2_Gapfilled_Output\\LST_Day\\Output_Final_30k_2030pc\\LST_Day_All.vrt"; int xsize = 512; int ysize = 512; int nbands = 727; Stopwatch sw = new Stopwatch(); sw.Start(); //var arr = GDAL_Operations.ReadGDALRasterBandsToFlatArray(testFile, xsize, ysize, 20480, 9216, null); var arr = TestReadTileAcrossTime(40, 18); sw.Stop(); Console.WriteLine("Time elapsed reading tif data into flat array via pointers: {0}", sw.Elapsed); sw.Restart(); int nPx = xsize * ysize; var cellArr = new float[nPx][]; for (int y = 0; y < ysize; y++) { for (int x = 0; x < xsize; x++) { int cellNum = y * xsize + x; cellArr[cellNum] = new float[nbands]; for (int z = 0; z < nbands; z++) { cellArr[cellNum][z] = arr[nPx * z + cellNum]; } } } Console.WriteLine("Time elapsed reformatting flat data into cell-band order: {0}", sw.Elapsed); arr = null; sw.Restart(); var arr3 = GDAL_Operations.ReadGDALRasterBandsToFlatArray(testFile, xsize, ysize, 20480, 9216, null); sw.Stop(); Console.WriteLine("Time elapsed reading vrt data into flat array via pointers: {0}", sw.Elapsed); sw.Restart(); var cellArr3 = new float[nPx][]; for (int y = 0; y < ysize; y++) { for (int x = 0; x < xsize; x++) { int cellNum = y * xsize + x; cellArr3[cellNum] = new float[nbands]; for (int z = 0; z < nbands; z++) { cellArr3[cellNum][z] = arr3[nPx * z + cellNum]; } } } Console.WriteLine("Time elapsed reformatting flat vrt data into cell-band order: {0}", sw.Elapsed); arr3 = null; sw.Restart(); var arr2 = GDAL_Operations.ReadGDALRasterBandsToJaggedArray(testFile, xsize, ysize, 20480, 9216, null); sw.Stop(); Console.WriteLine("Time elapsed reading data into jagged array via pointers: {0}", sw.Elapsed); sw.Restart(); var cellArr2 = new float[xsize * ysize][]; for (int y = 0; y < ysize; y++) { for (int x = 0; x < xsize; x++) { int cellNum = y * xsize + x; cellArr2[cellNum] = new float[nbands]; for (int z = 0; z < nbands; z++) { cellArr2[cellNum][z] = arr2[z][cellNum]; } } } Console.WriteLine("Time elapsed reformatting jagged data into cell-band order: {0}", sw.Elapsed); System.Console.ReadKey(); }
/// <summary> /// Runs a temperature suitability model for all pixels in a region specified by pixel limits. /// Output is a jagged array with one value for each cell starting at top left and then row by /// row to bottom right, EXCEPT if no pixel in the tile is in a data area in which case the output /// is an array with length zero. /// Otherwise, each value is an array with one TS value for each month of the run period, /// EXCEPT if the cell is in the sea / masked area, in which case it is an array of length 0. /// Each cell location is done independently and this is therefore multithreaded. /// </summary> /// <param name="xOff"></param> /// <param name="yOff"></param> /// <param name="xSize"></param> /// <param name="ySize"></param> /// <returns></returns> public float[][] RunTile(int xOff, int yOff, int xSize, int ySize) { // test area: int xOff=20480, int yOff=9216, int xSize=512, int ySize=512 var lsMask = GDAL_Operations.ReadGDALRasterBandsToFlatArray( _cfg.dataPathConfig.MaskFile, xSize, ySize, xOff, yOff, 1); if (!lsMask.Any(v => v == _cfg.modelRunConfig.MaskValidValue)) { // this whole tile is in the sea, no need to run, return as a special case a zero length cell array return(new float[0][]); } var maxTempData = _maxReader.ReadCellData(xOff, yOff, xSize, ySize); var lats = _maxReader.GetSubsetLatitudeCoords(yOff, ySize); var lons = _maxReader.GetSubsetLongitudeCoords(xOff, xSize); var minTempData = _minReader.ReadCellData(xOff, yOff, xSize, ySize); int numCells = xSize * ySize; // there's no reason in principle why we couldn't allow different numbers of min and max temp files although of // course we'd have to pass separate dates arrays into the model then, but hey. It would be a bit more effort // to handle different geotransforms in the max and min temps data and this way we make it less likely that // they've come from separate sources. Debug.Assert(minTempData.Length == maxTempData.Length); Debug.Assert(maxTempData.Length == numCells); var dates = _maxReader.Filedates.ToArray(); var nFiles = dates.Length; // get the model parameters from the default settings file, bearing in mind that this could have been re-set // at initialisation to a file specified on the commandline, rather than just being the default app config //var set = Properties.Settings.Default; var set = _cfg.modelConfig; PopulationParams popParams = new PopulationParams(); popParams.DegreeDayThreshold = set.SporogenesisDegreeDays; popParams.MinTempThreshold = set.MinTempThresholdCelsius; popParams.MosquitoDeathTemperature = set.DeathTempCelsius;; popParams.MosquitoLifespanDays = new TimeSpan((int)set.LifespanDays, 0, 0, 0);; popParams.SliceLength = new TimeSpan((int)set.SliceLengthHours, 0, 0); popParams.MaxTempSuitability = set.MaxTSNormaliser; // max ts for default settings is 34.2467; the Weiss code had 33.89401 , not sure how generated. // I got this using iterative solver in excel. Console.WriteLine("Tile data loaded, computation beginning"); var mConfig = _cfg.modelRunConfig; float[][] tsOut = new float[numCells][]; DateTime[] outputDates = null; ParallelOptions b = new ParallelOptions(); if (mConfig.MaxThreads != 0) { // set threads to 1 for easier step-through debugging or some other number to not hog the whole machine b.MaxDegreeOfParallelism = (int)mConfig.MaxThreads; //System.Threading.ThreadPool.SetMaxThreads(set.MaxThreads, set.MaxThreads); //System.Threading.ThreadPool.SetMinThreads(set.MinThreads, set.MinThreads); } int testnum = 0; while (outputDates == null && testnum < numCells) { // if we haven't got at least 50% of the data and 100+ points it's probably crap // (unless we're playing with synoptic data or something, so make this threshold configurable). // This doesn't affect the date calculation but the spline will throw an error // on initialisation var nValid = Math.Min( maxTempData[testnum].Count(v => v != _maxReader.NoDataValue), minTempData[testnum].Count(v => v != _minReader.NoDataValue)); if (nValid < nFiles / 2 || nValid < mConfig.MinRequiredDataPoints) { testnum += 1; continue; } // set up a dummy model purely to parse the output dates (that they will all share) // avoids the need to test for the first one to do this in the parallel loop, which needs a lock, // which slows things right down with >>20 cores TSCellModel tsModel = new TSCellModel( popParams, new GeographicCellLocation() { Latitude = lats[0], Longitude = lons[0] }, PopulationTypes.Pointers); if (!tsModel.SetData(maxTempData[testnum], minTempData[testnum], dates, _maxReader.NoDataValue.Value, mConfig.MaxTempFilesAreLST, mConfig.MinTempFilesAreLST)) { throw new ApplicationException("Pop goes the weasel"); } ; outputDates = tsModel.OutputDates; break; } Parallel.For(0, numCells, b, c => { if (lsMask[c] != mConfig.MaskValidValue) { // this cell is in the sea, no need to run, return as a special case a zero length result array tsOut[c] = new float[0]; } else { int rownum = c / xSize; int colnum = c % xSize; GeographicCellLocation geogParams = new GeographicCellLocation(); geogParams.Latitude = lats[rownum]; geogParams.Longitude = lons[colnum]; //geogParams.ModelRuntimeDays = nDays; //geogParams.StartJulianDay = 0; // run only if we've got at least 50% of the data and 100+ points (or whatever is configured) var nValid = Math.Min( maxTempData[c].Count(v => v != _maxReader.NoDataValue), minTempData[c].Count(v => v != _minReader.NoDataValue)); if (nValid < nFiles / 2 || nValid < mConfig.MinRequiredDataPoints) { tsOut[c] = new float[0]; } else { TSCellModel tsModel = new TSCellModel(popParams, geogParams, PopulationTypes.Pointers); // var dd = dayData[c]; // var nd = nightData[c]; // float optimal = 28.6857194664029F; // for (int i = 0; i < 727; i++) { // dd[i] = optimal; // if (i%3==0) { dd[i] = 43; } // nd[i] = optimal; } //tsModel.SetData(dd, nd, dates, _maxReader.NoDataValue.Value, false); if (!tsModel.SetData(maxTempData[c], minTempData[c], dates, _maxReader.NoDataValue.Value, mConfig.MaxTempFilesAreLST, mConfig.MinTempFilesAreLST)) { throw new ApplicationException("Pop goes the weasel"); } ; // run the entire ts model for this location float[] tsCell = tsModel.RunModel(); int nOutputPoints = tsCell.Length; tsOut[c] = tsCell; /*lock (_lockobj) // ensure only 1 thread makes this check * { * // calculate and record the dates of the outputs for an arbitrary one of the cell models * if (outputDates == null) * { * outputDates = tsModel.OutputDates; * } * }*/ } } } ); if (_outputDates == null) { _outputDates = outputDates; } else if (outputDates != null && !_outputDates.SequenceEqual(outputDates)) { throw new ApplicationException("Dates have changed between tiles somehow, this shouldn't happen..."); } return(tsOut); }