metafold 0.13.1.dev0__tar.gz → 0.13.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. {metafold-0.13.1.dev0 → metafold-0.13.2}/PKG-INFO +1 -1
  2. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/simulation/compression_simulation.py +45 -24
  3. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/simulation/run_experiment.py +11 -0
  4. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold.egg-info/PKG-INFO +1 -1
  5. {metafold-0.13.1.dev0 → metafold-0.13.2}/pyproject.toml +1 -1
  6. {metafold-0.13.1.dev0 → metafold-0.13.2}/LICENSE +0 -0
  7. {metafold-0.13.1.dev0 → metafold-0.13.2}/README.md +0 -0
  8. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/__init__.py +0 -0
  9. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/api.py +0 -0
  10. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/assets.py +0 -0
  11. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/auth.py +0 -0
  12. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/client.py +0 -0
  13. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/exceptions.py +0 -0
  14. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/jobs.py +0 -0
  15. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/materials.py +0 -0
  16. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/projects.py +0 -0
  17. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/simulation/__init__.py +0 -0
  18. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/simulation/compression_experiment.py +0 -0
  19. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/utils.py +0 -0
  20. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold/workflows.py +0 -0
  21. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold.egg-info/SOURCES.txt +0 -0
  22. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold.egg-info/dependency_links.txt +0 -0
  23. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold.egg-info/requires.txt +0 -0
  24. {metafold-0.13.1.dev0 → metafold-0.13.2}/metafold.egg-info/top_level.txt +0 -0
  25. {metafold-0.13.1.dev0 → metafold-0.13.2}/setup.cfg +0 -0
  26. {metafold-0.13.1.dev0 → metafold-0.13.2}/tests/test_assets.py +0 -0
  27. {metafold-0.13.1.dev0 → metafold-0.13.2}/tests/test_compession_experiment.py +0 -0
  28. {metafold-0.13.1.dev0 → metafold-0.13.2}/tests/test_compression_simulation.py +0 -0
  29. {metafold-0.13.1.dev0 → metafold-0.13.2}/tests/test_jobs.py +0 -0
  30. {metafold-0.13.1.dev0 → metafold-0.13.2}/tests/test_materials.py +0 -0
  31. {metafold-0.13.1.dev0 → metafold-0.13.2}/tests/test_projects.py +0 -0
  32. {metafold-0.13.1.dev0 → metafold-0.13.2}/tests/test_run_experiment.py +0 -0
  33. {metafold-0.13.1.dev0 → metafold-0.13.2}/tests/test_shear_simulation.py +0 -0
  34. {metafold-0.13.1.dev0 → metafold-0.13.2}/tests/test_utils.py +0 -0
  35. {metafold-0.13.1.dev0 → metafold-0.13.2}/tests/test_workflows.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metafold
3
- Version: 0.13.1.dev0
3
+ Version: 0.13.2
4
4
  Summary: Metafold SDK for Python
5
5
  Author-email: Metafold 3D <info@metafold3d.com>
6
6
  License: Copyright 2024 Metafold 3D
