or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdconfiguration.mdcontainer.mdcore-indexing.mdcustom-storage.mdindex.mdutilities.md

advanced-features.mddocs/

0

# Advanced Features

1

2

Advanced spatial indexing capabilities that extend beyond basic CRUD operations. These features provide high-performance bulk operations, custom storage implementations, temporal indexing, and set operations between indexes.

3

4

## Capabilities

5

6

### Bulk Operations with NumPy

7

8

High-performance bulk queries using NumPy arrays for processing multiple spatial queries efficiently.

9

10

```python { .api }

11

def intersection_v(self, mins, maxs):

12

"""

13

Bulk intersection query for multiple bounding boxes.

14

15

Parameters:

16

- mins (array-like): Minimum coordinates for each query box

17

- maxs (array-like): Maximum coordinates for each query box

18

19

Returns:

20

tuple: (ids, counts) where:

21

- ids: Flattened array of all intersecting item IDs

22

- counts: Array of intersection counts for each query box

23

"""

24

25

def nearest_v(self, mins, maxs, *, num_results=1, max_dists=None, strict=False, return_max_dists=False):

26

"""

27

Bulk k-nearest neighbor query for multiple bounding boxes.

28

29

Parameters:

30

- mins (array-like): Minimum coordinates for each query box

31

- maxs (array-like): Maximum coordinates for each query box

32

- num_results (int): Number of nearest neighbors to find per query

33

- max_dists (array-like, optional): Maximum search distances

34

- strict (bool): Strict distance checking

35

- return_max_dists (bool): Return maximum distances found

36

37

Returns:

38

tuple: (ids, counts) or (ids, counts, distances) if return_max_dists=True

39

"""

40

```

41

42

Usage example:

43

44

```python

45

import numpy as np

46

from rtree import index

47

48

# Create index with sample data

49

idx = index.Index()

50

for i in range(100):

51

x, y = i % 10, i // 10

52

idx.insert(i, (x, y, x+1, y+1))

53

54

# Bulk intersection queries

55

query_mins = np.array([[0, 0], [2, 2], [5, 5]])

56

query_maxs = np.array([[1, 1], [3, 3], [6, 6]])

57

58

ids, counts = idx.intersection_v(query_mins, query_maxs)

59

print(f"Found {len(ids)} total intersections")

60

print(f"Per-query counts: {counts}")

61

62

# Bulk nearest neighbor queries

63

nearest_ids, nearest_counts = idx.nearest_v(query_mins, query_maxs, num_results=3)

64

print(f"Found {len(nearest_ids)} nearest neighbors")

65

```

66

67

### Custom Storage Implementation

68

69

Implement custom storage backends for specialized use cases like ZODB integration or custom persistence layers.

70

71

```python { .api }

72

class ICustomStorage:

73

"""

74

Interface for custom storage implementations.

75

76

Must implement all abstract methods for data persistence.

77

"""

78

79

def create(self, name): ...

80

def destroy(self, name): ...

81

def open(self, name): ...

82

def close(self): ...

83

def flush(self): ...

84

def read(self, page, length): ...

85

def write(self, page, data): ...

86

def delete(self, page): ...

87

88

class CustomStorageBase(ICustomStorage):

89

"""

90

Base class for custom storage with default implementations.

91

92

Provides basic structure that can be extended for specific storage needs.

93

"""

94

95

class CustomStorage(ICustomStorage):

96

"""

97

Template custom storage implementation.

98

99

Example implementation showing the storage interface pattern.

100

"""

101

```

102

103

Usage example:

104

105

```python

106

from rtree import index

107

108

class MemoryStorage(index.CustomStorageBase):

109

def __init__(self):

110

self._data = {}

111

self._next_page = 0

112

113

def create(self, name):

114

self._data = {}

115

return 0

116

117

def write(self, page, data):

118

self._data[page] = data

119

return len(data)

120

121

def read(self, page, length):

122

return self._data.get(page, b'')

123

124

# Use custom storage

125

storage = MemoryStorage()

126

idx = index.Index(storage=storage)

127

```

128

129

### TPR-Tree Temporal Indexing

130

131

Support for Time-Parameterized R-Trees (TPR-Tree) that handle moving objects with temporal queries.

132

133

```python { .api }

134

class Property:

135

tpr_horizon: float

136

"""

137

Time horizon for TPR-Tree temporal queries.

138

139

Sets the time window for trajectory prediction.

140

"""

141

```

142

143

TPR-Tree indexes use specialized coordinate formats that include velocity information:

144

145

```python

146

from rtree import index

147

148

# Configure for TPR-Tree

149

p = index.Property()

150

p.type = index.RT_TPRTree

151

p.tpr_horizon = 100.0

152

153

tpr_idx = index.Index(properties=p)

154

155

# Insert moving object: ((position_bounds), (velocity_bounds), time)

156

tpr_idx.insert(0, ((0, 0, 1, 1), (0.1, 0.1, 0.1, 0.1), 0.0))

157

```

