geobox 2.0.1__py3-none-any.whl → 2.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- geobox/aio/analysis.py +757 -0
- geobox/aio/api.py +101 -2
- geobox/aio/raster.py +1273 -869
- geobox/aio/task.py +1 -1
- geobox/aio/vectorlayer.py +109 -2
- geobox/analysis.py +757 -0
- geobox/api.py +102 -2
- geobox/enums.py +402 -348
- geobox/raster.py +1270 -863
- geobox/task.py +1 -1
- geobox/vectorlayer.py +107 -2
- {geobox-2.0.1.dist-info → geobox-2.1.0.dist-info}/METADATA +1 -1
- {geobox-2.0.1.dist-info → geobox-2.1.0.dist-info}/RECORD +16 -14
- {geobox-2.0.1.dist-info → geobox-2.1.0.dist-info}/WHEEL +0 -0
- {geobox-2.0.1.dist-info → geobox-2.1.0.dist-info}/licenses/LICENSE +0 -0
- {geobox-2.0.1.dist-info → geobox-2.1.0.dist-info}/top_level.txt +0 -0
geobox/raster.py
CHANGED
|
@@ -1,863 +1,1270 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from urllib.parse import urljoin, urlencode
|
|
3
|
-
from typing import Optional, Dict, List, Optional, Union, TYPE_CHECKING
|
|
4
|
-
import mimetypes
|
|
5
|
-
import requests
|
|
6
|
-
import sys
|
|
7
|
-
|
|
8
|
-
from .
|
|
9
|
-
|
|
10
|
-
from .
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
>>>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
'
|
|
75
|
-
'
|
|
76
|
-
'
|
|
77
|
-
'
|
|
78
|
-
'
|
|
79
|
-
'
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
>>>
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
>>>
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
>>>
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
str:
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
'
|
|
499
|
-
'
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
"""
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
"""
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
...
|
|
684
|
-
...
|
|
685
|
-
...
|
|
686
|
-
...
|
|
687
|
-
...
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
>>>
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
"""
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
>>>
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
"""
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
'
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
"""
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
>>>
|
|
859
|
-
>>>
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
1
|
+
import os
|
|
2
|
+
from urllib.parse import urljoin, urlencode
|
|
3
|
+
from typing import Optional, Dict, List, Optional, Union, TYPE_CHECKING
|
|
4
|
+
import mimetypes
|
|
5
|
+
import requests
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from geobox.field import Field
|
|
9
|
+
|
|
10
|
+
from .base import Base
|
|
11
|
+
from .utils import clean_data, join_url_params
|
|
12
|
+
from .task import Task
|
|
13
|
+
from .vectorlayer import VectorLayer
|
|
14
|
+
from .view import VectorLayerView
|
|
15
|
+
from .enums import PolygonizeConnectivity, AnalysisResampleMethod, SlopeUnit, AnalysisAlgorithm, AnalysisDataType, RangeBound, DistanceUnit
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from . import GeoboxClient
|
|
19
|
+
from .user import User
|
|
20
|
+
from .aio import AsyncGeoboxClient
|
|
21
|
+
from .aio.raster import Raster as AsyncRaster
|
|
22
|
+
|
|
23
|
+
class Raster(Base):
|
|
24
|
+
|
|
25
|
+
BASE_ENDPOINT: str = 'rasters/'
|
|
26
|
+
|
|
27
|
+
def __init__(self,
|
|
28
|
+
api: 'GeoboxClient',
|
|
29
|
+
uuid: str,
|
|
30
|
+
data: Optional[Dict] = {}):
|
|
31
|
+
"""
|
|
32
|
+
Constructs all the necessary attributes for the Raster object.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
api (GeoboxClient): The API instance.
|
|
36
|
+
uuid (str): The UUID of the raster.
|
|
37
|
+
data (Dict, optional): The raster data.
|
|
38
|
+
"""
|
|
39
|
+
super().__init__(api, uuid=uuid, data=data)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def get_rasters(cls, api: 'GeoboxClient', **kwargs) -> Union[List['Raster'], int]:
|
|
44
|
+
"""
|
|
45
|
+
Get all rasters.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
api (GeoboxClient): The API instance.
|
|
49
|
+
|
|
50
|
+
Keyword Args:
|
|
51
|
+
terrain (bool): whether to get terrain rasters.
|
|
52
|
+
q (str): query filter based on OGC CQL standard. e.g. "field1 LIKE '%GIS%' AND created_at > '2021-01-01'"
|
|
53
|
+
search (str): search term for keyword-based searching among search_fields or all textual fields if search_fields does not have value. NOTE: if q param is defined this param will be ignored.
|
|
54
|
+
search_fields (str): comma separated list of fields for searching
|
|
55
|
+
order_by (str): comma separated list of fields for sorting results [field1 A|D, field2 A|D, …]. e.g. name A, type D. NOTE: "A" denotes ascending order and "D" denotes descending order.
|
|
56
|
+
return_count (bool): whether to return the total count of rasters. default is False.
|
|
57
|
+
skip (int): number of rasters to skip. minimum is 0.
|
|
58
|
+
limit (int): number of rasters to return. minimum is 1.
|
|
59
|
+
user_id (int): user id to show the rasters of the user. privileges required.
|
|
60
|
+
shared (bool): whether to return shared rasters. default is False.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
List[Raster] | int: A list of Raster objects or the total count of rasters.
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
>>> from geobox import GeoboxClient
|
|
67
|
+
>>> from geobox.raster import Raster
|
|
68
|
+
>>> client = GeoboxClient()
|
|
69
|
+
>>> rasters = Raster.get_rasters(client, terrain=True, q="name LIKE '%GIS%'")
|
|
70
|
+
or
|
|
71
|
+
>>> rasters = client.get_rasters(terrain=True, q="name LIKE '%GIS%'")
|
|
72
|
+
"""
|
|
73
|
+
params = {
|
|
74
|
+
'terrain': kwargs.get('terrain', None),
|
|
75
|
+
'f': 'json',
|
|
76
|
+
'q': kwargs.get('q', None),
|
|
77
|
+
'search': kwargs.get('search', None),
|
|
78
|
+
'search_fields': kwargs.get('search_fields', None),
|
|
79
|
+
'order_by': kwargs.get('order_by', None),
|
|
80
|
+
'return_count': kwargs.get('return_count', False),
|
|
81
|
+
'skip': kwargs.get('skip', 0),
|
|
82
|
+
'limit': kwargs.get('limit', 100),
|
|
83
|
+
'user_id': kwargs.get('user_id', None),
|
|
84
|
+
'shared': kwargs.get('shared', False)
|
|
85
|
+
}
|
|
86
|
+
return super()._get_list(api, cls.BASE_ENDPOINT, params, factory_func=lambda api, item: Raster(api, item['uuid'], item))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@classmethod
|
|
91
|
+
def get_rasters_by_ids(cls, api: 'GeoboxClient', ids: List[str], user_id: int = None) -> List['Raster']:
|
|
92
|
+
"""
|
|
93
|
+
Get rasters by their IDs.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
api (GeoboxClient): The API instance.
|
|
97
|
+
ids (List[str]): The IDs of the rasters.
|
|
98
|
+
user_id (int, optional): specific user. privileges required.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
List['Raster']: A list of Raster objects.
|
|
102
|
+
|
|
103
|
+
Example:
|
|
104
|
+
>>> from geobox import GeoboxClient
|
|
105
|
+
>>> from geobox.raster import Raster
|
|
106
|
+
>>> client = GeoboxClient()
|
|
107
|
+
>>> rasters = Raster.get_rasters_by_ids(client, ids=['123', '456'])
|
|
108
|
+
or
|
|
109
|
+
>>> rasters = client.get_rasters_by_ids(ids=['123', '456'])
|
|
110
|
+
"""
|
|
111
|
+
params = {
|
|
112
|
+
'ids': ids,
|
|
113
|
+
'user_id': user_id,
|
|
114
|
+
}
|
|
115
|
+
endpoint = urljoin(cls.BASE_ENDPOINT, 'get-rasters/')
|
|
116
|
+
|
|
117
|
+
return super()._get_list_by_ids(api, endpoint, params, factory_func=lambda api, item: Raster(api, item['uuid'], item))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@classmethod
|
|
121
|
+
def get_raster(cls, api: 'GeoboxClient', uuid: str, user_id: int = None) -> 'Raster':
|
|
122
|
+
"""
|
|
123
|
+
Get a raster by its UUID.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
api (GeoboxClient): The API instance.
|
|
127
|
+
uuid (str): The UUID of the raster.
|
|
128
|
+
user_id (int, optional): specific user. privileges required.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Raster: A Raster object.
|
|
132
|
+
|
|
133
|
+
Example:
|
|
134
|
+
>>> from geobox import GeoboxClient
|
|
135
|
+
>>> from geobox.raster import Raster
|
|
136
|
+
>>> client = GeoboxClient()
|
|
137
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
138
|
+
or
|
|
139
|
+
>>> raster = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
140
|
+
"""
|
|
141
|
+
params = {
|
|
142
|
+
'f': 'json',
|
|
143
|
+
'user_id': user_id
|
|
144
|
+
}
|
|
145
|
+
return super()._get_detail(api, cls.BASE_ENDPOINT, uuid, params, factory_func=lambda api, item: Raster(api, item['uuid'], item))
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@classmethod
|
|
149
|
+
def get_raster_by_name(cls, api: 'GeoboxClient', name: str, user_id: int = None) -> Union['Raster', None]:
|
|
150
|
+
"""
|
|
151
|
+
Get a raster by name
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
api (GeoboxClient): The GeoboxClient instance for making requests.
|
|
155
|
+
name (str): the name of the raster to get
|
|
156
|
+
user_id (int, optional): specific user. privileges required.
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
Raster | None: returns the raster if a raster matches the given name, else None
|
|
160
|
+
|
|
161
|
+
Example:
|
|
162
|
+
>>> from geobox import GeoboxClient
|
|
163
|
+
>>> from geobox.raster import Raster
|
|
164
|
+
>>> client = GeoboxClient()
|
|
165
|
+
>>> raster = Raster.get_raster_by_name(client, name='test')
|
|
166
|
+
or
|
|
167
|
+
>>> raster = client.get_raster_by_name(name='test')
|
|
168
|
+
"""
|
|
169
|
+
rasters = cls.get_rasters(api, q=f"name = '{name}'", user_id=user_id)
|
|
170
|
+
if rasters and rasters[0].name == name:
|
|
171
|
+
return rasters[0]
|
|
172
|
+
else:
|
|
173
|
+
return None
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def update(self, **kwargs) -> None:
|
|
177
|
+
"""
|
|
178
|
+
Update the raster.
|
|
179
|
+
|
|
180
|
+
Keyword Args:
|
|
181
|
+
name (str): The name of the raster.
|
|
182
|
+
display_name (str): The display name of the raster.
|
|
183
|
+
description (str): The description of the raster.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
None
|
|
187
|
+
|
|
188
|
+
Example:
|
|
189
|
+
>>> from geobox import GeoboxClient
|
|
190
|
+
>>> from geobox.raster import Raster
|
|
191
|
+
>>> client = GeoboxClient()
|
|
192
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
193
|
+
>>> raster.update(name="new_name")
|
|
194
|
+
"""
|
|
195
|
+
params = {
|
|
196
|
+
'name': kwargs.get('name'),
|
|
197
|
+
'display_name': kwargs.get('display_name'),
|
|
198
|
+
'description': kwargs.get('description')
|
|
199
|
+
}
|
|
200
|
+
return super()._update(self.endpoint, params)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def delete(self) -> None:
|
|
204
|
+
"""
|
|
205
|
+
Delete the raster.
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
None
|
|
209
|
+
|
|
210
|
+
Example:
|
|
211
|
+
>>> from geobox import GeoboxClient
|
|
212
|
+
>>> from geobox.raster import Raster
|
|
213
|
+
>>> client = GeoboxClient()
|
|
214
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
215
|
+
>>> raster.delete()
|
|
216
|
+
"""
|
|
217
|
+
super().delete(self.endpoint)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def thumbnail(self) -> str:
|
|
222
|
+
"""
|
|
223
|
+
Get the thumbnail of the raster.
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
str: The url of the thumbnail.
|
|
227
|
+
|
|
228
|
+
Example:
|
|
229
|
+
>>> from geobox import GeoboxClient
|
|
230
|
+
>>> from geobox.raster import Raster
|
|
231
|
+
>>> client = GeoboxClient()
|
|
232
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
233
|
+
>>> raster.thumbnail
|
|
234
|
+
"""
|
|
235
|
+
return super().thumbnail(format='')
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def info(self) -> Dict:
|
|
240
|
+
"""
|
|
241
|
+
Get the info of the raster.
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
Dict: The info of the raster.
|
|
245
|
+
|
|
246
|
+
Example:
|
|
247
|
+
>>> from geobox import GeoboxClient
|
|
248
|
+
>>> from geobox.raster import Raster
|
|
249
|
+
>>> client = GeoboxClient()
|
|
250
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
251
|
+
>>> raster.info
|
|
252
|
+
"""
|
|
253
|
+
endpoint = urljoin(self.endpoint, 'info/')
|
|
254
|
+
return self.api.get(endpoint)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def get_statistics(self, indexes: str = None) -> Dict:
|
|
258
|
+
"""
|
|
259
|
+
Get the statistics of the raster.
|
|
260
|
+
|
|
261
|
+
Args:
|
|
262
|
+
indexes (str): list of comma separated band indexes. e.g. 1, 2, 3
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
Dict: The statistics of the raster.
|
|
266
|
+
|
|
267
|
+
Example:
|
|
268
|
+
>>> from geobox import GeoboxClient
|
|
269
|
+
>>> from geobox.raster import Raster
|
|
270
|
+
>>> client = GeoboxClient()
|
|
271
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
272
|
+
>>> raster.get_statistics(indexes='1, 2, 3')
|
|
273
|
+
"""
|
|
274
|
+
params = clean_data({
|
|
275
|
+
'indexes': indexes,
|
|
276
|
+
})
|
|
277
|
+
query_string = urlencode(params)
|
|
278
|
+
endpoint = urljoin(self.endpoint, f'statistics/?{query_string}')
|
|
279
|
+
return self.api.get(endpoint)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def get_point(self, lat: float, lng: float) -> Dict:
|
|
283
|
+
"""
|
|
284
|
+
Get the point of the raster.
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
lat (float): The latitude of the point. minimum is -90, maximum is 90.
|
|
288
|
+
lng (float): The longitude of the point. minimum is -180, maximum is 180.
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
Dict: The point of the raster.
|
|
292
|
+
|
|
293
|
+
Example:
|
|
294
|
+
>>> from geobox import GeoboxClient
|
|
295
|
+
>>> from geobox.raster import Raster
|
|
296
|
+
>>> client = GeoboxClient()
|
|
297
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
298
|
+
>>> raster.get_point(lat=60, lng=50)
|
|
299
|
+
"""
|
|
300
|
+
if lat < -90 or lat > 90:
|
|
301
|
+
raise ValueError("lat must be between -90 and 90")
|
|
302
|
+
if lng < -180 or lng > 180:
|
|
303
|
+
raise ValueError("lng must be between -180 and 180")
|
|
304
|
+
|
|
305
|
+
params = clean_data({
|
|
306
|
+
'lat': lat,
|
|
307
|
+
'lng': lng,
|
|
308
|
+
})
|
|
309
|
+
query_string = urlencode(params)
|
|
310
|
+
endpoint = urljoin(self.endpoint, f'point?{query_string}')
|
|
311
|
+
return self.api.get(endpoint)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def _get_save_path(self, save_path: str = None) -> str:
|
|
315
|
+
"""
|
|
316
|
+
Get the path where the file should be saved.
|
|
317
|
+
|
|
318
|
+
Args:
|
|
319
|
+
save_path (str, optional): The path to save the file.
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
str: The path where the file is saved.
|
|
323
|
+
|
|
324
|
+
Raises:
|
|
325
|
+
ValueError: If save_path does not end with a '/'.
|
|
326
|
+
"""
|
|
327
|
+
# If save_path is provided, check if it ends with a '/'
|
|
328
|
+
if save_path and save_path.endswith('/'):
|
|
329
|
+
return f'{save_path}'
|
|
330
|
+
|
|
331
|
+
if save_path and not save_path.endswith('/'):
|
|
332
|
+
raise ValueError("save_path must end with a '/'")
|
|
333
|
+
|
|
334
|
+
return os.getcwd()
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def _get_file_name(self, response: requests.Response) -> str:
|
|
338
|
+
"""
|
|
339
|
+
Get the file name from the response.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
response (requests.Response): The response of the request.
|
|
343
|
+
|
|
344
|
+
Returns:
|
|
345
|
+
str: The file name
|
|
346
|
+
"""
|
|
347
|
+
if 'Content-Disposition' in response.headers and 'filename=' in response.headers['Content-Disposition']:
|
|
348
|
+
file_name = response.headers['Content-Disposition'].split('filename=')[-1].strip().strip('"')
|
|
349
|
+
|
|
350
|
+
else:
|
|
351
|
+
content_type = response.headers.get("Content-Type", "")
|
|
352
|
+
file_name = f'{self.name}.{mimetypes.guess_extension(content_type.split(";")[0])}'
|
|
353
|
+
|
|
354
|
+
return file_name
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def _create_progress_bar(self) -> 'tqdm':
|
|
358
|
+
"""Creates a progress bar for the task."""
|
|
359
|
+
try:
|
|
360
|
+
from tqdm.auto import tqdm
|
|
361
|
+
except ImportError:
|
|
362
|
+
from .api import logger
|
|
363
|
+
logger.warning("[tqdm] extra is required to show the progress bar. install with: pip insatll geobox[tqdm]")
|
|
364
|
+
return None
|
|
365
|
+
|
|
366
|
+
return tqdm(unit="B",
|
|
367
|
+
total=int(self.size),
|
|
368
|
+
file=sys.stdout,
|
|
369
|
+
dynamic_ncols=True,
|
|
370
|
+
desc="Downloading",
|
|
371
|
+
unit_scale=True,
|
|
372
|
+
unit_divisor=1024,
|
|
373
|
+
ascii=True
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def download(self, save_path: str = None, progress_bar: bool = True) -> str:
|
|
378
|
+
"""
|
|
379
|
+
Download the raster.
|
|
380
|
+
|
|
381
|
+
Args:
|
|
382
|
+
save_path (str, optional): Path where the file should be saved.
|
|
383
|
+
If not provided, it saves to the current working directory
|
|
384
|
+
using the original filename and appropriate extension.
|
|
385
|
+
progress_bar (bool, optional): Whether to show a progress bar. default: True
|
|
386
|
+
|
|
387
|
+
Returns:
|
|
388
|
+
str: The path to save the raster.
|
|
389
|
+
|
|
390
|
+
Raises:
|
|
391
|
+
ValueError: If file_uuid is not set
|
|
392
|
+
OSError: If there are issues with file operations
|
|
393
|
+
|
|
394
|
+
Example:
|
|
395
|
+
>>> from geobox import GeoboxClient
|
|
396
|
+
>>> from geobox.raster import Raster
|
|
397
|
+
>>> client = GeoboxClient()
|
|
398
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
399
|
+
>>> raster.download(save_path="path/to/save/")
|
|
400
|
+
"""
|
|
401
|
+
if not self.uuid:
|
|
402
|
+
raise ValueError("Raster UUID is required to download the raster file")
|
|
403
|
+
|
|
404
|
+
save_path = self._get_save_path(save_path)
|
|
405
|
+
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
|
406
|
+
|
|
407
|
+
with self.api.get(f"{self.endpoint}download/", stream=True) as response:
|
|
408
|
+
file_name = self._get_file_name(response)
|
|
409
|
+
full_path = f"{save_path}/{file_name}"
|
|
410
|
+
with open(full_path, 'wb') as f:
|
|
411
|
+
pbar = self._create_progress_bar() if progress_bar else None
|
|
412
|
+
for chunk in response.iter_content(chunk_size=8192):
|
|
413
|
+
f.write(chunk)
|
|
414
|
+
if pbar:
|
|
415
|
+
pbar.update(len(chunk))
|
|
416
|
+
pbar.refresh()
|
|
417
|
+
if pbar:
|
|
418
|
+
pbar.close()
|
|
419
|
+
|
|
420
|
+
return os.path.abspath(full_path)
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def get_content_file(self, save_path: str = None, progress_bar: bool = True) -> str:
|
|
424
|
+
"""
|
|
425
|
+
Get Raster Content URL
|
|
426
|
+
|
|
427
|
+
Args:
|
|
428
|
+
save_path (str, optional): Path where the file should be saved.
|
|
429
|
+
If not provided, it saves to the current working directory
|
|
430
|
+
using the original filename and appropriate extension.
|
|
431
|
+
progress_bar (bool, optional): Whether to show a progress bar. default: True
|
|
432
|
+
|
|
433
|
+
Returns:
|
|
434
|
+
str: The path to save the raster.
|
|
435
|
+
|
|
436
|
+
Raises:
|
|
437
|
+
ValueError: If uuid is not set
|
|
438
|
+
OSError: If there are issues with file operations
|
|
439
|
+
|
|
440
|
+
Examples:
|
|
441
|
+
>>> from geobox import GeoboxClient
|
|
442
|
+
>>> from geobox.raster import Raster
|
|
443
|
+
>>> client = GeoboxClient()
|
|
444
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
445
|
+
>>> raster_tiff = raste.get_content_file()
|
|
446
|
+
"""
|
|
447
|
+
if not self.uuid:
|
|
448
|
+
raise ValueError("Raster UUID is required to download the raster content")
|
|
449
|
+
|
|
450
|
+
save_path = self._get_save_path(save_path)
|
|
451
|
+
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
|
452
|
+
|
|
453
|
+
with self.api.get(f"{self.endpoint}content/", stream=True) as response:
|
|
454
|
+
file_name = self._get_file_name(response)
|
|
455
|
+
full_path = f"{save_path}/{file_name}"
|
|
456
|
+
with open(full_path, 'wb') as f:
|
|
457
|
+
pbar = self._create_progress_bar() if progress_bar else None
|
|
458
|
+
for chunk in response.iter_content(chunk_size=8192):
|
|
459
|
+
f.write(chunk)
|
|
460
|
+
if pbar:
|
|
461
|
+
pbar.update(len(chunk))
|
|
462
|
+
pbar.refresh()
|
|
463
|
+
if pbar:
|
|
464
|
+
pbar.close()
|
|
465
|
+
|
|
466
|
+
return os.path.abspath(full_path)
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
def get_render_png_url(self, x: int, y: int, z: int, **kwargs) -> str:
|
|
470
|
+
"""
|
|
471
|
+
Get the PNG URL of the raster.
|
|
472
|
+
|
|
473
|
+
Args:
|
|
474
|
+
x (int): The x coordinate of the tile.
|
|
475
|
+
y (int): The y coordinate of the tile.
|
|
476
|
+
z (int): The zoom level of the tile.
|
|
477
|
+
|
|
478
|
+
Keyword Args:
|
|
479
|
+
indexes (str, optional): list of comma separated band indexes to be rendered. e.g. 1, 2, 3
|
|
480
|
+
nodata (int, optional)
|
|
481
|
+
expression (str, optional): band math expression. e.g. b1*b2+b3
|
|
482
|
+
rescale (List, optional): comma (',') separated Min,Max range. Can set multiple time for multiple bands.
|
|
483
|
+
color_formula (str, optional): Color formula. e.g. gamma R 0.5
|
|
484
|
+
colormap_name (str, optional)
|
|
485
|
+
colormap (str, optional): JSON encoded custom Colormap. e.g. {"0": "#ff0000", "1": "#00ff00"} or [[[0, 100], "#ff0000"], [[100, 200], "#00ff00"]]
|
|
486
|
+
|
|
487
|
+
Returns:
|
|
488
|
+
str: The PNG Render URL of the raster.
|
|
489
|
+
|
|
490
|
+
Example:
|
|
491
|
+
>>> from geobox import GeoboxClient
|
|
492
|
+
>>> from geobox.raster import Raster
|
|
493
|
+
>>> client = GeoboxClient()
|
|
494
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
495
|
+
>>> raster.get_tile_render_url(x=10, y=20, z=1)
|
|
496
|
+
"""
|
|
497
|
+
params = clean_data({
|
|
498
|
+
'indexes': kwargs.get('indexes'),
|
|
499
|
+
'nodata': kwargs.get('nodata'),
|
|
500
|
+
'expression': kwargs.get('expression'),
|
|
501
|
+
'rescale': kwargs.get('rescale'),
|
|
502
|
+
'color_formula': kwargs.get('color_formula'),
|
|
503
|
+
'colormap_name': kwargs.get('colormap_name'),
|
|
504
|
+
'colormap': kwargs.get('colormap')
|
|
505
|
+
})
|
|
506
|
+
query_string = urlencode(params)
|
|
507
|
+
endpoint = f'{self.api.base_url}{self.endpoint}render/{z}/{x}/{y}.png'
|
|
508
|
+
if query_string:
|
|
509
|
+
endpoint = f'{endpoint}?{query_string}'
|
|
510
|
+
|
|
511
|
+
if not self.api.access_token and self.api.apikey:
|
|
512
|
+
endpoint = join_url_params(endpoint, {"apikey": self.api.apikey})
|
|
513
|
+
|
|
514
|
+
return endpoint
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def get_tile_pbf_url(self, x: int = '{x}', y: int = '{y}', z: int = '{z}', indexes: str = None) -> str:
|
|
518
|
+
"""
|
|
519
|
+
Get the URL of the tile.
|
|
520
|
+
|
|
521
|
+
Args:
|
|
522
|
+
x (int, optional): The x coordinate of the tile.
|
|
523
|
+
y (int, optional): The y coordinate of the tile.
|
|
524
|
+
z (int, optional): The zoom level of the tile.
|
|
525
|
+
indexes (str, optional): list of comma separated band indexes to be rendered. e.g. 1, 2, 3
|
|
526
|
+
|
|
527
|
+
Returns:
|
|
528
|
+
str: The URL of the tile.
|
|
529
|
+
|
|
530
|
+
Example:
|
|
531
|
+
>>> from geobox import GeoboxClient
|
|
532
|
+
>>> from geobox.raster import Raster
|
|
533
|
+
>>> client = GeoboxClient()
|
|
534
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
535
|
+
>>> raster.get_tile_pbf_url(x=10, y=20, z=1)
|
|
536
|
+
"""
|
|
537
|
+
params = clean_data({
|
|
538
|
+
'indexes': indexes
|
|
539
|
+
})
|
|
540
|
+
query_string = urlencode(params)
|
|
541
|
+
endpoint = urljoin(self.api.base_url, f'{self.endpoint}tiles/{z}/{x}/{y}.pbf')
|
|
542
|
+
endpoint = urljoin(endpoint, f'?{query_string}')
|
|
543
|
+
|
|
544
|
+
if not self.api.access_token and self.api.apikey:
|
|
545
|
+
endpoint = join_url_params(endpoint, {"apikey": self.api.apikey})
|
|
546
|
+
|
|
547
|
+
return endpoint
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
def get_tile_png_url(self, x: int = 'x', y: int = 'y', z: int = 'z') -> str:
|
|
551
|
+
"""
|
|
552
|
+
Get the URL of the tile.
|
|
553
|
+
|
|
554
|
+
Args:
|
|
555
|
+
x (int, optional): The x coordinate of the tile.
|
|
556
|
+
y (int, optional): The y coordinate of the tile.
|
|
557
|
+
z (int, optional): The zoom level of the tile.
|
|
558
|
+
|
|
559
|
+
Returns:
|
|
560
|
+
str: The URL of the tile.
|
|
561
|
+
|
|
562
|
+
Example:
|
|
563
|
+
>>> from geobox import GeoboxClient
|
|
564
|
+
>>> from geobox.raster import Raster
|
|
565
|
+
>>> client = GeoboxClient()
|
|
566
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
567
|
+
>>> raster.get_tile_png_url(x=10, y=20, z=1)
|
|
568
|
+
"""
|
|
569
|
+
endpoint = f'{self.api.base_url}{self.endpoint}tiles/{z}/{x}/{y}.png'
|
|
570
|
+
|
|
571
|
+
if not self.api.access_token and self.api.apikey:
|
|
572
|
+
endpoint = f'{endpoint}?apikey={self.api.apikey}'
|
|
573
|
+
|
|
574
|
+
return endpoint
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def get_tile_json(self) -> Dict:
|
|
578
|
+
"""
|
|
579
|
+
Get the tile JSON of the raster.
|
|
580
|
+
|
|
581
|
+
Returns:
|
|
582
|
+
Dict: The tile JSON of the raster.
|
|
583
|
+
|
|
584
|
+
Example:
|
|
585
|
+
>>> from geobox import GeoboxClient
|
|
586
|
+
>>> from geobox.raster import Raster
|
|
587
|
+
>>> client = GeoboxClient()
|
|
588
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
589
|
+
>>> raster.get_tile_json()
|
|
590
|
+
"""
|
|
591
|
+
endpoint = urljoin(self.endpoint, 'tilejson.json')
|
|
592
|
+
return self.api.get(endpoint)
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
def wmts(self, scale: int = None) -> str:
|
|
596
|
+
"""
|
|
597
|
+
Get the WMTS URL
|
|
598
|
+
|
|
599
|
+
Args:
|
|
600
|
+
scale (int, optional): The scale of the raster. values are: 1, 2
|
|
601
|
+
|
|
602
|
+
Returns:
|
|
603
|
+
str: the raster WMTS URL
|
|
604
|
+
|
|
605
|
+
Example:
|
|
606
|
+
>>> from geobox import GeoboxClient
|
|
607
|
+
>>> from geobox.raster import Raster
|
|
608
|
+
>>> client = GeoboxClient()
|
|
609
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
610
|
+
>>> raster.wmts(scale=1)
|
|
611
|
+
"""
|
|
612
|
+
endpoint = urljoin(self.api.base_url, f'{self.endpoint}wmts/')
|
|
613
|
+
if scale:
|
|
614
|
+
endpoint = f"{endpoint}?scale={scale}"
|
|
615
|
+
|
|
616
|
+
if not self.api.access_token and self.api.apikey:
|
|
617
|
+
endpoint = join_url_params(endpoint, {"apikey": self.api.apikey})
|
|
618
|
+
|
|
619
|
+
return endpoint
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
@property
|
|
623
|
+
def settings(self) -> Dict:
|
|
624
|
+
"""
|
|
625
|
+
Get the settings of the raster.
|
|
626
|
+
|
|
627
|
+
Returns:
|
|
628
|
+
Dict: The settings of the raster.
|
|
629
|
+
|
|
630
|
+
Example:
|
|
631
|
+
>>> from geobox import GeoboxClient
|
|
632
|
+
>>> from geobox.raster import Raster
|
|
633
|
+
>>> client = GeoboxClient()
|
|
634
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
635
|
+
>>> raster.settings
|
|
636
|
+
"""
|
|
637
|
+
return super()._get_settings(self.endpoint)
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
def update_settings(self, settings: Dict) -> Dict:
|
|
641
|
+
"""
|
|
642
|
+
Update the settings
|
|
643
|
+
|
|
644
|
+
settings (Dict): settings dictionary
|
|
645
|
+
|
|
646
|
+
Returns:
|
|
647
|
+
Dict: updated settings
|
|
648
|
+
|
|
649
|
+
Example:
|
|
650
|
+
>>> from geobox import GeoboxClient
|
|
651
|
+
>>> client = GeoboxClient()
|
|
652
|
+
>>> raster1 = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
653
|
+
>>> raster2 = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
654
|
+
>>> raster1.update_settings(raster2.settings)
|
|
655
|
+
"""
|
|
656
|
+
return super()._set_settings(self.endpoint, settings)
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
def set_settings(self, **kwargs) -> None:
|
|
660
|
+
"""
|
|
661
|
+
Set the settings of the raster.
|
|
662
|
+
|
|
663
|
+
Keyword Args:
|
|
664
|
+
nodata (int): The nodata value of the raster.
|
|
665
|
+
indexes (list[int]): The indexes of the raster.
|
|
666
|
+
rescale (list[int]): The rescale of the raster.
|
|
667
|
+
colormap_name (str): The colormap name of the raster.
|
|
668
|
+
color_formula (str): The color formula of the raster.
|
|
669
|
+
expression (str): The expression of the raster.
|
|
670
|
+
exaggeraion (int): The exaggeraion of the raster.
|
|
671
|
+
min_zoom (int): The min zoom of the raster.
|
|
672
|
+
max_zoom (int): The max zoom of the raster.
|
|
673
|
+
use_cache (bool): Whether to use cache of the raster.
|
|
674
|
+
cache_until_zoom (int): The cache until zoom of the raster.
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
Example:
|
|
678
|
+
>>> from geobox import GeoboxClient
|
|
679
|
+
>>> from geobox.raster import Raster
|
|
680
|
+
>>> client = GeoboxClient()
|
|
681
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
682
|
+
>>> raster.set_settings(nodata=0,
|
|
683
|
+
... indexes=[1],
|
|
684
|
+
... rescale=[[0, 10000]],
|
|
685
|
+
... colormap_name='gist_rainbow',
|
|
686
|
+
... color_formula='Gamma R 0.5',
|
|
687
|
+
... expression='b1 * 2',
|
|
688
|
+
... exaggeraion=10,
|
|
689
|
+
... min_zoom=0,
|
|
690
|
+
... max_zoom=22,
|
|
691
|
+
... use_cache=True,
|
|
692
|
+
... cache_until_zoom=17)
|
|
693
|
+
"""
|
|
694
|
+
visual_settings = {
|
|
695
|
+
'nodata', 'indexes', 'rescale', 'colormap_name',
|
|
696
|
+
'color_formula', 'expression', 'exaggeraion'
|
|
697
|
+
}
|
|
698
|
+
tile_settings = {
|
|
699
|
+
'min_zoom', 'max_zoom', 'use_cache', 'cache_until_zoom'
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
settings = self.settings
|
|
703
|
+
|
|
704
|
+
for key, value in kwargs.items():
|
|
705
|
+
if key in visual_settings:
|
|
706
|
+
settings['visual_settings'][key] = value
|
|
707
|
+
elif key in tile_settings:
|
|
708
|
+
settings['tile_settings'][key] = value
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
return super()._set_settings(self.endpoint, settings)
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
def share(self, users: List['User']) -> None:
|
|
715
|
+
"""
|
|
716
|
+
Shares the raster with specified users.
|
|
717
|
+
|
|
718
|
+
Args:
|
|
719
|
+
users (List[User]): The list of user objects to share the raster with.
|
|
720
|
+
|
|
721
|
+
Returns:
|
|
722
|
+
None
|
|
723
|
+
|
|
724
|
+
Example:
|
|
725
|
+
>>> from geobox import GeoboxClient
|
|
726
|
+
>>> from geobox.raster import Raster
|
|
727
|
+
>>> client = GeoboxClient()
|
|
728
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
729
|
+
>>> users = client.search_users(search="John")
|
|
730
|
+
>>> raster.share(users=users)
|
|
731
|
+
"""
|
|
732
|
+
super()._share(self.endpoint, users)
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
def unshare(self, users: List['User']) -> None:
|
|
736
|
+
"""
|
|
737
|
+
Unshares the raster with specified users.
|
|
738
|
+
|
|
739
|
+
Args:
|
|
740
|
+
users (List[User]): The list of user objects to unshare the raster with.
|
|
741
|
+
|
|
742
|
+
Returns:
|
|
743
|
+
None
|
|
744
|
+
|
|
745
|
+
Example:
|
|
746
|
+
>>> from geobox import GeoboxClient
|
|
747
|
+
>>> from geobox.raster import Raster
|
|
748
|
+
>>> client = GeoboxClient()
|
|
749
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
750
|
+
>>> users = client.search_users(search="John")
|
|
751
|
+
>>> raster.unshare(users=users)
|
|
752
|
+
"""
|
|
753
|
+
super()._unshare(self.endpoint, users)
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
def get_shared_users(self, search: str = None, skip: int = 0, limit: int = 10) -> List['User']:
|
|
757
|
+
"""
|
|
758
|
+
Retrieves the list of users the raster is shared with.
|
|
759
|
+
|
|
760
|
+
Args:
|
|
761
|
+
search (str, optional): The search query.
|
|
762
|
+
skip (int, optional): The number of users to skip.
|
|
763
|
+
limit (int, optional): The maximum number of users to retrieve.
|
|
764
|
+
|
|
765
|
+
Returns:
|
|
766
|
+
List[User]: The list of shared users.
|
|
767
|
+
|
|
768
|
+
Example:
|
|
769
|
+
>>> from geobox import GeoboxClient
|
|
770
|
+
>>> from geobox.raster import Raster
|
|
771
|
+
>>> client = GeoboxClient()
|
|
772
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
773
|
+
>>> raster.get_shared_users(search='John', skip=0, limit=10)
|
|
774
|
+
"""
|
|
775
|
+
params = {
|
|
776
|
+
'search': search,
|
|
777
|
+
'skip': skip,
|
|
778
|
+
'limit': limit
|
|
779
|
+
}
|
|
780
|
+
return super()._get_shared_users(self.endpoint, params)
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
def seed_cache(self, from_zoom: int = None, to_zoom: int = None, extent: List[int] = None, workers: int = 1) -> List['Task']:
|
|
784
|
+
"""
|
|
785
|
+
Seed the cache of the raster.
|
|
786
|
+
|
|
787
|
+
Args:
|
|
788
|
+
from_zoom (int, optional): The from zoom of the raster.
|
|
789
|
+
to_zoom (int, optional): The to zoom of the raster.
|
|
790
|
+
extent (List[int], optional): The extent of the raster.
|
|
791
|
+
workers (int, optional): The number of workers to use. default is 1.
|
|
792
|
+
|
|
793
|
+
Returns:
|
|
794
|
+
Task: The task of the seed cache.
|
|
795
|
+
|
|
796
|
+
Example:
|
|
797
|
+
>>> from geobox import GeoboxClient
|
|
798
|
+
>>> from geobox.raster import Raster
|
|
799
|
+
>>> client = GeoboxClient()
|
|
800
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
801
|
+
>>> task = raster.seed_cache(from_zoom=0, to_zoom=22, extent=[0, 0, 100, 100], workers=1)
|
|
802
|
+
"""
|
|
803
|
+
data = {
|
|
804
|
+
'from_zoom': from_zoom,
|
|
805
|
+
'to_zoom': to_zoom,
|
|
806
|
+
'extent': extent,
|
|
807
|
+
'workers': workers
|
|
808
|
+
}
|
|
809
|
+
return super()._seed_cache(self.endpoint, data)
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
def clear_cache(self) -> None:
|
|
813
|
+
"""
|
|
814
|
+
Clear the cache of the raster.
|
|
815
|
+
|
|
816
|
+
Returns:
|
|
817
|
+
None
|
|
818
|
+
|
|
819
|
+
Example:
|
|
820
|
+
>>> from geobox import GeoboxClient
|
|
821
|
+
>>> from geobox.raster import Raster
|
|
822
|
+
>>> client = GeoboxClient()
|
|
823
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
824
|
+
>>> raster.clear_cache()
|
|
825
|
+
"""
|
|
826
|
+
super()._clear_cache(self.endpoint)
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
@property
|
|
830
|
+
def cache_size(self) -> int:
|
|
831
|
+
"""
|
|
832
|
+
Get the size of the cache of the raster.
|
|
833
|
+
|
|
834
|
+
Returns:
|
|
835
|
+
int: The size of the cache of the raster.
|
|
836
|
+
|
|
837
|
+
Example:
|
|
838
|
+
>>> from geobox import GeoboxClient
|
|
839
|
+
>>> from geobox.raster import Raster
|
|
840
|
+
>>> client = GeoboxClient()
|
|
841
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
842
|
+
>>> raster.cache_size
|
|
843
|
+
"""
|
|
844
|
+
return super()._cache_size(self.endpoint)
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
def to_async(self, async_client: 'AsyncGeoboxClient') -> 'AsyncRaster':
|
|
848
|
+
"""
|
|
849
|
+
Switch to async version of the raster instance to have access to the async methods
|
|
850
|
+
|
|
851
|
+
Args:
|
|
852
|
+
async_client (AsyncGeoboxClient): The async version of the GeoboxClient instance for making requests.
|
|
853
|
+
|
|
854
|
+
Returns:
|
|
855
|
+
geobox.aio.raster.Raster: the async instance of the raster.
|
|
856
|
+
|
|
857
|
+
Example:
|
|
858
|
+
>>> from geobox import Geoboxclient
|
|
859
|
+
>>> from geobox.aio import AsyncGeoboxClient
|
|
860
|
+
>>> from geobox.raster import Raster
|
|
861
|
+
>>> client = GeoboxClient()
|
|
862
|
+
>>> raster = Raster.get_raster(client, uuid="12345678-1234-5678-1234-567812345678")
|
|
863
|
+
>>> async with AsyncGeoboxClient() as async_client:
|
|
864
|
+
>>> async_raster = raster.to_async(async_client)
|
|
865
|
+
"""
|
|
866
|
+
from .aio.raster import Raster as AsyncRaster
|
|
867
|
+
|
|
868
|
+
return AsyncRaster(api=async_client, uuid=self.uuid, data=self.data)
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
def polygonize(self,
|
|
872
|
+
output_layer_name: str,
|
|
873
|
+
band_index: int = 1,
|
|
874
|
+
value_field: Optional[str] = None,
|
|
875
|
+
mask_nodata: bool = False,
|
|
876
|
+
connectivity: PolygonizeConnectivity = PolygonizeConnectivity.connected_4,
|
|
877
|
+
keep_values: Optional[str] = None,
|
|
878
|
+
layer_name: Optional[str] = None,
|
|
879
|
+
user_id: Optional[int] = None) -> 'Task':
|
|
880
|
+
"""
|
|
881
|
+
Convert a raster to vector polygons
|
|
882
|
+
|
|
883
|
+
vectorizes a raster (polygonize) to a vector dataset (*.gpkg). Only users with Publisher role or higher can perform this operation
|
|
884
|
+
|
|
885
|
+
Args:
|
|
886
|
+
api (GeoboxClient): The GeoboxClient instance for making requests
|
|
887
|
+
raster (Raster): Raster instance
|
|
888
|
+
output_layer_name (str): Name for the output vector layer.
|
|
889
|
+
band_index (int, optional): Raster band to polygonize. default: 1
|
|
890
|
+
value_field (str, optional): Name of attribute field storing the pixel value. default: None
|
|
891
|
+
mask_nodata (bool, optional): If True, NoData pixels are excluded using the band mask. default: False
|
|
892
|
+
connectivity (PolygonizeConnectivity, optional): 4 or 8 connectivity for region grouping. default: PolygonizeConnectivity.connected_4
|
|
893
|
+
keep_values (str, optional): JSON array of values to keep (e.g., '[1,2,3]'). default: None
|
|
894
|
+
layer_name (str, optional): Output layer name. default: None
|
|
895
|
+
user_id (int, optional): specific user. priviledges required!
|
|
896
|
+
|
|
897
|
+
Returns:
|
|
898
|
+
Task: task instance of the process
|
|
899
|
+
|
|
900
|
+
Example:
|
|
901
|
+
>>> from geobox import GeoboxClient
|
|
902
|
+
>>> client = GeoboxClient()
|
|
903
|
+
>>> raster = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
904
|
+
>>> raster.polygonize(output_layer_name='test')
|
|
905
|
+
"""
|
|
906
|
+
from .analysis import Analysis
|
|
907
|
+
return Analysis.polygonize(self.api,
|
|
908
|
+
self,
|
|
909
|
+
output_layer_name=output_layer_name,
|
|
910
|
+
band_index=band_index,
|
|
911
|
+
value_field=value_field,
|
|
912
|
+
mask_nodata=mask_nodata,
|
|
913
|
+
connectivity=connectivity,
|
|
914
|
+
keep_values=keep_values,
|
|
915
|
+
layer_name=layer_name,
|
|
916
|
+
user_id=user_id)
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
def clip(self,
|
|
920
|
+
layer: Union[VectorLayer, VectorLayerView],
|
|
921
|
+
output_raster_name: str,
|
|
922
|
+
where: Optional[str] = None,
|
|
923
|
+
dst_nodata: int = -9999,
|
|
924
|
+
crop: bool = True,
|
|
925
|
+
resample: AnalysisResampleMethod = AnalysisResampleMethod.near,
|
|
926
|
+
user_id: Optional[int] = None) -> 'Task':
|
|
927
|
+
"""
|
|
928
|
+
Clip a raster using a vector layer as a mask
|
|
929
|
+
|
|
930
|
+
clips a raster dataset using a vector layer as the clipping boundary. Only users with Publisher role or higher can perform this operation
|
|
931
|
+
|
|
932
|
+
Args:
|
|
933
|
+
api (GeoboxClient): The GeoboxClient instance for making requests
|
|
934
|
+
raster (Raster): Raster instance
|
|
935
|
+
layer (VectorLayer | VectorLayerView): VectorLayer or VectorLayerView instance
|
|
936
|
+
output_raster_name (str): Name for the output raster dataset
|
|
937
|
+
where (str, optional): Optional attribute filter, e.g. 'VEG=forest'.
|
|
938
|
+
dst_nodata (int, optional): Output NoData value. default: -9999
|
|
939
|
+
crop (bool, optional): True=shrink extent to polygon(s); False=keep full extent but mask outside. default: True
|
|
940
|
+
resample (AnalysisResampleMethod, optional): Resampling method: 'near', 'bilinear', 'cubic', 'lanczos', etc. default: AnalysisResampleMethod.near
|
|
941
|
+
user_id (int, optional): specific user. priviledges required!
|
|
942
|
+
|
|
943
|
+
Returns:
|
|
944
|
+
Task: task instance of the process
|
|
945
|
+
|
|
946
|
+
Example:
|
|
947
|
+
>>> from geobox import GeoboxClient
|
|
948
|
+
>>> client = GeoboxClient()
|
|
949
|
+
>>> raster = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
950
|
+
>>> vector = client.get_vector(uuid="12345678-1234-5678-1234-567812345678")
|
|
951
|
+
>>> raster.clip(layer=vector, output_raster_name='test')
|
|
952
|
+
"""
|
|
953
|
+
from .analysis import Analysis
|
|
954
|
+
return Analysis.clip(self.api,
|
|
955
|
+
self,
|
|
956
|
+
layer=layer,
|
|
957
|
+
output_raster_name=output_raster_name,
|
|
958
|
+
where=where,
|
|
959
|
+
dst_nodata=dst_nodata,
|
|
960
|
+
crop=crop,
|
|
961
|
+
resample=resample,
|
|
962
|
+
user_id=user_id)
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
def slope(self,
|
|
966
|
+
output_raster_name: str,
|
|
967
|
+
slope_units: SlopeUnit = SlopeUnit.degree,
|
|
968
|
+
algorithm: AnalysisAlgorithm = AnalysisAlgorithm.Horn,
|
|
969
|
+
scale: int = 1,
|
|
970
|
+
compute_edges: bool = True,
|
|
971
|
+
nodata_out: int = -9999,
|
|
972
|
+
user_id: Optional[int] = None) -> 'Task':
|
|
973
|
+
"""
|
|
974
|
+
Calculate slope from a DEM raster.
|
|
975
|
+
|
|
976
|
+
This endpoint creates a slope raster from a Digital Elevation Model (DEM). Only users with Publisher role or higher can perform this operation.
|
|
977
|
+
|
|
978
|
+
Args:
|
|
979
|
+
output_raster_name (str): Name for the output raster dataset.
|
|
980
|
+
slope_units (SlopeUnit, optional): Slope units: 'degree' or 'percent'. default: SlopeUnit.degree
|
|
981
|
+
algorithm (AnalysisAlgorithm, optional): Algorithm: 'Horn' or 'ZevenbergenThorne'. default: AnalysisAlgorithm.Horn
|
|
982
|
+
scale (int, optional): Ratio of vertical units to horizontal units. default: 1
|
|
983
|
+
compute_edges (bool, optional): Whether to compute edges. default: True
|
|
984
|
+
nodata (int, optional): NoData value for the output raster. default = -9999
|
|
985
|
+
user_id (int, optional): specific user. priviledges required!
|
|
986
|
+
|
|
987
|
+
Returns:
|
|
988
|
+
Task: task instance of the process
|
|
989
|
+
|
|
990
|
+
Example:
|
|
991
|
+
>>> from geobox import GeoboxClient
|
|
992
|
+
>>> client = GeoboxClient()
|
|
993
|
+
>>> raster = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
994
|
+
>>> raster.slope(output_raster_name='test')
|
|
995
|
+
"""
|
|
996
|
+
from .analysis import Analysis
|
|
997
|
+
return Analysis.slope(self.api,
|
|
998
|
+
self,
|
|
999
|
+
slope_units=slope_units,
|
|
1000
|
+
output_raster_name=output_raster_name,
|
|
1001
|
+
algorithm=algorithm,
|
|
1002
|
+
scale=scale,
|
|
1003
|
+
compute_edges=compute_edges,
|
|
1004
|
+
nodata_out=nodata_out,
|
|
1005
|
+
user_id=user_id)
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
def aspect(self,
|
|
1009
|
+
output_raster_name: str,
|
|
1010
|
+
algorithm: AnalysisAlgorithm = AnalysisAlgorithm.Horn,
|
|
1011
|
+
trigonometric: bool = False,
|
|
1012
|
+
zero_for_flat: bool = True,
|
|
1013
|
+
compute_edges: bool = True,
|
|
1014
|
+
nodata_out: int = -9999,
|
|
1015
|
+
user_id: Optional[int] = None) -> 'Task':
|
|
1016
|
+
"""
|
|
1017
|
+
Calculate aspect from a DEM raster.
|
|
1018
|
+
|
|
1019
|
+
it creates an aspect raster (degrees 0–360) from a Digital Elevation Model (DEM).
|
|
1020
|
+
Only users with Publisher role or higher can perform this operation.
|
|
1021
|
+
|
|
1022
|
+
Args:
|
|
1023
|
+
api (GeoboxClient): The GeoboxClient instance for making requests
|
|
1024
|
+
raster (Raster): DEM Raster instance
|
|
1025
|
+
output_raster_name (str): Name for the output raster dataset.
|
|
1026
|
+
algorithm (AnalysisAlgorithm, optional): Algorithm: 'Horn' or 'ZevenbergenThorne'. default: AnalysisAlgorithm.Horn
|
|
1027
|
+
trigonometric (bool, optional): False: azimuth (0°=N, 90°=E, clockwise); True: 0°=E, counter-clockwise. default: False
|
|
1028
|
+
zero_for_flat (bool, optional): Set flats (slope==0) to 0 instead of NoData. default: True
|
|
1029
|
+
compute_edges (bool, optional): Whether to compute edges. default: True
|
|
1030
|
+
nodata (int, optional): NoData value for the output raster. default = -9999
|
|
1031
|
+
user_id (int, optional): specific user. priviledges required!
|
|
1032
|
+
|
|
1033
|
+
Returns:
|
|
1034
|
+
Task: task instance of the process
|
|
1035
|
+
|
|
1036
|
+
Example:
|
|
1037
|
+
>>> from geobox import GeoboxClient
|
|
1038
|
+
>>> client = GeoboxClient()
|
|
1039
|
+
>>> raster = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
1040
|
+
>>> raster.aspect(output_raster_name='test')
|
|
1041
|
+
"""
|
|
1042
|
+
from .analysis import Analysis
|
|
1043
|
+
return Analysis.aspect(self.api,
|
|
1044
|
+
self,
|
|
1045
|
+
output_raster_name=output_raster_name,
|
|
1046
|
+
algorithm=algorithm,
|
|
1047
|
+
trigonometric=trigonometric,
|
|
1048
|
+
zero_for_flat=zero_for_flat,
|
|
1049
|
+
compute_edges=compute_edges,
|
|
1050
|
+
nodata_out=nodata_out,
|
|
1051
|
+
user_id=user_id)
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
def reclassify(self,
|
|
1055
|
+
output_raster_name: str,
|
|
1056
|
+
rules: str,
|
|
1057
|
+
default_value: Optional[int] = None,
|
|
1058
|
+
nodata_in: int = -9999,
|
|
1059
|
+
nodata_out: int = -9999,
|
|
1060
|
+
out_dtype: AnalysisDataType = AnalysisDataType.int16,
|
|
1061
|
+
inclusive: RangeBound = RangeBound.left,
|
|
1062
|
+
user_id: Optional[int] = None) -> 'Task':
|
|
1063
|
+
"""
|
|
1064
|
+
Reclassify a raster using value mapping or class breaks.
|
|
1065
|
+
|
|
1066
|
+
This endpoint reclassifies raster values according to specified rules.
|
|
1067
|
+
Only users with Publisher role or higher can perform this operation.
|
|
1068
|
+
|
|
1069
|
+
Args:
|
|
1070
|
+
output_raster_name (str): Name for the output reclassified raster dataset.
|
|
1071
|
+
rules (str): JSON string containing reclassification rules.
|
|
1072
|
+
For mode='exact', it should be a dict {old_value: new_value}.
|
|
1073
|
+
For mode='range', it should be a list of (low, high, new_value).
|
|
1074
|
+
Example for mode='exact': '{"1": 10, "2": 20, "3": 30}'.
|
|
1075
|
+
Example for mode='range': '[[0, 10, 1], [10, 20, 2], [20, 30, 3]]'.
|
|
1076
|
+
the method would detect the mode type based on the rules input.
|
|
1077
|
+
default_value (str, optional): Value to assign when a pixel matches no rule.
|
|
1078
|
+
nodata_in (int, optional): NoData of input. If None, tries to get from the input raster.
|
|
1079
|
+
nodata_out (int, optional): NoData value to set on output band.
|
|
1080
|
+
out_dtype (AnalysisDataType, optional): Output data type. default: AnalysisDataType.int16
|
|
1081
|
+
inclusive (RangeBound, optional): Range bound semantics for mode='range': 'left', 'right', 'both', 'neither'. default: RangeBound.left
|
|
1082
|
+
user_id (int, optional): specific user. priviledges required!
|
|
1083
|
+
|
|
1084
|
+
Returns:
|
|
1085
|
+
Task: task instance of the process
|
|
1086
|
+
|
|
1087
|
+
Example:
|
|
1088
|
+
>>> from geobox import GeoboxClient
|
|
1089
|
+
>>> client = GeoboxClient()
|
|
1090
|
+
>>> raster = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
1091
|
+
>>> raster.reclassify(output_raster_name='test', rules='{"1": 10, "2": 20, "3": 30}')
|
|
1092
|
+
"""
|
|
1093
|
+
from .analysis import Analysis
|
|
1094
|
+
return Analysis.reclassify(self.api,
|
|
1095
|
+
self,
|
|
1096
|
+
output_raster_name=output_raster_name,
|
|
1097
|
+
rules=rules,
|
|
1098
|
+
default_value=default_value,
|
|
1099
|
+
nodata_in=nodata_in,
|
|
1100
|
+
nodata_out=nodata_out,
|
|
1101
|
+
out_dtype=out_dtype,
|
|
1102
|
+
inclusive=inclusive,
|
|
1103
|
+
user_id=user_id)
|
|
1104
|
+
|
|
1105
|
+
|
|
1106
|
+
def resample(self,
|
|
1107
|
+
output_raster_name: str,
|
|
1108
|
+
out_res: Optional[str] = None,
|
|
1109
|
+
scale_factor: Optional[str] = None,
|
|
1110
|
+
match_raster_uuid: Optional[str] = None,
|
|
1111
|
+
resample_method: AnalysisResampleMethod = AnalysisResampleMethod.near,
|
|
1112
|
+
dst_nodata: int = -9999,
|
|
1113
|
+
user_id: Optional[int] = None) -> 'Task':
|
|
1114
|
+
"""
|
|
1115
|
+
Resample a raster to a different resolution.
|
|
1116
|
+
|
|
1117
|
+
it resamples a raster using GDAL Warp.
|
|
1118
|
+
Exactly one of out_res, scale_factor, or match_raster_uuid must be provided.
|
|
1119
|
+
Only users with Publisher role or higher can perform this operation.
|
|
1120
|
+
|
|
1121
|
+
Args:
|
|
1122
|
+
output_raster_name (str): Name for the output reclassified raster dataset.
|
|
1123
|
+
out_res (str, optional): Output resolution as 'x_res,y_res' (e.g., '10,10').
|
|
1124
|
+
scale_factor (int, optional): Scale factor (e.g., 2.0 for 2x finer resolution).
|
|
1125
|
+
match_raster_uuid (str, optional): UUID of reference raster to match resolution/extent.
|
|
1126
|
+
resample_method (AnalysisResampleMethod, optional): Resampling method: 'near', 'bilinear', 'cubic', 'lanczos', etc.
|
|
1127
|
+
dst_nodata (int, optional): Output NoData value.
|
|
1128
|
+
user_id (int, optional): specific user. priviledges required!
|
|
1129
|
+
|
|
1130
|
+
Returns:
|
|
1131
|
+
Task: task instance of the process
|
|
1132
|
+
|
|
1133
|
+
Example:
|
|
1134
|
+
>>> from geobox import GeoboxClient
|
|
1135
|
+
>>> client = GeoboxClient()
|
|
1136
|
+
>>> raster = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
1137
|
+
>>> raster.resample(output_raster_name='test')
|
|
1138
|
+
"""
|
|
1139
|
+
from .analysis import Analysis
|
|
1140
|
+
return Analysis.resample(self.api,
|
|
1141
|
+
self,
|
|
1142
|
+
output_raster_name=output_raster_name,
|
|
1143
|
+
out_res=out_res,
|
|
1144
|
+
scale_factor=scale_factor,
|
|
1145
|
+
match_raster_uuid=match_raster_uuid,
|
|
1146
|
+
resample_method=resample_method,
|
|
1147
|
+
dst_nodata=dst_nodata,
|
|
1148
|
+
user_id=user_id)
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
def fill_nodata(self,
|
|
1152
|
+
output_raster_name: str,
|
|
1153
|
+
band: Union[int, str] = 1,
|
|
1154
|
+
nodata: Optional[int] = None,
|
|
1155
|
+
max_search_dist: Optional[int] = None,
|
|
1156
|
+
smoothing_iterations: Optional[int] = None,
|
|
1157
|
+
mask_raster_uuid: Optional[str] = None,
|
|
1158
|
+
user_id: Optional[int] = None) -> 'Task':
|
|
1159
|
+
"""
|
|
1160
|
+
Fill NoData regions in a raster using GDAL's FillNodata algorithm.
|
|
1161
|
+
|
|
1162
|
+
it fills gaps (NoData regions) in a raster by interpolating values from surrounding valid pixels.
|
|
1163
|
+
This is commonly used for data cleaning and gap filling in remote sensing and elevation data.
|
|
1164
|
+
Only users with Publisher role or higher can perform this operation.
|
|
1165
|
+
|
|
1166
|
+
Args:
|
|
1167
|
+
output_raster_name (str): Name for the output filled raster dataset.
|
|
1168
|
+
band (int | str): 1-based band index to process or 'all' to process all bands. default: 1
|
|
1169
|
+
nodata (int, optional): NoData value to use. If None, uses the band's existing NoData.
|
|
1170
|
+
max_search_dist (int, optoinal): Maximum distance in pixels to search for valid data.
|
|
1171
|
+
smoothing_iterations (int, optional): Number of smoothing iterations to apply.
|
|
1172
|
+
mask_raster_uuid (str, optional): Optional UUID of a mask raster (0=masked, >0=valid).
|
|
1173
|
+
user_id (int, optional): specific user. priviledges required!
|
|
1174
|
+
|
|
1175
|
+
Returns:
|
|
1176
|
+
Task: task instance of the process
|
|
1177
|
+
|
|
1178
|
+
Example:
|
|
1179
|
+
>>> from geobox import GeoboxClient
|
|
1180
|
+
>>> client = GeoboxClient()
|
|
1181
|
+
>>> raster = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
1182
|
+
>>> task = raster.fill_nodata(output_raster_name='test')
|
|
1183
|
+
"""
|
|
1184
|
+
from .analysis import Analysis
|
|
1185
|
+
return Analysis.fill_nodata(self.api,
|
|
1186
|
+
self,
|
|
1187
|
+
output_raster_name=output_raster_name,
|
|
1188
|
+
band=band,
|
|
1189
|
+
nodata=nodata,
|
|
1190
|
+
max_search_dist=max_search_dist,
|
|
1191
|
+
smoothing_iterations=smoothing_iterations,
|
|
1192
|
+
mask_raster_uuid=mask_raster_uuid,
|
|
1193
|
+
user_id=user_id)
|
|
1194
|
+
|
|
1195
|
+
|
|
1196
|
+
def proximity(self,
|
|
1197
|
+
output_raster_name: str,
|
|
1198
|
+
dist_units: DistanceUnit = DistanceUnit.GEO,
|
|
1199
|
+
burn_value: int = 1,
|
|
1200
|
+
nodata: int = -9999,
|
|
1201
|
+
user_id: Optional[int] = None) -> 'Task':
|
|
1202
|
+
"""
|
|
1203
|
+
Create a proximity (distance) raster from a raster layer.
|
|
1204
|
+
|
|
1205
|
+
it creates a raster showing the distance from each pixel to the nearest pixel in the input raster layer.
|
|
1206
|
+
Only users with Publisher role or higher can perform this operation.
|
|
1207
|
+
|
|
1208
|
+
Args:
|
|
1209
|
+
output_raster_name (str): Name for the output proximity raster dataset.
|
|
1210
|
+
dist_units (DistanceUnit, optional): Distance units: 'GEO' for georeferenced units, 'PIXEL' for pixels. default: DistanceUnit.GEO
|
|
1211
|
+
burn_value (int, optional): Value treated as targets (distance 0). default: 1
|
|
1212
|
+
nodata (int, optional): NoData value to use in the output raster. default: -9999
|
|
1213
|
+
user_id (int, optional): specific user. priviledges required!
|
|
1214
|
+
|
|
1215
|
+
Returns:
|
|
1216
|
+
Task: task instance of the process
|
|
1217
|
+
|
|
1218
|
+
Example:
|
|
1219
|
+
>>> from geobox import GeoboxClient
|
|
1220
|
+
>>> client = GeoboxClient()
|
|
1221
|
+
>>> raster = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
1222
|
+
>>> task = raster.proximity(output_raster_name='test')
|
|
1223
|
+
"""
|
|
1224
|
+
from .analysis import Analysis
|
|
1225
|
+
return Analysis.proximity(self.api,
|
|
1226
|
+
self,
|
|
1227
|
+
output_raster_name=output_raster_name,
|
|
1228
|
+
dist_units=dist_units,
|
|
1229
|
+
burn_value=burn_value,
|
|
1230
|
+
nodata=nodata,
|
|
1231
|
+
user_id=user_id)
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
def profile(self,
|
|
1235
|
+
polyline: List,
|
|
1236
|
+
number_of_samples: int = 100,
|
|
1237
|
+
output_epsg: Optional[int] = None,
|
|
1238
|
+
include_distance: bool = True,
|
|
1239
|
+
treat_nodata_as_null: bool = True) -> Dict:
|
|
1240
|
+
"""
|
|
1241
|
+
Create a profile form a raster along a path
|
|
1242
|
+
|
|
1243
|
+
Args:
|
|
1244
|
+
polyline (List): Path coordinates as [x, y] pairs. Use raster CRS unless `output_epsg` is provided.
|
|
1245
|
+
number_of_samples (int, optional): Number of samples along the path. default: 100.
|
|
1246
|
+
output_epsg (int, optional): EPSG code for output coordinates. If None, use raster CRS.
|
|
1247
|
+
include_distance (bool, optional): Include cumulative distance for each sample. default: True.
|
|
1248
|
+
treat_nodata_as_null (bool, optional): Treat NoData pixels as null values. default: True.
|
|
1249
|
+
|
|
1250
|
+
Returns:
|
|
1251
|
+
Dict: the profile result as geojson
|
|
1252
|
+
|
|
1253
|
+
Example:
|
|
1254
|
+
>>> from geobox import GeoboxClient
|
|
1255
|
+
>>> client = GeoboxClient()
|
|
1256
|
+
>>> raster = client.get_raster(uuid="12345678-1234-5678-1234-567812345678")
|
|
1257
|
+
>>> task = raster.profile(polyline=[[0, 0], [10, 10]], number_of_samples=200)
|
|
1258
|
+
"""
|
|
1259
|
+
endpoint = f"{self.endpoint}profile/"
|
|
1260
|
+
|
|
1261
|
+
data = clean_data({
|
|
1262
|
+
'polyline': polyline,
|
|
1263
|
+
'number_of_samples': number_of_samples,
|
|
1264
|
+
'output_epsg': output_epsg,
|
|
1265
|
+
'include_distance': include_distance,
|
|
1266
|
+
'treat_nodata_as_null': treat_nodata_as_null
|
|
1267
|
+
})
|
|
1268
|
+
|
|
1269
|
+
response = self.api.post(endpoint=endpoint, payload=data)
|
|
1270
|
+
return response
|