@@ -299,6 +299,39 @@ class ExperimentSupportParallelepiped(ExperimentParallelepiped, ExperimentSuppor
299
299
  material: Material = field(default_factory=lambda: DEFAULT_SUPPORT_MATERIAL)
300
300
 
301
301
 
302
+ def validate_simulation_parts(parts: list) -> None:
303
+ """Raise ValueError if the parts can't produce a compression simulation.
304
+
305
+ Callers that dispatch work asynchronously should call this up front so
306
+ invalid input fails before any project or job is created.
307
+ """
308
+ if not parts:
309
+ return
310
+
311
+ has_piston = False
312
+ has_support = False
313
+ piston_moves = False
314
+ for p in parts:
315
+ if isinstance(p, ExperimentPistonBase):
316
+ has_piston = True
317
+ piston_moves = piston_moves or _has_motion(p.velocity)
318
+ elif isinstance(p, ExperimentSupportBase):
319
+ has_support = True
320
+
321
+ if not has_piston and not has_support:
322
+ raise ValueError(
323
+ "No piston part: a compression simulation needs "
324
+ "a rigid part to apply load. Add a part of type piston_mesh, "
325
+ "piston_cylinder, or piston_box."
326
+ )
327
+ # Supports are stationary by design, so only pistons must move.
328
+ if has_piston and not piston_moves:
329
+ raise ValueError(
330
+ "Piston velocity is zero. Set a velocity "
331
+ "profile of [time, vx, vy, vz] rows with a non-zero component."
332
+ )
333
+
334
+
302
335
  @dataclass
303
336
  class ReferenceData:
304
337
  csv_path: Path = Path("")
@@ -491,28 +524,7 @@ class CompressionSimulation:
491
524
  self.part_infos.append(inner_part)
492
525
 
493
526
  # A rigid part drives the compression.
494
- if parts:
495
- has_piston = False
496
- has_support = False
497
- piston_moves = False
498
- for p in parts:
499
- if isinstance(p, ExperimentPistonBase):
500
- has_piston = True
501
- piston_moves = piston_moves or _has_motion(p.velocity)
502
- elif isinstance(p, ExperimentSupportBase):
503
- has_support = True
504
- if not has_piston and not has_support:
505
- raise ValueError(
506
- "No piston part: a compression simulation needs "
507
- "a rigid part to apply load. Add a part of type piston_mesh, "
508
- "piston_cylinder, or piston_box."
509
- )
510
- # Supports are stationary by design, so only pistons must move.
511
- if has_piston and not piston_moves:
512
- raise ValueError(
513
- "Piston velocity is zero. Set a velocity "
514
- "profile of [time, vx, vy, vz] rows with a non-zero component."
515
- )
527
+ validate_simulation_parts(parts)
516
528
 
517
529
  self.setup_ply_files(stl_folder_path)
518
530
  self.setup_results(output_path)
@@ -644,6 +656,7 @@ class CompressionSimulation:
644
656
  base_url: str = "https://api.metafold3d.com/",
645
657
  cancel_existing_workflows: bool = True,
646
658
  project_access: Access = Access.PRIVATE,
659
+ user: Optional[str] = None,
647
660
  ) -> str:
648
661
  """Find an existing project by name or create a new one.
649
662
 
@@ -651,6 +664,10 @@ class CompressionSimulation:
651
664
  client_id + client_secret (local/programmable use, reads from env via
652
665
  setup_client). base_url must match the audience the token was issued for.
653
666
 
667
+ When user is given, only the caller's own projects are reused; a
668
+ same-named project owned by someone else (visible under org access) is
669
+ ignored so it can't be overwritten.
670
+
654
671
  When cancel_existing_workflows is True and an existing project is
655
672
  reused, its running workflows are cancelled first.
656
673
 
@@ -663,10 +680,14 @@ class CompressionSimulation:
663
680
  auth_domain=auth_domain,
664
681
  base_url=base_url,
665
682
  )
666
- # Quote the project_name string for multi-word name searchess
683
+ # Quote the values so multi-word names stay a single search term.
684
+ q = f'name:"{project_name}"'
685
+ if user is not None:
686
+ q = f'{q} AND user:"{user}"'
667
687
  existing = [
668
- p for p in client.projects.list(q=f'name:"{project_name}"')
688
+ p for p in client.projects.list(q=q)
669
689
  if p.name == project_name # ensure full match
690
+ and (user is None or p.user == user)
670
691
  ]
671
692
  if existing:
672
693
  project_id = existing[0].id
@@ -160,6 +160,7 @@ from metafold.simulation.compression_simulation import (
160
160
  ExperimentPistonMesh,
161
161
  SimulationParameters,
162
162
  WorkflowStep,
163
+ validate_simulation_parts,
163
164
  )
164
165
 
165
166
  # Build preset lookup from all Material constants in the materials module.
@@ -243,6 +244,16 @@ def _build_parts(parts_config: list[dict]) -> list[ExperimentPart]:
243
244
  return parts
244
245
 
245
246
 
247
+ def validate_experiment_config(config: dict) -> None:
248
+ """Raise ValueError if a manifest can't produce a runnable experiment.
249
+ Mirrors the checks run_experiment performs so an API can reject bad
250
+ input before creating a project.
251
+ """
252
+ if not config.get("project_name", ""):
253
+ raise ValueError("project_name is required")
254
+ validate_simulation_parts(_build_parts(config.get("parts", [])))
255
+
256
+
246
257
  def _build_varying(varying_config: list[dict]) -> list[ExperimentVarying]:
247
258
  varying: list[ExperimentVarying] = []
248
259
  for entry in varying_config:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metafold
3
- Version: 0.13.1.dev0
3
+ Version: 0.13.2
4
4
  Summary: Metafold SDK for Python
5
5
  Author-email: Metafold 3D <info@metafold3d.com>
6
6
  License: Copyright 2024 Metafold 3D
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "metafold"
7
- version = "0.13.1.dev0"
7
+ version = "0.13.2"
8
8
  authors = [
9
9
  {name = "Metafold 3D", email = "info@metafold3d.com"},
10
10
  ]
File without changes
File without changes
File without changes