Skip to content

Commit 0b64f27

Browse files
author
Adam Collins
committedJan 28, 2025
#250 fix points to grid
1 parent e88b886 commit 0b64f27

File tree

4 files changed

+112
-114
lines changed

4 files changed

+112
-114
lines changed
 

‎grails-app/services/au/org/ala/spatial/TaskQueueService.groovy

+7
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ class TaskQueueService {
193193
taskWrapper.task.message = 'finished'
194194
taskWrapper.task.history.put(System.currentTimeMillis() as String, "finished (id:${taskWrapper.task.id})" as String)
195195

196+
// map output.task to task when null to prevent error when flushing task
197+
taskWrapper.task.output.each {
198+
if (!it.task) {
199+
it.task = taskWrapper.task
200+
}
201+
}
202+
196203
// flush task because it is finished
197204
Task.withTransaction {
198205
if (!taskWrapper.task.save(flush: true)) {

‎src/main/groovy/au/org/ala/spatial/layers/OccurrenceDensity.groovy

+10-13
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ class OccurrenceDensity {
6565
this.resolution = resolution
6666
this.bbox = bbox
6767

68-
width = (int) ((bbox[2] - bbox[0]) / resolution)
69-
height = (int) ((bbox[3] - bbox[1]) / resolution)
68+
width = (int) Math.round((bbox[2] - bbox[0]) / resolution)
69+
height = (int) Math.round((bbox[3] - bbox[1]) / resolution)
7070
}
7171

7272
/**
@@ -81,17 +81,17 @@ class OccurrenceDensity {
8181
*/
8282
void setResolution(double resolution) {
8383
this.resolution = resolution
84-
width = (int) ((bbox[2] - bbox[0]) / resolution)
85-
height = (int) ((bbox[3] - bbox[1]) / resolution)
84+
width = (int) Math.round((bbox[2] - bbox[0]) / resolution)
85+
height = (int) Math.round((bbox[3] - bbox[1]) / resolution)
8686
}
8787

8888
/**
8989
* @param bbox
9090
*/
9191
void setBBox(double[] bbox) {
9292
this.bbox = bbox
93-
width = (int) ((bbox[2] - bbox[0]) / resolution)
94-
height = (int) ((bbox[3] - bbox[1]) / resolution)
93+
width = (int) Math.round((bbox[2] - bbox[0]) / resolution)
94+
height = (int) Math.round((bbox[3] - bbox[1]) / resolution)
9595
}
9696

9797
/**
@@ -143,15 +143,14 @@ class OccurrenceDensity {
143143
boolean worldwrap = (bbox[2] - bbox[0]) == 360
144144
float[] values = new float[width]
145145

146-
int partCount = threadCount * 5
146+
int partCount = threadCount;
147147
int partSize = (int) Math.ceil(width / (double) partCount)
148148
GetValuesOccurrencesThread[] getValues = new GetValuesOccurrencesThread[threadCount]
149149
LinkedBlockingQueue<Integer> lbqGetValues = new LinkedBlockingQueue<Integer>()
150150

151151
int[] rowStarts = records.sortedRowStarts(bbox[1], height, resolution)
152152

153153
for (int row = 0; row < height; row++) {
154-
long start = System.currentTimeMillis()
155154
//get rows
156155
int[] oldRow = cRows[0]
157156
if (row == 0) {
@@ -167,7 +166,6 @@ class OccurrenceDensity {
167166
}
168167
}
169168
}
170-
long t1 = System.currentTimeMillis()
171169

172170
//operate on current row
173171
int startRow = (row == 0) ? 0 : row + gridSize / 2 //gridSize is odd
@@ -225,7 +223,6 @@ class OccurrenceDensity {
225223
bw.append("\n")
226224
}
227225
}
228-
long end = System.currentTimeMillis()
229226
}
230227

231228
for (int i = 0; i < threadCount; i++) {
@@ -260,11 +257,11 @@ class OccurrenceDensity {
260257
}
261258

262259
int len = (row + 1 < rowStarts.length) ? rowStarts[row + 1] : records.getRecordsSize()
263-
for (int i = rowStarts[row]; i < len; i++) {
264-
int y = height - 1 - (int) ((records.getSortedLatitude(i) - bbox[1]) / resolution)
260+
for (int i = (row < rowStarts.length ? rowStarts[row] : len); i < len; i++) {
261+
int y = height - 1 - Math.round((records.getSortedLatitude(i) - bbox[1]) / resolution)
265262

266263
if (y == row) {
267-
int x = (int) ((records.getSortedLongitude(i) - bbox[0]) / resolution)
264+
int x = Math.round((records.getSortedLongitude(i) - bbox[0]) / resolution)
268265

269266
if (x >= 0 && x < width) {
270267
counts[x]++

‎src/main/groovy/au/org/ala/spatial/process/PointsToGrid.groovy

+1-5
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class PointsToGrid extends SlaveProcess {
7171

7272
// dump the species data to a file
7373
taskLog("getting species data")
74-
Records records = getRecords(speciesArea.bs.toString(), speciesArea.q.join('&fq='), bbox, null, null)
74+
Records records = new Records(speciesArea.bs.toString(), speciesArea.q.join('&fq='), bbox, null, null, "names_and_lsid", false)
7575

7676
//update bbox with spatial extent of records
7777
double minx = 180, miny = 90, maxx = -180, maxy = -90
@@ -182,10 +182,6 @@ class PointsToGrid extends SlaveProcess {
182182
}
183183
}
184184

185-
def getRecords(String bs, String q, double[] bbox, String filename, SimpleRegion region) {
186-
new Records(bs, q, bbox, filename, region)
187-
}
188-
189185
void writeMetadata(String filename, String title, Records records, double[] bbox, boolean odensity, boolean sdensity, int[] counts, String addAreaSqKm, String speciesName, Double gridCellSize, String movingAverage) throws IOException {
190186
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss")
191187
FileWriter fw = new FileWriter(filename)

‎src/main/groovy/au/org/ala/spatial/util/Records.groovy

+94-96
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import java.util.zip.GZIPInputStream
1313
* @author Adam
1414
*/
1515
@Slf4j
16-
@CompileStatic
1716
class Records {
1817

1918
//private static final Logger logger = log.getLogger(Records.class);
@@ -36,8 +35,8 @@ class Records {
3635
init(biocache_service_url, q, bbox, filename, region, "names_and_lsid")
3736
}
3837

39-
Records(String biocache_service_url, String q, double[] bbox, String filename, SimpleRegion region, String facetField) throws IOException {
40-
init(biocache_service_url, q, bbox, filename, region, facetField)
38+
Records(String biocache_service_url, String q, double[] bbox, String filename, SimpleRegion region, String facetField, Boolean includeYear = true) throws IOException {
39+
init(biocache_service_url, q, bbox, filename, region, facetField, includeYear)
4140
}
4241

4342
Records(String filename) throws IOException {
@@ -307,10 +306,12 @@ class Records {
307306
}
308307
}
309308

310-
void init(String biocache_service_url, String q, double[] bbox, String filename, SimpleRegion region, String facetField) throws IOException {
309+
void init(String biocache_service_url, String q, double[] bbox, String filename, SimpleRegion region, String facetField, Boolean includeYear = true) throws IOException {
311310
int speciesEstimate = 250000
312311
int recordsEstimate = 26000000
313-
int pageSize = 50000
312+
int pageSize = 300000000 // Use a large number as a workaround for paging not working. Paging was added
313+
// for an introduced nginx timeout value so this could be considered a revert.
314+
// The biocache-service endpoint is streaming now, except for old sandbox instances.
314315

315316
String bboxTerm = null
316317
if (bbox != null) {
@@ -336,107 +337,104 @@ class Records {
336337
if (facetField == null) {
337338
facetFieldTerm = ''
338339
}
339-
while (start < 300000000) {
340-
String url = biocache_service_url + "/webportal/occurrences.gz?q=" + q.replace(" ", "%20") + bboxTerm + "&pageSize=" + pageSize + "&fq=year%3A*&start=" + start + "&fl=longitude,latitude" + facetFieldTerm + ",year"
341-
342-
int tryCount = 0
343-
InputStream is = null
344-
CSVReader csv = null
345-
int maxTrys = 4
346-
while (tryCount < maxTrys && csv == null) {
347-
tryCount++
348-
try {
349-
is = getUrlStream(url)
350-
csv = new CSVReader(new InputStreamReader(new GZIPInputStream(is)))
351-
} catch (Exception e) {
352-
log.error("failed try " + tryCount + " of " + maxTrys + ": " + url, e)
353-
}
354-
}
355340

356-
if (csv == null) {
357-
throw new IOException("failed to get records from biocache.")
341+
String yearFq = includeYear ? '&fq=year%3A*' : ''
342+
343+
// no longer using paging
344+
String url = biocache_service_url + "/webportal/occurrences.gz?q=" + q.replace(" ", "%20") + bboxTerm + "&pageSize=" + pageSize + yearFq + "&start=" + start + "&fl=longitude,latitude" + facetFieldTerm + (includeYear ? ",year" : "")
345+
346+
int tryCount = 0
347+
InputStream is = null
348+
CSVReader csv = null
349+
int maxTrys = 4
350+
while (tryCount < maxTrys && csv == null) {
351+
tryCount++
352+
try {
353+
is = getUrlStream(url)
354+
csv = new CSVReader(new InputStreamReader(new GZIPInputStream(is)))
355+
} catch (Exception e) {
356+
log.error("failed try " + tryCount + " of " + maxTrys + ": " + url, e)
358357
}
358+
}
359359

360-
String[] line
361-
int[] header = new int[4] //to contain [0]=lsid, [1]=longitude, [2]=latitude, [3]=year
362-
int row = start
363-
int currentCount = 0
364-
while ((line = csv.readNext()) != null) {
365-
if (raf != null) {
366-
for (int i = 0; i < line.length; i++) {
367-
if (i > 0) {
368-
raf.write(",".bytes)
369-
}
370-
raf.write(line[i].bytes)
360+
if (csv == null) {
361+
throw new IOException("failed to get records from biocache.")
362+
}
363+
364+
String[] line
365+
int[] header = new int[4] //to contain [0]=lsid, [1]=longitude, [2]=latitude, [3]=year
366+
int row = start
367+
int currentCount = 0
368+
while ((line = csv.readNext()) != null) {
369+
if (raf != null) {
370+
for (int i = 0; i < line.length; i++) {
371+
if (i > 0) {
372+
raf.write(",".bytes)
371373
}
372-
raf.write("\n".bytes)
374+
raf.write(line[i].bytes)
373375
}
374-
currentCount++
375-
if (currentCount == 1) {
376-
//determine header
377-
for (int i = 0; i < line.length; i++) {
378-
if (line[i] == facetField) {
379-
header[0] = i
380-
}
381-
if (line[i] == "longitude") {
382-
header[1] = i
383-
}
384-
if (line[i] == "latitude") {
385-
header[2] = i
386-
}
387-
if (line[i] == "year") {
388-
header[3] = i
389-
}
376+
raf.write("\n".bytes)
377+
}
378+
currentCount++
379+
if (currentCount == 1) {
380+
//determine header
381+
for (int i = 0; i < line.length; i++) {
382+
if (line[i] == facetField) {
383+
header[0] = i
390384
}
391-
log.debug("header info:" + header[0] + "," + header[1] + "," + header[2] + "," + header[3])
392-
} else {
393-
if (line.length >= 3) {
394-
try {
395-
double longitude = Double.parseDouble(line[header[1]])
396-
double latitude = Double.parseDouble(line[header[2]])
397-
if (region == null || region.isWithin_EPSG900913(longitude, latitude)) {
398-
points.add(longitude)
399-
points.add(latitude)
400-
String species = facetField == null ? 'species' : line[header[0]]
401-
Integer idx = lsidMap.get(species)
402-
if (idx == null) {
403-
idx = lsidMap.size()
404-
lsidMap.put(species, idx)
405-
}
406-
lsidIdx.add(idx)
407-
years.add(Short.parseShort(line[header[3]]))
385+
if (line[i] == "longitude") {
386+
header[1] = i
387+
}
388+
if (line[i] == "latitude") {
389+
header[2] = i
390+
}
391+
if (line[i] == "year") {
392+
header[3] = i
393+
}
394+
}
395+
log.debug("header info:" + header[0] + "," + header[1] + "," + header[2] + "," + header[3])
396+
} else {
397+
if (line.length >= 3) {
398+
try {
399+
double longitude = Double.parseDouble(line[header[1]])
400+
double latitude = Double.parseDouble(line[header[2]])
401+
if (region == null || region.isWithin_EPSG900913(longitude, latitude)) {
402+
points.add(longitude)
403+
points.add(latitude)
404+
String species = facetField == null ? 'species' : line[header[0]]
405+
Integer idx = lsidMap.get(species)
406+
if (idx == null) {
407+
idx = lsidMap.size()
408+
lsidMap.put(species, idx)
408409
}
409-
} catch (Exception ignored) {
410-
411-
} finally {
412-
if (lsidIdx.size() * 2 < points.size()) {
413-
points.remove(points.size() - 1)
414-
points.remove(points.size() - 1)
415-
} else if (years.size() < lsidIdx.size()) {
416-
years.add((short) 0)
410+
lsidIdx.add(idx)
411+
if (includeYear) {
412+
years.add(Short.parseShort(line[header[3]]))
417413
}
418414
}
415+
} catch (Exception ignored) {
416+
417+
} finally {
418+
if (lsidIdx.size() * 2 < points.size()) {
419+
points.remove(points.size() - 1)
420+
points.remove(points.size() - 1)
421+
} else if (years.size() < lsidIdx.size()) {
422+
years.add((short) 0)
423+
}
419424
}
420425
}
421-
row++
422-
}
423-
if (start == 0) {
424-
start = row - 1 //offset for header
425426
}
427+
row++
428+
}
426429

427-
csv.close()
428-
is.close()
430+
csv.close()
431+
is.close()
429432

430-
if (is != null) {
431-
try {
432-
is.close()
433-
} catch (Exception e) {
434-
log.error(e.getMessage(), e)
435-
}
436-
}
437-
438-
if (currentCount == 0 || currentCount < pageSize) {
439-
break
433+
if (is != null) {
434+
try {
435+
is.close()
436+
} catch (Exception e) {
437+
log.error(e.getMessage(), e)
440438
}
441439
}
442440

@@ -511,15 +509,15 @@ class Records {
511509

512510
@Override
513511
int compare(Integer o1, Integer o2) {
514-
return (h - 1 - ((int) ((points.get(o1) - mLat) / res)))-(h - 1 - ((int) ((points.get(o2) - mLat) / res)))
512+
return (h - 1 - (Math.round((points.get(o1) - mLat) / res)))-(h - 1 - (Math.round((points.get(o2) - mLat) / res)))
515513
}
516514
})
517515

518516
//get row starts
519517
int[] rowStarts = new int[height]
520518
int row = 0
521519
for (int i = 0; i < sortOrder.length; i++) {
522-
int thisRow = (h - 1 - (int) ((points.get(sortOrder[i]) - mLat) / res))
520+
int thisRow = (h - 1 - (int) Math.round((points.get(sortOrder[i]) - mLat) / res))
523521

524522
//handle overflow
525523
if (thisRow >= height) {
@@ -578,10 +576,10 @@ class Records {
578576

579577
@Override
580578
int compare(Integer o1, Integer o2) {
581-
int v = ((int) ((points.get(o1) - mLat) / res))-((int) ((points.get(o2) - mLat) / res))
579+
int v = (int) (Math.round((points.get(o1) - mLat) / res) - Math.round((points.get(o2) - mLat) / res))
582580

583581
if (v == 0) {
584-
return ((int) ((points.get(o1 - 1) - mLong) / res))-((int) ((points.get(o2 - 1) - mLong) / res))
582+
return (int) (Math.round((points.get(o1 - 1) - mLong) / res) - Math.round((points.get(o2 - 1) - mLong) / res))
585583
} else {
586584
return v
587585
}

0 commit comments

Comments
 (0)
Failed to load comments.