simstack 2.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- simstack/__init__.py +0 -0
- simstack/_version.py +24 -0
- simstack/core/__init__.py +0 -0
- simstack/core/artifacts.py +406 -0
- simstack/core/asnyc_helper.py +14 -0
- simstack/core/config_file.py +60 -0
- simstack/core/context.py +283 -0
- simstack/core/definitions.py +22 -0
- simstack/core/engine.py +115 -0
- simstack/core/find_simstack_modules.py +41 -0
- simstack/core/hash.py +179 -0
- simstack/core/node.py +1137 -0
- simstack/core/node_claim.py +31 -0
- simstack/core/node_runner.py +362 -0
- simstack/core/process_results.py +102 -0
- simstack/core/recompute_artifacts.py +117 -0
- simstack/core/reset_db.py +12 -0
- simstack/core/resource_assignment.py +222 -0
- simstack/core/resources.py +90 -0
- simstack/core/route_table.py +24 -0
- simstack/core/run_docker.py +109 -0
- simstack/core/run_node.py +71 -0
- simstack/core/runner.py +169 -0
- simstack/core/services/__init__.py +11 -0
- simstack/core/services/base_service.py +191 -0
- simstack/core/services/file_transfer_service.py +117 -0
- simstack/core/services/git_restart_service.py +12 -0
- simstack/core/services/git_uv_update_service.py +105 -0
- simstack/core/services/node_execution_service.py +182 -0
- simstack/core/services/resource_branch_monitor_service.py +71 -0
- simstack/core/services/runner_cleanup_service.py +149 -0
- simstack/core/services/runner_manager.py +163 -0
- simstack/core/services/runner_status_service.py +10 -0
- simstack/core/services/slurm_status_service.py +67 -0
- simstack/core/services/stop_check_service.py +27 -0
- simstack/core/services/timeout_restart_service.py +26 -0
- simstack/core/simstack_result.py +39 -0
- simstack/core/submit_node.py +217 -0
- simstack/core/task_id.py +22 -0
- simstack/methods/__init__.py +0 -0
- simstack/methods/archive_files.py +292 -0
- simstack/methods/fire_and_forget_runner.py +113 -0
- simstack/methods/generate_test.py +125 -0
- simstack/methods/get_file.py +26 -0
- simstack/methods/mass_runner.py +154 -0
- simstack/methods/multiple_executor.py +307 -0
- simstack/methods/switch_git.py +16 -0
- simstack/methods/upload_helpers.py +81 -0
- simstack/models/__init__.py +74 -0
- simstack/models/array_list.py +21 -0
- simstack/models/array_storage.py +83 -0
- simstack/models/artifact_models.py +127 -0
- simstack/models/base_lists.py +51 -0
- simstack/models/base_types.py +209 -0
- simstack/models/charts_artifact.py +690 -0
- simstack/models/dataset.py +451 -0
- simstack/models/dataset_metadata.py +390 -0
- simstack/models/datasettuple.py +587 -0
- simstack/models/file_instance.py +150 -0
- simstack/models/file_list.py +45 -0
- simstack/models/files.py +424 -0
- simstack/models/fire_and_forget_result.py +19 -0
- simstack/models/images2d.py +113 -0
- simstack/models/log_entry_model.py +37 -0
- simstack/models/models.py +52 -0
- simstack/models/named_data_reference.py +36 -0
- simstack/models/node_registry.py +96 -0
- simstack/models/pandas_model.py +239 -0
- simstack/models/parameters.py +402 -0
- simstack/models/pickle_models.py +300 -0
- simstack/models/project.py +13 -0
- simstack/models/resource_assignment.py +170 -0
- simstack/models/resource_definition.py +125 -0
- simstack/models/runner_model.py +39 -0
- simstack/models/simple_table.py +79 -0
- simstack/models/simstack_model.py +97 -0
- simstack/models/slurm_info.py +17 -0
- simstack/models/table_artifact.py +87 -0
- simstack/models/tag.py +12 -0
- simstack/models/unused_test_file.py +5 -0
- simstack/simstack_marker.com +1 -0
- simstack/static/docs/.buildinfo +4 -0
- simstack/static/docs/_images/GUI Concept.webp +0 -0
- simstack/static/docs/_modules/index.html +434 -0
- simstack/static/docs/_modules/simstack/core/artifacts.html +743 -0
- simstack/static/docs/_modules/simstack/core/asnyc_helper.html +330 -0
- simstack/static/docs/_modules/simstack/core/config_file.html +379 -0
- simstack/static/docs/_modules/simstack/core/definitions.html +341 -0
- simstack/static/docs/_modules/simstack/core/engine.html +437 -0
- simstack/static/docs/_modules/simstack/core/find_simstack_modules.html +360 -0
- simstack/static/docs/_modules/simstack/core/hash.html +528 -0
- simstack/static/docs/_modules/simstack/core/node.html +1392 -0
- simstack/static/docs/_modules/simstack/core/node_claim.html +347 -0
- simstack/static/docs/_modules/simstack/core/node_runner.html +711 -0
- simstack/static/docs/_modules/simstack/core/process_results.html +418 -0
- simstack/static/docs/_modules/simstack/core/recompute_artifacts.html +433 -0
- simstack/static/docs/_modules/simstack/core/reset_db.html +328 -0
- simstack/static/docs/_modules/simstack/core/resource_assignment.html +553 -0
- simstack/static/docs/_modules/simstack/core/resources.html +424 -0
- simstack/static/docs/_modules/simstack/core/route_table.html +349 -0
- simstack/static/docs/_modules/simstack/core/run_docker.html +425 -0
- simstack/static/docs/_modules/simstack/core/run_node.html +390 -0
- simstack/static/docs/_modules/simstack/core/runner.html +491 -0
- simstack/static/docs/_modules/simstack/core/services/base_service.html +522 -0
- simstack/static/docs/_modules/simstack/core/services/file_transfer_service.html +436 -0
- simstack/static/docs/_modules/simstack/core/services/git_restart_service.html +331 -0
- simstack/static/docs/_modules/simstack/core/services/git_uv_update_service.html +427 -0
- simstack/static/docs/_modules/simstack/core/services/node_execution_service.html +507 -0
- simstack/static/docs/_modules/simstack/core/services/resource_branch_monitor_service.html +390 -0
- simstack/static/docs/_modules/simstack/core/services/runner_cleanup_service.html +468 -0
- simstack/static/docs/_modules/simstack/core/services/runner_manager.html +485 -0
- simstack/static/docs/_modules/simstack/core/services/runner_status_service.html +329 -0
- simstack/static/docs/_modules/simstack/core/services/slurm_status_service.html +386 -0
- simstack/static/docs/_modules/simstack/core/services/stop_check_service.html +346 -0
- simstack/static/docs/_modules/simstack/core/services/timeout_restart_service.html +345 -0
- simstack/static/docs/_modules/simstack/core/simstack_result.html +355 -0
- simstack/static/docs/_modules/simstack/core/submit_node.html +536 -0
- simstack/static/docs/_modules/simstack/core/task_id.html +344 -0
- simstack/static/docs/_modules/simstack/methods/archive_files.html +598 -0
- simstack/static/docs/_modules/simstack/methods/fire_and_forget_runner.html +432 -0
- simstack/static/docs/_modules/simstack/methods/generate_test.html +443 -0
- simstack/static/docs/_modules/simstack/methods/get_file.html +342 -0
- simstack/static/docs/_modules/simstack/methods/mass_runner.html +476 -0
- simstack/static/docs/_modules/simstack/methods/multiple_executor.html +674 -0
- simstack/static/docs/_modules/simstack/methods/switch_git.html +332 -0
- simstack/static/docs/_modules/simstack/methods/upload_helpers.html +403 -0
- simstack/static/docs/_modules/simstack/models/array_list.html +337 -0
- simstack/static/docs/_modules/simstack/models/array_storage.html +417 -0
- simstack/static/docs/_modules/simstack/models/base_lists.html +374 -0
- simstack/static/docs/_modules/simstack/models/base_types.html +588 -0
- simstack/static/docs/_modules/simstack/models/charts_artifact.html +1035 -0
- simstack/static/docs/_modules/simstack/models/dataset.html +866 -0
- simstack/static/docs/_modules/simstack/models/dataset_metadata.html +711 -0
- simstack/static/docs/_modules/simstack/models/datasettuple.html +1005 -0
- simstack/static/docs/_modules/simstack/models/file_instance.html +472 -0
- simstack/static/docs/_modules/simstack/models/file_list.html +367 -0
- simstack/static/docs/_modules/simstack/models/files.html +773 -0
- simstack/static/docs/_modules/simstack/models/fire_and_forget_result.html +335 -0
- simstack/static/docs/_modules/simstack/models/images2d.html +447 -0
- simstack/static/docs/_modules/simstack/models/log_entry_model.html +356 -0
- simstack/static/docs/_modules/simstack/models/models.html +374 -0
- simstack/static/docs/_modules/simstack/models/named_data_reference.html +355 -0
- simstack/static/docs/_modules/simstack/models/node_registry.html +415 -0
- simstack/static/docs/_modules/simstack/models/pandas_model.html +570 -0
- simstack/static/docs/_modules/simstack/models/parameters.html +739 -0
- simstack/static/docs/_modules/simstack/models/pickle_models.html +631 -0
- simstack/static/docs/_modules/simstack/models/project.html +329 -0
- simstack/static/docs/_modules/simstack/models/resource_assignment.html +501 -0
- simstack/static/docs/_modules/simstack/models/resource_definition.html +477 -0
- simstack/static/docs/_modules/simstack/models/runner_model.html +361 -0
- simstack/static/docs/_modules/simstack/models/simple_table.html +413 -0
- simstack/static/docs/_modules/simstack/models/simstack_model.html +416 -0
- simstack/static/docs/_modules/simstack/models/slurm_info.html +333 -0
- simstack/static/docs/_modules/simstack/models/table_artifact.html +406 -0
- simstack/static/docs/_modules/simstack/models/tag.html +328 -0
- simstack/static/docs/_modules/simstack/tables/model_table.html +519 -0
- simstack/static/docs/_modules/simstack/tables/node_children.html +538 -0
- simstack/static/docs/_modules/simstack/tables/node_table.html +854 -0
- simstack/static/docs/_modules/simstack/tables/table_builder.html +642 -0
- simstack/static/docs/_modules/simstack/util/async_zip_utils.html +337 -0
- simstack/static/docs/_modules/simstack/util/b64mixin.html +339 -0
- simstack/static/docs/_modules/simstack/util/cleaned_json_schema.html +336 -0
- simstack/static/docs/_modules/simstack/util/config_reader.html +498 -0
- simstack/static/docs/_modules/simstack/util/custom_model_dump.html +391 -0
- simstack/static/docs/_modules/simstack/util/database_information.html +488 -0
- simstack/static/docs/_modules/simstack/util/db.html +1392 -0
- simstack/static/docs/_modules/simstack/util/db_logger.html +448 -0
- simstack/static/docs/_modules/simstack/util/default_from_dict.html +376 -0
- simstack/static/docs/_modules/simstack/util/directory_iterator.html +553 -0
- simstack/static/docs/_modules/simstack/util/docstring_parser.html +526 -0
- simstack/static/docs/_modules/simstack/util/file_hashing.html +394 -0
- simstack/static/docs/_modules/simstack/util/file_transfer_client.html +791 -0
- simstack/static/docs/_modules/simstack/util/files.html +733 -0
- simstack/static/docs/_modules/simstack/util/find_python_files.html +349 -0
- simstack/static/docs/_modules/simstack/util/generate_ui_schema.html +396 -0
- simstack/static/docs/_modules/simstack/util/generic_list_mixin.html +487 -0
- simstack/static/docs/_modules/simstack/util/get_module_path.html +336 -0
- simstack/static/docs/_modules/simstack/util/git_pull.html +381 -0
- simstack/static/docs/_modules/simstack/util/git_repository_status.html +411 -0
- simstack/static/docs/_modules/simstack/util/import_module.html +377 -0
- simstack/static/docs/_modules/simstack/util/importer.html +637 -0
- simstack/static/docs/_modules/simstack/util/init_data_source.html +357 -0
- simstack/static/docs/_modules/simstack/util/make_graph.html +423 -0
- simstack/static/docs/_modules/simstack/util/make_table.html +1171 -0
- simstack/static/docs/_modules/simstack/util/mappings.html +378 -0
- simstack/static/docs/_modules/simstack/util/minimal_route_finder.html +388 -0
- simstack/static/docs/_modules/simstack/util/mock_db.html +472 -0
- simstack/static/docs/_modules/simstack/util/module_path_checker.html +354 -0
- simstack/static/docs/_modules/simstack/util/object_list_mixin.html +649 -0
- simstack/static/docs/_modules/simstack/util/path_manager.html +566 -0
- simstack/static/docs/_modules/simstack/util/project_root_finder.html +357 -0
- simstack/static/docs/_modules/simstack/util/queue_watcher.html +593 -0
- simstack/static/docs/_modules/simstack/util/resource_config.html +532 -0
- simstack/static/docs/_modules/simstack/util/route_finder.html +390 -0
- simstack/static/docs/_modules/simstack/util/runner_util.html +487 -0
- simstack/static/docs/_modules/simstack/util/runner_utils.html +468 -0
- simstack/static/docs/_modules/simstack/util/safe_code_executor.html +510 -0
- simstack/static/docs/_modules/simstack/util/sample_config.html +414 -0
- simstack/static/docs/_modules/simstack/util/sensitive_content_filter.html +364 -0
- simstack/static/docs/_modules/simstack/util/setup_logging.html +365 -0
- simstack/static/docs/_modules/simstack/util/submit_to_watchdog.html +425 -0
- simstack/static/docs/_modules/simstack/util/toml_reader.html +482 -0
- simstack/static/docs/_modules/simstack/util/transform_file_name.html +357 -0
- simstack/static/docs/_modules/simstack/util/ui_tools.html +541 -0
- simstack/static/docs/_sources/architecture.rst.txt +25 -0
- simstack/static/docs/_sources/array_lists.rst.txt +60 -0
- simstack/static/docs/_sources/ci_pipeline.rst.txt +34 -0
- simstack/static/docs/_sources/data.rst.txt +175 -0
- simstack/static/docs/_sources/database_migrations.rst.txt +310 -0
- simstack/static/docs/_sources/datasets.rst.txt +93 -0
- simstack/static/docs/_sources/developer_guide.rst.txt +25 -0
- simstack/static/docs/_sources/docker_nodes.rst.txt +149 -0
- simstack/static/docs/_sources/files.rst.txt +159 -0
- simstack/static/docs/_sources/fire_and_forget_runner.rst.txt +67 -0
- simstack/static/docs/_sources/index.rst.txt +25 -0
- simstack/static/docs/_sources/installation.rst.txt +213 -0
- simstack/static/docs/_sources/lists.rst.txt +111 -0
- simstack/static/docs/_sources/mass_runner.rst.txt +91 -0
- simstack/static/docs/_sources/misc.rst.txt +106 -0
- simstack/static/docs/_sources/overview.rst.txt +91 -0
- simstack/static/docs/_sources/recovery.rst.txt +38 -0
- simstack/static/docs/_sources/resource_config.rst.txt +141 -0
- simstack/static/docs/_sources/simstack/modules/modules.rst.txt +7 -0
- simstack/static/docs/_sources/simstack/modules/simstack.core.rst.txt +205 -0
- simstack/static/docs/_sources/simstack/modules/simstack.core.services.rst.txt +109 -0
- simstack/static/docs/_sources/simstack/modules/simstack.methods.rst.txt +77 -0
- simstack/static/docs/_sources/simstack/modules/simstack.models.rst.txt +261 -0
- simstack/static/docs/_sources/simstack/modules/simstack.rst.txt +22 -0
- simstack/static/docs/_sources/simstack/modules/simstack.tables.rst.txt +45 -0
- simstack/static/docs/_sources/simstack/modules/simstack.util.rst.txt +381 -0
- simstack/static/docs/_sources/submit.rst.txt +141 -0
- simstack/static/docs/_sources/tables.rst.txt +50 -0
- simstack/static/docs/_sources/testing_complex_nodes.rst.txt +92 -0
- simstack/static/docs/_sources/ui_documentation.rst.txt +272 -0
- simstack/static/docs/_sources/workflows.rst.txt +446 -0
- simstack/static/docs/_static/base-stemmer.js +476 -0
- simstack/static/docs/_static/basic.css +906 -0
- simstack/static/docs/_static/cobalt2-theme.css +1 -0
- simstack/static/docs/_static/debug.css +69 -0
- simstack/static/docs/_static/docs-build-badge.css +51 -0
- simstack/static/docs/_static/docs-build-badge.js +51 -0
- simstack/static/docs/_static/doctools.js +150 -0
- simstack/static/docs/_static/documentation_options.js +13 -0
- simstack/static/docs/_static/english-stemmer.js +1066 -0
- simstack/static/docs/_static/file.png +0 -0
- simstack/static/docs/_static/language_data.js +13 -0
- simstack/static/docs/_static/minus.png +0 -0
- simstack/static/docs/_static/plus.png +0 -0
- simstack/static/docs/_static/pygments.css +250 -0
- simstack/static/docs/_static/scripts/furo-extensions.js +0 -0
- simstack/static/docs/_static/scripts/furo.js +3 -0
- simstack/static/docs/_static/scripts/furo.js.LICENSE.txt +7 -0
- simstack/static/docs/_static/scripts/furo.js.map +1 -0
- simstack/static/docs/_static/searchtools.js +693 -0
- simstack/static/docs/_static/skeleton.css +296 -0
- simstack/static/docs/_static/sphinx_highlight.js +159 -0
- simstack/static/docs/_static/styles/furo-extensions.css +2 -0
- simstack/static/docs/_static/styles/furo-extensions.css.map +1 -0
- simstack/static/docs/_static/styles/furo.css +2 -0
- simstack/static/docs/_static/styles/furo.css.map +1 -0
- simstack/static/docs/architecture.html +340 -0
- simstack/static/docs/array_lists.html +678 -0
- simstack/static/docs/ci_pipeline.html +385 -0
- simstack/static/docs/data.html +545 -0
- simstack/static/docs/database_migrations.html +652 -0
- simstack/static/docs/datasets.html +1268 -0
- simstack/static/docs/developer_guide.html +359 -0
- simstack/static/docs/docker_nodes.html +503 -0
- simstack/static/docs/files.html +718 -0
- simstack/static/docs/fire_and_forget_runner.html +641 -0
- simstack/static/docs/genindex.html +6390 -0
- simstack/static/docs/index.html +516 -0
- simstack/static/docs/installation.html +553 -0
- simstack/static/docs/lists.html +478 -0
- simstack/static/docs/mass_runner.html +481 -0
- simstack/static/docs/misc.html +454 -0
- simstack/static/docs/objects.inv +0 -0
- simstack/static/docs/overview.html +469 -0
- simstack/static/docs/py-modindex.html +1111 -0
- simstack/static/docs/recovery.html +371 -0
- simstack/static/docs/resource_config.html +590 -0
- simstack/static/docs/search.html +327 -0
- simstack/static/docs/searchindex.js +1 -0
- simstack/static/docs/simstack/modules/modules.html +489 -0
- simstack/static/docs/simstack/modules/simstack.core.html +1883 -0
- simstack/static/docs/simstack/modules/simstack.core.services.html +698 -0
- simstack/static/docs/simstack/modules/simstack.html +3060 -0
- simstack/static/docs/simstack/modules/simstack.methods.html +1150 -0
- simstack/static/docs/simstack/modules/simstack.models.html +13113 -0
- simstack/static/docs/simstack/modules/simstack.tables.html +635 -0
- simstack/static/docs/simstack/modules/simstack.util.html +3320 -0
- simstack/static/docs/submit.html +487 -0
- simstack/static/docs/tables.html +539 -0
- simstack/static/docs/testing_complex_nodes.html +458 -0
- simstack/static/docs/ui_documentation.html +788 -0
- simstack/static/docs/workflows.html +766 -0
- simstack/tables/__init__.py +0 -0
- simstack/tables/model_table.py +191 -0
- simstack/tables/node_children.py +219 -0
- simstack/tables/node_table.py +517 -0
- simstack/tables/table_builder.py +314 -0
- simstack/util/__init__.py +0 -0
- simstack/util/async_zip_utils.py +18 -0
- simstack/util/b64mixin.py +23 -0
- simstack/util/cleaned_json_schema.py +20 -0
- simstack/util/config_reader.py +179 -0
- simstack/util/custom_model_dump.py +75 -0
- simstack/util/database_information.py +160 -0
- simstack/util/db.py +1013 -0
- simstack/util/db_logger.py +117 -0
- simstack/util/default_from_dict.py +57 -0
- simstack/util/directory_iterator.py +216 -0
- simstack/util/docstring_parser.py +186 -0
- simstack/util/file_hashing.py +72 -0
- simstack/util/file_transfer_client.py +427 -0
- simstack/util/files.py +396 -0
- simstack/util/find_python_files.py +33 -0
- simstack/util/generate_ui_schema.py +80 -0
- simstack/util/generic_list_mixin.py +120 -0
- simstack/util/geometry_utils.py +118 -0
- simstack/util/get_module_path.py +20 -0
- simstack/util/git_pull.py +65 -0
- simstack/util/git_repository_status.py +95 -0
- simstack/util/import_module.py +63 -0
- simstack/util/importer.py +312 -0
- simstack/util/init_data_source.py +41 -0
- simstack/util/make_graph.py +107 -0
- simstack/util/make_table.py +837 -0
- simstack/util/mappings.py +41 -0
- simstack/util/minimal_route_finder.py +72 -0
- simstack/util/mock_db.py +144 -0
- simstack/util/module_path_checker.py +38 -0
- simstack/util/object_list_mixin.py +282 -0
- simstack/util/path_manager.py +223 -0
- simstack/util/project_root_finder.py +41 -0
- simstack/util/queue_watcher.py +262 -0
- simstack/util/resource_config.py +198 -0
- simstack/util/route_finder.py +74 -0
- simstack/util/runner_util.py +166 -0
- simstack/util/runner_utils.py +143 -0
- simstack/util/safe_code_executor.py +194 -0
- simstack/util/sample_config.py +98 -0
- simstack/util/sensitive_content_filter.py +48 -0
- simstack/util/setup_logging.py +49 -0
- simstack/util/submit_to_watchdog.py +106 -0
- simstack/util/toml_reader.py +142 -0
- simstack/util/transform_file_name.py +41 -0
- simstack/util/ui_tools.py +213 -0
- simstack-2.0.1.dist-info/METADATA +454 -0
- simstack-2.0.1.dist-info/RECORD +354 -0
- simstack-2.0.1.dist-info/WHEEL +5 -0
- simstack-2.0.1.dist-info/entry_points.txt +12 -0
- simstack-2.0.1.dist-info/licenses/LICENSE +21 -0
- simstack-2.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
from typing import Optional, Literal, Dict, Any, Union
|
|
2
|
+
import base64
|
|
3
|
+
import os
|
|
4
|
+
from odmantic import Model, Field, ObjectId
|
|
5
|
+
from simstack.models.simstack_model import simstack_model
|
|
6
|
+
|
|
7
|
+
@simstack_model
|
|
8
|
+
class Image2DArtifactModel(Model):
|
|
9
|
+
"""Model for storing 2D image artifacts in MongoDB."""
|
|
10
|
+
|
|
11
|
+
parent_id: Optional[ObjectId] = None
|
|
12
|
+
name: str = Field(..., description="Name of the image artifact")
|
|
13
|
+
description: Optional[str] = Field(None, description="Description of the image")
|
|
14
|
+
format: Literal["png", "jpg", "jpeg", "svg", "gif", "bmp", "webp"] = Field(
|
|
15
|
+
..., description="Image format"
|
|
16
|
+
)
|
|
17
|
+
data: bytes = Field(..., description="Binary image data")
|
|
18
|
+
width: Optional[int] = Field(None, description="Image width in pixels")
|
|
19
|
+
height: Optional[int] = Field(None, description="Image height in pixels")
|
|
20
|
+
metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
|
|
21
|
+
|
|
22
|
+
def to_base64(self) -> str:
|
|
23
|
+
"""Convert binary data to base64 string."""
|
|
24
|
+
return base64.b64encode(self.data).decode("utf-8")
|
|
25
|
+
|
|
26
|
+
def get_data_uri(self) -> str:
|
|
27
|
+
"""Get data URI for the image."""
|
|
28
|
+
mime_type = f"image/{self.format}"
|
|
29
|
+
if self.format == "svg":
|
|
30
|
+
mime_type = "image/svg+xml"
|
|
31
|
+
return f"data:{mime_type};base64,{self.to_base64()}"
|
|
32
|
+
|
|
33
|
+
def make_table_entries(
|
|
34
|
+
self,
|
|
35
|
+
max_recursion_level=1,
|
|
36
|
+
drop_id=True,
|
|
37
|
+
current_level=0,
|
|
38
|
+
visited=None,
|
|
39
|
+
field_prefix="",
|
|
40
|
+
):
|
|
41
|
+
return {
|
|
42
|
+
"name": self.name,
|
|
43
|
+
"format": self.format,
|
|
44
|
+
"size": f"{self.width}x{self.height}" if self.width and self.height else "unknown"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
def make_column_defs_instance(
|
|
48
|
+
self,
|
|
49
|
+
table_name=None,
|
|
50
|
+
max_recursion_level=1,
|
|
51
|
+
drop_id=True,
|
|
52
|
+
current_level=0,
|
|
53
|
+
visited=None,
|
|
54
|
+
field_prefix="",
|
|
55
|
+
):
|
|
56
|
+
return [
|
|
57
|
+
{"field": "name", "headerName": "Name"},
|
|
58
|
+
{"field": "format", "headerName": "Format"},
|
|
59
|
+
{"field": "size", "headerName": "Size"},
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
def create_image_artifact(
|
|
63
|
+
name: str,
|
|
64
|
+
data: bytes,
|
|
65
|
+
format: str,
|
|
66
|
+
description: Optional[str] = None,
|
|
67
|
+
parent_id: Optional[ObjectId] = None,
|
|
68
|
+
width: Optional[int] = None,
|
|
69
|
+
height: Optional[int] = None,
|
|
70
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
71
|
+
) -> Image2DArtifactModel:
|
|
72
|
+
"""Create an Image2DArtifactModel instance."""
|
|
73
|
+
return Image2DArtifactModel(
|
|
74
|
+
name=name,
|
|
75
|
+
data=data,
|
|
76
|
+
format=format.lower(),
|
|
77
|
+
description=description,
|
|
78
|
+
parent_id=parent_id,
|
|
79
|
+
width=width,
|
|
80
|
+
height=height,
|
|
81
|
+
metadata=metadata or {},
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def create_image_artifact_from_file(
|
|
85
|
+
path: str,
|
|
86
|
+
name: Optional[str] = None,
|
|
87
|
+
description: Optional[str] = None,
|
|
88
|
+
parent_id: Optional[ObjectId] = None,
|
|
89
|
+
) -> Image2DArtifactModel:
|
|
90
|
+
"""Create an Image2DArtifactModel instance from a file path."""
|
|
91
|
+
if not os.path.exists(path):
|
|
92
|
+
raise FileNotFoundError(f"Image file not found: {path}")
|
|
93
|
+
|
|
94
|
+
filename = os.path.basename(path)
|
|
95
|
+
if name is None:
|
|
96
|
+
name = filename
|
|
97
|
+
|
|
98
|
+
# Extract format from extension
|
|
99
|
+
_, ext = os.path.splitext(filename)
|
|
100
|
+
format = ext.lstrip(".").lower()
|
|
101
|
+
if not format:
|
|
102
|
+
format = "png" # Default
|
|
103
|
+
|
|
104
|
+
with open(path, "rb") as f:
|
|
105
|
+
data = f.read()
|
|
106
|
+
|
|
107
|
+
return create_image_artifact(
|
|
108
|
+
name=name,
|
|
109
|
+
data=data,
|
|
110
|
+
format=format,
|
|
111
|
+
description=description,
|
|
112
|
+
parent_id=parent_id
|
|
113
|
+
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from odmantic import Model, Field
|
|
6
|
+
|
|
7
|
+
from simstack.models import Parameters
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class LogLevel(str, Enum):
|
|
11
|
+
DEBUG = "DEBUG"
|
|
12
|
+
INFO = "INFO"
|
|
13
|
+
WARNING = "WARNING"
|
|
14
|
+
ERROR = "ERROR"
|
|
15
|
+
CRITICAL = "CRITICAL"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class LogEntry(Model):
|
|
19
|
+
timestamp: datetime = Field(default_factory=datetime.utcnow)
|
|
20
|
+
level: LogLevel # Use enum for validation
|
|
21
|
+
logger_name: str
|
|
22
|
+
message: str
|
|
23
|
+
module: str
|
|
24
|
+
function: str
|
|
25
|
+
line: int
|
|
26
|
+
task_id: Optional[str] = None
|
|
27
|
+
resource: Optional[str] = None
|
|
28
|
+
thread_name: Optional[str] = None
|
|
29
|
+
process_name: Optional[str] = None
|
|
30
|
+
exception_type: Optional[str] = None
|
|
31
|
+
exception_message: Optional[str] = None
|
|
32
|
+
exception_traceback: Optional[str] = None
|
|
33
|
+
# extra_data: Dict[str, Any] = Field(default_factory=dict)
|
|
34
|
+
parameters: Optional[Parameters] = None # If Parameters is related to LogEntry
|
|
35
|
+
|
|
36
|
+
# Replace Config class with model_config
|
|
37
|
+
model_config = {"collection": "logs"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import logging
|
|
3
|
+
from typing import List, Optional, TypeVar
|
|
4
|
+
|
|
5
|
+
from odmantic import EmbeddedModel, Field, Model
|
|
6
|
+
|
|
7
|
+
from simstack.models.parameters import Parameters
|
|
8
|
+
from simstack.models.pickle_models import FunctionPickle
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger("Models")
|
|
11
|
+
|
|
12
|
+
T = TypeVar("T")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ModelMapping(Model):
|
|
16
|
+
"""
|
|
17
|
+
name: shorthand - must be unique
|
|
18
|
+
mapping: full name - path relative to project root in module.module.class/function format
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
name: str = Field(unique=True)
|
|
22
|
+
mapping: str = Field(unique=True)
|
|
23
|
+
version: Optional[str] = None
|
|
24
|
+
collection_name: str
|
|
25
|
+
json_schema: Optional[str] = None
|
|
26
|
+
ui_schema: Optional[str] = None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class DataMapping(EmbeddedModel):
|
|
30
|
+
name: str
|
|
31
|
+
mapping: str
|
|
32
|
+
description: Optional[str] = ""
|
|
33
|
+
version: Optional[str] = None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class NodeModel(Model):
|
|
37
|
+
name: str = Field(unique=True)
|
|
38
|
+
function_mapping: str = Field(unique=True)
|
|
39
|
+
version: Optional[str] = None
|
|
40
|
+
input_mappings: List[DataMapping]
|
|
41
|
+
result_mappings: List[DataMapping] = Field(default_factory=list)
|
|
42
|
+
called_nodes: List[str] = Field(default_factory=list)
|
|
43
|
+
description: Optional[str] = ""
|
|
44
|
+
favorite: bool = False
|
|
45
|
+
default_parameters: Parameters
|
|
46
|
+
# Reference to FunctionPickle if available.
|
|
47
|
+
pickle_function: Optional[FunctionPickle] = None
|
|
48
|
+
|
|
49
|
+
model_config = {
|
|
50
|
+
"collection": "node_model",
|
|
51
|
+
"json_encoders": {bytes: lambda b: base64.b64encode(b).decode("ascii")},
|
|
52
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from odmantic import EmbeddedModel, ObjectId, Model
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
class NamedDataReference(EmbeddedModel):
|
|
10
|
+
variable_name: str
|
|
11
|
+
variable_mapping: str
|
|
12
|
+
reference: ObjectId
|
|
13
|
+
|
|
14
|
+
def __repr__(self) -> str:
|
|
15
|
+
return f"NamedDataReference(variable_name='{self.variable_name}', variable_mapping='{self.variable_mapping}', reference='{self.reference}')"
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
def from_variable(cls, variable: Model, variable_name: Optional[str] = None, task_id: Optional[str] = None):
|
|
19
|
+
from simstack.core.context import context
|
|
20
|
+
if not isinstance(variable, Model):
|
|
21
|
+
logger.error(f"task_id: {task_id} Processing Variable {variable} must be an instance of Model")
|
|
22
|
+
raise ValueError(f"Variable must be an instance of Model")
|
|
23
|
+
|
|
24
|
+
variable_class_name = variable.__class__.__name__
|
|
25
|
+
table_name = context.model_mappings.get_by_name(variable_class_name)
|
|
26
|
+
if table_name is None:
|
|
27
|
+
logger.error(f"Could not find table name for {variable_class_name}")
|
|
28
|
+
raise ValueError(f"Could not find table name for {variable_class_name}")
|
|
29
|
+
if variable_name is None:
|
|
30
|
+
# Check if variable already has a field_name we can use
|
|
31
|
+
if hasattr(variable, "field_name") and variable.field_name:
|
|
32
|
+
variable_name = variable.field_name
|
|
33
|
+
else:
|
|
34
|
+
variable_name = "variable"
|
|
35
|
+
|
|
36
|
+
return cls(variable_name=variable_name, variable_mapping=table_name.mapping, reference=variable.id)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Optional, List
|
|
3
|
+
|
|
4
|
+
from odmantic import Model, Field, ObjectId, Reference
|
|
5
|
+
|
|
6
|
+
from simstack.core.definitions import TaskStatus
|
|
7
|
+
from simstack.models.file_list import FileList
|
|
8
|
+
from simstack.models.parameters import Parameters
|
|
9
|
+
from simstack.models.named_data_reference import NamedDataReference
|
|
10
|
+
|
|
11
|
+
class NodeRegistry(Model):
|
|
12
|
+
"""
|
|
13
|
+
Represents a registry for nodes with associated metadata, configurations, and status
|
|
14
|
+
information. It allows tracking the state and attributes of a workflow node, including its
|
|
15
|
+
execution parameters, process status, and relationship to other nodes.
|
|
16
|
+
|
|
17
|
+
This class is designed for managing workflow instances and their lifecycle, with
|
|
18
|
+
capabilities to monitor execution states, inputs, outputs, and associated timestamps.
|
|
19
|
+
|
|
20
|
+
:ivar name: The name of the node.
|
|
21
|
+
:type name: str
|
|
22
|
+
:ivar custom_name: An optional custom name for the node.
|
|
23
|
+
:type custom_name: Optional[str]
|
|
24
|
+
:ivar status: TheTaskStatus of the node in string format.
|
|
25
|
+
:type status: TaskStatus
|
|
26
|
+
:ivar category: An optional category classification for the node.
|
|
27
|
+
:type category: Optional[str]
|
|
28
|
+
:ivar description: An optional description providing details about the node.
|
|
29
|
+
:type description: Optional[str]
|
|
30
|
+
:ivar input_references: List of references to input data.
|
|
31
|
+
:type input_references: List[NamedDataReference]
|
|
32
|
+
:ivar results_references: List of references to result data.
|
|
33
|
+
:type results_references: List[NamedDataReference]
|
|
34
|
+
:ivar parent_ids: A list of identifiers representing parent nodes associated with this node.
|
|
35
|
+
:type parent_ids: List[ObjectId]
|
|
36
|
+
:ivar created_at: The timestamp when the node was created.
|
|
37
|
+
:type created_at: datetime
|
|
38
|
+
:ivar started_at: An optional timestamp indicating when the execution of the node started.
|
|
39
|
+
:type started_at: Optional[datetime]
|
|
40
|
+
:ivar completed_at: An optional timestamp indicating when the execution of the node was
|
|
41
|
+
completed.
|
|
42
|
+
:type completed_at: Optional[datetime]
|
|
43
|
+
:ivar function_hash: A hash value representing the unique function executed by this node.
|
|
44
|
+
:type function_hash: str
|
|
45
|
+
:ivar arg_hash: A hash value representing the unique arguments passed to the function of
|
|
46
|
+
this node.
|
|
47
|
+
:type arg_hash: str
|
|
48
|
+
:ivar func_mapping: A mapping identifier associated with the function executed by this
|
|
49
|
+
node.
|
|
50
|
+
:type func_mapping: str
|
|
51
|
+
:ivar is_async: A boolean value indicating whether the node execution is asynchronous.
|
|
52
|
+
:type is_async: bool
|
|
53
|
+
:ivar parameters: Parameters associated with the node execution.
|
|
54
|
+
:type parameters: Parameters
|
|
55
|
+
:ivar call_path: An optional path indicating where the function is called from by concatenating the name of all nodes in the call stack.
|
|
56
|
+
:type call_path: Optional[str]
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
name: str
|
|
60
|
+
status: TaskStatus
|
|
61
|
+
custom_name: Optional[str] = None
|
|
62
|
+
version: Optional[str] = None
|
|
63
|
+
# Keep this as Optional[ObjectId] instead of Reference(Project):
|
|
64
|
+
# in the ODMantic version used here, nullable references are not supported
|
|
65
|
+
# as Optional[Project] + Reference() field definitions.
|
|
66
|
+
project: Optional[ObjectId] = Field(default=None)
|
|
67
|
+
category: Optional[str] = None
|
|
68
|
+
description: Optional[str] = None
|
|
69
|
+
call_path: Optional[str] = None
|
|
70
|
+
assignment_rule_id: Optional[str] = None
|
|
71
|
+
assignment_rule_name: Optional[str] = None
|
|
72
|
+
assignment_pattern: Optional[str] = None
|
|
73
|
+
error: Optional[str] = None
|
|
74
|
+
message: Optional[str] = None
|
|
75
|
+
|
|
76
|
+
input_references: List[NamedDataReference] = Field(default_factory=list)
|
|
77
|
+
results_references: List[NamedDataReference] = Field(default_factory=list)
|
|
78
|
+
|
|
79
|
+
info_files: FileList = Field(default_factory=FileList)
|
|
80
|
+
|
|
81
|
+
parent_ids: List[ObjectId] = Field(default_factory=list)
|
|
82
|
+
artifact_ids: List[ObjectId] = Field(default_factory=list)
|
|
83
|
+
created_at: datetime = Field(default_factory=datetime.now)
|
|
84
|
+
started_at: Optional[datetime] = Field(default=None)
|
|
85
|
+
completed_at: Optional[datetime] = Field(default=None)
|
|
86
|
+
job_id: Optional[str] = None
|
|
87
|
+
function_hash: str
|
|
88
|
+
arg_hash: str
|
|
89
|
+
func_mapping: str
|
|
90
|
+
is_async: bool = False
|
|
91
|
+
parameters: Parameters = Reference()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
async def find_child_nodes(task_id: str) -> List[NodeRegistry]:
|
|
95
|
+
from simstack.core.context import context
|
|
96
|
+
return await context.db.find(NodeRegistry, {"parent_ids": {"$in": [task_id]}})
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import json
|
|
3
|
+
import io
|
|
4
|
+
from pprint import pprint
|
|
5
|
+
from typing import Any, Dict, Optional
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
from odmantic import Model
|
|
10
|
+
|
|
11
|
+
from simstack.core.context import context
|
|
12
|
+
from simstack.models import simstack_model
|
|
13
|
+
from simstack.models.files import FileStack
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _format_df_for_console(df: pd.DataFrame, precision: int = 2, max_rows: int = 60, max_cols: int = 30) -> str:
|
|
17
|
+
"""
|
|
18
|
+
Console-safe DataFrame formatting (no optional deps like jinja2 required).
|
|
19
|
+
"""
|
|
20
|
+
if df is None or df.empty:
|
|
21
|
+
return "Empty DataFrame"
|
|
22
|
+
|
|
23
|
+
df_out = df.copy()
|
|
24
|
+
|
|
25
|
+
# Round only numeric columns to avoid touching strings/datetimes
|
|
26
|
+
numeric_cols = df_out.select_dtypes(include=["number"]).columns
|
|
27
|
+
if len(numeric_cols) > 0:
|
|
28
|
+
df_out[numeric_cols] = df_out[numeric_cols].round(precision)
|
|
29
|
+
|
|
30
|
+
with pd.option_context(
|
|
31
|
+
"display.max_rows", max_rows,
|
|
32
|
+
"display.max_columns", max_cols,
|
|
33
|
+
"display.width", 0, # auto-detect width
|
|
34
|
+
"display.max_colwidth", 200,
|
|
35
|
+
):
|
|
36
|
+
return df_out.to_string(index=False)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _format_datetime_columns(df):
|
|
40
|
+
"""
|
|
41
|
+
Format all datetime columns to match the expected format: YYYY-MM-DDThh:mm:ss
|
|
42
|
+
Returns a copy of the dataframe with formatted datetime columns.
|
|
43
|
+
"""
|
|
44
|
+
df_copy = df.copy()
|
|
45
|
+
# Format datetime columns to match expected format without microseconds and Z
|
|
46
|
+
for col in df_copy.select_dtypes(include=["datetime64"]):
|
|
47
|
+
df_copy[col] = df_copy[col].dt.strftime("%Y-%m-%dT%H:%M:%S")
|
|
48
|
+
return df_copy
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@simstack_model
|
|
52
|
+
class PandasModel(Model):
|
|
53
|
+
model_config = {"indexes": [("field_name", {"unique": True})]}
|
|
54
|
+
|
|
55
|
+
field_name: str = "pandas_model"
|
|
56
|
+
content_: bytes = b""
|
|
57
|
+
file_stack: Optional[FileStack] = None
|
|
58
|
+
|
|
59
|
+
@classmethod
|
|
60
|
+
def from_data_frame(cls, df):
|
|
61
|
+
new_instance = cls()
|
|
62
|
+
new_instance.table = df
|
|
63
|
+
return new_instance
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def table(self):
|
|
67
|
+
if not self.content_:
|
|
68
|
+
return pd.DataFrame()
|
|
69
|
+
|
|
70
|
+
# Create a BytesIO object from the binary content
|
|
71
|
+
buffer = io.BytesIO(self.content_)
|
|
72
|
+
|
|
73
|
+
# Use pandas read_pickle to decompress and load the DataFrame
|
|
74
|
+
return pd.read_pickle(buffer)
|
|
75
|
+
|
|
76
|
+
@table.setter
|
|
77
|
+
def table(self, df):
|
|
78
|
+
if not isinstance(df, pd.DataFrame):
|
|
79
|
+
raise TypeError("Expected a pandas DataFrame")
|
|
80
|
+
|
|
81
|
+
# Create a BytesIO object to store the binary content
|
|
82
|
+
buffer = io.BytesIO()
|
|
83
|
+
|
|
84
|
+
# Serialize the DataFrame to the buffer
|
|
85
|
+
df.to_pickle(buffer)
|
|
86
|
+
|
|
87
|
+
# Get the binary content from the buffer
|
|
88
|
+
self.content_ = buffer.getvalue()
|
|
89
|
+
|
|
90
|
+
def to_react_json(self, orient="records"):
|
|
91
|
+
"""
|
|
92
|
+
Convert the DataFrame to a JSON string suitable for React visualization libraries.
|
|
93
|
+
|
|
94
|
+
Parameters:
|
|
95
|
+
- orient: Determines the JSON string layout:
|
|
96
|
+
'records' - list like [{column -> value}, ... , {column -> value}] (default)
|
|
97
|
+
'columns' - {column -> [values, ...]}
|
|
98
|
+
'index' - {column -> value}}
|
|
99
|
+
'split' - {index -> [index], columns -> [columns], data -> [values]}
|
|
100
|
+
'table' - {'schema': {schema}, 'data': {data}}
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
- String: JSON formatted string ready for React
|
|
104
|
+
"""
|
|
105
|
+
df = self.table
|
|
106
|
+
if df.empty:
|
|
107
|
+
return json.dumps([])
|
|
108
|
+
|
|
109
|
+
# Format datetime columns
|
|
110
|
+
df = _format_datetime_columns(df)
|
|
111
|
+
|
|
112
|
+
# Create a custom serializer to handle NumPy types properly
|
|
113
|
+
class NumpyEncoder(json.JSONEncoder):
|
|
114
|
+
def default(self, obj):
|
|
115
|
+
if isinstance(obj, np.integer):
|
|
116
|
+
return int(obj) # Keep integers as integers
|
|
117
|
+
elif isinstance(obj, np.floating):
|
|
118
|
+
return float(obj) # Convert numpy float to Python float
|
|
119
|
+
elif isinstance(obj, np.ndarray):
|
|
120
|
+
return obj.tolist() # Convert arrays to lists
|
|
121
|
+
elif pd.isna(obj):
|
|
122
|
+
return None # Convert NaN/NaT to None
|
|
123
|
+
return super().default(obj)
|
|
124
|
+
|
|
125
|
+
# Convert DataFrame to dictionary while preserving data types
|
|
126
|
+
if orient == "records":
|
|
127
|
+
data = df.to_dict(orient="records")
|
|
128
|
+
else:
|
|
129
|
+
data = df.to_dict(orient=orient)
|
|
130
|
+
|
|
131
|
+
# Use custom JSON encoder to handle NumPy types properly
|
|
132
|
+
return json.dumps(data, cls=NumpyEncoder)
|
|
133
|
+
|
|
134
|
+
def to_react_data(self, orient="records"):
|
|
135
|
+
"""
|
|
136
|
+
Convert the DataFrame to a Python object suitable for conversion to JSON.
|
|
137
|
+
This can be used in API responses.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
- List/Dict: Python object ready for json.dumps()
|
|
141
|
+
"""
|
|
142
|
+
df = self.table
|
|
143
|
+
if df.empty:
|
|
144
|
+
return []
|
|
145
|
+
|
|
146
|
+
# Format datetime columns using the same helper method
|
|
147
|
+
df = _format_datetime_columns(df)
|
|
148
|
+
|
|
149
|
+
# Convert DataFrame to dictionary while preserving data types
|
|
150
|
+
if orient == "records":
|
|
151
|
+
data = df.to_dict(orient="records")
|
|
152
|
+
else:
|
|
153
|
+
data = df.to_dict(orient=orient)
|
|
154
|
+
|
|
155
|
+
# Replace NaN values with None
|
|
156
|
+
if isinstance(data, list):
|
|
157
|
+
for item in data:
|
|
158
|
+
for key, value in item.items():
|
|
159
|
+
if pd.isna(value):
|
|
160
|
+
item[key] = None
|
|
161
|
+
elif isinstance(data, dict):
|
|
162
|
+
for key, values in data.items():
|
|
163
|
+
if isinstance(values, dict):
|
|
164
|
+
for sub_key, value in values.items():
|
|
165
|
+
if pd.isna(value):
|
|
166
|
+
values[sub_key] = None
|
|
167
|
+
elif isinstance(values, list):
|
|
168
|
+
data[key] = [None if pd.isna(v) else v for v in values]
|
|
169
|
+
|
|
170
|
+
return data
|
|
171
|
+
|
|
172
|
+
async def custom_model_dump(self, **kwargs) -> Dict[str, Any]:
|
|
173
|
+
dumped_data = self.to_react_data("dict")
|
|
174
|
+
# del dumped_data["content"] # Exclude content from the dumped data
|
|
175
|
+
return dumped_data
|
|
176
|
+
|
|
177
|
+
def __repr__(self):
|
|
178
|
+
if not self.content_:
|
|
179
|
+
return "PandasModel(empty table)"
|
|
180
|
+
|
|
181
|
+
df = self.table
|
|
182
|
+
rows, cols = df.shape
|
|
183
|
+
return f"PandasModel({rows} rows × {cols} columns)"
|
|
184
|
+
|
|
185
|
+
def __str__(self):
|
|
186
|
+
if not self.content_:
|
|
187
|
+
return "Empty pandas table"
|
|
188
|
+
|
|
189
|
+
df = self.table
|
|
190
|
+
if len(df) > 5:
|
|
191
|
+
return f"PandasModel with shape {df.shape}:\n{df.head(5).to_string()}\n..."
|
|
192
|
+
return f"PandasModel with shape {df.shape}:\n{df.to_string()}"
|
|
193
|
+
|
|
194
|
+
#TODO move to test
|
|
195
|
+
async def main():
|
|
196
|
+
await context.initialize()
|
|
197
|
+
# Create the data structure
|
|
198
|
+
data = []
|
|
199
|
+
|
|
200
|
+
# Iteration names
|
|
201
|
+
iterations = ["iter1", "iter2", "iter3"]
|
|
202
|
+
|
|
203
|
+
# For each iteration
|
|
204
|
+
for index, iteration in enumerate(iterations):
|
|
205
|
+
# Generate 4 x values (for example, increasing by 0.5)
|
|
206
|
+
x_values = np.arange(1, 3, 0.5) # Creates [1.0, 1.5, 2.0, 2.5]
|
|
207
|
+
|
|
208
|
+
# Generate 2 sets of 4 y values for each iteration
|
|
209
|
+
y_values_set1 = np.sin((index + 1) * x_values) # 4 random values around mean=8
|
|
210
|
+
y_values_set2 = np.sin((index + 1) * x_values)
|
|
211
|
+
# Add the data for this iteration
|
|
212
|
+
for i, x in enumerate(x_values):
|
|
213
|
+
data.append(
|
|
214
|
+
{
|
|
215
|
+
"iteration": iteration,
|
|
216
|
+
"x": x,
|
|
217
|
+
"y_set1": y_values_set1[i],
|
|
218
|
+
"y_set2": y_values_set2[i],
|
|
219
|
+
}
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# Create the DataFrame
|
|
223
|
+
df = pd.DataFrame(data)
|
|
224
|
+
# Replace Styler usage (requires jinja2) with console-safe formatting.
|
|
225
|
+
print(_format_df_for_console(df, precision=2))
|
|
226
|
+
|
|
227
|
+
model = PandasModel.from_data_frame(df)
|
|
228
|
+
|
|
229
|
+
pprint(await model.custom_model_dump())
|
|
230
|
+
saved_model = await context.db.save(model)
|
|
231
|
+
|
|
232
|
+
retrieved_model = await context.db.find_one(
|
|
233
|
+
PandasModel, PandasModel.id == saved_model.id
|
|
234
|
+
)
|
|
235
|
+
print("Retrieved Model", retrieved_model)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
if __name__ == "__main__":
|
|
239
|
+
asyncio.run(main())
|