wandb 0.21.2__py3-none-macosx_12_0_x86_64.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.
- package_readme.md +97 -0
- wandb/__init__.py +248 -0
- wandb/__init__.pyi +1230 -0
- wandb/__main__.py +3 -0
- wandb/_iterutils.py +65 -0
- wandb/_pydantic/__init__.py +30 -0
- wandb/_pydantic/base.py +128 -0
- wandb/_pydantic/utils.py +80 -0
- wandb/_pydantic/v1_compat.py +284 -0
- wandb/agents/__init__.py +0 -0
- wandb/agents/pyagent.py +386 -0
- wandb/analytics/__init__.py +3 -0
- wandb/analytics/sentry.py +267 -0
- wandb/apis/__init__.py +48 -0
- wandb/apis/attrs.py +50 -0
- wandb/apis/importers/__init__.py +1 -0
- wandb/apis/importers/internals/internal.py +382 -0
- wandb/apis/importers/internals/protocols.py +103 -0
- wandb/apis/importers/internals/util.py +78 -0
- wandb/apis/importers/mlflow.py +254 -0
- wandb/apis/importers/validation.py +108 -0
- wandb/apis/importers/wandb.py +1608 -0
- wandb/apis/internal.py +239 -0
- wandb/apis/normalize.py +81 -0
- wandb/apis/paginator.py +138 -0
- wandb/apis/public/__init__.py +35 -0
- wandb/apis/public/api.py +2449 -0
- wandb/apis/public/artifacts.py +1046 -0
- wandb/apis/public/automations.py +85 -0
- wandb/apis/public/const.py +4 -0
- wandb/apis/public/files.py +402 -0
- wandb/apis/public/history.py +201 -0
- wandb/apis/public/integrations.py +203 -0
- wandb/apis/public/jobs.py +742 -0
- wandb/apis/public/projects.py +276 -0
- wandb/apis/public/query_generator.py +176 -0
- wandb/apis/public/registries/__init__.py +0 -0
- wandb/apis/public/registries/_freezable_list.py +179 -0
- wandb/apis/public/registries/_utils.py +138 -0
- wandb/apis/public/registries/registries_search.py +347 -0
- wandb/apis/public/registries/registry.py +358 -0
- wandb/apis/public/reports.py +595 -0
- wandb/apis/public/runs.py +1216 -0
- wandb/apis/public/sweeps.py +440 -0
- wandb/apis/public/teams.py +235 -0
- wandb/apis/public/users.py +177 -0
- wandb/apis/public/utils.py +210 -0
- wandb/apis/reports/__init__.py +1 -0
- wandb/apis/reports/v1/__init__.py +8 -0
- wandb/apis/reports/v2/__init__.py +8 -0
- wandb/apis/workspaces/__init__.py +8 -0
- wandb/automations/__init__.py +73 -0
- wandb/automations/_filters/__init__.py +40 -0
- wandb/automations/_filters/expressions.py +181 -0
- wandb/automations/_filters/operators.py +258 -0
- wandb/automations/_filters/run_metrics.py +330 -0
- wandb/automations/_generated/__init__.py +177 -0
- wandb/automations/_generated/create_automation.py +17 -0
- wandb/automations/_generated/create_generic_webhook_integration.py +43 -0
- wandb/automations/_generated/delete_automation.py +15 -0
- wandb/automations/_generated/enums.py +35 -0
- wandb/automations/_generated/fragments.py +358 -0
- wandb/automations/_generated/generic_webhook_integrations_by_entity.py +22 -0
- wandb/automations/_generated/get_automations.py +24 -0
- wandb/automations/_generated/get_automations_by_entity.py +26 -0
- wandb/automations/_generated/input_types.py +104 -0
- wandb/automations/_generated/integrations_by_entity.py +22 -0
- wandb/automations/_generated/operations.py +647 -0
- wandb/automations/_generated/slack_integrations_by_entity.py +22 -0
- wandb/automations/_generated/update_automation.py +17 -0
- wandb/automations/_utils.py +235 -0
- wandb/automations/_validators.py +165 -0
- wandb/automations/actions.py +218 -0
- wandb/automations/automations.py +85 -0
- wandb/automations/events.py +285 -0
- wandb/automations/integrations.py +45 -0
- wandb/automations/scopes.py +78 -0
- wandb/beta/workflows.py +324 -0
- wandb/bin/gpu_stats +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/__init__.py +0 -0
- wandb/cli/beta.py +175 -0
- wandb/cli/cli.py +2883 -0
- wandb/data_types.py +66 -0
- wandb/docker/__init__.py +290 -0
- wandb/docker/names.py +40 -0
- wandb/docker/wandb-entrypoint.sh +33 -0
- wandb/env.py +535 -0
- wandb/errors/__init__.py +17 -0
- wandb/errors/errors.py +40 -0
- wandb/errors/links.py +73 -0
- wandb/errors/term.py +415 -0
- wandb/errors/util.py +57 -0
- wandb/errors/warnings.py +2 -0
- wandb/filesync/__init__.py +0 -0
- wandb/filesync/dir_watcher.py +404 -0
- wandb/filesync/stats.py +100 -0
- wandb/filesync/step_checksum.py +142 -0
- wandb/filesync/step_prepare.py +179 -0
- wandb/filesync/step_upload.py +287 -0
- wandb/filesync/upload_job.py +142 -0
- wandb/integration/__init__.py +0 -0
- wandb/integration/catboost/__init__.py +5 -0
- wandb/integration/catboost/catboost.py +182 -0
- wandb/integration/cohere/__init__.py +3 -0
- wandb/integration/cohere/cohere.py +21 -0
- wandb/integration/cohere/resolver.py +347 -0
- wandb/integration/diffusers/__init__.py +3 -0
- wandb/integration/diffusers/autologger.py +76 -0
- wandb/integration/diffusers/pipeline_resolver.py +50 -0
- wandb/integration/diffusers/resolvers/__init__.py +9 -0
- wandb/integration/diffusers/resolvers/multimodal.py +881 -0
- wandb/integration/diffusers/resolvers/utils.py +102 -0
- wandb/integration/fastai/__init__.py +243 -0
- wandb/integration/gym/__init__.py +98 -0
- wandb/integration/huggingface/__init__.py +3 -0
- wandb/integration/huggingface/huggingface.py +18 -0
- wandb/integration/huggingface/resolver.py +213 -0
- wandb/integration/keras/__init__.py +11 -0
- wandb/integration/keras/callbacks/__init__.py +5 -0
- wandb/integration/keras/callbacks/metrics_logger.py +129 -0
- wandb/integration/keras/callbacks/model_checkpoint.py +188 -0
- wandb/integration/keras/callbacks/tables_builder.py +228 -0
- wandb/integration/keras/keras.py +1086 -0
- wandb/integration/kfp/__init__.py +6 -0
- wandb/integration/kfp/helpers.py +28 -0
- wandb/integration/kfp/kfp_patch.py +335 -0
- wandb/integration/kfp/wandb_logging.py +182 -0
- wandb/integration/langchain/__init__.py +3 -0
- wandb/integration/langchain/wandb_tracer.py +49 -0
- wandb/integration/lightgbm/__init__.py +239 -0
- wandb/integration/lightning/__init__.py +0 -0
- wandb/integration/lightning/fabric/__init__.py +3 -0
- wandb/integration/lightning/fabric/logger.py +763 -0
- wandb/integration/metaflow/__init__.py +9 -0
- wandb/integration/metaflow/data_pandas.py +74 -0
- wandb/integration/metaflow/data_pytorch.py +75 -0
- wandb/integration/metaflow/data_sklearn.py +76 -0
- wandb/integration/metaflow/errors.py +13 -0
- wandb/integration/metaflow/metaflow.py +327 -0
- wandb/integration/openai/__init__.py +3 -0
- wandb/integration/openai/fine_tuning.py +480 -0
- wandb/integration/openai/openai.py +22 -0
- wandb/integration/openai/resolver.py +240 -0
- wandb/integration/prodigy/__init__.py +3 -0
- wandb/integration/prodigy/prodigy.py +291 -0
- wandb/integration/sacred/__init__.py +117 -0
- wandb/integration/sagemaker/__init__.py +14 -0
- wandb/integration/sagemaker/auth.py +29 -0
- wandb/integration/sagemaker/config.py +58 -0
- wandb/integration/sagemaker/files.py +2 -0
- wandb/integration/sagemaker/resources.py +63 -0
- wandb/integration/sb3/__init__.py +3 -0
- wandb/integration/sb3/sb3.py +147 -0
- wandb/integration/sklearn/__init__.py +37 -0
- wandb/integration/sklearn/calculate/__init__.py +32 -0
- wandb/integration/sklearn/calculate/calibration_curves.py +125 -0
- wandb/integration/sklearn/calculate/class_proportions.py +68 -0
- wandb/integration/sklearn/calculate/confusion_matrix.py +93 -0
- wandb/integration/sklearn/calculate/decision_boundaries.py +40 -0
- wandb/integration/sklearn/calculate/elbow_curve.py +55 -0
- wandb/integration/sklearn/calculate/feature_importances.py +67 -0
- wandb/integration/sklearn/calculate/learning_curve.py +64 -0
- wandb/integration/sklearn/calculate/outlier_candidates.py +69 -0
- wandb/integration/sklearn/calculate/residuals.py +86 -0
- wandb/integration/sklearn/calculate/silhouette.py +118 -0
- wandb/integration/sklearn/calculate/summary_metrics.py +62 -0
- wandb/integration/sklearn/plot/__init__.py +35 -0
- wandb/integration/sklearn/plot/classifier.py +329 -0
- wandb/integration/sklearn/plot/clusterer.py +146 -0
- wandb/integration/sklearn/plot/regressor.py +121 -0
- wandb/integration/sklearn/plot/shared.py +91 -0
- wandb/integration/sklearn/utils.py +184 -0
- wandb/integration/tensorboard/__init__.py +10 -0
- wandb/integration/tensorboard/log.py +351 -0
- wandb/integration/tensorboard/monkeypatch.py +186 -0
- wandb/integration/tensorflow/__init__.py +5 -0
- wandb/integration/tensorflow/estimator_hook.py +54 -0
- wandb/integration/torch/__init__.py +0 -0
- wandb/integration/torch/wandb_torch.py +554 -0
- wandb/integration/ultralytics/__init__.py +11 -0
- wandb/integration/ultralytics/bbox_utils.py +215 -0
- wandb/integration/ultralytics/callback.py +528 -0
- wandb/integration/ultralytics/classification_utils.py +83 -0
- wandb/integration/ultralytics/mask_utils.py +202 -0
- wandb/integration/ultralytics/pose_utils.py +103 -0
- wandb/integration/weave/__init__.py +6 -0
- wandb/integration/weave/interface.py +49 -0
- wandb/integration/weave/weave.py +63 -0
- wandb/integration/xgboost/__init__.py +11 -0
- wandb/integration/xgboost/xgboost.py +189 -0
- wandb/integration/yolov8/__init__.py +0 -0
- wandb/integration/yolov8/yolov8.py +284 -0
- wandb/jupyter.py +538 -0
- wandb/mpmain/__init__.py +0 -0
- wandb/mpmain/__main__.py +1 -0
- wandb/old/__init__.py +0 -0
- wandb/old/core.py +53 -0
- wandb/old/settings.py +176 -0
- wandb/old/summary.py +438 -0
- wandb/plot/__init__.py +30 -0
- wandb/plot/bar.py +71 -0
- wandb/plot/confusion_matrix.py +185 -0
- wandb/plot/custom_chart.py +147 -0
- wandb/plot/histogram.py +66 -0
- wandb/plot/line.py +75 -0
- wandb/plot/line_series.py +173 -0
- wandb/plot/pr_curve.py +186 -0
- wandb/plot/roc_curve.py +163 -0
- wandb/plot/scatter.py +66 -0
- wandb/plot/utils.py +184 -0
- wandb/plot/viz.py +41 -0
- wandb/proto/__init__.py +0 -0
- wandb/proto/v3/__init__.py +0 -0
- wandb/proto/v3/wandb_base_pb2.py +55 -0
- wandb/proto/v3/wandb_internal_pb2.py +1728 -0
- wandb/proto/v3/wandb_server_pb2.py +228 -0
- wandb/proto/v3/wandb_settings_pb2.py +122 -0
- wandb/proto/v3/wandb_telemetry_pb2.py +106 -0
- wandb/proto/v4/__init__.py +0 -0
- wandb/proto/v4/wandb_base_pb2.py +30 -0
- wandb/proto/v4/wandb_internal_pb2.py +382 -0
- wandb/proto/v4/wandb_server_pb2.py +67 -0
- wandb/proto/v4/wandb_settings_pb2.py +47 -0
- wandb/proto/v4/wandb_telemetry_pb2.py +41 -0
- wandb/proto/v5/wandb_base_pb2.py +31 -0
- wandb/proto/v5/wandb_internal_pb2.py +383 -0
- wandb/proto/v5/wandb_server_pb2.py +68 -0
- wandb/proto/v5/wandb_settings_pb2.py +48 -0
- wandb/proto/v5/wandb_telemetry_pb2.py +42 -0
- wandb/proto/v6/wandb_base_pb2.py +41 -0
- wandb/proto/v6/wandb_internal_pb2.py +393 -0
- wandb/proto/v6/wandb_server_pb2.py +78 -0
- wandb/proto/v6/wandb_settings_pb2.py +58 -0
- wandb/proto/v6/wandb_telemetry_pb2.py +52 -0
- wandb/proto/wandb_base_pb2.py +12 -0
- wandb/proto/wandb_deprecated.py +59 -0
- wandb/proto/wandb_generate_deprecated.py +30 -0
- wandb/proto/wandb_generate_proto.py +49 -0
- wandb/proto/wandb_internal_pb2.py +18 -0
- wandb/proto/wandb_server_pb2.py +12 -0
- wandb/proto/wandb_settings_pb2.py +12 -0
- wandb/proto/wandb_telemetry_pb2.py +12 -0
- wandb/py.typed +0 -0
- wandb/sdk/__init__.py +37 -0
- wandb/sdk/artifacts/__init__.py +0 -0
- wandb/sdk/artifacts/_factories.py +17 -0
- wandb/sdk/artifacts/_generated/__init__.py +508 -0
- wandb/sdk/artifacts/_generated/add_aliases.py +21 -0
- wandb/sdk/artifacts/_generated/artifact_by_id.py +17 -0
- wandb/sdk/artifacts/_generated/artifact_by_name.py +22 -0
- wandb/sdk/artifacts/_generated/artifact_collection_membership_file_urls.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_collection_membership_files.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_created_by.py +47 -0
- wandb/sdk/artifacts/_generated/artifact_file_urls.py +22 -0
- wandb/sdk/artifacts/_generated/artifact_type.py +31 -0
- wandb/sdk/artifacts/_generated/artifact_used_by.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_version_files.py +36 -0
- wandb/sdk/artifacts/_generated/artifact_via_membership_by_name.py +26 -0
- wandb/sdk/artifacts/_generated/create_artifact_collection_tag_assignments.py +36 -0
- wandb/sdk/artifacts/_generated/delete_aliases.py +21 -0
- wandb/sdk/artifacts/_generated/delete_artifact.py +28 -0
- wandb/sdk/artifacts/_generated/delete_artifact_collection_tag_assignments.py +25 -0
- wandb/sdk/artifacts/_generated/delete_artifact_portfolio.py +35 -0
- wandb/sdk/artifacts/_generated/delete_artifact_sequence.py +35 -0
- wandb/sdk/artifacts/_generated/enums.py +22 -0
- wandb/sdk/artifacts/_generated/fetch_artifact_manifest.py +38 -0
- wandb/sdk/artifacts/_generated/fetch_linked_artifacts.py +67 -0
- wandb/sdk/artifacts/_generated/fetch_registries.py +32 -0
- wandb/sdk/artifacts/_generated/fragments.py +459 -0
- wandb/sdk/artifacts/_generated/input_types.py +46 -0
- wandb/sdk/artifacts/_generated/link_artifact.py +27 -0
- wandb/sdk/artifacts/_generated/move_artifact_collection.py +35 -0
- wandb/sdk/artifacts/_generated/operations.py +1223 -0
- wandb/sdk/artifacts/_generated/project_artifact_collection.py +101 -0
- wandb/sdk/artifacts/_generated/project_artifact_collections.py +33 -0
- wandb/sdk/artifacts/_generated/project_artifact_type.py +24 -0
- wandb/sdk/artifacts/_generated/project_artifact_types.py +24 -0
- wandb/sdk/artifacts/_generated/project_artifacts.py +42 -0
- wandb/sdk/artifacts/_generated/registry_collections.py +34 -0
- wandb/sdk/artifacts/_generated/registry_versions.py +34 -0
- wandb/sdk/artifacts/_generated/run_input_artifacts.py +51 -0
- wandb/sdk/artifacts/_generated/run_output_artifacts.py +51 -0
- wandb/sdk/artifacts/_generated/unlink_artifact.py +25 -0
- wandb/sdk/artifacts/_generated/update_artifact.py +26 -0
- wandb/sdk/artifacts/_generated/update_artifact_portfolio.py +35 -0
- wandb/sdk/artifacts/_generated/update_artifact_sequence.py +35 -0
- wandb/sdk/artifacts/_graphql_fragments.py +19 -0
- wandb/sdk/artifacts/_internal_artifact.py +54 -0
- wandb/sdk/artifacts/_validators.py +309 -0
- wandb/sdk/artifacts/artifact.py +2702 -0
- wandb/sdk/artifacts/artifact_download_logger.py +45 -0
- wandb/sdk/artifacts/artifact_file_cache.py +251 -0
- wandb/sdk/artifacts/artifact_instance_cache.py +17 -0
- wandb/sdk/artifacts/artifact_manifest.py +76 -0
- wandb/sdk/artifacts/artifact_manifest_entry.py +258 -0
- wandb/sdk/artifacts/artifact_manifests/__init__.py +0 -0
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +94 -0
- wandb/sdk/artifacts/artifact_saver.py +277 -0
- wandb/sdk/artifacts/artifact_state.py +13 -0
- wandb/sdk/artifacts/artifact_ttl.py +9 -0
- wandb/sdk/artifacts/exceptions.py +71 -0
- wandb/sdk/artifacts/staging.py +27 -0
- wandb/sdk/artifacts/storage_handler.py +62 -0
- wandb/sdk/artifacts/storage_handlers/__init__.py +0 -0
- wandb/sdk/artifacts/storage_handlers/azure_handler.py +214 -0
- wandb/sdk/artifacts/storage_handlers/gcs_handler.py +224 -0
- wandb/sdk/artifacts/storage_handlers/http_handler.py +114 -0
- wandb/sdk/artifacts/storage_handlers/local_file_handler.py +142 -0
- wandb/sdk/artifacts/storage_handlers/multi_handler.py +56 -0
- wandb/sdk/artifacts/storage_handlers/s3_handler.py +339 -0
- wandb/sdk/artifacts/storage_handlers/tracking_handler.py +68 -0
- wandb/sdk/artifacts/storage_handlers/wb_artifact_handler.py +131 -0
- wandb/sdk/artifacts/storage_handlers/wb_local_artifact_handler.py +74 -0
- wandb/sdk/artifacts/storage_layout.py +8 -0
- wandb/sdk/artifacts/storage_policies/__init__.py +4 -0
- wandb/sdk/artifacts/storage_policies/register.py +1 -0
- wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +580 -0
- wandb/sdk/artifacts/storage_policy.py +75 -0
- wandb/sdk/backend/__init__.py +0 -0
- wandb/sdk/backend/backend.py +57 -0
- wandb/sdk/data_types/__init__.py +0 -0
- wandb/sdk/data_types/_dtypes.py +914 -0
- wandb/sdk/data_types/_private.py +10 -0
- wandb/sdk/data_types/audio.py +208 -0
- wandb/sdk/data_types/base_types/__init__.py +0 -0
- wandb/sdk/data_types/base_types/json_metadata.py +55 -0
- wandb/sdk/data_types/base_types/media.py +339 -0
- wandb/sdk/data_types/base_types/wb_value.py +295 -0
- wandb/sdk/data_types/bokeh.py +87 -0
- wandb/sdk/data_types/graph.py +439 -0
- wandb/sdk/data_types/helper_types/__init__.py +0 -0
- wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +327 -0
- wandb/sdk/data_types/helper_types/classes.py +159 -0
- wandb/sdk/data_types/helper_types/image_mask.py +251 -0
- wandb/sdk/data_types/histogram.py +107 -0
- wandb/sdk/data_types/html.py +165 -0
- wandb/sdk/data_types/image.py +974 -0
- wandb/sdk/data_types/molecule.py +250 -0
- wandb/sdk/data_types/object_3d.py +495 -0
- wandb/sdk/data_types/plotly.py +95 -0
- wandb/sdk/data_types/saved_model.py +435 -0
- wandb/sdk/data_types/table.py +1468 -0
- wandb/sdk/data_types/table_decorators.py +108 -0
- wandb/sdk/data_types/trace_tree.py +440 -0
- wandb/sdk/data_types/utils.py +260 -0
- wandb/sdk/data_types/video.py +303 -0
- wandb/sdk/integration_utils/__init__.py +0 -0
- wandb/sdk/integration_utils/auto_logging.py +232 -0
- wandb/sdk/integration_utils/data_logging.py +475 -0
- wandb/sdk/interface/__init__.py +0 -0
- wandb/sdk/interface/constants.py +4 -0
- wandb/sdk/interface/interface.py +1056 -0
- wandb/sdk/interface/interface_queue.py +40 -0
- wandb/sdk/interface/interface_shared.py +471 -0
- wandb/sdk/interface/interface_sock.py +49 -0
- wandb/sdk/interface/summary_record.py +67 -0
- wandb/sdk/internal/__init__.py +0 -0
- wandb/sdk/internal/_generated/__init__.py +15 -0
- wandb/sdk/internal/_generated/enums.py +4 -0
- wandb/sdk/internal/_generated/input_types.py +4 -0
- wandb/sdk/internal/_generated/operations.py +15 -0
- wandb/sdk/internal/_generated/server_features_query.py +27 -0
- wandb/sdk/internal/context.py +89 -0
- wandb/sdk/internal/datastore.py +293 -0
- wandb/sdk/internal/file_pusher.py +177 -0
- wandb/sdk/internal/file_stream.py +686 -0
- wandb/sdk/internal/handler.py +854 -0
- wandb/sdk/internal/incremental_table_util.py +53 -0
- wandb/sdk/internal/internal_api.py +4723 -0
- wandb/sdk/internal/job_builder.py +639 -0
- wandb/sdk/internal/profiler.py +79 -0
- wandb/sdk/internal/progress.py +77 -0
- wandb/sdk/internal/run.py +27 -0
- wandb/sdk/internal/sample.py +70 -0
- wandb/sdk/internal/sender.py +1692 -0
- wandb/sdk/internal/sender_config.py +203 -0
- wandb/sdk/internal/settings_static.py +120 -0
- wandb/sdk/internal/tb_watcher.py +519 -0
- wandb/sdk/internal/thread_local_settings.py +18 -0
- wandb/sdk/launch/__init__.py +15 -0
- wandb/sdk/launch/_launch.py +331 -0
- wandb/sdk/launch/_launch_add.py +255 -0
- wandb/sdk/launch/_project_spec.py +565 -0
- wandb/sdk/launch/agent/__init__.py +5 -0
- wandb/sdk/launch/agent/agent.py +931 -0
- wandb/sdk/launch/agent/config.py +296 -0
- wandb/sdk/launch/agent/job_status_tracker.py +55 -0
- wandb/sdk/launch/agent/run_queue_item_file_saver.py +39 -0
- wandb/sdk/launch/builder/__init__.py +0 -0
- wandb/sdk/launch/builder/abstract.py +156 -0
- wandb/sdk/launch/builder/build.py +296 -0
- wandb/sdk/launch/builder/context_manager.py +235 -0
- wandb/sdk/launch/builder/docker_builder.py +177 -0
- wandb/sdk/launch/builder/kaniko_builder.py +595 -0
- wandb/sdk/launch/builder/noop.py +58 -0
- wandb/sdk/launch/builder/templates/_wandb_bootstrap.py +188 -0
- wandb/sdk/launch/builder/templates/dockerfile.py +92 -0
- wandb/sdk/launch/create_job.py +541 -0
- wandb/sdk/launch/environment/abstract.py +29 -0
- wandb/sdk/launch/environment/aws_environment.py +322 -0
- wandb/sdk/launch/environment/azure_environment.py +105 -0
- wandb/sdk/launch/environment/gcp_environment.py +334 -0
- wandb/sdk/launch/environment/local_environment.py +65 -0
- wandb/sdk/launch/errors.py +13 -0
- wandb/sdk/launch/git_reference.py +109 -0
- wandb/sdk/launch/inputs/files.py +148 -0
- wandb/sdk/launch/inputs/internal.py +314 -0
- wandb/sdk/launch/inputs/manage.py +113 -0
- wandb/sdk/launch/inputs/schema.py +40 -0
- wandb/sdk/launch/loader.py +249 -0
- wandb/sdk/launch/registry/abstract.py +48 -0
- wandb/sdk/launch/registry/anon.py +29 -0
- wandb/sdk/launch/registry/azure_container_registry.py +124 -0
- wandb/sdk/launch/registry/elastic_container_registry.py +192 -0
- wandb/sdk/launch/registry/google_artifact_registry.py +219 -0
- wandb/sdk/launch/registry/local_registry.py +65 -0
- wandb/sdk/launch/runner/__init__.py +0 -0
- wandb/sdk/launch/runner/abstract.py +185 -0
- wandb/sdk/launch/runner/kubernetes_monitor.py +473 -0
- wandb/sdk/launch/runner/kubernetes_runner.py +1285 -0
- wandb/sdk/launch/runner/local_container.py +301 -0
- wandb/sdk/launch/runner/local_process.py +78 -0
- wandb/sdk/launch/runner/sagemaker_runner.py +424 -0
- wandb/sdk/launch/runner/vertex_runner.py +225 -0
- wandb/sdk/launch/sweeps/__init__.py +37 -0
- wandb/sdk/launch/sweeps/scheduler.py +739 -0
- wandb/sdk/launch/sweeps/scheduler_sweep.py +90 -0
- wandb/sdk/launch/sweeps/utils.py +324 -0
- wandb/sdk/launch/utils.py +746 -0
- wandb/sdk/launch/wandb_reference.py +138 -0
- wandb/sdk/lib/__init__.py +5 -0
- wandb/sdk/lib/apikey.py +334 -0
- wandb/sdk/lib/asyncio_compat.py +213 -0
- wandb/sdk/lib/asyncio_manager.py +252 -0
- wandb/sdk/lib/capped_dict.py +26 -0
- wandb/sdk/lib/config_util.py +101 -0
- wandb/sdk/lib/console_capture.py +219 -0
- wandb/sdk/lib/credentials.py +141 -0
- wandb/sdk/lib/deprecate.py +27 -0
- wandb/sdk/lib/disabled.py +30 -0
- wandb/sdk/lib/exit_hooks.py +54 -0
- wandb/sdk/lib/file_stream_utils.py +118 -0
- wandb/sdk/lib/filenames.py +64 -0
- wandb/sdk/lib/filesystem.py +372 -0
- wandb/sdk/lib/fsm.py +165 -0
- wandb/sdk/lib/gitlib.py +240 -0
- wandb/sdk/lib/gql_request.py +65 -0
- wandb/sdk/lib/handler_util.py +21 -0
- wandb/sdk/lib/hashutil.py +106 -0
- wandb/sdk/lib/import_hooks.py +275 -0
- wandb/sdk/lib/interrupt.py +37 -0
- wandb/sdk/lib/ipython.py +126 -0
- wandb/sdk/lib/json_util.py +75 -0
- wandb/sdk/lib/lazyloader.py +63 -0
- wandb/sdk/lib/module.py +72 -0
- wandb/sdk/lib/paths.py +106 -0
- wandb/sdk/lib/preinit.py +42 -0
- wandb/sdk/lib/printer.py +571 -0
- wandb/sdk/lib/printer_asyncio.py +48 -0
- wandb/sdk/lib/progress.py +320 -0
- wandb/sdk/lib/proto_util.py +90 -0
- wandb/sdk/lib/redirect.py +876 -0
- wandb/sdk/lib/retry.py +395 -0
- wandb/sdk/lib/run_moment.py +82 -0
- wandb/sdk/lib/runid.py +12 -0
- wandb/sdk/lib/server.py +58 -0
- wandb/sdk/lib/service/ipc_support.py +13 -0
- wandb/sdk/lib/service/service_client.py +106 -0
- wandb/sdk/lib/service/service_connection.py +192 -0
- wandb/sdk/lib/service/service_port_file.py +105 -0
- wandb/sdk/lib/service/service_process.py +111 -0
- wandb/sdk/lib/service/service_token.py +181 -0
- wandb/sdk/lib/sparkline.py +44 -0
- wandb/sdk/lib/telemetry.py +100 -0
- wandb/sdk/lib/timed_input.py +133 -0
- wandb/sdk/lib/timer.py +19 -0
- wandb/sdk/lib/wb_logging.py +161 -0
- wandb/sdk/mailbox/__init__.py +23 -0
- wandb/sdk/mailbox/mailbox.py +143 -0
- wandb/sdk/mailbox/mailbox_handle.py +132 -0
- wandb/sdk/mailbox/response_handle.py +99 -0
- wandb/sdk/mailbox/wait_with_progress.py +100 -0
- wandb/sdk/projects/_generated/__init__.py +47 -0
- wandb/sdk/projects/_generated/delete_project.py +22 -0
- wandb/sdk/projects/_generated/enums.py +4 -0
- wandb/sdk/projects/_generated/fetch_registry.py +22 -0
- wandb/sdk/projects/_generated/fragments.py +41 -0
- wandb/sdk/projects/_generated/input_types.py +13 -0
- wandb/sdk/projects/_generated/operations.py +88 -0
- wandb/sdk/projects/_generated/rename_project.py +27 -0
- wandb/sdk/projects/_generated/upsert_registry_project.py +27 -0
- wandb/sdk/verify/__init__.py +0 -0
- wandb/sdk/verify/verify.py +555 -0
- wandb/sdk/wandb_alerts.py +12 -0
- wandb/sdk/wandb_config.py +323 -0
- wandb/sdk/wandb_helper.py +54 -0
- wandb/sdk/wandb_init.py +1581 -0
- wandb/sdk/wandb_login.py +332 -0
- wandb/sdk/wandb_metric.py +112 -0
- wandb/sdk/wandb_require.py +88 -0
- wandb/sdk/wandb_require_helpers.py +44 -0
- wandb/sdk/wandb_run.py +4088 -0
- wandb/sdk/wandb_settings.py +2105 -0
- wandb/sdk/wandb_setup.py +560 -0
- wandb/sdk/wandb_summary.py +150 -0
- wandb/sdk/wandb_sweep.py +120 -0
- wandb/sdk/wandb_sync.py +71 -0
- wandb/sdk/wandb_watch.py +146 -0
- wandb/sklearn.py +35 -0
- wandb/sync/__init__.py +3 -0
- wandb/sync/sync.py +452 -0
- wandb/trigger.py +29 -0
- wandb/util.py +2040 -0
- wandb/vendor/__init__.py +0 -0
- wandb/vendor/gql-0.2.0/setup.py +40 -0
- wandb/vendor/gql-0.2.0/tests/__init__.py +0 -0
- wandb/vendor/gql-0.2.0/tests/starwars/__init__.py +0 -0
- wandb/vendor/gql-0.2.0/tests/starwars/fixtures.py +96 -0
- wandb/vendor/gql-0.2.0/tests/starwars/schema.py +146 -0
- wandb/vendor/gql-0.2.0/tests/starwars/test_dsl.py +293 -0
- wandb/vendor/gql-0.2.0/tests/starwars/test_query.py +355 -0
- wandb/vendor/gql-0.2.0/tests/starwars/test_validation.py +171 -0
- wandb/vendor/gql-0.2.0/tests/test_client.py +31 -0
- wandb/vendor/gql-0.2.0/tests/test_transport.py +89 -0
- wandb/vendor/gql-0.2.0/wandb_gql/__init__.py +4 -0
- wandb/vendor/gql-0.2.0/wandb_gql/client.py +75 -0
- wandb/vendor/gql-0.2.0/wandb_gql/dsl.py +152 -0
- wandb/vendor/gql-0.2.0/wandb_gql/gql.py +10 -0
- wandb/vendor/gql-0.2.0/wandb_gql/transport/__init__.py +0 -0
- wandb/vendor/gql-0.2.0/wandb_gql/transport/http.py +6 -0
- wandb/vendor/gql-0.2.0/wandb_gql/transport/local_schema.py +15 -0
- wandb/vendor/gql-0.2.0/wandb_gql/transport/requests.py +46 -0
- wandb/vendor/gql-0.2.0/wandb_gql/utils.py +21 -0
- wandb/vendor/graphql-core-1.1/setup.py +86 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/__init__.py +287 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/error/__init__.py +6 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/error/base.py +42 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/error/format_error.py +11 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/error/located_error.py +29 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/error/syntax_error.py +36 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/__init__.py +26 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/base.py +311 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executor.py +398 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/__init__.py +0 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/asyncio.py +53 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/gevent.py +22 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/process.py +32 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/sync.py +7 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/thread.py +35 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/executors/utils.py +6 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/experimental/__init__.py +0 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/experimental/executor.py +66 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/experimental/fragment.py +252 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/experimental/resolver.py +151 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/experimental/utils.py +7 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/middleware.py +57 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/execution/values.py +145 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/graphql.py +60 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/__init__.py +0 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/ast.py +1349 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/base.py +19 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/lexer.py +435 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/location.py +30 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/parser.py +779 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/printer.py +193 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/source.py +18 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/visitor.py +222 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/language/visitor_meta.py +82 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/__init__.py +0 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/cached_property.py +17 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/contain_subset.py +28 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/default_ordered_dict.py +40 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/ordereddict.py +8 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/pair_set.py +43 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/pyutils/version.py +78 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/__init__.py +67 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/definition.py +619 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/directives.py +132 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/introspection.py +440 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/scalars.py +131 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/schema.py +100 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/type/typemap.py +145 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/__init__.py +0 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/assert_valid_name.py +9 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/ast_from_value.py +65 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/ast_to_code.py +49 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/ast_to_dict.py +24 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/base.py +75 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/build_ast_schema.py +291 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/build_client_schema.py +250 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/concat_ast.py +9 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/extend_schema.py +357 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/get_field_def.py +27 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/get_operation_ast.py +21 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/introspection_query.py +90 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/is_valid_literal_value.py +67 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/is_valid_value.py +66 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/quoted_or_list.py +21 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/schema_printer.py +168 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/suggestion_list.py +56 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/type_comparators.py +69 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/type_from_ast.py +21 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/type_info.py +149 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/utils/value_from_ast.py +69 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/__init__.py +4 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/__init__.py +79 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/arguments_of_correct_type.py +24 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/base.py +8 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/default_values_of_correct_type.py +44 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/fields_on_correct_type.py +113 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/fragments_on_composite_types.py +33 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/known_argument_names.py +70 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/known_directives.py +97 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/known_fragment_names.py +19 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/known_type_names.py +43 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/lone_anonymous_operation.py +23 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/no_fragment_cycles.py +59 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/no_undefined_variables.py +36 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/no_unused_fragments.py +38 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/no_unused_variables.py +37 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/overlapping_fields_can_be_merged.py +529 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/possible_fragment_spreads.py +44 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/provided_non_null_arguments.py +46 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/scalar_leafs.py +33 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/unique_argument_names.py +32 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/unique_fragment_names.py +28 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/unique_input_field_names.py +33 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/unique_operation_names.py +31 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/unique_variable_names.py +27 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/variables_are_input_types.py +21 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/rules/variables_in_allowed_position.py +53 -0
- wandb/vendor/graphql-core-1.1/wandb_graphql/validation/validation.py +158 -0
- wandb/vendor/promise-2.3.0/conftest.py +30 -0
- wandb/vendor/promise-2.3.0/setup.py +64 -0
- wandb/vendor/promise-2.3.0/tests/__init__.py +0 -0
- wandb/vendor/promise-2.3.0/tests/conftest.py +8 -0
- wandb/vendor/promise-2.3.0/tests/test_awaitable.py +32 -0
- wandb/vendor/promise-2.3.0/tests/test_awaitable_35.py +47 -0
- wandb/vendor/promise-2.3.0/tests/test_benchmark.py +116 -0
- wandb/vendor/promise-2.3.0/tests/test_complex_threads.py +23 -0
- wandb/vendor/promise-2.3.0/tests/test_dataloader.py +452 -0
- wandb/vendor/promise-2.3.0/tests/test_dataloader_awaitable_35.py +99 -0
- wandb/vendor/promise-2.3.0/tests/test_dataloader_extra.py +65 -0
- wandb/vendor/promise-2.3.0/tests/test_extra.py +670 -0
- wandb/vendor/promise-2.3.0/tests/test_issues.py +132 -0
- wandb/vendor/promise-2.3.0/tests/test_promise_list.py +70 -0
- wandb/vendor/promise-2.3.0/tests/test_spec.py +584 -0
- wandb/vendor/promise-2.3.0/tests/test_thread_safety.py +115 -0
- wandb/vendor/promise-2.3.0/tests/utils.py +3 -0
- wandb/vendor/promise-2.3.0/wandb_promise/__init__.py +38 -0
- wandb/vendor/promise-2.3.0/wandb_promise/async_.py +135 -0
- wandb/vendor/promise-2.3.0/wandb_promise/compat.py +32 -0
- wandb/vendor/promise-2.3.0/wandb_promise/dataloader.py +326 -0
- wandb/vendor/promise-2.3.0/wandb_promise/iterate_promise.py +12 -0
- wandb/vendor/promise-2.3.0/wandb_promise/promise.py +848 -0
- wandb/vendor/promise-2.3.0/wandb_promise/promise_list.py +151 -0
- wandb/vendor/promise-2.3.0/wandb_promise/pyutils/__init__.py +0 -0
- wandb/vendor/promise-2.3.0/wandb_promise/pyutils/version.py +83 -0
- wandb/vendor/promise-2.3.0/wandb_promise/schedulers/__init__.py +0 -0
- wandb/vendor/promise-2.3.0/wandb_promise/schedulers/asyncio.py +22 -0
- wandb/vendor/promise-2.3.0/wandb_promise/schedulers/gevent.py +21 -0
- wandb/vendor/promise-2.3.0/wandb_promise/schedulers/immediate.py +27 -0
- wandb/vendor/promise-2.3.0/wandb_promise/schedulers/thread.py +18 -0
- wandb/vendor/promise-2.3.0/wandb_promise/utils.py +56 -0
- wandb/vendor/pygments/__init__.py +90 -0
- wandb/vendor/pygments/cmdline.py +568 -0
- wandb/vendor/pygments/console.py +74 -0
- wandb/vendor/pygments/filter.py +74 -0
- wandb/vendor/pygments/filters/__init__.py +350 -0
- wandb/vendor/pygments/formatter.py +95 -0
- wandb/vendor/pygments/formatters/__init__.py +153 -0
- wandb/vendor/pygments/formatters/_mapping.py +85 -0
- wandb/vendor/pygments/formatters/bbcode.py +109 -0
- wandb/vendor/pygments/formatters/html.py +851 -0
- wandb/vendor/pygments/formatters/img.py +600 -0
- wandb/vendor/pygments/formatters/irc.py +182 -0
- wandb/vendor/pygments/formatters/latex.py +482 -0
- wandb/vendor/pygments/formatters/other.py +160 -0
- wandb/vendor/pygments/formatters/rtf.py +147 -0
- wandb/vendor/pygments/formatters/svg.py +153 -0
- wandb/vendor/pygments/formatters/terminal.py +136 -0
- wandb/vendor/pygments/formatters/terminal256.py +309 -0
- wandb/vendor/pygments/lexer.py +871 -0
- wandb/vendor/pygments/lexers/__init__.py +329 -0
- wandb/vendor/pygments/lexers/_asy_builtins.py +1645 -0
- wandb/vendor/pygments/lexers/_cl_builtins.py +232 -0
- wandb/vendor/pygments/lexers/_cocoa_builtins.py +72 -0
- wandb/vendor/pygments/lexers/_csound_builtins.py +1346 -0
- wandb/vendor/pygments/lexers/_lasso_builtins.py +5327 -0
- wandb/vendor/pygments/lexers/_lua_builtins.py +295 -0
- wandb/vendor/pygments/lexers/_mapping.py +500 -0
- wandb/vendor/pygments/lexers/_mql_builtins.py +1172 -0
- wandb/vendor/pygments/lexers/_openedge_builtins.py +2547 -0
- wandb/vendor/pygments/lexers/_php_builtins.py +4756 -0
- wandb/vendor/pygments/lexers/_postgres_builtins.py +621 -0
- wandb/vendor/pygments/lexers/_scilab_builtins.py +3094 -0
- wandb/vendor/pygments/lexers/_sourcemod_builtins.py +1163 -0
- wandb/vendor/pygments/lexers/_stan_builtins.py +532 -0
- wandb/vendor/pygments/lexers/_stata_builtins.py +419 -0
- wandb/vendor/pygments/lexers/_tsql_builtins.py +1004 -0
- wandb/vendor/pygments/lexers/_vim_builtins.py +1939 -0
- wandb/vendor/pygments/lexers/actionscript.py +240 -0
- wandb/vendor/pygments/lexers/agile.py +24 -0
- wandb/vendor/pygments/lexers/algebra.py +221 -0
- wandb/vendor/pygments/lexers/ambient.py +76 -0
- wandb/vendor/pygments/lexers/ampl.py +87 -0
- wandb/vendor/pygments/lexers/apl.py +101 -0
- wandb/vendor/pygments/lexers/archetype.py +318 -0
- wandb/vendor/pygments/lexers/asm.py +641 -0
- wandb/vendor/pygments/lexers/automation.py +374 -0
- wandb/vendor/pygments/lexers/basic.py +500 -0
- wandb/vendor/pygments/lexers/bibtex.py +160 -0
- wandb/vendor/pygments/lexers/business.py +612 -0
- wandb/vendor/pygments/lexers/c_cpp.py +252 -0
- wandb/vendor/pygments/lexers/c_like.py +541 -0
- wandb/vendor/pygments/lexers/capnproto.py +78 -0
- wandb/vendor/pygments/lexers/chapel.py +102 -0
- wandb/vendor/pygments/lexers/clean.py +288 -0
- wandb/vendor/pygments/lexers/compiled.py +34 -0
- wandb/vendor/pygments/lexers/configs.py +833 -0
- wandb/vendor/pygments/lexers/console.py +114 -0
- wandb/vendor/pygments/lexers/crystal.py +393 -0
- wandb/vendor/pygments/lexers/csound.py +366 -0
- wandb/vendor/pygments/lexers/css.py +689 -0
- wandb/vendor/pygments/lexers/d.py +251 -0
- wandb/vendor/pygments/lexers/dalvik.py +125 -0
- wandb/vendor/pygments/lexers/data.py +555 -0
- wandb/vendor/pygments/lexers/diff.py +165 -0
- wandb/vendor/pygments/lexers/dotnet.py +691 -0
- wandb/vendor/pygments/lexers/dsls.py +878 -0
- wandb/vendor/pygments/lexers/dylan.py +289 -0
- wandb/vendor/pygments/lexers/ecl.py +125 -0
- wandb/vendor/pygments/lexers/eiffel.py +65 -0
- wandb/vendor/pygments/lexers/elm.py +121 -0
- wandb/vendor/pygments/lexers/erlang.py +533 -0
- wandb/vendor/pygments/lexers/esoteric.py +277 -0
- wandb/vendor/pygments/lexers/ezhil.py +69 -0
- wandb/vendor/pygments/lexers/factor.py +344 -0
- wandb/vendor/pygments/lexers/fantom.py +250 -0
- wandb/vendor/pygments/lexers/felix.py +273 -0
- wandb/vendor/pygments/lexers/forth.py +177 -0
- wandb/vendor/pygments/lexers/fortran.py +205 -0
- wandb/vendor/pygments/lexers/foxpro.py +428 -0
- wandb/vendor/pygments/lexers/functional.py +21 -0
- wandb/vendor/pygments/lexers/go.py +101 -0
- wandb/vendor/pygments/lexers/grammar_notation.py +213 -0
- wandb/vendor/pygments/lexers/graph.py +80 -0
- wandb/vendor/pygments/lexers/graphics.py +553 -0
- wandb/vendor/pygments/lexers/haskell.py +843 -0
- wandb/vendor/pygments/lexers/haxe.py +936 -0
- wandb/vendor/pygments/lexers/hdl.py +382 -0
- wandb/vendor/pygments/lexers/hexdump.py +103 -0
- wandb/vendor/pygments/lexers/html.py +602 -0
- wandb/vendor/pygments/lexers/idl.py +270 -0
- wandb/vendor/pygments/lexers/igor.py +288 -0
- wandb/vendor/pygments/lexers/inferno.py +96 -0
- wandb/vendor/pygments/lexers/installers.py +322 -0
- wandb/vendor/pygments/lexers/int_fiction.py +1343 -0
- wandb/vendor/pygments/lexers/iolang.py +63 -0
- wandb/vendor/pygments/lexers/j.py +146 -0
- wandb/vendor/pygments/lexers/javascript.py +1525 -0
- wandb/vendor/pygments/lexers/julia.py +333 -0
- wandb/vendor/pygments/lexers/jvm.py +1573 -0
- wandb/vendor/pygments/lexers/lisp.py +2621 -0
- wandb/vendor/pygments/lexers/make.py +202 -0
- wandb/vendor/pygments/lexers/markup.py +595 -0
- wandb/vendor/pygments/lexers/math.py +21 -0
- wandb/vendor/pygments/lexers/matlab.py +663 -0
- wandb/vendor/pygments/lexers/ml.py +769 -0
- wandb/vendor/pygments/lexers/modeling.py +358 -0
- wandb/vendor/pygments/lexers/modula2.py +1561 -0
- wandb/vendor/pygments/lexers/monte.py +204 -0
- wandb/vendor/pygments/lexers/ncl.py +894 -0
- wandb/vendor/pygments/lexers/nimrod.py +159 -0
- wandb/vendor/pygments/lexers/nit.py +64 -0
- wandb/vendor/pygments/lexers/nix.py +136 -0
- wandb/vendor/pygments/lexers/oberon.py +105 -0
- wandb/vendor/pygments/lexers/objective.py +504 -0
- wandb/vendor/pygments/lexers/ooc.py +85 -0
- wandb/vendor/pygments/lexers/other.py +41 -0
- wandb/vendor/pygments/lexers/parasail.py +79 -0
- wandb/vendor/pygments/lexers/parsers.py +835 -0
- wandb/vendor/pygments/lexers/pascal.py +644 -0
- wandb/vendor/pygments/lexers/pawn.py +199 -0
- wandb/vendor/pygments/lexers/perl.py +620 -0
- wandb/vendor/pygments/lexers/php.py +267 -0
- wandb/vendor/pygments/lexers/praat.py +294 -0
- wandb/vendor/pygments/lexers/prolog.py +306 -0
- wandb/vendor/pygments/lexers/python.py +939 -0
- wandb/vendor/pygments/lexers/qvt.py +152 -0
- wandb/vendor/pygments/lexers/r.py +453 -0
- wandb/vendor/pygments/lexers/rdf.py +270 -0
- wandb/vendor/pygments/lexers/rebol.py +431 -0
- wandb/vendor/pygments/lexers/resource.py +85 -0
- wandb/vendor/pygments/lexers/rnc.py +67 -0
- wandb/vendor/pygments/lexers/roboconf.py +82 -0
- wandb/vendor/pygments/lexers/robotframework.py +560 -0
- wandb/vendor/pygments/lexers/ruby.py +519 -0
- wandb/vendor/pygments/lexers/rust.py +220 -0
- wandb/vendor/pygments/lexers/sas.py +228 -0
- wandb/vendor/pygments/lexers/scripting.py +1222 -0
- wandb/vendor/pygments/lexers/shell.py +794 -0
- wandb/vendor/pygments/lexers/smalltalk.py +195 -0
- wandb/vendor/pygments/lexers/smv.py +79 -0
- wandb/vendor/pygments/lexers/snobol.py +83 -0
- wandb/vendor/pygments/lexers/special.py +103 -0
- wandb/vendor/pygments/lexers/sql.py +681 -0
- wandb/vendor/pygments/lexers/stata.py +108 -0
- wandb/vendor/pygments/lexers/supercollider.py +90 -0
- wandb/vendor/pygments/lexers/tcl.py +145 -0
- wandb/vendor/pygments/lexers/templates.py +2283 -0
- wandb/vendor/pygments/lexers/testing.py +207 -0
- wandb/vendor/pygments/lexers/text.py +25 -0
- wandb/vendor/pygments/lexers/textedit.py +169 -0
- wandb/vendor/pygments/lexers/textfmts.py +297 -0
- wandb/vendor/pygments/lexers/theorem.py +458 -0
- wandb/vendor/pygments/lexers/trafficscript.py +54 -0
- wandb/vendor/pygments/lexers/typoscript.py +226 -0
- wandb/vendor/pygments/lexers/urbi.py +133 -0
- wandb/vendor/pygments/lexers/varnish.py +190 -0
- wandb/vendor/pygments/lexers/verification.py +111 -0
- wandb/vendor/pygments/lexers/web.py +24 -0
- wandb/vendor/pygments/lexers/webmisc.py +988 -0
- wandb/vendor/pygments/lexers/whiley.py +116 -0
- wandb/vendor/pygments/lexers/x10.py +69 -0
- wandb/vendor/pygments/modeline.py +44 -0
- wandb/vendor/pygments/plugin.py +68 -0
- wandb/vendor/pygments/regexopt.py +92 -0
- wandb/vendor/pygments/scanner.py +105 -0
- wandb/vendor/pygments/sphinxext.py +158 -0
- wandb/vendor/pygments/style.py +155 -0
- wandb/vendor/pygments/styles/__init__.py +80 -0
- wandb/vendor/pygments/styles/abap.py +29 -0
- wandb/vendor/pygments/styles/algol.py +63 -0
- wandb/vendor/pygments/styles/algol_nu.py +63 -0
- wandb/vendor/pygments/styles/arduino.py +98 -0
- wandb/vendor/pygments/styles/autumn.py +65 -0
- wandb/vendor/pygments/styles/borland.py +51 -0
- wandb/vendor/pygments/styles/bw.py +49 -0
- wandb/vendor/pygments/styles/colorful.py +81 -0
- wandb/vendor/pygments/styles/default.py +73 -0
- wandb/vendor/pygments/styles/emacs.py +72 -0
- wandb/vendor/pygments/styles/friendly.py +72 -0
- wandb/vendor/pygments/styles/fruity.py +42 -0
- wandb/vendor/pygments/styles/igor.py +29 -0
- wandb/vendor/pygments/styles/lovelace.py +97 -0
- wandb/vendor/pygments/styles/manni.py +75 -0
- wandb/vendor/pygments/styles/monokai.py +106 -0
- wandb/vendor/pygments/styles/murphy.py +80 -0
- wandb/vendor/pygments/styles/native.py +65 -0
- wandb/vendor/pygments/styles/paraiso_dark.py +125 -0
- wandb/vendor/pygments/styles/paraiso_light.py +125 -0
- wandb/vendor/pygments/styles/pastie.py +75 -0
- wandb/vendor/pygments/styles/perldoc.py +69 -0
- wandb/vendor/pygments/styles/rainbow_dash.py +89 -0
- wandb/vendor/pygments/styles/rrt.py +33 -0
- wandb/vendor/pygments/styles/sas.py +44 -0
- wandb/vendor/pygments/styles/stata.py +40 -0
- wandb/vendor/pygments/styles/tango.py +141 -0
- wandb/vendor/pygments/styles/trac.py +63 -0
- wandb/vendor/pygments/styles/vim.py +63 -0
- wandb/vendor/pygments/styles/vs.py +38 -0
- wandb/vendor/pygments/styles/xcode.py +51 -0
- wandb/vendor/pygments/token.py +213 -0
- wandb/vendor/pygments/unistring.py +217 -0
- wandb/vendor/pygments/util.py +388 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/__init__.py +17 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/events.py +615 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/__init__.py +98 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/api.py +369 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/fsevents.py +172 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/fsevents2.py +239 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/inotify.py +218 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/inotify_buffer.py +81 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/inotify_c.py +575 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/kqueue.py +730 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/polling.py +145 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/read_directory_changes.py +133 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/observers/winapi.py +348 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/patterns.py +265 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/tricks/__init__.py +174 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/__init__.py +151 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/bricks.py +249 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/compat.py +29 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/decorators.py +198 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/delayed_queue.py +88 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/dirsnapshot.py +293 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/echo.py +157 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/event_backport.py +41 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/importlib2.py +40 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/platform.py +57 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/unicode_paths.py +64 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/utils/win32stat.py +123 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/version.py +28 -0
- wandb/vendor/watchdog_0_9_0/wandb_watchdog/watchmedo.py +577 -0
- wandb/wandb_agent.py +580 -0
- wandb/wandb_controller.py +719 -0
- wandb/wandb_run.py +8 -0
- wandb-0.21.2.dist-info/METADATA +223 -0
- wandb-0.21.2.dist-info/RECORD +904 -0
- wandb-0.21.2.dist-info/WHEEL +4 -0
- wandb-0.21.2.dist-info/entry_points.txt +3 -0
- wandb-0.21.2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,974 @@
|
|
1
|
+
import hashlib
|
2
|
+
import logging
|
3
|
+
import os
|
4
|
+
import pathlib
|
5
|
+
from io import BytesIO
|
6
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Type, Union, cast
|
7
|
+
from urllib import parse
|
8
|
+
|
9
|
+
from packaging.version import parse as parse_version
|
10
|
+
|
11
|
+
import wandb
|
12
|
+
from wandb import util
|
13
|
+
from wandb.sdk.lib import hashutil, runid
|
14
|
+
from wandb.sdk.lib.paths import LogicalPath
|
15
|
+
|
16
|
+
from . import _dtypes
|
17
|
+
from ._private import MEDIA_TMP
|
18
|
+
from .base_types.media import BatchableMedia, Media
|
19
|
+
from .helper_types.bounding_boxes_2d import BoundingBoxes2D
|
20
|
+
from .helper_types.classes import Classes
|
21
|
+
from .helper_types.image_mask import ImageMask
|
22
|
+
|
23
|
+
if TYPE_CHECKING: # pragma: no cover
|
24
|
+
import matplotlib # type: ignore
|
25
|
+
import numpy as np
|
26
|
+
import torch # type: ignore
|
27
|
+
from PIL.Image import Image as PILImage
|
28
|
+
|
29
|
+
from wandb.sdk.artifacts.artifact import Artifact
|
30
|
+
|
31
|
+
ImageDataType = Union[
|
32
|
+
"matplotlib.artist.Artist", "PILImage", "TorchTensorType", "np.ndarray"
|
33
|
+
]
|
34
|
+
ImageDataOrPathType = Union[str, pathlib.Path, "Image", ImageDataType]
|
35
|
+
TorchTensorType = Union["torch.Tensor", "torch.Variable"]
|
36
|
+
|
37
|
+
|
38
|
+
def _warn_on_invalid_data_range(
|
39
|
+
data: "np.ndarray",
|
40
|
+
normalize: bool = True,
|
41
|
+
) -> None:
|
42
|
+
if not normalize:
|
43
|
+
return
|
44
|
+
|
45
|
+
np = util.get_module(
|
46
|
+
"numpy",
|
47
|
+
required="wandb.Image requires numpy if not supplying PIL Images: pip install numpy",
|
48
|
+
)
|
49
|
+
|
50
|
+
if np.min(data) < 0 or np.max(data) > 255:
|
51
|
+
wandb.termwarn(
|
52
|
+
"Data passed to `wandb.Image` should consist of values in the range [0, 255], "
|
53
|
+
"image data will be normalized to this range, "
|
54
|
+
"but behavior will be removed in a future version of wandb.",
|
55
|
+
repeat=False,
|
56
|
+
)
|
57
|
+
|
58
|
+
|
59
|
+
def _guess_and_rescale_to_0_255(data: "np.ndarray") -> "np.ndarray":
|
60
|
+
"""Guess the image's format and rescale its values to the range [0, 255].
|
61
|
+
|
62
|
+
This is an unfortunate design flaw carried forward for backward
|
63
|
+
compatibility. A better design would have been to document the expected
|
64
|
+
data format and not mangle the data provided by the user.
|
65
|
+
|
66
|
+
If given data in the range [0, 1], we multiply all values by 255
|
67
|
+
and round down to get integers.
|
68
|
+
|
69
|
+
If given data in the range [-1, 1], we rescale it by mapping -1 to 0 and
|
70
|
+
1 to 255, then round down to get integers.
|
71
|
+
|
72
|
+
We clip and round all other data.
|
73
|
+
"""
|
74
|
+
try:
|
75
|
+
import numpy as np
|
76
|
+
except ImportError:
|
77
|
+
raise wandb.Error(
|
78
|
+
"wandb.Image requires numpy if not supplying PIL images: pip install numpy"
|
79
|
+
) from None
|
80
|
+
|
81
|
+
data_min: float = data.min()
|
82
|
+
data_max: float = data.max()
|
83
|
+
|
84
|
+
if 0 <= data_min and data_max <= 1:
|
85
|
+
return (data * 255).astype(np.uint8)
|
86
|
+
|
87
|
+
elif -1 <= data_min and data_max <= 1:
|
88
|
+
return (255 * 0.5 * (data + 1)).astype(np.uint8)
|
89
|
+
|
90
|
+
else:
|
91
|
+
return data.clip(0, 255).astype(np.uint8)
|
92
|
+
|
93
|
+
|
94
|
+
def _convert_to_uint8(data: "np.ndarray") -> "np.ndarray":
|
95
|
+
np = util.get_module(
|
96
|
+
"numpy",
|
97
|
+
required="wandb.Image requires numpy if not supplying PIL Images: pip install numpy",
|
98
|
+
)
|
99
|
+
return data.astype(np.uint8)
|
100
|
+
|
101
|
+
|
102
|
+
def _server_accepts_image_filenames(run: "wandb.Run") -> bool:
|
103
|
+
if run.offline:
|
104
|
+
return True
|
105
|
+
|
106
|
+
# Newer versions of wandb accept large image filenames arrays
|
107
|
+
# but older versions would have issues with this.
|
108
|
+
max_cli_version = util._get_max_cli_version()
|
109
|
+
if max_cli_version is None:
|
110
|
+
return False
|
111
|
+
|
112
|
+
accepts_image_filenames: bool = parse_version(max_cli_version) >= parse_version(
|
113
|
+
"0.12.10"
|
114
|
+
)
|
115
|
+
return accepts_image_filenames
|
116
|
+
|
117
|
+
|
118
|
+
def _server_accepts_artifact_path(run: "wandb.Run") -> bool:
|
119
|
+
if run.offline:
|
120
|
+
return False
|
121
|
+
|
122
|
+
max_cli_version = util._get_max_cli_version()
|
123
|
+
if max_cli_version is None:
|
124
|
+
return False
|
125
|
+
|
126
|
+
return parse_version(max_cli_version) >= parse_version("0.12.14")
|
127
|
+
|
128
|
+
|
129
|
+
class Image(BatchableMedia):
|
130
|
+
"""A class for logging images to W&B."""
|
131
|
+
|
132
|
+
MAX_ITEMS = 108
|
133
|
+
|
134
|
+
# PIL limit
|
135
|
+
MAX_DIMENSION = 65500
|
136
|
+
|
137
|
+
_log_type = "image-file"
|
138
|
+
|
139
|
+
format: Optional[str]
|
140
|
+
_grouping: Optional[int]
|
141
|
+
_caption: Optional[str]
|
142
|
+
_width: Optional[int]
|
143
|
+
_height: Optional[int]
|
144
|
+
_image: Optional["PILImage"]
|
145
|
+
_classes: Optional["Classes"]
|
146
|
+
_boxes: Optional[Dict[str, "BoundingBoxes2D"]]
|
147
|
+
_masks: Optional[Dict[str, "ImageMask"]]
|
148
|
+
_file_type: Optional[str]
|
149
|
+
|
150
|
+
def __init__(
|
151
|
+
self,
|
152
|
+
data_or_path: "ImageDataOrPathType",
|
153
|
+
mode: Optional[str] = None,
|
154
|
+
caption: Optional[str] = None,
|
155
|
+
grouping: Optional[int] = None,
|
156
|
+
classes: Optional[Union["Classes", Sequence[dict]]] = None,
|
157
|
+
boxes: Optional[Union[Dict[str, "BoundingBoxes2D"], Dict[str, dict]]] = None,
|
158
|
+
masks: Optional[Union[Dict[str, "ImageMask"], Dict[str, dict]]] = None,
|
159
|
+
file_type: Optional[str] = None,
|
160
|
+
normalize: bool = True,
|
161
|
+
) -> None:
|
162
|
+
"""Initialize a `wandb.Image` object.
|
163
|
+
|
164
|
+
Args:
|
165
|
+
data_or_path: Accepts NumPy array/pytorch tensor of image data,
|
166
|
+
a PIL image object, or a path to an image file. If a NumPy
|
167
|
+
array or pytorch tensor is provided,
|
168
|
+
the image data will be saved to the given file type.
|
169
|
+
If the values are not in the range [0, 255] or all values are in the range [0, 1],
|
170
|
+
the image pixel values will be normalized to the range [0, 255]
|
171
|
+
unless `normalize` is set to False.
|
172
|
+
- pytorch tensor should be in the format (channel, height, width)
|
173
|
+
- NumPy array should be in the format (height, width, channel)
|
174
|
+
mode: The PIL mode for an image. Most common are "L", "RGB",
|
175
|
+
"RGBA". Full explanation at https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes
|
176
|
+
caption: Label for display of image.
|
177
|
+
grouping: The grouping number for the image.
|
178
|
+
classes: A list of class information for the image,
|
179
|
+
used for labeling bounding boxes, and image masks.
|
180
|
+
boxes: A dictionary containing bounding box information for the image.
|
181
|
+
see: https://docs.wandb.ai/ref/python/data-types/boundingboxes2d/
|
182
|
+
masks: A dictionary containing mask information for the image.
|
183
|
+
see: https://docs.wandb.ai/ref/python/data-types/imagemask/
|
184
|
+
file_type: The file type to save the image as.
|
185
|
+
This parameter has no effect if data_or_path is a path to an image file.
|
186
|
+
normalize: If True, normalize the image pixel values to fall within the range of [0, 255].
|
187
|
+
Normalize is only applied if data_or_path is a numpy array or pytorch tensor.
|
188
|
+
|
189
|
+
Examples:
|
190
|
+
Create a wandb.Image from a numpy array
|
191
|
+
|
192
|
+
```python
|
193
|
+
import numpy as np
|
194
|
+
import wandb
|
195
|
+
|
196
|
+
with wandb.init() as run:
|
197
|
+
examples = []
|
198
|
+
for i in range(3):
|
199
|
+
pixels = np.random.randint(low=0, high=256, size=(100, 100, 3))
|
200
|
+
image = wandb.Image(pixels, caption=f"random field {i}")
|
201
|
+
examples.append(image)
|
202
|
+
run.log({"examples": examples})
|
203
|
+
```
|
204
|
+
|
205
|
+
Create a wandb.Image from a PILImage
|
206
|
+
|
207
|
+
```python
|
208
|
+
import numpy as np
|
209
|
+
from PIL import Image as PILImage
|
210
|
+
import wandb
|
211
|
+
|
212
|
+
with wandb.init() as run:
|
213
|
+
examples = []
|
214
|
+
for i in range(3):
|
215
|
+
pixels = np.random.randint(
|
216
|
+
low=0, high=256, size=(100, 100, 3), dtype=np.uint8
|
217
|
+
)
|
218
|
+
pil_image = PILImage.fromarray(pixels, mode="RGB")
|
219
|
+
image = wandb.Image(pil_image, caption=f"random field {i}")
|
220
|
+
examples.append(image)
|
221
|
+
run.log({"examples": examples})
|
222
|
+
```
|
223
|
+
|
224
|
+
Log .jpg rather than .png (default)
|
225
|
+
|
226
|
+
```python
|
227
|
+
import numpy as np
|
228
|
+
import wandb
|
229
|
+
|
230
|
+
with wandb.init() as run:
|
231
|
+
examples = []
|
232
|
+
for i in range(3):
|
233
|
+
pixels = np.random.randint(low=0, high=256, size=(100, 100, 3))
|
234
|
+
image = wandb.Image(
|
235
|
+
pixels, caption=f"random field {i}", file_type="jpg"
|
236
|
+
)
|
237
|
+
examples.append(image)
|
238
|
+
run.log({"examples": examples})
|
239
|
+
```
|
240
|
+
"""
|
241
|
+
super().__init__(caption=caption)
|
242
|
+
# TODO: We should remove grouping, it's a terrible name and I don't
|
243
|
+
# think anyone uses it.
|
244
|
+
|
245
|
+
self._grouping = None
|
246
|
+
self._width = None
|
247
|
+
self._height = None
|
248
|
+
self._image = None
|
249
|
+
self._classes = None
|
250
|
+
self._boxes = None
|
251
|
+
self._masks = None
|
252
|
+
self._file_type = None
|
253
|
+
|
254
|
+
# Allows the user to pass an Image object as the first parameter and have a perfect copy,
|
255
|
+
# only overriding additional metadata passed in. If this pattern is compelling, we can generalize.
|
256
|
+
if isinstance(data_or_path, Image):
|
257
|
+
self._initialize_from_wbimage(data_or_path)
|
258
|
+
elif isinstance(data_or_path, (str, pathlib.Path)):
|
259
|
+
data_or_path = str(data_or_path)
|
260
|
+
|
261
|
+
if self.path_is_reference(data_or_path):
|
262
|
+
self._initialize_from_reference(data_or_path)
|
263
|
+
else:
|
264
|
+
self._initialize_from_path(data_or_path)
|
265
|
+
else:
|
266
|
+
self._initialize_from_data(data_or_path, mode, file_type, normalize)
|
267
|
+
self._set_initialization_meta(
|
268
|
+
grouping, caption, classes, boxes, masks, file_type
|
269
|
+
)
|
270
|
+
|
271
|
+
def _set_initialization_meta(
|
272
|
+
self,
|
273
|
+
grouping: Optional[int] = None,
|
274
|
+
caption: Optional[str] = None,
|
275
|
+
classes: Optional[Union["Classes", Sequence[dict]]] = None,
|
276
|
+
boxes: Optional[Union[Dict[str, "BoundingBoxes2D"], Dict[str, dict]]] = None,
|
277
|
+
masks: Optional[Union[Dict[str, "ImageMask"], Dict[str, dict]]] = None,
|
278
|
+
file_type: Optional[str] = None,
|
279
|
+
) -> None:
|
280
|
+
if grouping is not None:
|
281
|
+
self._grouping = grouping
|
282
|
+
|
283
|
+
total_classes = {}
|
284
|
+
|
285
|
+
if boxes:
|
286
|
+
if not isinstance(boxes, dict):
|
287
|
+
raise ValueError('Images "boxes" argument must be a dictionary')
|
288
|
+
boxes_final: Dict[str, BoundingBoxes2D] = {}
|
289
|
+
for key in boxes:
|
290
|
+
box_item = boxes[key]
|
291
|
+
if isinstance(box_item, BoundingBoxes2D):
|
292
|
+
boxes_final[key] = box_item
|
293
|
+
elif isinstance(box_item, dict):
|
294
|
+
# TODO: Consider injecting top-level classes if user-provided is empty
|
295
|
+
boxes_final[key] = BoundingBoxes2D(box_item, key)
|
296
|
+
total_classes.update(boxes_final[key]._class_labels)
|
297
|
+
self._boxes = boxes_final
|
298
|
+
|
299
|
+
if masks:
|
300
|
+
if not isinstance(masks, dict):
|
301
|
+
raise ValueError('Images "masks" argument must be a dictionary')
|
302
|
+
masks_final: Dict[str, ImageMask] = {}
|
303
|
+
for key in masks:
|
304
|
+
mask_item = masks[key]
|
305
|
+
if isinstance(mask_item, ImageMask):
|
306
|
+
masks_final[key] = mask_item
|
307
|
+
elif isinstance(mask_item, dict):
|
308
|
+
# TODO: Consider injecting top-level classes if user-provided is empty
|
309
|
+
masks_final[key] = ImageMask(mask_item, key)
|
310
|
+
if hasattr(masks_final[key], "_val"):
|
311
|
+
total_classes.update(masks_final[key]._val["class_labels"])
|
312
|
+
self._masks = masks_final
|
313
|
+
|
314
|
+
if classes is not None:
|
315
|
+
if isinstance(classes, Classes):
|
316
|
+
total_classes.update(
|
317
|
+
{val["id"]: val["name"] for val in classes._class_set}
|
318
|
+
)
|
319
|
+
else:
|
320
|
+
total_classes.update({val["id"]: val["name"] for val in classes})
|
321
|
+
|
322
|
+
if len(total_classes.keys()) > 0:
|
323
|
+
self._classes = Classes(
|
324
|
+
[
|
325
|
+
{"id": key, "name": total_classes[key]}
|
326
|
+
for key in total_classes.keys()
|
327
|
+
]
|
328
|
+
)
|
329
|
+
if self.image is not None:
|
330
|
+
self._width, self._height = self.image.size
|
331
|
+
self._free_ram()
|
332
|
+
|
333
|
+
def _initialize_from_wbimage(self, wbimage: "Image") -> None:
|
334
|
+
self._grouping = wbimage._grouping
|
335
|
+
self._caption = wbimage._caption
|
336
|
+
self._width = wbimage._width
|
337
|
+
self._height = wbimage._height
|
338
|
+
self._image = wbimage._image
|
339
|
+
self._classes = wbimage._classes
|
340
|
+
self._path = wbimage._path
|
341
|
+
self._is_tmp = wbimage._is_tmp
|
342
|
+
self._extension = wbimage._extension
|
343
|
+
self._sha256 = wbimage._sha256
|
344
|
+
self._size = wbimage._size
|
345
|
+
self.format = wbimage.format
|
346
|
+
self._file_type = wbimage._file_type
|
347
|
+
self._artifact_source = wbimage._artifact_source
|
348
|
+
self._artifact_target = wbimage._artifact_target
|
349
|
+
|
350
|
+
# We do not want to implicitly copy boxes or masks, just the image-related data.
|
351
|
+
# self._boxes = wbimage._boxes
|
352
|
+
# self._masks = wbimage._masks
|
353
|
+
|
354
|
+
def _initialize_from_path(self, path: str) -> None:
|
355
|
+
pil_image = util.get_module(
|
356
|
+
"PIL.Image",
|
357
|
+
required='wandb.Image needs the PIL package. To get it, run "pip install pillow".',
|
358
|
+
)
|
359
|
+
self._set_file(path, is_tmp=False)
|
360
|
+
self._image = pil_image.open(path)
|
361
|
+
assert self._image is not None
|
362
|
+
self._image.load()
|
363
|
+
ext = os.path.splitext(path)[1][1:]
|
364
|
+
self.format = ext
|
365
|
+
|
366
|
+
def _initialize_from_reference(self, path: str) -> None:
|
367
|
+
self._path = path
|
368
|
+
self._is_tmp = False
|
369
|
+
self._sha256 = hashlib.sha256(path.encode("utf-8")).hexdigest()
|
370
|
+
path = parse.urlparse(path).path
|
371
|
+
ext = path.split("/")[-1].split(".")[-1]
|
372
|
+
self.format = ext
|
373
|
+
|
374
|
+
def _initialize_from_data(
|
375
|
+
self,
|
376
|
+
data: "ImageDataType",
|
377
|
+
mode: Optional[str] = None,
|
378
|
+
file_type: Optional[str] = None,
|
379
|
+
normalize: bool = True,
|
380
|
+
) -> None:
|
381
|
+
pil_image = util.get_module(
|
382
|
+
"PIL.Image",
|
383
|
+
required='wandb.Image needs the PIL package. To get it, run "pip install pillow".',
|
384
|
+
)
|
385
|
+
|
386
|
+
accepted_formats = ["png", "jpg", "jpeg", "bmp"]
|
387
|
+
self.format = file_type or "png"
|
388
|
+
|
389
|
+
if self.format not in accepted_formats:
|
390
|
+
raise ValueError(f"file_type must be one of {accepted_formats}")
|
391
|
+
|
392
|
+
tmp_path = os.path.join(MEDIA_TMP.name, runid.generate_id() + "." + self.format)
|
393
|
+
|
394
|
+
if util.is_matplotlib_typename(util.get_full_typename(data)):
|
395
|
+
buf = BytesIO()
|
396
|
+
util.ensure_matplotlib_figure(data).savefig(buf, format=self.format)
|
397
|
+
self._image = pil_image.open(buf)
|
398
|
+
elif isinstance(data, pil_image.Image):
|
399
|
+
self._image = data
|
400
|
+
elif util.is_pytorch_tensor_typename(util.get_full_typename(data)):
|
401
|
+
if hasattr(data, "requires_grad") and data.requires_grad:
|
402
|
+
data = data.detach() # type: ignore
|
403
|
+
if hasattr(data, "dtype") and str(data.dtype) == "torch.uint8":
|
404
|
+
data = data.to(float) # type: ignore [union-attr]
|
405
|
+
mode = mode or self.guess_mode(data, file_type)
|
406
|
+
data = data.permute(1, 2, 0).cpu().numpy() # type: ignore [union-attr]
|
407
|
+
|
408
|
+
_warn_on_invalid_data_range(data, normalize)
|
409
|
+
|
410
|
+
data = _guess_and_rescale_to_0_255(data) if normalize else data # type: ignore [arg-type]
|
411
|
+
data = _convert_to_uint8(data)
|
412
|
+
|
413
|
+
if data.ndim > 2:
|
414
|
+
data = data.squeeze()
|
415
|
+
|
416
|
+
self._image = pil_image.fromarray(
|
417
|
+
data,
|
418
|
+
mode=mode,
|
419
|
+
)
|
420
|
+
else:
|
421
|
+
if hasattr(data, "numpy"): # TF data eager tensors
|
422
|
+
data = data.numpy()
|
423
|
+
if data.ndim > 2: # type: ignore [union-attr]
|
424
|
+
# get rid of trivial dimensions as a convenience
|
425
|
+
data = data.squeeze() # type: ignore [union-attr]
|
426
|
+
|
427
|
+
_warn_on_invalid_data_range(data, normalize) # type: ignore [arg-type]
|
428
|
+
|
429
|
+
mode = mode or self.guess_mode(data, file_type)
|
430
|
+
data = _guess_and_rescale_to_0_255(data) if normalize else data # type: ignore [arg-type]
|
431
|
+
data = _convert_to_uint8(data) # type: ignore [arg-type]
|
432
|
+
self._image = pil_image.fromarray(
|
433
|
+
data,
|
434
|
+
mode=mode,
|
435
|
+
)
|
436
|
+
|
437
|
+
assert self._image is not None
|
438
|
+
self._image.save(tmp_path, transparency=None)
|
439
|
+
self._set_file(tmp_path, is_tmp=True)
|
440
|
+
|
441
|
+
@classmethod
|
442
|
+
def from_json(
|
443
|
+
cls: Type["Image"], json_obj: dict, source_artifact: "Artifact"
|
444
|
+
) -> "Image":
|
445
|
+
"""Factory method to create an Audio object from a JSON object.
|
446
|
+
|
447
|
+
"<!-- lazydoc-ignore-classmethod: internal -->
|
448
|
+
"""
|
449
|
+
classes: Optional[Classes] = None
|
450
|
+
if json_obj.get("classes") is not None:
|
451
|
+
value = source_artifact.get(json_obj["classes"]["path"])
|
452
|
+
assert isinstance(value, (type(None), Classes))
|
453
|
+
classes = value
|
454
|
+
|
455
|
+
masks = json_obj.get("masks")
|
456
|
+
_masks: Optional[Dict[str, ImageMask]] = None
|
457
|
+
if masks:
|
458
|
+
_masks = {}
|
459
|
+
for key in masks:
|
460
|
+
_masks[key] = ImageMask.from_json(masks[key], source_artifact)
|
461
|
+
_masks[key]._set_artifact_source(source_artifact)
|
462
|
+
_masks[key]._key = key
|
463
|
+
|
464
|
+
boxes = json_obj.get("boxes")
|
465
|
+
_boxes: Optional[Dict[str, BoundingBoxes2D]] = None
|
466
|
+
if boxes:
|
467
|
+
_boxes = {}
|
468
|
+
for key in boxes:
|
469
|
+
_boxes[key] = BoundingBoxes2D.from_json(boxes[key], source_artifact)
|
470
|
+
_boxes[key]._key = key
|
471
|
+
|
472
|
+
return cls(
|
473
|
+
source_artifact.get_entry(json_obj["path"]).download(),
|
474
|
+
caption=json_obj.get("caption"),
|
475
|
+
grouping=json_obj.get("grouping"),
|
476
|
+
classes=classes,
|
477
|
+
boxes=_boxes,
|
478
|
+
masks=_masks,
|
479
|
+
)
|
480
|
+
|
481
|
+
@classmethod
|
482
|
+
def get_media_subdir(cls: Type["Image"]) -> str:
|
483
|
+
"""Get media subdirectory.
|
484
|
+
|
485
|
+
"<!-- lazydoc-ignore-classmethod: internal -->
|
486
|
+
"""
|
487
|
+
return os.path.join("media", "images")
|
488
|
+
|
489
|
+
def bind_to_run(
|
490
|
+
self,
|
491
|
+
run: "wandb.Run",
|
492
|
+
key: Union[int, str],
|
493
|
+
step: Union[int, str],
|
494
|
+
id_: Optional[Union[int, str]] = None,
|
495
|
+
ignore_copy_err: Optional[bool] = None,
|
496
|
+
) -> None:
|
497
|
+
"""Bind this object to a run.
|
498
|
+
|
499
|
+
<!-- lazydoc-ignore: internal -->
|
500
|
+
"""
|
501
|
+
# For Images, we are going to avoid copying the image file to the run.
|
502
|
+
# We should make this common functionality for all media types, but that
|
503
|
+
# requires a broader UI refactor. This model can easily be moved to the
|
504
|
+
# higher level Media class, but that will require every UI surface area
|
505
|
+
# that depends on the `path` to be able to instead consume
|
506
|
+
# `artifact_path`. I (Tim) think the media panel makes up most of this
|
507
|
+
# space, but there are also custom charts, and maybe others. Let's
|
508
|
+
# commit to getting all that fixed up before moving this to the top
|
509
|
+
# level Media class.
|
510
|
+
if self.path_is_reference(self._path):
|
511
|
+
raise ValueError(
|
512
|
+
"Image media created by a reference to external storage cannot currently be added to a run"
|
513
|
+
)
|
514
|
+
|
515
|
+
if (
|
516
|
+
not _server_accepts_artifact_path(run)
|
517
|
+
or self._get_artifact_entry_ref_url() is None
|
518
|
+
):
|
519
|
+
super().bind_to_run(run, key, step, id_, ignore_copy_err=ignore_copy_err)
|
520
|
+
if self._boxes is not None:
|
521
|
+
for i, k in enumerate(self._boxes):
|
522
|
+
id_ = f"{id_}{i}" if id_ is not None else None
|
523
|
+
self._boxes[k].bind_to_run(
|
524
|
+
run, key, step, id_, ignore_copy_err=ignore_copy_err
|
525
|
+
)
|
526
|
+
|
527
|
+
if self._masks is not None:
|
528
|
+
for i, k in enumerate(self._masks):
|
529
|
+
id_ = f"{id_}{i}" if id_ is not None else None
|
530
|
+
self._masks[k].bind_to_run(
|
531
|
+
run, key, step, id_, ignore_copy_err=ignore_copy_err
|
532
|
+
)
|
533
|
+
|
534
|
+
def to_json(self, run_or_artifact: Union["wandb.Run", "Artifact"]) -> dict:
|
535
|
+
"""Returns the JSON representation expected by the backend.
|
536
|
+
|
537
|
+
<!-- lazydoc-ignore: internal -->
|
538
|
+
"""
|
539
|
+
json_dict = super().to_json(run_or_artifact)
|
540
|
+
json_dict["_type"] = Image._log_type
|
541
|
+
json_dict["format"] = self.format
|
542
|
+
|
543
|
+
if self._width is not None:
|
544
|
+
json_dict["width"] = self._width
|
545
|
+
if self._height is not None:
|
546
|
+
json_dict["height"] = self._height
|
547
|
+
if self._grouping:
|
548
|
+
json_dict["grouping"] = self._grouping
|
549
|
+
|
550
|
+
if isinstance(run_or_artifact, wandb.Artifact):
|
551
|
+
artifact = run_or_artifact
|
552
|
+
if (
|
553
|
+
self._masks is not None or self._boxes is not None
|
554
|
+
) and self._classes is None:
|
555
|
+
raise ValueError(
|
556
|
+
"classes must be passed to wandb.Image which have masks or bounding boxes when adding to artifacts"
|
557
|
+
)
|
558
|
+
|
559
|
+
if self._classes is not None:
|
560
|
+
class_id = hashutil._md5(
|
561
|
+
str(self._classes._class_set).encode("utf-8")
|
562
|
+
).hexdigest()
|
563
|
+
class_name = os.path.join(
|
564
|
+
"media",
|
565
|
+
"classes",
|
566
|
+
class_id + "_cls",
|
567
|
+
)
|
568
|
+
classes_entry = artifact.add(self._classes, class_name)
|
569
|
+
json_dict["classes"] = {
|
570
|
+
"type": "classes-file",
|
571
|
+
"path": classes_entry.path,
|
572
|
+
"digest": classes_entry.digest,
|
573
|
+
}
|
574
|
+
|
575
|
+
elif not isinstance(run_or_artifact, wandb.Run):
|
576
|
+
raise TypeError("to_json accepts wandb.Run or wandb_artifact.Artifact")
|
577
|
+
|
578
|
+
if self._boxes:
|
579
|
+
json_dict["boxes"] = {
|
580
|
+
k: box.to_json(run_or_artifact) for (k, box) in self._boxes.items()
|
581
|
+
}
|
582
|
+
if self._masks:
|
583
|
+
json_dict["masks"] = {
|
584
|
+
k: mask.to_json(run_or_artifact) for (k, mask) in self._masks.items()
|
585
|
+
}
|
586
|
+
return json_dict
|
587
|
+
|
588
|
+
def guess_mode(
|
589
|
+
self,
|
590
|
+
data: Union["np.ndarray", "torch.Tensor"],
|
591
|
+
file_type: Optional[str] = None,
|
592
|
+
) -> str:
|
593
|
+
"""Guess what type of image the np.array is representing.
|
594
|
+
|
595
|
+
<!-- lazydoc-ignore: internal -->
|
596
|
+
"""
|
597
|
+
# TODO: do we want to support dimensions being at the beginning of the array?
|
598
|
+
ndims = data.ndim
|
599
|
+
if util.is_pytorch_tensor_typename(util.get_full_typename(data)):
|
600
|
+
# Torch tenors typically have the channels dimension first
|
601
|
+
num_channels = data.shape[0]
|
602
|
+
else:
|
603
|
+
num_channels = data.shape[-1]
|
604
|
+
|
605
|
+
if ndims == 2 or num_channels == 1:
|
606
|
+
return "L"
|
607
|
+
elif num_channels == 3:
|
608
|
+
return "RGB"
|
609
|
+
elif num_channels == 4:
|
610
|
+
if file_type in ["jpg", "jpeg"]:
|
611
|
+
wandb.termwarn(
|
612
|
+
"JPEG format does not support transparency. "
|
613
|
+
"Ignoring alpha channel.",
|
614
|
+
repeat=False,
|
615
|
+
)
|
616
|
+
return "RGB"
|
617
|
+
else:
|
618
|
+
return "RGBA"
|
619
|
+
else:
|
620
|
+
raise ValueError(
|
621
|
+
f"Un-supported shape for image conversion {list(data.shape)}"
|
622
|
+
)
|
623
|
+
|
624
|
+
@classmethod
|
625
|
+
def seq_to_json(
|
626
|
+
cls: Type["Image"],
|
627
|
+
seq: Sequence["BatchableMedia"],
|
628
|
+
run: "wandb.Run",
|
629
|
+
key: str,
|
630
|
+
step: Union[int, str],
|
631
|
+
) -> dict:
|
632
|
+
"""Convert a sequence of Image objects to a JSON representation.
|
633
|
+
|
634
|
+
"<!-- lazydoc-ignore-classmethod: internal -->
|
635
|
+
"""
|
636
|
+
if TYPE_CHECKING:
|
637
|
+
seq = cast(Sequence["Image"], seq)
|
638
|
+
|
639
|
+
jsons = [obj.to_json(run) for obj in seq]
|
640
|
+
|
641
|
+
media_dir = cls.get_media_subdir()
|
642
|
+
|
643
|
+
for obj in jsons:
|
644
|
+
expected = LogicalPath(media_dir)
|
645
|
+
if "path" in obj and not obj["path"].startswith(expected):
|
646
|
+
raise ValueError(
|
647
|
+
"Files in an array of Image's must be in the {} directory, not {}".format(
|
648
|
+
cls.get_media_subdir(), obj["path"]
|
649
|
+
)
|
650
|
+
)
|
651
|
+
|
652
|
+
num_images_to_log = len(seq)
|
653
|
+
width, height = seq[0].image.size # type: ignore
|
654
|
+
format = jsons[0]["format"]
|
655
|
+
|
656
|
+
def size_equals_image(image: "Image") -> bool:
|
657
|
+
img_width, img_height = image.image.size # type: ignore
|
658
|
+
return img_width == width and img_height == height
|
659
|
+
|
660
|
+
sizes_match = all(size_equals_image(img) for img in seq)
|
661
|
+
if not sizes_match:
|
662
|
+
logging.warning(
|
663
|
+
"Images sizes do not match. This will causes images to be display incorrectly in the UI."
|
664
|
+
)
|
665
|
+
|
666
|
+
meta = {
|
667
|
+
"_type": "images/separated",
|
668
|
+
"width": width,
|
669
|
+
"height": height,
|
670
|
+
"format": format,
|
671
|
+
"count": num_images_to_log,
|
672
|
+
}
|
673
|
+
if _server_accepts_image_filenames(run):
|
674
|
+
meta["filenames"] = [
|
675
|
+
obj.get("path", obj.get("artifact_path")) for obj in jsons
|
676
|
+
]
|
677
|
+
else:
|
678
|
+
wandb.termwarn(
|
679
|
+
"Unable to log image array filenames. In some cases, this can prevent images from being "
|
680
|
+
"viewed in the UI. Please upgrade your wandb server",
|
681
|
+
repeat=False,
|
682
|
+
)
|
683
|
+
|
684
|
+
captions = Image.all_captions(seq)
|
685
|
+
|
686
|
+
if captions:
|
687
|
+
meta["captions"] = captions
|
688
|
+
|
689
|
+
all_masks = Image.all_masks(seq, run, key, step)
|
690
|
+
|
691
|
+
if all_masks:
|
692
|
+
meta["all_masks"] = all_masks
|
693
|
+
|
694
|
+
all_boxes = Image.all_boxes(seq, run, key, step)
|
695
|
+
|
696
|
+
if all_boxes:
|
697
|
+
meta["all_boxes"] = all_boxes
|
698
|
+
|
699
|
+
return meta
|
700
|
+
|
701
|
+
@classmethod
|
702
|
+
def all_masks(
|
703
|
+
cls: Type["Image"],
|
704
|
+
images: Sequence["Image"],
|
705
|
+
run: "wandb.Run",
|
706
|
+
run_key: str,
|
707
|
+
step: Union[int, str],
|
708
|
+
) -> Union[List[Optional[dict]], bool]:
|
709
|
+
"""Collect all masks from a list of images.
|
710
|
+
|
711
|
+
"<!-- lazydoc-ignore-classmethod: internal -->
|
712
|
+
"""
|
713
|
+
all_mask_groups: List[Optional[dict]] = []
|
714
|
+
for image in images:
|
715
|
+
if image._masks:
|
716
|
+
mask_group = {}
|
717
|
+
for k in image._masks:
|
718
|
+
mask = image._masks[k]
|
719
|
+
mask_group[k] = mask.to_json(run)
|
720
|
+
all_mask_groups.append(mask_group)
|
721
|
+
else:
|
722
|
+
all_mask_groups.append(None)
|
723
|
+
if all_mask_groups and not all(x is None for x in all_mask_groups):
|
724
|
+
return all_mask_groups
|
725
|
+
else:
|
726
|
+
return False
|
727
|
+
|
728
|
+
@classmethod
|
729
|
+
def all_boxes(
|
730
|
+
cls: Type["Image"],
|
731
|
+
images: Sequence["Image"],
|
732
|
+
run: "wandb.Run",
|
733
|
+
run_key: str,
|
734
|
+
step: Union[int, str],
|
735
|
+
) -> Union[List[Optional[dict]], bool]:
|
736
|
+
"""Collect all boxes from a list of images.
|
737
|
+
|
738
|
+
"<!-- lazydoc-ignore-classmethod: internal -->
|
739
|
+
"""
|
740
|
+
all_box_groups: List[Optional[dict]] = []
|
741
|
+
for image in images:
|
742
|
+
if image._boxes:
|
743
|
+
box_group = {}
|
744
|
+
for k in image._boxes:
|
745
|
+
box = image._boxes[k]
|
746
|
+
box_group[k] = box.to_json(run)
|
747
|
+
all_box_groups.append(box_group)
|
748
|
+
else:
|
749
|
+
all_box_groups.append(None)
|
750
|
+
if all_box_groups and not all(x is None for x in all_box_groups):
|
751
|
+
return all_box_groups
|
752
|
+
else:
|
753
|
+
return False
|
754
|
+
|
755
|
+
@classmethod
|
756
|
+
def all_captions(
|
757
|
+
cls: Type["Image"], images: Sequence["Media"]
|
758
|
+
) -> Union[bool, Sequence[Optional[str]]]:
|
759
|
+
"""Get captions from a list of images.
|
760
|
+
|
761
|
+
"<!-- lazydoc-ignore-classmethod: internal -->
|
762
|
+
"""
|
763
|
+
return cls.captions(images)
|
764
|
+
|
765
|
+
def __ne__(self, other: object) -> bool:
|
766
|
+
return not self.__eq__(other)
|
767
|
+
|
768
|
+
def __eq__(self, other: object) -> bool:
|
769
|
+
if not isinstance(other, Image):
|
770
|
+
return False
|
771
|
+
else:
|
772
|
+
if self.path_is_reference(self._path) and self.path_is_reference(
|
773
|
+
other._path
|
774
|
+
):
|
775
|
+
return self._path == other._path
|
776
|
+
self_image = self.image
|
777
|
+
other_image = other.image
|
778
|
+
if self_image is not None:
|
779
|
+
self_image = list(self_image.getdata()) # type: ignore
|
780
|
+
if other_image is not None:
|
781
|
+
other_image = list(other_image.getdata()) # type: ignore
|
782
|
+
|
783
|
+
return (
|
784
|
+
self._grouping == other._grouping
|
785
|
+
and self._caption == other._caption
|
786
|
+
and self._width == other._width
|
787
|
+
and self._height == other._height
|
788
|
+
and self_image == other_image
|
789
|
+
and self._classes == other._classes
|
790
|
+
)
|
791
|
+
|
792
|
+
def to_data_array(self) -> List[Any]:
|
793
|
+
"""Convert to data array.
|
794
|
+
|
795
|
+
<!-- lazydoc-ignore: internal -->
|
796
|
+
"""
|
797
|
+
res = []
|
798
|
+
if self.image is not None:
|
799
|
+
data = list(self.image.getdata())
|
800
|
+
for i in range(self.image.height):
|
801
|
+
res.append(data[i * self.image.width : (i + 1) * self.image.width])
|
802
|
+
self._free_ram()
|
803
|
+
return res
|
804
|
+
|
805
|
+
def _free_ram(self) -> None:
|
806
|
+
if self._path is not None:
|
807
|
+
self._image = None
|
808
|
+
|
809
|
+
@property
|
810
|
+
def image(self) -> Optional["PILImage"]:
|
811
|
+
if self._image is None:
|
812
|
+
if self._path is not None and not self.path_is_reference(self._path):
|
813
|
+
pil_image = util.get_module(
|
814
|
+
"PIL.Image",
|
815
|
+
required='wandb.Image needs the PIL package. To get it, run "pip install pillow".',
|
816
|
+
)
|
817
|
+
self._image = pil_image.open(self._path)
|
818
|
+
self._image.load()
|
819
|
+
return self._image
|
820
|
+
|
821
|
+
|
822
|
+
# Custom dtypes for typing system
|
823
|
+
class _ImageFileType(_dtypes.Type):
|
824
|
+
name = "image-file"
|
825
|
+
legacy_names = ["wandb.Image"]
|
826
|
+
types = [Image]
|
827
|
+
|
828
|
+
def __init__(
|
829
|
+
self,
|
830
|
+
box_layers=None,
|
831
|
+
box_score_keys=None,
|
832
|
+
mask_layers=None,
|
833
|
+
class_map=None,
|
834
|
+
**kwargs,
|
835
|
+
):
|
836
|
+
box_layers = box_layers or {}
|
837
|
+
box_score_keys = box_score_keys or []
|
838
|
+
mask_layers = mask_layers or {}
|
839
|
+
class_map = class_map or {}
|
840
|
+
|
841
|
+
if isinstance(box_layers, _dtypes.ConstType):
|
842
|
+
box_layers = box_layers._params["val"]
|
843
|
+
if not isinstance(box_layers, dict):
|
844
|
+
raise TypeError("box_layers must be a dict")
|
845
|
+
else:
|
846
|
+
box_layers = _dtypes.ConstType(
|
847
|
+
{layer_key: set(box_layers[layer_key]) for layer_key in box_layers}
|
848
|
+
)
|
849
|
+
|
850
|
+
if isinstance(mask_layers, _dtypes.ConstType):
|
851
|
+
mask_layers = mask_layers._params["val"]
|
852
|
+
if not isinstance(mask_layers, dict):
|
853
|
+
raise TypeError("mask_layers must be a dict")
|
854
|
+
else:
|
855
|
+
mask_layers = _dtypes.ConstType(
|
856
|
+
{layer_key: set(mask_layers[layer_key]) for layer_key in mask_layers}
|
857
|
+
)
|
858
|
+
|
859
|
+
if isinstance(box_score_keys, _dtypes.ConstType):
|
860
|
+
box_score_keys = box_score_keys._params["val"]
|
861
|
+
if not isinstance(box_score_keys, list) and not isinstance(box_score_keys, set):
|
862
|
+
raise TypeError("box_score_keys must be a list or a set")
|
863
|
+
else:
|
864
|
+
box_score_keys = _dtypes.ConstType(set(box_score_keys))
|
865
|
+
|
866
|
+
if isinstance(class_map, _dtypes.ConstType):
|
867
|
+
class_map = class_map._params["val"]
|
868
|
+
if not isinstance(class_map, dict):
|
869
|
+
raise TypeError("class_map must be a dict")
|
870
|
+
else:
|
871
|
+
class_map = _dtypes.ConstType(class_map)
|
872
|
+
|
873
|
+
self.params.update(
|
874
|
+
{
|
875
|
+
"box_layers": box_layers,
|
876
|
+
"box_score_keys": box_score_keys,
|
877
|
+
"mask_layers": mask_layers,
|
878
|
+
"class_map": class_map,
|
879
|
+
}
|
880
|
+
)
|
881
|
+
|
882
|
+
def assign_type(self, wb_type=None):
|
883
|
+
if isinstance(wb_type, _ImageFileType):
|
884
|
+
box_layers_self = self.params["box_layers"].params["val"] or {}
|
885
|
+
box_score_keys_self = self.params["box_score_keys"].params["val"] or []
|
886
|
+
mask_layers_self = self.params["mask_layers"].params["val"] or {}
|
887
|
+
class_map_self = self.params["class_map"].params["val"] or {}
|
888
|
+
|
889
|
+
box_layers_other = wb_type.params["box_layers"].params["val"] or {}
|
890
|
+
box_score_keys_other = wb_type.params["box_score_keys"].params["val"] or []
|
891
|
+
mask_layers_other = wb_type.params["mask_layers"].params["val"] or {}
|
892
|
+
class_map_other = wb_type.params["class_map"].params["val"] or {}
|
893
|
+
|
894
|
+
# Merge the class_ids from each set of box_layers
|
895
|
+
box_layers = {
|
896
|
+
str(key): set(
|
897
|
+
list(box_layers_self.get(key, []))
|
898
|
+
+ list(box_layers_other.get(key, []))
|
899
|
+
)
|
900
|
+
for key in set(
|
901
|
+
list(box_layers_self.keys()) + list(box_layers_other.keys())
|
902
|
+
)
|
903
|
+
}
|
904
|
+
|
905
|
+
# Merge the class_ids from each set of mask_layers
|
906
|
+
mask_layers = {
|
907
|
+
str(key): set(
|
908
|
+
list(mask_layers_self.get(key, []))
|
909
|
+
+ list(mask_layers_other.get(key, []))
|
910
|
+
)
|
911
|
+
for key in set(
|
912
|
+
list(mask_layers_self.keys()) + list(mask_layers_other.keys())
|
913
|
+
)
|
914
|
+
}
|
915
|
+
|
916
|
+
# Merge the box score keys
|
917
|
+
box_score_keys = set(list(box_score_keys_self) + list(box_score_keys_other))
|
918
|
+
|
919
|
+
# Merge the class_map
|
920
|
+
class_map = {
|
921
|
+
str(key): class_map_self.get(key, class_map_other.get(key, None))
|
922
|
+
for key in set(
|
923
|
+
list(class_map_self.keys()) + list(class_map_other.keys())
|
924
|
+
)
|
925
|
+
}
|
926
|
+
|
927
|
+
return _ImageFileType(box_layers, box_score_keys, mask_layers, class_map)
|
928
|
+
|
929
|
+
return _dtypes.InvalidType()
|
930
|
+
|
931
|
+
@classmethod
|
932
|
+
def from_obj(cls, py_obj):
|
933
|
+
if not isinstance(py_obj, Image):
|
934
|
+
raise TypeError("py_obj must be a wandb.Image")
|
935
|
+
else:
|
936
|
+
if hasattr(py_obj, "_boxes") and py_obj._boxes:
|
937
|
+
box_layers = {
|
938
|
+
str(key): set(py_obj._boxes[key]._class_labels.keys())
|
939
|
+
for key in py_obj._boxes.keys()
|
940
|
+
}
|
941
|
+
box_score_keys = {
|
942
|
+
key
|
943
|
+
for val in py_obj._boxes.values()
|
944
|
+
for box in val._val
|
945
|
+
for key in box.get("scores", {}).keys()
|
946
|
+
}
|
947
|
+
|
948
|
+
else:
|
949
|
+
box_layers = {}
|
950
|
+
box_score_keys = set()
|
951
|
+
|
952
|
+
if hasattr(py_obj, "_masks") and py_obj._masks:
|
953
|
+
mask_layers = {
|
954
|
+
str(key): set(
|
955
|
+
py_obj._masks[key]._val["class_labels"].keys()
|
956
|
+
if hasattr(py_obj._masks[key], "_val")
|
957
|
+
else []
|
958
|
+
)
|
959
|
+
for key in py_obj._masks.keys()
|
960
|
+
}
|
961
|
+
else:
|
962
|
+
mask_layers = {}
|
963
|
+
|
964
|
+
if hasattr(py_obj, "_classes") and py_obj._classes:
|
965
|
+
class_set = {
|
966
|
+
str(item["id"]): item["name"] for item in py_obj._classes._class_set
|
967
|
+
}
|
968
|
+
else:
|
969
|
+
class_set = {}
|
970
|
+
|
971
|
+
return cls(box_layers, box_score_keys, mask_layers, class_set)
|
972
|
+
|
973
|
+
|
974
|
+
_dtypes.TypeRegistry.add(_ImageFileType)
|