deepdoctection 1.2.9__tar.gz → 1.2.11__tar.gz
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.
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/PKG-INFO +1 -1
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/pyproject.toml +1 -1
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/__init__.py +1 -1
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/anngen.py +157 -45
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/order.py +1 -1
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection.egg-info/PKG-INFO +1 -1
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/README.md +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/setup.cfg +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/analyzer/__init__.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/analyzer/config.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/analyzer/dd.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/analyzer/factory.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/configs/__init__.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/configs/conf_dd_one.yaml +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/configs/conf_tesseract.yaml +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/configs/profiles.jsonl +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/eval/__init__.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/eval/accmetric.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/eval/base.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/eval/cocometric.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/eval/eval.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/eval/registry.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/eval/tedsmetric.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/__init__.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/base.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/d2detect.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/deskew.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/doctrocr.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/hfdetr.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/hflayoutlm.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/hflm.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/model.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/pdftext.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/tessocr.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/extern/texocr.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/__init__.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/base.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/common.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/concurrency.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/doctectionpipe.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/language.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/layout.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/lm.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/refine.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/registry.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/segment.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/sub_layout.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/text.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/pipe/transform.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/py.typed +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/train/__init__.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/train/d2_frcnn_train.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/train/hf_detr_train.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/train/hf_layoutlm_train.py +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection.egg-info/SOURCES.txt +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection.egg-info/dependency_links.txt +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection.egg-info/requires.txt +0 -0
- {deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection.egg-info/top_level.txt +0 -0
|
@@ -12,7 +12,7 @@ from dd_core.utils.env_info import collect_env_info
|
|
|
12
12
|
from dd_core.utils.file_utils import _LazyModule
|
|
13
13
|
from dd_core.utils.logger import LoggingRecord, logger
|
|
14
14
|
|
|
15
|
-
__version__ = "1.2.
|
|
15
|
+
__version__ = "1.2.11"
|
|
16
16
|
_IMPORT_STRUCTURE = {
|
|
17
17
|
"analyzer": ["config_sanity_checks", "get_dd_analyzer", "ServiceFactory", "update_cfg_from_defaults"],
|
|
18
18
|
"eval": [
|
|
@@ -50,6 +50,9 @@ class DataPointCacheStore(ABC):
|
|
|
50
50
|
datapoints.
|
|
51
51
|
"""
|
|
52
52
|
|
|
53
|
+
def __init__(self, max_pages: int) -> None:
|
|
54
|
+
self.max_pages = max_pages
|
|
55
|
+
|
|
53
56
|
@abstractmethod
|
|
54
57
|
def put_datapoint(self, document_id: str, page_number: int, image: Image, job_id: str | None = None) -> None:
|
|
55
58
|
"""
|
|
@@ -127,8 +130,9 @@ class LocalDataPointCacheStore(DataPointCacheStore):
|
|
|
127
130
|
Args:
|
|
128
131
|
max_pages (int): Maximum number of pages to keep per document.
|
|
129
132
|
"""
|
|
130
|
-
|
|
133
|
+
|
|
131
134
|
self._pages: dict[str, dict[int, dict[str, Any]]] = {}
|
|
135
|
+
super().__init__(max_pages)
|
|
132
136
|
|
|
133
137
|
def _get_cache_key(self, document_id: str, job_id: str | None) -> str:
|
|
134
138
|
"""
|
|
@@ -211,6 +215,17 @@ class DatapointManager:
|
|
|
211
215
|
- `image.clear_image()`
|
|
212
216
|
- `image.remove_image_from_lower_hierarchy(pixel_values_only=True)`
|
|
213
217
|
|
|
218
|
+
Async concurrency:
|
|
219
|
+
When `enable_async_handle=True`, the manager maintains a per-job-id registry of active datapoints
|
|
220
|
+
(`_datapoint_handle`, `_cache_anns_handle`). This makes it safe to use a single component instance
|
|
221
|
+
across concurrent async calls, each identified by a unique `job_id`. The assumption is that a given
|
|
222
|
+
`job_id` maps to exactly one document and its pages are processed sequentially within a job.
|
|
223
|
+
|
|
224
|
+
Use `set_datapoint(dp, job_id)` / `get_datapoint(job_id)` / `release_datapoint(job_id)` for the
|
|
225
|
+
async path. Pass `job_id` to all annotation methods that accept it to route to the correct slot.
|
|
226
|
+
|
|
227
|
+
When `enable_async_handle=False` (default), all behavior is identical to the original implementation.
|
|
228
|
+
|
|
214
229
|
The manager is part of each `PipelineComponent`.
|
|
215
230
|
"""
|
|
216
231
|
|
|
@@ -220,21 +235,83 @@ class DatapointManager:
|
|
|
220
235
|
model_id: Optional[str] = None,
|
|
221
236
|
num_cached_datapoints: int = 0,
|
|
222
237
|
remove_pixel_values_from_cache: bool = True,
|
|
223
|
-
cache_store:
|
|
238
|
+
cache_store: DataPointCacheStore | None = None,
|
|
239
|
+
enable_async_handle: bool = False,
|
|
224
240
|
) -> None:
|
|
225
241
|
self._datapoint: Optional[Image] = None
|
|
226
242
|
self._cache_anns: dict[str, ImageAnnotation] = {}
|
|
227
243
|
self.datapoint_is_passed: bool = False
|
|
228
244
|
self.service_id = service_id
|
|
229
245
|
self.model_id = model_id
|
|
246
|
+
self.enable_async_handle = enable_async_handle
|
|
230
247
|
|
|
231
248
|
if num_cached_datapoints < 0:
|
|
232
249
|
raise ValueError("num_cached_datapoints must be >= 0")
|
|
233
250
|
self.remove_pixel_values_from_cache = remove_pixel_values_from_cache
|
|
234
251
|
|
|
235
|
-
self._cache_store = cache_store or LocalDataPointCacheStore(
|
|
252
|
+
self._cache_store: DataPointCacheStore = cache_store or LocalDataPointCacheStore(
|
|
253
|
+
max_pages=num_cached_datapoints
|
|
254
|
+
)
|
|
236
255
|
self.num_cached_datapoints = self._cache_store.max_pages
|
|
237
256
|
|
|
257
|
+
self._datapoint_handle: dict[str, Image] = {}
|
|
258
|
+
self._cache_anns_handle: dict[str, dict[str, ImageAnnotation]] = {}
|
|
259
|
+
|
|
260
|
+
def set_datapoint(self, dp: Image, job_id: str) -> None:
|
|
261
|
+
"""
|
|
262
|
+
Register a datapoint for the given job_id in the async-safe slot.
|
|
263
|
+
|
|
264
|
+
Only used when `enable_async_handle=True`. Must be called before any annotation
|
|
265
|
+
methods are invoked with this job_id.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
dp: The image datapoint to register.
|
|
269
|
+
job_id: Unique identifier for the current processing job.
|
|
270
|
+
"""
|
|
271
|
+
self._datapoint_handle[job_id] = dp
|
|
272
|
+
self._cache_anns_handle[job_id] = {ann.annotation_id: ann for ann in dp.get_annotation()}
|
|
273
|
+
|
|
274
|
+
def get_datapoint(self, job_id: str) -> Image:
|
|
275
|
+
"""
|
|
276
|
+
Retrieve the datapoint registered for the given job_id.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
job_id: Unique identifier for the current processing job.
|
|
280
|
+
|
|
281
|
+
Returns:
|
|
282
|
+
The registered image datapoint.
|
|
283
|
+
|
|
284
|
+
Raises:
|
|
285
|
+
ValueError: If no datapoint has been registered for this job_id.
|
|
286
|
+
"""
|
|
287
|
+
try:
|
|
288
|
+
return self._datapoint_handle[job_id]
|
|
289
|
+
except KeyError as exc:
|
|
290
|
+
raise ValueError(f"No datapoint passed for job_id={job_id}") from exc
|
|
291
|
+
|
|
292
|
+
def release_datapoint(self, job_id: str) -> None:
|
|
293
|
+
"""
|
|
294
|
+
Remove the datapoint slot for the given job_id.
|
|
295
|
+
|
|
296
|
+
Should be called once the datapoint leaves the component (after `maybe_cache_datapoint`)
|
|
297
|
+
to free memory and avoid stale state.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
job_id: Unique identifier for the current processing job.
|
|
301
|
+
"""
|
|
302
|
+
self._datapoint_handle.pop(job_id, None)
|
|
303
|
+
self._cache_anns_handle.pop(job_id, None)
|
|
304
|
+
|
|
305
|
+
def _resolve_datapoint(self, job_id: str | None) -> Image:
|
|
306
|
+
if self.enable_async_handle and job_id is not None:
|
|
307
|
+
return self.get_datapoint(job_id)
|
|
308
|
+
return self.datapoint
|
|
309
|
+
|
|
310
|
+
def _resolve_cache_anns(self, job_id: str | None) -> dict[str, ImageAnnotation]:
|
|
311
|
+
if self.enable_async_handle and job_id is not None:
|
|
312
|
+
return self._cache_anns_handle[job_id]
|
|
313
|
+
return self._cache_anns
|
|
314
|
+
|
|
238
315
|
def maybe_cache_datapoint(self, image: Optional[Image], job_id: str | None = None) -> None:
|
|
239
316
|
"""
|
|
240
317
|
Cache the given datapoint if caching is enabled.
|
|
@@ -250,10 +327,8 @@ class DatapointManager:
|
|
|
250
327
|
return
|
|
251
328
|
if self.num_cached_datapoints <= 0:
|
|
252
329
|
return
|
|
253
|
-
|
|
254
330
|
if self.remove_pixel_values_from_cache:
|
|
255
331
|
image.clear_image()
|
|
256
|
-
|
|
257
332
|
self._cache_store.put_datapoint(
|
|
258
333
|
document_id=image.document_id,
|
|
259
334
|
page_number=image.page_number,
|
|
@@ -292,14 +367,23 @@ class DatapointManager:
|
|
|
292
367
|
"""Re-sets the model_id."""
|
|
293
368
|
self.model_id = model_id
|
|
294
369
|
|
|
295
|
-
def assert_datapoint_passed(self) -> None:
|
|
370
|
+
def assert_datapoint_passed(self, job_id: str | None = None) -> None:
|
|
296
371
|
"""
|
|
297
372
|
Asserts that a datapoint is passed.
|
|
298
373
|
|
|
374
|
+
When `enable_async_handle=True` and `job_id` is provided, checks the per-job slot.
|
|
375
|
+
Otherwise falls back to the legacy flag check.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
job_id: Optional job identifier used for async routing.
|
|
379
|
+
|
|
299
380
|
Raises:
|
|
300
381
|
AssertionError: If a datapoint has not been passed to `DatapointManager` before creating annotations.
|
|
301
382
|
"""
|
|
302
|
-
|
|
383
|
+
if self.enable_async_handle and job_id is not None:
|
|
384
|
+
assert job_id in self._datapoint_handle, "Pass datapoint to DatapointManager before creating anns"
|
|
385
|
+
else:
|
|
386
|
+
assert self.datapoint_is_passed, "Pass datapoint to DatapointManager before creating anns"
|
|
303
387
|
|
|
304
388
|
def set_image_annotation(
|
|
305
389
|
self,
|
|
@@ -309,6 +393,7 @@ class DatapointManager:
|
|
|
309
393
|
crop_image: bool = False,
|
|
310
394
|
detect_result_max_width: Optional[float] = None,
|
|
311
395
|
detect_result_max_height: Optional[float] = None,
|
|
396
|
+
job_id: str | None = None,
|
|
312
397
|
) -> Optional[str]:
|
|
313
398
|
"""
|
|
314
399
|
Creates an image annotation from a raw `DetectionResult` dataclass.
|
|
@@ -332,6 +417,7 @@ class DatapointManager:
|
|
|
332
417
|
pass the max width possible so coordinates can be rescaled.
|
|
333
418
|
detect_result_max_height: If the detect result has a different scaling scheme from the image it refers to,
|
|
334
419
|
pass the max height possible so coordinates can be rescaled.
|
|
420
|
+
job_id: Optional job identifier for async routing.
|
|
335
421
|
|
|
336
422
|
Returns:
|
|
337
423
|
The `annotation_id` of the generated image annotation, or `None` if there was a context error.
|
|
@@ -340,13 +426,15 @@ class DatapointManager:
|
|
|
340
426
|
TypeError: If `detect_result.box` is not of type list or `np.ndarray`.
|
|
341
427
|
ValueError: If the parent annotation's image is None or if the annotation's image is None.
|
|
342
428
|
"""
|
|
343
|
-
self.assert_datapoint_passed()
|
|
429
|
+
self.assert_datapoint_passed(job_id)
|
|
344
430
|
if not isinstance(detect_result.box, (list, np.ndarray)):
|
|
345
431
|
raise TypeError(
|
|
346
432
|
f"detect_result.box must be of type list or np.ndarray, but is of type {(type(detect_result.box))}"
|
|
347
433
|
)
|
|
434
|
+
dp = self._resolve_datapoint(job_id)
|
|
435
|
+
cache_anns = self._resolve_cache_anns(job_id)
|
|
348
436
|
with MappingContextManager(
|
|
349
|
-
dp_name=
|
|
437
|
+
dp_name=dp.file_name, filter_level="annotation", detect_result=asdict(detect_result)
|
|
350
438
|
) as annotation_context:
|
|
351
439
|
box = BoundingBox(
|
|
352
440
|
ulx=detect_result.box[0],
|
|
@@ -360,8 +448,8 @@ class DatapointManager:
|
|
|
360
448
|
box,
|
|
361
449
|
detect_result_max_width,
|
|
362
450
|
detect_result_max_height,
|
|
363
|
-
|
|
364
|
-
|
|
451
|
+
dp.width,
|
|
452
|
+
dp.height,
|
|
365
453
|
)
|
|
366
454
|
ann = ImageAnnotation(
|
|
367
455
|
category_name=detect_result.class_name,
|
|
@@ -372,7 +460,7 @@ class DatapointManager:
|
|
|
372
460
|
model_id=self.model_id,
|
|
373
461
|
)
|
|
374
462
|
if to_annotation_id is not None:
|
|
375
|
-
parent_ann =
|
|
463
|
+
parent_ann = cache_anns[to_annotation_id]
|
|
376
464
|
if parent_ann.image is None:
|
|
377
465
|
raise ValueError("image cannot be None")
|
|
378
466
|
parent_ann.image.dump(ann)
|
|
@@ -381,8 +469,8 @@ class DatapointManager:
|
|
|
381
469
|
ann.bounding_box.transform( # type:ignore # pylint: disable=E1101
|
|
382
470
|
image_width=parent_ann.image.width, image_height=parent_ann.image.height, absolute_coords=True
|
|
383
471
|
),
|
|
384
|
-
parent_ann.get_bounding_box(
|
|
385
|
-
image_width=
|
|
472
|
+
parent_ann.get_bounding_box(dp.image_id).transform(
|
|
473
|
+
image_width=dp.width, image_height=dp.height, absolute_coords=True
|
|
386
474
|
),
|
|
387
475
|
)
|
|
388
476
|
if ann.image is None:
|
|
@@ -394,16 +482,16 @@ class DatapointManager:
|
|
|
394
482
|
),
|
|
395
483
|
)
|
|
396
484
|
ann.image.set_embedding( # pylint: disable=E1101
|
|
397
|
-
|
|
398
|
-
ann_global_box.transform(image_width=
|
|
485
|
+
dp.image_id,
|
|
486
|
+
ann_global_box.transform(image_width=dp.width, image_height=dp.height),
|
|
399
487
|
)
|
|
400
488
|
parent_ann.dump_relationship(RelationshipKey.CHILD, ann.annotation_id)
|
|
401
489
|
|
|
402
|
-
|
|
403
|
-
|
|
490
|
+
dp.dump(ann)
|
|
491
|
+
cache_anns[ann.annotation_id] = ann
|
|
404
492
|
|
|
405
493
|
if to_image and to_annotation_id is None:
|
|
406
|
-
|
|
494
|
+
dp.image_ann_to_image(annotation_id=ann.annotation_id, crop_image=crop_image)
|
|
407
495
|
|
|
408
496
|
if annotation_context.context_error:
|
|
409
497
|
return None
|
|
@@ -416,6 +504,7 @@ class DatapointManager:
|
|
|
416
504
|
sub_cat_key: ObjectTypes,
|
|
417
505
|
annotation_id: str,
|
|
418
506
|
score: Optional[float] = None,
|
|
507
|
+
job_id: str | None = None,
|
|
419
508
|
) -> Optional[str]:
|
|
420
509
|
"""
|
|
421
510
|
Creates a category annotation and dumps it as a subcategory to an already created annotation.
|
|
@@ -426,13 +515,16 @@ class DatapointManager:
|
|
|
426
515
|
sub_cat_key: The key to dump the created annotation to.
|
|
427
516
|
annotation_id: The id of the parent annotation. Currently, this can only be an image annotation.
|
|
428
517
|
score: The score to add.
|
|
518
|
+
job_id: Optional job identifier for async routing.
|
|
429
519
|
|
|
430
520
|
Returns:
|
|
431
521
|
The `annotation_id` of the generated category annotation, or `None` if there was a context error.
|
|
432
522
|
"""
|
|
433
|
-
self.assert_datapoint_passed()
|
|
523
|
+
self.assert_datapoint_passed(job_id)
|
|
524
|
+
dp = self._resolve_datapoint(job_id)
|
|
525
|
+
cache_anns = self._resolve_cache_anns(job_id)
|
|
434
526
|
with MappingContextManager(
|
|
435
|
-
dp_name=
|
|
527
|
+
dp_name=dp.file_name,
|
|
436
528
|
filter_level="annotation",
|
|
437
529
|
category_annotation={
|
|
438
530
|
"category_name": category_name.value,
|
|
@@ -447,7 +539,7 @@ class DatapointManager:
|
|
|
447
539
|
service_id=self.service_id,
|
|
448
540
|
model_id=self.model_id,
|
|
449
541
|
)
|
|
450
|
-
|
|
542
|
+
cache_anns[annotation_id].dump_sub_category(sub_cat_key, cat_ann)
|
|
451
543
|
if annotation_context.context_error:
|
|
452
544
|
return None
|
|
453
545
|
return cat_ann.annotation_id
|
|
@@ -460,6 +552,7 @@ class DatapointManager:
|
|
|
460
552
|
annotation_id: str,
|
|
461
553
|
value: Union[str, list[str], ReferencePayload],
|
|
462
554
|
score: Optional[float] = None,
|
|
555
|
+
job_id: str | None = None,
|
|
463
556
|
) -> Optional[str]:
|
|
464
557
|
"""
|
|
465
558
|
Creates a container annotation and dumps it as a subcategory to an already created annotation.
|
|
@@ -471,13 +564,16 @@ class DatapointManager:
|
|
|
471
564
|
annotation_id: The id of the parent annotation. Currently, this can only be an image annotation.
|
|
472
565
|
value: The value to store.
|
|
473
566
|
score: The score to add.
|
|
567
|
+
job_id: Optional job identifier for async routing.
|
|
474
568
|
|
|
475
569
|
Returns:
|
|
476
570
|
The `annotation_id` of the generated container annotation, or None if there was a context error.
|
|
477
571
|
"""
|
|
478
|
-
self.assert_datapoint_passed()
|
|
572
|
+
self.assert_datapoint_passed(job_id)
|
|
573
|
+
dp = self._resolve_datapoint(job_id)
|
|
574
|
+
cache_anns = self._resolve_cache_anns(job_id)
|
|
479
575
|
with MappingContextManager(
|
|
480
|
-
dp_name=
|
|
576
|
+
dp_name=dp.file_name,
|
|
481
577
|
filter_level="annotation",
|
|
482
578
|
container_annotation={
|
|
483
579
|
"category_name": category_name.value,
|
|
@@ -494,13 +590,17 @@ class DatapointManager:
|
|
|
494
590
|
service_id=self.service_id,
|
|
495
591
|
model_id=self.model_id,
|
|
496
592
|
)
|
|
497
|
-
|
|
593
|
+
cache_anns[annotation_id].dump_sub_category(sub_cat_key, cont_ann)
|
|
498
594
|
if annotation_context.context_error:
|
|
499
595
|
return None
|
|
500
596
|
return cont_ann.annotation_id
|
|
501
597
|
|
|
502
598
|
def set_relationship_annotation(
|
|
503
|
-
self,
|
|
599
|
+
self,
|
|
600
|
+
relationship_name: ObjectTypes,
|
|
601
|
+
target_annotation_id: str,
|
|
602
|
+
annotation_id: str,
|
|
603
|
+
job_id: str | None = None,
|
|
504
604
|
) -> Optional[str]:
|
|
505
605
|
"""
|
|
506
606
|
Creates a relationship annotation and dumps it to the target annotation.
|
|
@@ -509,14 +609,17 @@ class DatapointManager:
|
|
|
509
609
|
relationship_name: The relationship key.
|
|
510
610
|
target_annotation_id: The `annotation_id` of the parent `ImageAnnotation`.
|
|
511
611
|
annotation_id: The `annotation_id` to dump the relationship to.
|
|
612
|
+
job_id: Optional job identifier for async routing.
|
|
512
613
|
|
|
513
614
|
Returns:
|
|
514
615
|
The `annotation_id` of the parent `ImageAnnotation` for reference if the dump has been successful, or `None`
|
|
515
616
|
if there was a context error.
|
|
516
617
|
"""
|
|
517
|
-
self.assert_datapoint_passed()
|
|
618
|
+
self.assert_datapoint_passed(job_id)
|
|
619
|
+
dp = self._resolve_datapoint(job_id)
|
|
620
|
+
cache_anns = self._resolve_cache_anns(job_id)
|
|
518
621
|
with MappingContextManager(
|
|
519
|
-
dp_name=
|
|
622
|
+
dp_name=dp.file_name,
|
|
520
623
|
filter_level="annotation",
|
|
521
624
|
relationship_annotation={
|
|
522
625
|
"relationship_name": relationship_name.value,
|
|
@@ -524,7 +627,7 @@ class DatapointManager:
|
|
|
524
627
|
"annotation_id": annotation_id,
|
|
525
628
|
},
|
|
526
629
|
) as annotation_context:
|
|
527
|
-
|
|
630
|
+
cache_anns[target_annotation_id].dump_relationship(relationship_name, annotation_id)
|
|
528
631
|
if annotation_context.context_error:
|
|
529
632
|
return None
|
|
530
633
|
return target_annotation_id
|
|
@@ -537,6 +640,7 @@ class DatapointManager:
|
|
|
537
640
|
summary_value: Optional[Union[str, int, float, list[str], dict[str, Any]]] = None,
|
|
538
641
|
summary_score: Optional[float] = None,
|
|
539
642
|
annotation_id: Optional[str] = None,
|
|
643
|
+
job_id: str | None = None,
|
|
540
644
|
) -> Optional[str]:
|
|
541
645
|
"""
|
|
542
646
|
Creates a subcategory of a summary annotation.
|
|
@@ -550,15 +654,18 @@ class DatapointManager:
|
|
|
550
654
|
summary_value: Creates a `ContainerAnnotation` and stores the corresponding value.
|
|
551
655
|
summary_score: Stores the score.
|
|
552
656
|
annotation_id: The id of the parent annotation. Note that the parent annotation must have `image` not None.
|
|
657
|
+
job_id: Optional job identifier for async routing.
|
|
553
658
|
|
|
554
659
|
Returns:
|
|
555
660
|
The `annotation_id` of the generated category annotation, or None if there was a context error.
|
|
556
661
|
"""
|
|
557
|
-
self.assert_datapoint_passed()
|
|
662
|
+
self.assert_datapoint_passed(job_id)
|
|
663
|
+
cache_anns = self._resolve_cache_anns(job_id)
|
|
664
|
+
dp = self._resolve_datapoint(job_id)
|
|
558
665
|
if annotation_id is not None:
|
|
559
|
-
image =
|
|
666
|
+
image = cache_anns[annotation_id].image
|
|
560
667
|
else:
|
|
561
|
-
image =
|
|
668
|
+
image = dp
|
|
562
669
|
assert image is not None, image
|
|
563
670
|
|
|
564
671
|
ann: Union[CategoryAnnotation, ContainerAnnotation]
|
|
@@ -595,47 +702,53 @@ class DatapointManager:
|
|
|
595
702
|
return None
|
|
596
703
|
return ann.annotation_id
|
|
597
704
|
|
|
598
|
-
def remove_annotations(self, annotation_ids: Sequence[str]) -> None:
|
|
705
|
+
def remove_annotations(self, annotation_ids: Sequence[str], job_id: str | None = None) -> None:
|
|
599
706
|
"""
|
|
600
707
|
Removes the annotation by the given `annotation_id`.
|
|
601
708
|
|
|
602
709
|
Args:
|
|
603
710
|
annotation_ids: The `annotation_id` to remove.
|
|
711
|
+
job_id: Optional job identifier for async routing.
|
|
604
712
|
"""
|
|
605
|
-
self.assert_datapoint_passed()
|
|
606
|
-
self.
|
|
713
|
+
self.assert_datapoint_passed(job_id)
|
|
714
|
+
dp = self._resolve_datapoint(job_id)
|
|
715
|
+
cache_anns = self._resolve_cache_anns(job_id)
|
|
716
|
+
dp.remove(annotation_ids)
|
|
607
717
|
for ann_id in annotation_ids:
|
|
608
|
-
if ann_id in
|
|
609
|
-
|
|
718
|
+
if ann_id in cache_anns:
|
|
719
|
+
cache_anns.pop(ann_id)
|
|
610
720
|
|
|
611
|
-
def deactivate_annotation(self, annotation_id: str) -> None:
|
|
721
|
+
def deactivate_annotation(self, annotation_id: str, job_id: str | None = None) -> None:
|
|
612
722
|
"""
|
|
613
723
|
Deactivates the annotation by the given `annotation_id`.
|
|
614
724
|
|
|
615
725
|
Args:
|
|
616
726
|
annotation_id: The `annotation_id` to deactivate.
|
|
727
|
+
job_id: Optional job identifier for async routing.
|
|
617
728
|
"""
|
|
618
|
-
ann = self.
|
|
729
|
+
ann = self._resolve_cache_anns(job_id)[annotation_id]
|
|
619
730
|
ann.deactivate()
|
|
620
731
|
|
|
621
|
-
def get_annotation(self, annotation_id: str) -> ImageAnnotation:
|
|
732
|
+
def get_annotation(self, annotation_id: str, job_id: str | None = None) -> ImageAnnotation:
|
|
622
733
|
"""
|
|
623
734
|
Gets a single `ImageAnnotation`.
|
|
624
735
|
|
|
625
736
|
Args:
|
|
626
737
|
annotation_id: The `annotation_id` of the annotation to retrieve.
|
|
738
|
+
job_id: Optional job identifier for async routing.
|
|
627
739
|
|
|
628
740
|
Returns:
|
|
629
741
|
The `ImageAnnotation` corresponding to the given `annotation_id`.
|
|
630
742
|
"""
|
|
631
|
-
return self.
|
|
743
|
+
return self._resolve_cache_anns(job_id)[annotation_id]
|
|
632
744
|
|
|
633
|
-
def get_cached_datapoints(self, last_k: int) -> tuple[Image, ...]:
|
|
745
|
+
def get_cached_datapoints(self, last_k: int, job_id: str | None = None) -> tuple[Image, ...]:
|
|
634
746
|
"""
|
|
635
747
|
Returns a snapshot of the last `last_k` cached datapoints without removing them.
|
|
636
748
|
|
|
637
749
|
Args:
|
|
638
750
|
last_k: Number of most recently cached datapoints to return. Must be >= 0.
|
|
751
|
+
job_id: Optional job identifier to retrieve from the correct cache slot.
|
|
639
752
|
|
|
640
753
|
Returns:
|
|
641
754
|
A tuple containing up to the last `last_k` cached `Image` objects, ordered from older -> newer.
|
|
@@ -645,6 +758,5 @@ class DatapointManager:
|
|
|
645
758
|
raise ValueError("last_k must be >= 0")
|
|
646
759
|
if last_k == 0:
|
|
647
760
|
return tuple()
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
return self._cache_store.get_datapoints(document_id=doc_id, last_d=last_k)
|
|
761
|
+
doc_id = self._resolve_datapoint(job_id).document_id
|
|
762
|
+
return self._cache_store.get_datapoints(document_id=doc_id, last_d=last_k, job_id=job_id)
|
|
@@ -373,7 +373,7 @@ class OrderGenerator:
|
|
|
373
373
|
@staticmethod
|
|
374
374
|
def _make_column_detect_results(columns: Sequence[BoundingBox]) -> Sequence[DetectionResult]:
|
|
375
375
|
column_detect_result_list = []
|
|
376
|
-
if os.environ.get("
|
|
376
|
+
if os.environ.get("SHOW_WORD_ORDER_COLUMN", "False") == "True":
|
|
377
377
|
for box in columns:
|
|
378
378
|
column_detect_result_list.append(
|
|
379
379
|
DetectionResult(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/configs/conf_tesseract.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection/train/hf_layoutlm_train.py
RENAMED
|
File without changes
|
|
File without changes
|
{deepdoctection-1.2.9 → deepdoctection-1.2.11}/src/deepdoctection.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|