158

159

### Set Operations

160

161

Perform set operations between spatial indexes to combine or compare their contents.

162

163

```python { .api }

164

def __and__(self, other: Index) -> Index:

165

"""

166

Intersection of two indexes - items present in both indexes.

167

168

Parameters:

169

- other (Index): Another spatial index

170

171

Returns:

172

Index: New index containing items in both indexes

173

"""

174

175

def __or__(self, other: Index) -> Index:

176

"""

177

Union of two indexes - items present in either index.

178

179

Parameters:

180

- other (Index): Another spatial index

181

182

Returns:

183

Index: New index containing items from both indexes

184

"""

185

```

186

187

Usage example:

188

189

```python

190

from rtree import index

191

192

# Create two indexes

193

idx1 = index.Index()

194

idx1.insert(0, (0, 0, 1, 1))

195

idx1.insert(1, (1, 1, 2, 2))

196

197

idx2 = index.Index()

198

idx2.insert(1, (1, 1, 2, 2)) # Overlapping item

199

idx2.insert(2, (2, 2, 3, 3))

200

201

# Set operations

202

intersection_idx = idx1 & idx2 # Items in both

203

union_idx = idx1 | idx2 # Items in either

204

205

print(len(intersection_idx)) # 1

206

print(len(union_idx)) # 3

207

```

208

209

### Advanced Index Properties

210

211

Configure specialized index behaviors and performance characteristics.

212

213

```python { .api }

214

class Property:

215

near_minimum_overlap_factor: int

216

"""

217

Factor for near minimum overlap splitting in R*-Tree.

218

"""

219

220

split_distribution_factor: float

221

"""

222

Distribution factor for node splitting algorithms.

223

"""

224

225

reinsert_factor: float

226

"""

227

Reinsertion factor for R*-Tree forced reinsertion.

228

"""

229

230

tight_mbr: bool

231

"""

232

Use tight minimum bounding rectangles.

233

"""

234

235

buffering_capacity: int

236

"""

237

Buffer capacity for batched operations.

238

"""

239

240

point_pool_capacity: int

241

"""

242

Capacity of the point object pool.

243

"""

244

245

region_pool_capacity: int

246

"""

247

Capacity of the region object pool.

248

"""

249

```

250

251

### Stream-Based Bulk Loading

252

253

Load large datasets efficiently using stream-based bulk loading.

254

255

```python { .api }

256

def __init__(self, stream, **kwargs):

257

"""

258

Create index from a stream of data for efficient bulk loading.

259

260

Parameters:

261

- stream (iterable): Stream of (id, coordinates, object) tuples

262

263

Stream format:

264

- Regular R-Tree: (id, coordinates, object)

265

- TPR-Tree: (id, ((pos_coords), (vel_coords), time), object)

266

"""

267

```

268

269

Usage example:

270

271

```python

272

from rtree import index

273

274

def data_stream():

275

"""Generator that yields spatial data."""

276

for i in range(10000):

277

x, y = i % 100, i // 100

278

yield (i, (x, y, x+1, y+1), f"Object {i}")

279

280

# Bulk load from stream - more efficient than individual inserts

281

idx = index.Index(data_stream())

282

print(f"Bulk loaded {len(idx)} items")

283

```

284

285

### Serialization and Persistence

286

287

Control object serialization for stored data and index persistence.

288

289

```python { .api }

290

def dumps(self, obj: object) -> bytes:

291

"""

292

Serialize an object for storage in the index.

293

294

Parameters:

295

- obj (object): Object to serialize

296

297

Returns:

298

bytes: Serialized object data

299

300

Note:

301

Default implementation uses pickle. Override for custom serialization.

302

"""

303

304

def loads(self, string: bytes) -> object:

305

"""

306

Deserialize an object from index storage.

307

308

Parameters:

309

- string (bytes): Serialized object data

310

311

Returns:

312

object: Deserialized object

313

314

Note:

315

Default implementation uses pickle. Override for custom deserialization.

316

"""

317

318

def __getstate__(self) -> dict[str, Any]:

319

"""

320

Get state for pickle serialization of the index itself.

321

322

Returns:

323

dict: Index state for serialization

324

"""

325

326

def __setstate__(self, state: dict[str, Any]) -> None:

327

"""

328

Restore index state from pickle deserialization.

329

330

Parameters:

331

- state (dict): Index state from serialization

332

"""

333

```

334

335

Usage example with custom serialization:

336

337

```python

338

import json

339

from rtree import index

340

341

class JSONIndex(index.Index):

342

def dumps(self, obj):

343

return json.dumps(obj).encode('utf-8')

344

345

def loads(self, data):

346

return json.loads(data.decode('utf-8'))

347

348

# Use custom serialization

349

json_idx = JSONIndex()

350

json_idx.insert(0, (0, 0, 1, 1), obj={"name": "Building", "floors": 5})

351

352

# Objects are serialized as JSON instead of pickle

353

for item in json_idx.intersection((0, 0, 1, 1), objects=True):

354

print(item.object) # {"name": "Building", "floors": 5}

355

```

