scale-nucleus 0.12b9__tar.gz → 0.14.5b1__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.
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/LICENSE +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/PKG-INFO +13 -10
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/README.md +2 -2
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/client.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/datasets.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/helpers/__init__.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/helpers/nucleus_url.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/helpers/web_helper.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/install_completion.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/jobs.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/models.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/nu.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/reference.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/slices.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/cli/tests.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/__init__.py +198 -3
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/annotation.py +23 -1
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/annotation_uploader.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/async_utils.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/autocurate.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/camera_params.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/connection.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/constants.py +5 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/data_transfer_object/__init__.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/data_transfer_object/dataset_details.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/data_transfer_object/dataset_info.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/data_transfer_object/dataset_size.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/data_transfer_object/scenes_list.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/dataset.py +31 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/dataset_item.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/dataset_item_uploader.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/deprecation_warning.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/errors.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/job.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/logger.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metadata_manager.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/__init__.py +0 -1
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/base.py +34 -56
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/categorization_metrics.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/cuboid_metrics.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/cuboid_utils.py +4 -6
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/custom_types.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/errors.py +4 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/filtering.py +159 -1
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/filters.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/metric_utils.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/polygon_metrics.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/polygon_utils.py +3 -3
- scale-nucleus-0.14.5b1/nucleus/metrics/segmentation_loader.py +34 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/segmentation_metrics.py +197 -147
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/metrics/segmentation_to_poly_metrics.py +230 -106
- scale-nucleus-0.14.5b1/nucleus/metrics/segmentation_utils.py +279 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/model.py +57 -3
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/model_run.py +0 -0
- scale-nucleus-0.12b9/nucleus/shapely_not_installed.py → scale-nucleus-0.14.5b1/nucleus/package_not_installed.py +3 -3
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/payload_constructor.py +4 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/prediction.py +3 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/pydantic_base.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/quaternion.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/retry_strategy.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/scene.py +7 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/slice.py +63 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/upload_response.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/url_utils.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/utils.py +37 -4
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/__init__.py +1 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/client.py +46 -2
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/constants.py +1 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/data_transfer_objects/__init__.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/data_transfer_objects/eval_function.py +22 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/data_transfer_objects/scenario_test.py +0 -0
- scale-nucleus-0.14.5b1/nucleus/validate/data_transfer_objects/scenario_test_evaluations.py +27 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/data_transfer_objects/scenario_test_metric.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/errors.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/eval_functions/__init__.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/eval_functions/available_eval_functions.py +33 -20
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/eval_functions/base_eval_function.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/eval_functions/config_classes/__init__.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/eval_functions/config_classes/segmentation.py +2 -46
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/scenario_test.py +53 -3
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/scenario_test_evaluation.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/scenario_test_metric.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/validate/utils.py +0 -0
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/pyproject.toml +14 -10
- {scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/setup.py +8 -8
- scale-nucleus-0.12b9/nucleus/metrics/segmentation_utils.py +0 -48
- scale-nucleus-0.12b9/nucleus/validate/data_transfer_objects/scenario_test_evaluations.py +0 -11
File without changes
|
@@ -1,31 +1,34 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: scale-nucleus
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.14.5b1
|
4
4
|
Summary: The official Python client library for Nucleus, the Data Platform for AI
|
5
5
|
Home-page: https://scale.com/nucleus
|
6
6
|
License: MIT
|
7
7
|
Author: Scale AI Nucleus Team
|
8
8
|
Author-email: nucleusapi@scaleapi.com
|
9
|
-
Requires-Python: >=3.6.2,<4.0
|
9
|
+
Requires-Python: >=3.6.2,<4.0
|
10
10
|
Classifier: License :: OSI Approved :: MIT License
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
12
12
|
Classifier: Programming Language :: Python :: 3.10
|
13
13
|
Classifier: Programming Language :: Python :: 3.7
|
14
14
|
Classifier: Programming Language :: Python :: 3.8
|
15
15
|
Classifier: Programming Language :: Python :: 3.9
|
16
|
-
Provides-Extra:
|
16
|
+
Provides-Extra: launch
|
17
|
+
Provides-Extra: metrics
|
17
18
|
Requires-Dist: Pillow (>=7.1.2)
|
18
|
-
Requires-Dist: Shapely (>=1.8.0); extra == "
|
19
|
+
Requires-Dist: Shapely (>=1.8.0); extra == "metrics"
|
19
20
|
Requires-Dist: aiohttp (>=3.7.4,<4.0.0)
|
20
21
|
Requires-Dist: click (>=7.1.2,<9.0)
|
21
22
|
Requires-Dist: dataclasses (>=0.7,<0.8); python_full_version >= "3.6.1" and python_version < "3.7"
|
22
23
|
Requires-Dist: nest-asyncio (>=1.5.1,<2.0.0)
|
23
|
-
Requires-Dist: numpy (>=1.19.5
|
24
|
+
Requires-Dist: numpy (>=1.19.5); python_version >= "3.6" and python_version < "3.10"
|
25
|
+
Requires-Dist: numpy (>=1.22.0); python_version >= "3.10"
|
24
26
|
Requires-Dist: pydantic (>=1.8.2,<2.0.0)
|
25
|
-
Requires-Dist: rasterio (>=1.2.
|
27
|
+
Requires-Dist: rasterio (>=1.2.0); extra == "metrics"
|
26
28
|
Requires-Dist: requests (>=2.23.0,<3.0.0)
|
27
|
-
Requires-Dist: rich (>=10.15.2
|
28
|
-
Requires-Dist: s3fs (>=
|
29
|
+
Requires-Dist: rich (>=10.15.2)
|
30
|
+
Requires-Dist: s3fs (>=2021.9.0); extra == "metrics"
|
31
|
+
Requires-Dist: scale-launch (>=0.1.0); (python_version >= "3.7" and python_version < "4.0") and (extra == "launch")
|
29
32
|
Requires-Dist: scikit-learn (>=0.24.0)
|
30
33
|
Requires-Dist: scipy (>=1.4.1)
|
31
34
|
Requires-Dist: shellingham (>=1.4.0,<2.0.0)
|
@@ -224,7 +227,7 @@ sphinx-autobuild . ./_build/html --watch ../nucleus
|
|
224
227
|
|
225
228
|
## Custom Metrics using Shapely in scale-validate
|
226
229
|
|
227
|
-
Certain metrics use `
|
230
|
+
Certain metrics use `Shapely` and `rasterio` which is added as optional dependencies.
|
228
231
|
|
229
232
|
```bash
|
230
233
|
pip install scale-nucleus[metrics]
|
@@ -241,5 +244,5 @@ apt-get install libgeos-dev
|
|
241
244
|
|
242
245
|
To develop it locally use
|
243
246
|
|
244
|
-
`poetry install --extras
|
247
|
+
`poetry install --extras metrics`
|
245
248
|
|
@@ -188,7 +188,7 @@ sphinx-autobuild . ./_build/html --watch ../nucleus
|
|
188
188
|
|
189
189
|
## Custom Metrics using Shapely in scale-validate
|
190
190
|
|
191
|
-
Certain metrics use `
|
191
|
+
Certain metrics use `Shapely` and `rasterio` which is added as optional dependencies.
|
192
192
|
|
193
193
|
```bash
|
194
194
|
pip install scale-nucleus[metrics]
|
@@ -205,4 +205,4 @@ apt-get install libgeos-dev
|
|
205
205
|
|
206
206
|
To develop it locally use
|
207
207
|
|
208
|
-
`poetry install --extras
|
208
|
+
`poetry install --extras metrics`
|
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
|
@@ -40,7 +40,7 @@ __all__ = [
|
|
40
40
|
|
41
41
|
import os
|
42
42
|
import warnings
|
43
|
-
from typing import Dict, List, Optional, Sequence, Union
|
43
|
+
from typing import Any, Dict, List, Optional, Sequence, Union
|
44
44
|
|
45
45
|
import pkg_resources
|
46
46
|
import pydantic
|
@@ -91,6 +91,7 @@ from .constants import (
|
|
91
91
|
KEEP_HISTORY_KEY,
|
92
92
|
MESSAGE_KEY,
|
93
93
|
MODEL_RUN_ID_KEY,
|
94
|
+
MODEL_TAGS_KEY,
|
94
95
|
NAME_KEY,
|
95
96
|
NUCLEUS_ENDPOINT,
|
96
97
|
PREDICTIONS_IGNORED_KEY,
|
@@ -218,6 +219,7 @@ class NucleusClient:
|
|
218
219
|
reference_id=model["ref_id"],
|
219
220
|
metadata=model["metadata"] or None,
|
220
221
|
client=self,
|
222
|
+
tags=model.get(MODEL_TAGS_KEY, []),
|
221
223
|
)
|
222
224
|
for model in model_objects["models"]
|
223
225
|
]
|
@@ -484,6 +486,7 @@ class NucleusClient:
|
|
484
486
|
reference_id: str,
|
485
487
|
metadata: Optional[Dict] = None,
|
486
488
|
bundle_name: Optional[str] = None,
|
489
|
+
tags: Optional[List[str]] = None,
|
487
490
|
) -> Model:
|
488
491
|
"""Adds a :class:`Model` to Nucleus.
|
489
492
|
|
@@ -495,13 +498,15 @@ class NucleusClient:
|
|
495
498
|
metadata: An arbitrary dictionary of additional data about this model
|
496
499
|
that can be stored and retrieved. For example, you can store information
|
497
500
|
about the hyperparameters used in training this model.
|
501
|
+
bundle_name: Optional name of bundle attached to this model
|
502
|
+
tags: Optional list of tags to attach to this model
|
498
503
|
|
499
504
|
Returns:
|
500
505
|
:class:`Model`: The newly created model as an object.
|
501
506
|
"""
|
502
507
|
response = self.make_request(
|
503
508
|
construct_model_creation_payload(
|
504
|
-
name, reference_id, metadata, bundle_name
|
509
|
+
name, reference_id, metadata, bundle_name, tags
|
505
510
|
),
|
506
511
|
"models/add",
|
507
512
|
)
|
@@ -516,6 +521,197 @@ class NucleusClient:
|
|
516
521
|
metadata=metadata,
|
517
522
|
bundle_name=bundle_name,
|
518
523
|
client=self,
|
524
|
+
tags=tags,
|
525
|
+
)
|
526
|
+
|
527
|
+
def create_launch_model(
|
528
|
+
self,
|
529
|
+
name: str,
|
530
|
+
reference_id: str,
|
531
|
+
bundle_args: Dict[str, Any],
|
532
|
+
metadata: Optional[Dict] = None,
|
533
|
+
) -> Model:
|
534
|
+
"""
|
535
|
+
Adds a :class:`Model` to Nucleus, as well as a Launch bundle from a given function.
|
536
|
+
|
537
|
+
Parameters:
|
538
|
+
name: A human-readable name for the model.
|
539
|
+
reference_id: Unique, user-controlled ID for the model. This can be
|
540
|
+
used, for example, to link to an external storage of models which
|
541
|
+
may have its own id scheme.
|
542
|
+
bundle_args: Dict for kwargs for the creation of a Launch bundle,
|
543
|
+
more details on the keys below.
|
544
|
+
metadata: An arbitrary dictionary of additional data about this model
|
545
|
+
that can be stored and retrieved. For example, you can store information
|
546
|
+
about the hyperparameters used in training this model.
|
547
|
+
|
548
|
+
Returns:
|
549
|
+
:class:`Model`: The newly created model as an object.
|
550
|
+
|
551
|
+
Details on `bundle_args`:
|
552
|
+
Grabs a s3 signed url and uploads a model bundle to Scale Launch.
|
553
|
+
|
554
|
+
A model bundle consists of exactly {predict_fn_or_cls}, {load_predict_fn + model}, or {load_predict_fn + load_model_fn}.
|
555
|
+
Pre/post-processing code can be included inside load_predict_fn/model or in predict_fn_or_cls call.
|
556
|
+
|
557
|
+
Parameters:
|
558
|
+
model_bundle_name: Name of model bundle you want to create. This acts as a unique identifier.
|
559
|
+
predict_fn_or_cls: Function or a Callable class that runs end-to-end (pre/post processing and model inference) on the call.
|
560
|
+
I.e. `predict_fn_or_cls(REQUEST) -> RESPONSE`.
|
561
|
+
model: Typically a trained Neural Network, e.g. a Pytorch module
|
562
|
+
load_predict_fn: Function that when called with model, returns a function that carries out inference
|
563
|
+
I.e. `load_predict_fn(model) -> func; func(REQUEST) -> RESPONSE`
|
564
|
+
load_model_fn: Function that when run, loads a model, e.g. a Pytorch module
|
565
|
+
I.e. `load_predict_fn(load_model_fn()) -> func; func(REQUEST) -> RESPONSE`
|
566
|
+
bundle_url: Only for self-hosted mode. Desired location of bundle.
|
567
|
+
Overrides any value given by self.bundle_location_fn
|
568
|
+
requirements: A list of python package requirements, e.g.
|
569
|
+
["tensorflow==2.3.0", "tensorflow-hub==0.11.0"]. If no list has been passed, will default to the currently
|
570
|
+
imported list of packages.
|
571
|
+
app_config: Either a Dictionary that represents a YAML file contents or a local path to a YAML file.
|
572
|
+
env_params: A dictionary that dictates environment information e.g.
|
573
|
+
the use of pytorch or tensorflow, which cuda/cudnn versions to use.
|
574
|
+
Specifically, the dictionary should contain the following keys:
|
575
|
+
"framework_type": either "tensorflow" or "pytorch".
|
576
|
+
"pytorch_version": Version of pytorch, e.g. "1.5.1", "1.7.0", etc. Only applicable if framework_type is pytorch
|
577
|
+
"cuda_version": Version of cuda used, e.g. "11.0".
|
578
|
+
"cudnn_version" Version of cudnn used, e.g. "cudnn8-devel".
|
579
|
+
"tensorflow_version": Version of tensorflow, e.g. "2.3.0". Only applicable if framework_type is tensorflow
|
580
|
+
globals_copy: Dictionary of the global symbol table. Normally provided by `globals()` built-in function.
|
581
|
+
"""
|
582
|
+
from launch import LaunchClient
|
583
|
+
|
584
|
+
launch_client = LaunchClient(api_key=self.api_key)
|
585
|
+
|
586
|
+
model_exists = any(model.name == name for model in self.list_models())
|
587
|
+
bundle_exists = any(
|
588
|
+
bundle.name == name + "-nucleus-autogen"
|
589
|
+
for bundle in launch_client.list_model_bundles()
|
590
|
+
)
|
591
|
+
|
592
|
+
if bundle_exists or model_exists:
|
593
|
+
raise ModelCreationError(
|
594
|
+
"Bundle with the given name already exists, please try a different name"
|
595
|
+
)
|
596
|
+
|
597
|
+
kwargs = {
|
598
|
+
"model_bundle_name": name + "-nucleus-autogen",
|
599
|
+
**bundle_args,
|
600
|
+
}
|
601
|
+
|
602
|
+
bundle = launch_client.create_model_bundle(**kwargs)
|
603
|
+
return self.create_model(
|
604
|
+
name,
|
605
|
+
reference_id,
|
606
|
+
metadata,
|
607
|
+
bundle.name,
|
608
|
+
)
|
609
|
+
|
610
|
+
def create_launch_model_from_dir(
|
611
|
+
self,
|
612
|
+
name: str,
|
613
|
+
reference_id: str,
|
614
|
+
bundle_from_dir_args: Dict[str, Any],
|
615
|
+
metadata: Optional[Dict] = None,
|
616
|
+
) -> Model:
|
617
|
+
"""
|
618
|
+
Adds a :class:`Model` to Nucleus, as well as a Launch bundle from a directory.
|
619
|
+
|
620
|
+
Parameters:
|
621
|
+
name: A human-readable name for the model.
|
622
|
+
reference_id: Unique, user-controlled ID for the model. This can be
|
623
|
+
used, for example, to link to an external storage of models which
|
624
|
+
may have its own id scheme.
|
625
|
+
bundle_from_dir_args: Dict for kwargs for the creation of a bundle from directory,
|
626
|
+
more details on the keys below.
|
627
|
+
metadata: An arbitrary dictionary of additional data about this model
|
628
|
+
that can be stored and retrieved. For example, you can store information
|
629
|
+
about the hyperparameters used in training this model.
|
630
|
+
|
631
|
+
Returns:
|
632
|
+
:class:`Model`: The newly created model as an object.
|
633
|
+
|
634
|
+
Details on `bundle_from_dir_args`
|
635
|
+
Packages up code from one or more local filesystem folders and uploads them as a bundle to Scale Launch.
|
636
|
+
In this mode, a bundle is just local code instead of a serialized object.
|
637
|
+
|
638
|
+
For example, if you have a directory structure like so, and your current working directory is also `my_root`:
|
639
|
+
|
640
|
+
```
|
641
|
+
my_root/
|
642
|
+
my_module1/
|
643
|
+
__init__.py
|
644
|
+
...files and directories
|
645
|
+
my_inference_file.py
|
646
|
+
my_module2/
|
647
|
+
__init__.py
|
648
|
+
...files and directories
|
649
|
+
```
|
650
|
+
|
651
|
+
then calling `create_model_bundle_from_dirs` with `base_paths=["my_module1", "my_module2"]` essentially
|
652
|
+
creates a zip file without the root directory, e.g.:
|
653
|
+
|
654
|
+
```
|
655
|
+
my_module1/
|
656
|
+
__init__.py
|
657
|
+
...files and directories
|
658
|
+
my_inference_file.py
|
659
|
+
my_module2/
|
660
|
+
__init__.py
|
661
|
+
...files and directories
|
662
|
+
```
|
663
|
+
|
664
|
+
and these contents will be unzipped relative to the server side `PYTHONPATH`. Bear these points in mind when
|
665
|
+
referencing Python module paths for this bundle. For instance, if `my_inference_file.py` has `def f(...)`
|
666
|
+
as the desired inference loading function, then the `load_predict_fn_module_path` argument should be
|
667
|
+
`my_module1.my_inference_file.f`.
|
668
|
+
|
669
|
+
|
670
|
+
Keys for `bundle_from_dir_args`:
|
671
|
+
model_bundle_name: Name of model bundle you want to create. This acts as a unique identifier.
|
672
|
+
base_paths: The paths on the local filesystem where the bundle code lives.
|
673
|
+
requirements_path: A path on the local filesystem where a requirements.txt file lives.
|
674
|
+
env_params: A dictionary that dictates environment information e.g.
|
675
|
+
the use of pytorch or tensorflow, which cuda/cudnn versions to use.
|
676
|
+
Specifically, the dictionary should contain the following keys:
|
677
|
+
"framework_type": either "tensorflow" or "pytorch".
|
678
|
+
"pytorch_version": Version of pytorch, e.g. "1.5.1", "1.7.0", etc. Only applicable if framework_type is pytorch
|
679
|
+
"cuda_version": Version of cuda used, e.g. "11.0".
|
680
|
+
"cudnn_version" Version of cudnn used, e.g. "cudnn8-devel".
|
681
|
+
"tensorflow_version": Version of tensorflow, e.g. "2.3.0". Only applicable if framework_type is tensorflow
|
682
|
+
load_predict_fn_module_path: A python module path for a function that, when called with the output of
|
683
|
+
load_model_fn_module_path, returns a function that carries out inference.
|
684
|
+
load_model_fn_module_path: A python module path for a function that returns a model. The output feeds into
|
685
|
+
the function located at load_predict_fn_module_path.
|
686
|
+
app_config: Either a Dictionary that represents a YAML file contents or a local path to a YAML file.
|
687
|
+
"""
|
688
|
+
from launch import LaunchClient
|
689
|
+
|
690
|
+
launch_client = LaunchClient(api_key=self.api_key)
|
691
|
+
|
692
|
+
model_exists = any(model.name == name for model in self.list_models())
|
693
|
+
bundle_exists = any(
|
694
|
+
bundle.name == name + "-nucleus-autogen"
|
695
|
+
for bundle in launch_client.list_model_bundles()
|
696
|
+
)
|
697
|
+
|
698
|
+
if bundle_exists or model_exists:
|
699
|
+
raise ModelCreationError(
|
700
|
+
"Bundle with the given name already exists, please try a different name"
|
701
|
+
)
|
702
|
+
|
703
|
+
kwargs = {
|
704
|
+
"model_bundle_name": name + "-nucleus-autogen",
|
705
|
+
**bundle_from_dir_args,
|
706
|
+
}
|
707
|
+
|
708
|
+
bundle = launch_client.create_model_bundle_from_dir(**kwargs)
|
709
|
+
|
710
|
+
return self.create_model(
|
711
|
+
name,
|
712
|
+
reference_id,
|
713
|
+
metadata,
|
714
|
+
bundle.name,
|
519
715
|
)
|
520
716
|
|
521
717
|
@deprecated(
|
@@ -837,7 +1033,6 @@ class NucleusClient:
|
|
837
1033
|
Returns:
|
838
1034
|
Response payload as JSON dict.
|
839
1035
|
"""
|
840
|
-
print(payload, route)
|
841
1036
|
if payload is None:
|
842
1037
|
payload = {}
|
843
1038
|
if requests_command is requests.get:
|
@@ -180,6 +180,19 @@ class BoxAnnotation(Annotation): # pylint: disable=R0902
|
|
180
180
|
EMBEDDING_VECTOR_KEY: self.embedding_vector,
|
181
181
|
}
|
182
182
|
|
183
|
+
def __eq__(self, other):
|
184
|
+
return (
|
185
|
+
self.label == other.label
|
186
|
+
and self.x == other.x
|
187
|
+
and self.y == other.y
|
188
|
+
and self.width == other.width
|
189
|
+
and self.height == other.height
|
190
|
+
and self.reference_id == other.reference_id
|
191
|
+
and self.annotation_id == other.annotation_id
|
192
|
+
and sorted(self.metadata.items()) == sorted(other.metadata.items())
|
193
|
+
and self.embedding_vector == other.embedding_vector
|
194
|
+
)
|
195
|
+
|
183
196
|
|
184
197
|
@dataclass
|
185
198
|
class Point:
|
@@ -426,7 +439,7 @@ class KeypointsAnnotation(Annotation):
|
|
426
439
|
label="face",
|
427
440
|
keypoints=[Keypoint(100, 100), Keypoint(120, 120), Keypoint(visible=False), Keypoint(0, 0)],
|
428
441
|
names=["point1", "point2", "point3", "point4"],
|
429
|
-
skeleton=[[0, 1], [1, 2], [1, 3], [2,
|
442
|
+
skeleton=[[0, 1], [1, 2], [1, 3], [2, 3]],
|
430
443
|
reference_id="image_2",
|
431
444
|
annotation_id="image_2_face_keypoints_1",
|
432
445
|
metadata={"face_direction": "forward"},
|
@@ -473,11 +486,17 @@ class KeypointsAnnotation(Annotation):
|
|
473
486
|
)
|
474
487
|
seen.add(name)
|
475
488
|
|
489
|
+
max_segment_index = len(self.keypoints) - 1
|
476
490
|
for segment in self.skeleton:
|
477
491
|
if len(segment) != 2:
|
478
492
|
raise ValueError(
|
479
493
|
"The keypoints skeleton must contain a list of line segments with exactly 2 indices"
|
480
494
|
)
|
495
|
+
for index in segment:
|
496
|
+
if index > max_segment_index:
|
497
|
+
raise ValueError(
|
498
|
+
f"The skeleton index {index} is not a valid keypoint index"
|
499
|
+
)
|
481
500
|
|
482
501
|
@classmethod
|
483
502
|
def from_json(cls, payload: dict):
|
@@ -920,6 +939,9 @@ class AnnotationList:
|
|
920
939
|
), f"Unexpected annotation type: {type(annotation)}"
|
921
940
|
self.segmentation_annotations.append(annotation)
|
922
941
|
|
942
|
+
def items(self):
|
943
|
+
return self.__dict__.items()
|
944
|
+
|
923
945
|
def __len__(self):
|
924
946
|
return (
|
925
947
|
len(self.box_annotations)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -27,6 +27,7 @@ ANNOTATION_UPDATE_KEY = "update"
|
|
27
27
|
AUTOTAGS_KEY = "autotags"
|
28
28
|
AUTOTAG_SCORE_THRESHOLD = "score_threshold"
|
29
29
|
EXPORTED_ROWS = "exportedRows"
|
30
|
+
EXPORTED_SCALE_TASK_INFO_ROWS = "exportedScaleTaskInfoRows"
|
30
31
|
CAMERA_MODEL_KEY = "camera_model"
|
31
32
|
CAMERA_PARAMS_KEY = "camera_params"
|
32
33
|
CLASS_PDF_KEY = "class_pdf"
|
@@ -89,6 +90,7 @@ MAX_PAYLOAD_SIZE = 0x1FFFFFE8 # Set to max string size since we currently conve
|
|
89
90
|
MESSAGE_KEY = "message"
|
90
91
|
METADATA_KEY = "metadata"
|
91
92
|
MODEL_BUNDLE_NAME_KEY = "bundle_name"
|
93
|
+
MODEL_TAGS_KEY = "tags"
|
92
94
|
MODEL_ID_KEY = "model_id"
|
93
95
|
MODEL_RUN_ID_KEY = "model_run_id"
|
94
96
|
NAME_KEY = "name"
|
@@ -105,11 +107,14 @@ POINTCLOUD_LOCATION_KEY = "pointcloud_location"
|
|
105
107
|
POINTCLOUD_URL_KEY = "pointcloud_url"
|
106
108
|
POSITION_KEY = "position"
|
107
109
|
PREDICTIONS_IGNORED_KEY = "predictions_ignored"
|
110
|
+
PREDICTIONS_KEY = "predictions"
|
108
111
|
PREDICTIONS_PROCESSED_KEY = "predictions_processed"
|
109
112
|
REFERENCE_IDS_KEY = "reference_ids"
|
110
113
|
REFERENCE_ID_KEY = "reference_id"
|
111
114
|
BACKEND_REFERENCE_ID_KEY = "ref_id" # TODO(355762): Our backend returns this instead of the "proper" key sometimes.
|
112
115
|
REQUEST_ID_KEY = "requestId"
|
116
|
+
SCALE_TASK_INFO_KEY = "scale_task_info"
|
117
|
+
SCENE_KEY = "scene"
|
113
118
|
SCENES_KEY = "scenes"
|
114
119
|
SERIALIZED_REQUEST_KEY = "serialized_request"
|
115
120
|
SEGMENTATIONS_KEY = "segmentations"
|
File without changes
|
{scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/data_transfer_object/dataset_details.py
RENAMED
File without changes
|
{scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/data_transfer_object/dataset_info.py
RENAMED
File without changes
|
{scale-nucleus-0.12b9 → scale-nucleus-0.14.5b1}/nucleus/data_transfer_object/dataset_size.py
RENAMED
File without changes
|
File without changes
|
@@ -18,6 +18,7 @@ from nucleus.utils import (
|
|
18
18
|
convert_export_payload,
|
19
19
|
format_dataset_item_response,
|
20
20
|
format_prediction_response,
|
21
|
+
format_scale_task_info_response,
|
21
22
|
paginate_generator,
|
22
23
|
serialize_and_write_to_presigned_url,
|
23
24
|
)
|
@@ -1278,6 +1279,36 @@ class Dataset:
|
|
1278
1279
|
)
|
1279
1280
|
return format_prediction_response({ANNOTATIONS_KEY: json_response})
|
1280
1281
|
|
1282
|
+
def export_scale_task_info(self):
|
1283
|
+
"""Fetches info for all linked Scale tasks of items/scenes in the dataset.
|
1284
|
+
|
1285
|
+
Returns:
|
1286
|
+
A list of dicts, each with two keys, respectively mapping to items/scenes
|
1287
|
+
and info on their corresponding Scale tasks within the dataset::
|
1288
|
+
|
1289
|
+
List[{
|
1290
|
+
"item" | "scene": Union[:class:`DatasetItem`, :class:`Scene`],
|
1291
|
+
"scale_task_info": {
|
1292
|
+
"task_id": str,
|
1293
|
+
"subtask_id": str,
|
1294
|
+
"task_status": str,
|
1295
|
+
"task_audit_status": str,
|
1296
|
+
"task_audit_review_comment": Optional[str],
|
1297
|
+
"project_name": str,
|
1298
|
+
"batch": str,
|
1299
|
+
"created_at": str,
|
1300
|
+
"completed_at": Optional[str]
|
1301
|
+
}[]
|
1302
|
+
}]
|
1303
|
+
|
1304
|
+
"""
|
1305
|
+
response = self._client.make_request(
|
1306
|
+
payload=None,
|
1307
|
+
route=f"dataset/{self.id}/exportScaleTaskInfo",
|
1308
|
+
requests_command=requests.get,
|
1309
|
+
)
|
1310
|
+
return format_scale_task_info_response(response)
|
1311
|
+
|
1281
1312
|
def calculate_evaluation_metrics(self, model, options: dict = None):
|
1282
1313
|
"""Starts computation of evaluation metrics for a model on the dataset.
|
1283
1314
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -4,10 +4,13 @@ from dataclasses import dataclass
|
|
4
4
|
from typing import Iterable, List, Optional, Union
|
5
5
|
|
6
6
|
from nucleus.annotation import AnnotationList
|
7
|
+
from nucleus.metrics.errors import EverythingFilteredError
|
7
8
|
from nucleus.metrics.filtering import (
|
8
9
|
ListOfAndFilters,
|
9
10
|
ListOfOrAndFilters,
|
10
|
-
|
11
|
+
compose_helpful_filtering_error,
|
12
|
+
filter_annotation_list,
|
13
|
+
filter_prediction_list,
|
11
14
|
)
|
12
15
|
from nucleus.prediction import PredictionList
|
13
16
|
|
@@ -133,64 +136,16 @@ class Metric(ABC):
|
|
133
136
|
def __call__(
|
134
137
|
self, annotations: AnnotationList, predictions: PredictionList
|
135
138
|
) -> MetricResult:
|
136
|
-
|
137
|
-
|
138
|
-
return self.call_metric(annotations, predictions)
|
139
|
-
|
140
|
-
def _filter_annotations(self, annotations: AnnotationList):
|
141
|
-
if (
|
142
|
-
self.annotation_filters is None
|
143
|
-
or len(self.annotation_filters) == 0
|
144
|
-
):
|
145
|
-
return annotations
|
146
|
-
annotations.box_annotations = apply_filters(
|
147
|
-
annotations.box_annotations, self.annotation_filters
|
139
|
+
filtered_anns = filter_annotation_list(
|
140
|
+
annotations, self.annotation_filters
|
148
141
|
)
|
149
|
-
|
150
|
-
|
142
|
+
filtered_preds = filter_prediction_list(
|
143
|
+
predictions, self.prediction_filters
|
151
144
|
)
|
152
|
-
|
153
|
-
annotations
|
145
|
+
self._raise_if_everything_filtered(
|
146
|
+
annotations, filtered_anns, predictions, filtered_preds
|
154
147
|
)
|
155
|
-
|
156
|
-
annotations.cuboid_annotations, self.annotation_filters
|
157
|
-
)
|
158
|
-
annotations.category_annotations = apply_filters(
|
159
|
-
annotations.category_annotations, self.annotation_filters
|
160
|
-
)
|
161
|
-
annotations.multi_category_annotations = apply_filters(
|
162
|
-
annotations.multi_category_annotations, self.annotation_filters
|
163
|
-
)
|
164
|
-
annotations.segmentation_annotations = apply_filters(
|
165
|
-
annotations.segmentation_annotations, self.annotation_filters
|
166
|
-
)
|
167
|
-
return annotations
|
168
|
-
|
169
|
-
def _filter_predictions(self, predictions: PredictionList):
|
170
|
-
if (
|
171
|
-
self.prediction_filters is None
|
172
|
-
or len(self.prediction_filters) == 0
|
173
|
-
):
|
174
|
-
return predictions
|
175
|
-
predictions.box_predictions = apply_filters(
|
176
|
-
predictions.box_predictions, self.prediction_filters
|
177
|
-
)
|
178
|
-
predictions.line_predictions = apply_filters(
|
179
|
-
predictions.line_predictions, self.prediction_filters
|
180
|
-
)
|
181
|
-
predictions.polygon_predictions = apply_filters(
|
182
|
-
predictions.polygon_predictions, self.prediction_filters
|
183
|
-
)
|
184
|
-
predictions.cuboid_predictions = apply_filters(
|
185
|
-
predictions.cuboid_predictions, self.prediction_filters
|
186
|
-
)
|
187
|
-
predictions.category_predictions = apply_filters(
|
188
|
-
predictions.category_predictions, self.prediction_filters
|
189
|
-
)
|
190
|
-
predictions.segmentation_predictions = apply_filters(
|
191
|
-
predictions.segmentation_predictions, self.prediction_filters
|
192
|
-
)
|
193
|
-
return predictions
|
148
|
+
return self.call_metric(filtered_anns, filtered_preds)
|
194
149
|
|
195
150
|
@abstractmethod
|
196
151
|
def aggregate_score(self, results: List[MetricResult]) -> ScalarResult:
|
@@ -215,3 +170,26 @@ class Metric(ABC):
|
|
215
170
|
return ScalarResult(r2_score)
|
216
171
|
|
217
172
|
"""
|
173
|
+
|
174
|
+
def _raise_if_everything_filtered(
|
175
|
+
self,
|
176
|
+
annotations: AnnotationList,
|
177
|
+
filtered_annotations: AnnotationList,
|
178
|
+
predictions: PredictionList,
|
179
|
+
filtered_predictions: PredictionList,
|
180
|
+
):
|
181
|
+
msg = []
|
182
|
+
if len(filtered_annotations) == 0:
|
183
|
+
msg.extend(
|
184
|
+
compose_helpful_filtering_error(
|
185
|
+
annotations, self.annotation_filters
|
186
|
+
)
|
187
|
+
)
|
188
|
+
if len(filtered_predictions) == 0:
|
189
|
+
msg.extend(
|
190
|
+
compose_helpful_filtering_error(
|
191
|
+
predictions, self.prediction_filters
|
192
|
+
)
|
193
|
+
)
|
194
|
+
if msg:
|
195
|
+
raise EverythingFilteredError("\n".join(msg))
|
File without changes
|
File without changes
|