Skip to content

Commit a67c8dd

Browse files
author
Adam Collins
committed
#238 Improve raster loading progress
1 parent f5a2d85 commit a67c8dd

File tree

16 files changed

+285
-179
lines changed

16 files changed

+285
-179
lines changed

grails-app/conf/application.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ environments:
408408
remote: "https://spatial-test.ala.org.au/ws"
409409
geoserver:
410410
# use localhost to play nice with locally running geoserver docker instance.
411-
url: 'http://localhost:8079/geoserver'
411+
url: 'http://localhost:8080/geoserver'
412412
#url: 'https://spatial-test.ala.org.au/geoserver'
413413
username: 'admin'
414414
password: 'geoserver'

grails-app/conf/logback.xml

+6-7
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
88
<encoder>
99
<charset>UTF-8</charset>
10-
<pattern>[Spatial-service] %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(%logger{39} [%file:%line]){cyan} %clr(:){faint} %m%n%wex
11-
</pattern>
10+
<pattern>%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(%logger{39} [%file:%line]){cyan} %clr(:){faint} %m%n%wex</pattern>
1211
</encoder>
1312
</appender>
1413

@@ -21,12 +20,12 @@
2120
<logger name="org.quartz" level="ERROR"/>
2221
<logger name="asset.pipeline" level="ERROR"/>
2322
<logger name="au.org.ala.cas" level="WARN"/>
24-
<logger name="au.org.ala.spatial" level="DEBUG"/>
25-
<logger name="org.liquibase" level="INFO"/>
26-
<logger name="liquibase" level="INFO"/>
23+
<logger name="au.org.ala.spatial" level="WARN"/>
24+
<logger name="org.liquibase" level="WARN"/>
25+
<logger name="liquibase" level="WARN"/>
2726

28-
<root level="INFO">
27+
<root level="WARN">
2928
<appender-ref ref="STDOUT"/>
3029
</root>
3130

32-
</configuration>
31+
</configuration>