356

357

### Leaf Node Access

358

359

Access detailed information about index leaf nodes for advanced analysis.

360

361

```python { .api }

362

def leaves(self):

363

"""

364

Get information about leaf nodes in the index.

365

366

Returns:

367

Generator yielding leaf node information including:

368

- Node IDs

369

- Child item IDs

370

- Node bounding boxes

371

"""

372

```

373

374

Usage example:

375

376

```python

377

from rtree import index

378

379

idx = index.Index()

380

for i in range(10):

381

idx.insert(i, (i, i, i+1, i+1))

382

383

# Examine leaf structure

384

leaf_info = list(idx.leaves())

385

print(f"Index has {len(leaf_info)} leaf nodes")

386

```

387

388

### Result Set Control

389

390

Control query result pagination and limits.

391

392

```python { .api }

393

@property

394

def result_limit(self) -> int:

395

"""

396

Get/set the maximum number of results returned by queries.

397

398

Returns:

399

int: Current result limit

400

"""

401

402

@property

403

def result_offset(self) -> int:

404

"""

405

Get/set the offset for query results (pagination).

406

407

Returns:

408

int: Current result offset

409

"""

410

```

411

412

Usage example:

413

414

```python

415

from rtree import index

416

417

idx = index.Index()

418

for i in range(100):

419

idx.insert(i, (0, 0, 10, 10)) # All overlap

420

421

# Paginate results

422

idx.result_limit = 10

423

idx.result_offset = 20

424

425

hits = list(idx.intersection((0, 0, 10, 10)))

426

print(f"Got {len(hits)} results (page 3)") # Results 20-29

427

```

428

429

### Object-Oriented Container

430

431

Alternative object-oriented interface that automatically manages object-coordinate associations.

432

433

```python { .api }

434

class RtreeContainer:

435

"""

436

Object-oriented spatial container that automatically manages coordinate relationships.

437

438

Unlike the Index class which requires separate ID and coordinate management,

439

RtreeContainer directly stores objects and automatically handles coordinate associations.

440

"""

441

442

def __init__(self, *args: Any, **kwargs: Any) -> None:

443

"""

444

Create a new spatial container.

445

446

Parameters:

447

Same as Index constructor (properties, storage, etc.)

448

"""

449

450

def insert(self, obj: object, coordinates: Any) -> None:

451

"""

452

Insert an object with its spatial coordinates.

453

454

Parameters:

455

- obj (object): Object to store

456

- coordinates (sequence): Spatial coordinates

457

"""

458

459

def delete(self, obj: object, coordinates: Any) -> None:

460

"""

461

Delete an object from the container.

462

463

Parameters:

464

- obj (object): Object to remove

465

- coordinates (sequence): Object's coordinates

466

"""

467

468

def intersection(self, coordinates: Any, bbox: bool = False) -> Iterator[object | Item]:

469

"""

470

Find objects that intersect with coordinates.

471

472

Parameters:

473

- coordinates (sequence): Query bounds

474

- bbox (bool): Return Item objects with bounding boxes

475

476

Returns:

477

Iterator of objects or Item objects

478

"""

479

480

def nearest(self, coordinates: Any, num_results: int = 1, bbox: bool = True) -> Iterator[object | Item]:

481

"""

482

Find nearest objects to coordinates.

483

484

Parameters:

485

- coordinates (sequence): Query point

486

- num_results (int): Number of results

487

- bbox (bool): Return Item objects with bounding boxes

488

489

Returns:

490

Iterator of objects or Item objects

491

"""

492

493

def __contains__(self, obj: object) -> bool:

494

"""Check if object is in container."""

495

496

def __len__(self) -> int:

497

"""Get number of objects in container."""

498

499

def __iter__(self) -> Iterator[object]:

500

"""Iterate over all objects in container."""

501

```

502

503

Usage example:

504

505

```python

506

from rtree import index

507

508

# Create object-oriented container

509

container = index.RtreeContainer()

510

511

# Insert objects directly

512

buildings = [

513

{"name": "City Hall", "type": "government"},

514

{"name": "Library", "type": "public"},

515

{"name": "Mall", "type": "commercial"}

516

]

517

518

container.insert(buildings[0], (100, 100, 150, 150))

519

container.insert(buildings[1], (200, 200, 250, 250))

520

container.insert(buildings[2], (120, 120, 180, 180))

521

522

# Query for objects

523

for building in container.intersection((110, 110, 160, 160)):

524

print(f"Found: {building['name']}")

525

526

# Check membership

527

print(buildings[0] in container) # True

528

529

# Iterate over all objects

530

for building in container:

531

print(building['name'])

532

```