grails-app/controllers/au/org/ala/spatial/LoginInterceptor.groovy

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class LoginInterceptor {
2626
static final String[] USERID_HEADER_NAME = ["X-ALA-userId", "userId", "user_id"]
2727
static final String[] API_KEY_HEADER_NAME = ["apiKey", "api_key", "api-key"]
2828

29+
int order = LOWEST_PRECEDENCE
30+
2931
AuthService authService
3032
SpatialAuthService spatialAuthService
3133
SpatialConfig spatialConfig

grails-app/init/au/org/ala/spatial/BootStrap.groovy

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class BootStrap {
131131
"CREATE INDEX distributions_geom ON distributions USING GIST (the_geom);",
132132
"CREATE INDEX tabulation_geom ON tabulation USING GIST (the_geom);",
133133

134-
// objects.id sequence used in manual sql that creates objects
134+
// objects.spid sequence used in manual sql that creates objects
135135
"CREATE SEQUENCE objects_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1;",
136136

137137
// compound constraint

grails-app/services/au/org/ala/spatial/ManageLayersService.groovy

+3-30
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
package au.org.ala.spatial
1717

18+
import au.org.ala.spatial.grid.Bil2diva
1819
import au.org.ala.spatial.grid.Diva2bil
1920
import au.org.ala.spatial.intersect.Grid
2021
import au.org.ala.spatial.util.UploadSpatialResource
@@ -273,7 +274,7 @@ class ManageLayersService {
273274
map.put("error", "no layer files")
274275
} else {
275276
def errors = publishService.layerToGeoserver(new OutputParameter([
276-
file: ([shp.exists() ? shp.getPath() : bil.getPath()] as JSON).toString()
277+
file: ([shp.exists() ? shp.getPath() : tif.getPath()] as JSON).toString()
277278
]), null)
278279

279280
if (errors) {
@@ -503,7 +504,7 @@ class ManageLayersService {
503504
map.put("columns", columns)
504505
map.put("type", "Contextual")
505506
} else if (bil.exists()) {
506-
double[] minmax = getMinMax(bil)
507+
double[] minmax = Bil2diva.getMinMax(bil, spatialConfig.gdal.dir, spatialConfig.admin.timeout)
507508
map.put("environmentalvaluemin", minmax[0])
508509
map.put("environmentalvaluemax", minmax[1])
509510

@@ -1226,34 +1227,6 @@ class ManageLayersService {
12261227
// taskDao.addTask(UPDATE_GRID_CACHE, "", 3);
12271228
// }
12281229

1229-
def getMinMax(File bil) {
1230-
double[] minmax = new double[2]
1231-
1232-
//does .grd exist?
1233-
File grd = new File(bil.getPath().substring(0, bil.getPath().length() - 4) + ".grd")
1234-
File hdr = new File(bil.getPath().substring(0, bil.getPath().length() - 4) + ".hdr")
1235-
1236-
if (!grd.exists() && hdr.exists()) {
1237-
String n = bil.getPath().substring(0, bil.getPath().length() - 4)
1238-
Bil2diva.bil2diva(n, n, '')
1239-
}
1240-
1241-
try {
1242-
String info = grd.text
1243-
for (String line : info.split("\n")) {
1244-
if (line.startsWith("MinValue")) {
1245-
minmax[0] = Double.parseDouble(line.substring("MinValue=".length()).trim())
1246-
}
1247-
if (line.startsWith("MaxValue")) {
1248-
minmax[1] = Double.parseDouble(line.substring("MaxValue=".length()).trim())
1249-
}
1250-
}
1251-
} catch (IOException e) {
1252-
log.error("failed to get min max values in bil file: " + bil.getPath(), e)
1253-
}
1254-
return minmax
1255-
}
1256-
12571230
def distributionMap(String uploadId) {
12581231
String dir = spatialConfig.data.dir
12591232

grails-app/views/manageLayers/layer.gsp

+12-12
Original file line numberDiff line numberDiff line change
@@ -293,24 +293,24 @@
293293
</input>
294294
</td></tr><tr><td>
295295

296-
<label for="minlongitude">Minimum Longitude [readonly]</label></td><td>
297-
<input class="form-control" type="readonly" id="minlongitude" name="minlongitude"
298-
value="${minlongitude}" maxlength="256" readonly/>
296+
<label for="minlongitude">Minimum Longitude</label></td><td>
297+
<input class="form-control" id="minlongitude" name="minlongitude"
298+
value="${minlongitude}" maxlength="256"/>
299299
</td></tr><tr><td>
300300

301-
<label for="maxlongitude">Maximum Longitude [readonly]</label></td><td>
302-
<input class="form-control" type="readonly" id="maxlongitude" name="maxlongitude"
303-
value="${maxlongitude}" maxlength="256" readonly/>
301+
<label for="maxlongitude">Maximum Longitude</label></td><td>
302+
<input class="form-control" id="maxlongitude" name="maxlongitude"
303+
value="${maxlongitude}" maxlength="256"/>
304304
</td></tr><tr><td>
305305

306-
<label for="minlatitude">Minimum Latitude [readonly]</label></td><td>
307-
<input class="form-control" type="readonly" id="minlatitude" name="minlatitude"
308-
value="${minlatitude}" maxlength="256" readonly/>
306+
<label for="minlatitude">Minimum Latitude</label></td><td>
307+
<input class="form-control" id="minlatitude" name="minlatitude"
308+
value="${minlatitude}" maxlength="256" />
309309
</td></tr><tr><td>
310310

311-
<label for="maxlatitude">Maximum Latitude [readonly]</label></td><td>
312-
<input class="form-control" type="readonly" id="maxlatitude" name="maxlatitude"
313-
value="${maxlatitude}" maxlength="256" readonly/>
311+
<label for="maxlatitude">Maximum Latitude </label></td><td>
312+
<input class="form-control" id="maxlatitude" name="maxlatitude"
313+
value="${maxlatitude}" maxlength="256" />
314314
</td></tr><tr><td>
315315

316316
<label for="metadatapath">Metadata path (e.g. URL to original metadata, if available)</label>

scripts/bilConvert.c

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
Exmaple for converting an int16 raster values so that it can be converted to int8, halving the file size.
3+
4+
1. set the .bil file to open.
5+
2. set "arr", such that it is an ordered list of existing values. The new value will be the index position of the existing value.
6+
3. set the output.bil file for writing.
7+
8+
*/
9+
10+
#include <stdio.h>
11+
#include <stdint.h>
12+
13+
#define BUFFER_SIZE 1024*1024 // Adjust this value according to your system's memory capacity
14+
15+
// A recursive binary search function. It returns location of x in
16+
// given array arr[l..r] is present, otherwise returns -1
17+
int binarySearch(int arr[], int l, int r, int x){
18+
if (r >= l) {
19+
int mid = l + (r - l) / 2;
20+
21+
// If the element is present at the middle itself
22+
if (arr[mid] == x)
23+
return mid;
24+
25+
// If element is smaller than mid, then it can only be present
26+
// in left subarray
27+
if (arr[mid] > x)
28+
return binarySearch(arr, l, mid - 1, x);
29+
30+
// Else the element can only be present in right subarray
31+
return binarySearch(arr, mid + 1, r, x);
32+
}
33+
34+
// We reach here when element is not present in array
35+
return -1;
36+
}
37+
38+
int main() {
39+
FILE *file = fopen("/data/spatial-data/uploads/land_use/land_use.bil", "rb");
40+
if (file == NULL) {
41+
printf("Failed to open file.\n");
42+
return 1;
43+
}
44+
45+
FILE *outputFile = fopen("output.bil", "wb");
46+
if (outputFile == NULL) {
47+
printf("Failed to open output file.\n");
48+
return 1;
49+
}
50+
51+
// Determine the size of the file
52+
fseek(file, 0, SEEK_END);
53+
long fileSize = ftell(file);
54+
fseek(file, 0, SEEK_SET);
55+
56+
// Calculate the number of chunks
57+
long numChunks = fileSize / (BUFFER_SIZE * sizeof(int16_t));
58+
if (fileSize % (BUFFER_SIZE * sizeof(int16_t)) != 0) {
59+
numChunks++; // There is a partial chunk at the end of the file
60+
}
61+
62+
// Buffer to hold each chunk
63+
int16_t buffer[BUFFER_SIZE];
64+
65+
// create an int array to hold [1, 2, 3]
66+
int arr[192] = {0,110,111,112,113,114,115,116,117,120,121,122,123,124,125,130,131,132,133,134,210,220,221,222,310,311,312,313,314,320,321,322,323,324,325,330,331,332,333,334,335,336,337,338,340,341,342,343,344,345,346,347,348,349,350,351,352,353,360,361,362,363,364,365,410,411,412,413,414,420,421,422,423,424,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,460,461,462,463,464,465,510,511,512,513,514,515,520,521,522,523,524,525,526,527,528,530,531,532,533,534,535,536,537,538,540,541,542,543,544,545,550,551,552,553,554,555,560,561,562,563,564,565,566,567,570,571,572,573,574,575,580,581,582,583,584,590,591,592,593,594,595,610,611,612,613,614,620,621,622,623,630,631,632,633,640,641,642,643,650,651,652,653,654,660,661,662,663};
67+
68+
// initialize an array of length 100 with 0's
69+
int hist[1000] = {0};
70+
71+
printf("chunks %ld\n", numChunks);
72+
73+
// Process each chunk
74+
for (long i = 0; i < numChunks; i++) {
75+
// printf("%ld,", i);
76+
// printf(".");
77+
// Read the chunk into the buffer
78+
fread(buffer, sizeof(int16_t), BUFFER_SIZE, file);
79+
80+
// Iterate over the buffer and add 1 to each value
81+
for (int j = 0; j < BUFFER_SIZE; j++) {
82+
hist[buffer[j]]++;
83+
// printf("%d,", buffer[j]);
84+
buffer[j] = binarySearch(arr, 0, 191, buffer[j]);
85+
}
86+
87+
// Write the modified data to the output file
88+
fwrite(buffer, sizeof(int16_t), BUFFER_SIZE, outputFile);
89+
}
90+
91+
// print the histogram
92+
for (int i = 0; i < 1000; i++) {
93+
printf("\n%d: %d", i, hist[i]);
94+
}
95+
96+
fclose(file);
97+
fclose(outputFile);
98+
99+
return 0;
100+
}

scripts/bilStatus.c

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
3+
A work in progress. This will produce the "raster as contextual layer's" *.classes.json instead of using the built in process.
4+
5+
*/
6+
7+
#include <stdio.h>
8+
#include <stdint.h>
9+
10+
#define BUFFER_SIZE 1024*1024 // Adjust this value according to your system's memory capacity
11+
12+
int main() {
13+
FILE *file = fopen("/data/spatial-data/layer/land_use2.bil", "rb");
14+
if (file == NULL) {
15+
printf("Failed to open file.\n");
16+
return 1;
17+
}
18+
19+
FILE *outputFile = fopen("output.bil", "wb");
20+
if (outputFile == NULL) {
21+
printf("Failed to open output file.\n");
22+
return 1;
23+
}
24+
25+
// Determine the size of the file
26+
fseek(file, 0, SEEK_END);
27+
long fileSize = ftell(file);
28+
fseek(file, 0, SEEK_SET);
29+
30+
// Calculate the number of chunks
31+
long numChunks = fileSize / (BUFFER_SIZE * sizeof(unsigned char));
32+
if (fileSize % (BUFFER_SIZE * sizeof(unsigned char)) != 0) {
33+
numChunks++; // There is a partial chunk at the end of the file
34+
}
35+
36+
// Buffer to hold each chunk
37+
unsigned char buffer[BUFFER_SIZE];
38+
39+
int nrows = 73752;
40+
int ncols = 98262;
41+
42+
// initialize an array of length 100 with 0's
43+
int hist[192*73752] = {0};
44+
int minx[192] = {0};
45+
int miny[192] = {0};
46+
int maxx[192] = {0};
47+
int maxy[192] = {0};
48+
49+
printf("chunks %ld\n", numChunks);
50+
51+
long pos = 0;
52+
53+
54+
// Process each chunk
55+
for (long i = 0; i < numChunks; i++) {
56+
// printf("%ld,", i);
57+
// printf(".");
58+
// Read the chunk into the buffer
59+
fread(buffer, sizeof(int16_t), BUFFER_SIZE, file);
60+
61+
// Iterate over the buffer and add 1 to each value
62+
for (int j = 0; j < BUFFER_SIZE; j++) {
63+
int row = pos / ncols;
64+
int col = pos % ncols;
65+
66+
hist[buffer[j]]++;
67+
68+
minx[buffer[j]] = minx[buffer[j]] < col ? minx[buffer[j]] : col;
69+
miny[buffer[j]] = miny[buffer[j]] < row ? miny[buffer[j]] : row;
70+
maxx[buffer[j]] = maxx[buffer[j]] > col ? maxx[buffer[j]] : col;
71+
maxy[buffer[j]] = maxy[buffer[j]] > row ? maxy[buffer[j]] : row;
72+
73+
// printf("%d,", buffer[j]);
74+
// buffer[j] = binarySearch(arr, 0, 191, buffer[j]);
75+
76+
pos++;
77+
}
78+
79+
// Write the modified data to the output file
80+
fwrite(buffer, sizeof(int16_t), BUFFER_SIZE, outputFile);
81+
}
82+
83+
// print the histogram
84+
// for (int i = 0; i < 1000; i++) {
85+
// printf("\n%d: %d", i, hist[i]);
86+
// }
87+
88+
for (int i = 0; i < 192; i++) {
89+
printf("\n%d: %d, %d, %d, %d", i, hist[i], minx[i], miny[i], maxx[i], maxy[i]);
90+
}
91+
92+
fclose(file);
93+
fclose(outputFile);
94+
95+
return 0;
96+
}

src/main/groovy/au/org/ala/spatial/StreamGobbler.groovy

+6-1
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ class StreamGobbler extends Thread {
2626
BufferedReader br
2727
String logPrefix
2828
TaskWrapper taskWrapper
29+
StringBuffer stringBuffer
2930

30-
StreamGobbler(InputStream is, String logPrefix, TaskWrapper task) {
31+
StreamGobbler(InputStream is, String logPrefix, TaskWrapper task, StringBuffer stringBuffer) {
3132
br = new BufferedReader(new InputStreamReader(is))
3233
this.logPrefix = logPrefix
3334
this.taskWrapper = task
35+
this.stringBuffer = stringBuffer
3436
}
3537

3638
@Override
@@ -41,6 +43,9 @@ class StreamGobbler extends Thread {
4143
if (taskWrapper != null) {
4244
taskWrapper.task.history.put(System.currentTimeMillis() as String, logPrefix + ": " + line)
4345
}
46+
if (stringBuffer != null) {
47+
stringBuffer.append(line).append('\n');
48+
}
4449
log.debug logPrefix + ": " + line
4550
}
4651
} catch (Exception e) {

0 commit comments

Comments
 (0)