PyOpenMagnetics 1.1.3__tar.gz → 1.1.4__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 (60) hide show
  1. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/PKG-INFO +7 -6
  2. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/PyOpenMagnetics.pyi +35 -4
  3. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/README.md +6 -5
  4. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/examples/README.md +7 -6
  5. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/examples/buck_inductor.py +9 -6
  6. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/examples/flyback_design.py +22 -7
  7. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/llms.txt +12 -7
  8. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/notebooks/02_buck_inductor.ipynb +25 -10
  9. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/pyproject.toml +5 -3
  10. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_magnetic_adviser.py +29 -15
  11. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/.github/workflows/ci.yml +0 -0
  12. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/.github/workflows/publish.yml +0 -0
  13. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/.gitignore +0 -0
  14. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/CMakeLists.txt +0 -0
  15. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/LICENSE +0 -0
  16. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/api/MAS.py +0 -0
  17. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/api/mas_db_reader.py +0 -0
  18. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/api/validation.py +0 -0
  19. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/docs/compatibility.md +0 -0
  20. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/docs/errors.md +0 -0
  21. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/docs/performance.md +0 -0
  22. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/notebooks/01_getting_started.ipynb +0 -0
  23. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/notebooks/03_core_losses.ipynb +0 -0
  24. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/notebooks/README.md +0 -0
  25. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/requirements.txt +0 -0
  26. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/advisers.cpp +0 -0
  27. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/advisers.h +0 -0
  28. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/bobbin.cpp +0 -0
  29. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/bobbin.h +0 -0
  30. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/common.h +0 -0
  31. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/core.cpp +0 -0
  32. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/core.h +0 -0
  33. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/database.cpp +0 -0
  34. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/database.h +0 -0
  35. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/logging.cpp +0 -0
  36. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/logging.h +0 -0
  37. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/losses.cpp +0 -0
  38. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/losses.h +0 -0
  39. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/module.cpp +0 -0
  40. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/plotting.cpp +0 -0
  41. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/plotting.h +0 -0
  42. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/settings.cpp +0 -0
  43. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/settings.h +0 -0
  44. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/simulation.cpp +0 -0
  45. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/simulation.h +0 -0
  46. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/utils.cpp +0 -0
  47. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/utils.h +0 -0
  48. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/winding.cpp +0 -0
  49. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/winding.h +0 -0
  50. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/wire.cpp +0 -0
  51. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/src/wire.h +0 -0
  52. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/test.py +0 -0
  53. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/__init__.py +0 -0
  54. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/conftest.py +0 -0
  55. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_core.py +0 -0
  56. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_core_adviser.py +0 -0
  57. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_examples_integration.py +0 -0
  58. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_inputs.py +0 -0
  59. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_logging.py +0 -0
  60. {pyopenmagnetics-1.1.3 → pyopenmagnetics-1.1.4}/tests/test_winding.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: PyOpenMagnetics
3
- Version: 1.1.3
3
+ Version: 1.1.4
4
4
  Summary: Python wrapper for OpenMagnetics
5
5
  Author-Email: Alfonso Martinez <Alfonso_VII@hotmail.com>
6
6
  Classifier: Development Status :: 4 - Beta
@@ -121,12 +121,13 @@ processed_inputs = PyOpenMagnetics.process_inputs(inputs)
121
121
 
122
122
  # Get magnetic recommendations
123
123
  # core_mode: "available cores" (stock cores) or "standard cores" (all standard shapes)
124
- magnetics = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "standard cores")
124
+ result = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "standard cores")
125
125
 
126
- for i, mag in enumerate(magnetics):
127
- if "magnetic" in mag:
128
- core = mag["magnetic"]["core"]["functionalDescription"]
129
- print(f"{i+1}. {core['shape']['name']} - {core['material']['name']}")
126
+ # Result format: {"data": [{"mas": {...}, "scoring": float, "scoringPerFilter": {...}}, ...]}
127
+ for i, item in enumerate(result["data"]):
128
+ mag = item["mas"]["magnetic"]
129
+ core = mag["core"]["functionalDescription"]
130
+ print(f"{i+1}. {core['shape']['name']} - {core['material']['name']} (score: {item['scoring']:.3f})")
130
131
  ```
131
132
 
132
133
  ### Calculate Core Losses
@@ -505,6 +505,13 @@ def calculate_advised_cores(
505
505
  weights: {"EFFICIENCY": 1.0, "DIMENSIONS": 0.5, "COST": 0.3}.
506
506
  max_results: Maximum number of recommendations.
507
507
  core_mode: "STANDARD_CORES" or "AVAILABLE_CORES" (stock only).
508
+
509
+ Returns:
510
+ JSON object with "data" array containing ranked results.
511
+ Each result has:
512
+ - "mas": Mas object with magnetic, inputs, and optionally outputs
513
+ - "scoring": Overall float score
514
+ - "scoringPerFilter": Object with individual scores per filter
508
515
  """
509
516
  ...
510
517
 
@@ -512,11 +519,27 @@ def calculate_advised_magnetics(
512
519
  inputs: Inputs,
513
520
  max_results: int = 5,
514
521
  core_mode: str = "STANDARD_CORES"
515
- ) -> List[Mas]:
522
+ ) -> JsonDict:
516
523
  """Get complete magnetic designs (core + winding).
517
524
 
525
+ Args:
526
+ inputs: Processed inputs (from process_inputs).
527
+ max_results: Maximum number of recommendations.
528
+ core_mode: "STANDARD_CORES" or "AVAILABLE_CORES" (stock only).
529
+
518
530
  Returns:
519
- List of Mas objects with magnetic and outputs populated.
531
+ JSON object with "data" array containing ranked results.
532
+ Each result has:
533
+ - "mas": Mas object with magnetic, inputs, and optionally outputs
534
+ - "scoring": Overall float score
535
+ - "scoringPerFilter": Object with individual scores per filter
536
+ (e.g., {"COST": 0.8, "LOSSES": 0.9, "DIMENSIONS": 0.7})
537
+
538
+ Example:
539
+ >>> result = PyOpenMagnetics.calculate_advised_magnetics(inputs, 5, "STANDARD_CORES")
540
+ >>> for item in result["data"]:
541
+ ... mag = item["mas"]["magnetic"]
542
+ ... print(f"Score: {item['scoring']}, Core: {mag['core']['functionalDescription']['shape']['name']}")
520
543
  """
521
544
  ...
522
545
 
@@ -524,8 +547,16 @@ def calculate_advised_magnetics_from_catalog(
524
547
  inputs: Inputs,
525
548
  catalog: List[Magnetic],
526
549
  max_results: int = 5
527
- ) -> List[Mas]:
528
- """Get designs from custom catalog of magnetics."""
550
+ ) -> JsonDict:
551
+ """Get designs from custom catalog of magnetics.
552
+
553
+ Returns:
554
+ JSON object with "data" array containing ranked results.
555
+ Each result has:
556
+ - "mas": Mas object with magnetic data
557
+ - "scoring": Overall float score
558
+ - "scoringPerFilter": Object with individual scores per filter
559
+ """
529
560
  ...
530
561
 
531
562
  # =============================================================================
@@ -104,12 +104,13 @@ processed_inputs = PyOpenMagnetics.process_inputs(inputs)
104
104
 
105
105
  # Get magnetic recommendations
106
106
  # core_mode: "available cores" (stock cores) or "standard cores" (all standard shapes)
107
- magnetics = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "standard cores")
107
+ result = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "standard cores")
108
108
 
109
- for i, mag in enumerate(magnetics):
110
- if "magnetic" in mag:
111
- core = mag["magnetic"]["core"]["functionalDescription"]
112
- print(f"{i+1}. {core['shape']['name']} - {core['material']['name']}")
109
+ # Result format: {"data": [{"mas": {...}, "scoring": float, "scoringPerFilter": {...}}, ...]}
110
+ for i, item in enumerate(result["data"]):
111
+ mag = item["mas"]["magnetic"]
112
+ core = mag["core"]["functionalDescription"]
113
+ print(f"{i+1}. {core['shape']['name']} - {core['material']['name']} (score: {item['scoring']:.3f})")
113
114
  ```
114
115
 
115
116
  ### Calculate Core Losses
@@ -60,17 +60,18 @@ inputs = {
60
60
  processed = PyOpenMagnetics.process_inputs(inputs)
61
61
 
62
62
  # 3. Get recommendations
63
- magnetics = PyOpenMagnetics.calculate_advised_magnetics(processed, 5, "STANDARD_CORES")
63
+ result = PyOpenMagnetics.calculate_advised_magnetics(processed, 5, "STANDARD_CORES")
64
64
 
65
- # 4. Analyze results
66
- for mag in magnetics:
65
+ # 4. Analyze results - result["data"] contains list of {mas, scoring, scoringPerFilter}
66
+ for item in result["data"]:
67
+ mag = item["mas"]["magnetic"]
67
68
  losses = PyOpenMagnetics.calculate_core_losses(
68
- mag["magnetic"]["core"],
69
- mag["magnetic"]["coil"],
69
+ mag["core"],
70
+ mag["coil"],
70
71
  processed,
71
72
  {"coreLosses": "IGSE", "reluctance": "ZHANG"}
72
73
  )
73
- print(f"Core losses: {losses['coreLosses']:.3f} W")
74
+ print(f"Core losses: {losses['coreLosses']:.3f} W, Score: {item['scoring']:.3f}")
74
75
  ```
75
76
 
76
77
  ## Additional Resources
@@ -104,12 +104,13 @@ def design_buck_inductor():
104
104
  "COST": 0.3
105
105
  }
106
106
 
107
- magnetics = PyOpenMagnetics.calculate_advised_magnetics(
108
- processed,
109
- max_results=5,
110
- core_mode="STANDARD_CORES"
107
+ result = PyOpenMagnetics.calculate_advised_magnetics(
108
+ processed, 5, "STANDARD_CORES"
111
109
  )
112
110
 
111
+ # Extract magnetics list from result (v1.1.2+ format: {"data": [...]})
112
+ magnetics = result["data"] if isinstance(result, dict) and "data" in result else result
113
+
113
114
  print(f" Found {len(magnetics)} suitable designs")
114
115
 
115
116
  # Analyze designs
@@ -121,8 +122,10 @@ def design_buck_inductor():
121
122
  "reluctance": "ZHANG"
122
123
  }
123
124
 
124
- for i, mas in enumerate(magnetics[:3]):
125
- if "magnetic" not in mas:
125
+ for i, item in enumerate(magnetics[:3]):
126
+ # In v1.1.2+, each item has "mas" containing the magnetic data
127
+ mas = item.get("mas", item) if isinstance(item, dict) else item
128
+ if not isinstance(mas, dict) or "magnetic" not in mas:
126
129
  continue
127
130
 
128
131
  magnetic = mas["magnetic"]
@@ -107,12 +107,18 @@ def design_flyback_transformer():
107
107
  "COST": 0.3 # Tertiary: low cost
108
108
  }
109
109
 
110
- magnetics = PyOpenMagnetics.calculate_advised_magnetics(
111
- processed_inputs,
112
- max_results=3,
113
- core_mode="STANDARD_CORES"
110
+ result = PyOpenMagnetics.calculate_advised_magnetics(
111
+ processed_inputs, 3, "STANDARD_CORES"
114
112
  )
115
113
 
114
+ # Extract magnetics list from result (v1.1.2+ format: {"data": [...]})
115
+ # Note: If there's an error, data will be a string containing the exception message
116
+ data = result.get("data", result) if isinstance(result, dict) else result
117
+ if isinstance(data, str):
118
+ print(f" ✗ Error: {data}")
119
+ return None
120
+ magnetics = data
121
+
116
122
  print(f" ✓ Found {len(magnetics)} suitable designs")
117
123
 
118
124
  # Step 4: Analyze top recommendations
@@ -125,8 +131,10 @@ def design_flyback_transformer():
125
131
  "coreTemperature": "MANIKTALA"
126
132
  }
127
133
 
128
- for i, mas in enumerate(magnetics):
129
- if "magnetic" not in mas:
134
+ for i, item in enumerate(magnetics):
135
+ # In v1.1.2+, each item has "mas" containing the magnetic data
136
+ mas = item.get("mas", item) if isinstance(item, dict) else item
137
+ if not isinstance(mas, dict) or "magnetic" not in mas:
130
138
  continue
131
139
 
132
140
  magnetic = mas["magnetic"]
@@ -154,6 +162,9 @@ def design_flyback_transformer():
154
162
  total_loss = core_loss + winding_loss
155
163
 
156
164
  print(f"\nDesign #{i+1}: {shape_name} / {material_name}")
165
+ # Show scoring if available (v1.1.2+)
166
+ if 'scoring' in item:
167
+ print(f" Score: {item['scoring']:.3f}")
157
168
  print(f" Core losses: {core_loss:.3f} W")
158
169
  print(f" Winding losses: {winding_loss:.3f} W")
159
170
  print(f" Total losses: {total_loss:.3f} W")
@@ -167,7 +178,11 @@ def design_flyback_transformer():
167
178
  print("\n" + "=" * 60)
168
179
  print("Design complete! Best design is #1")
169
180
 
170
- return magnetics[0] if magnetics else None
181
+ # Return the first item's mas for backward compatibility
182
+ if magnetics:
183
+ first_item = magnetics[0]
184
+ return first_item.get("mas", first_item) if isinstance(first_item, dict) else first_item
185
+ return None
171
186
 
172
187
 
173
188
  def explore_core_database():
@@ -368,21 +368,25 @@ cores = PyOpenMagnetics.calculate_advised_cores(
368
368
  )
369
369
 
370
370
  # Get complete magnetic designs
371
- magnetics = PyOpenMagnetics.calculate_advised_magnetics(
371
+ result = PyOpenMagnetics.calculate_advised_magnetics(
372
372
  processed,
373
373
  max_results=5,
374
374
  core_mode="STANDARD_CORES"
375
375
  )
376
376
 
377
- # Each result contains complete Mas object:
378
- for mag in magnetics:
379
- core_name = mag["magnetic"]["core"]["functionalDescription"]["shape"]["name"]
380
- material = mag["magnetic"]["core"]["functionalDescription"]["material"]["name"]
377
+ # Result structure: {"data": [{"mas": {...}, "scoring": float, "scoringPerFilter": {...}}, ...]}
378
+ for item in result["data"]:
379
+ mag = item["mas"]["magnetic"]
380
+ core_name = mag["core"]["functionalDescription"]["shape"]["name"]
381
+ material = mag["core"]["functionalDescription"]["material"]["name"]
382
+ score = item["scoring"]
383
+ print(f"{core_name} - {material} (score: {score:.3f})")
381
384
 
382
385
  # From custom catalog
383
- catalog_results = PyOpenMagnetics.calculate_advised_magnetics_from_catalog(
386
+ catalog_result = PyOpenMagnetics.calculate_advised_magnetics_from_catalog(
384
387
  processed, catalog_magnetics, max_results=5
385
388
  )
389
+ # Same result structure as calculate_advised_magnetics
386
390
  ```
387
391
 
388
392
  ### Simulation
@@ -538,7 +542,8 @@ flyback = {
538
542
  "desiredTurnsRatios": [8.0, 19.2] # N_pri/N_sec for each output
539
543
  }
540
544
  inputs = PyOpenMagnetics.process_flyback(flyback)
541
- magnetics = PyOpenMagnetics.calculate_advised_magnetics(inputs, 5, "STANDARD_CORES")
545
+ result = PyOpenMagnetics.calculate_advised_magnetics(inputs, 5, "STANDARD_CORES")
546
+ # Result format: {"data": [{"mas": {...}, "scoring": float, "scoringPerFilter": {...}}, ...]}
542
547
  ```
543
548
 
544
549
  ### Buck Converter (Non-Isolated Step-Down)
@@ -153,20 +153,26 @@
153
153
  "# Get magnetic design recommendations\n",
154
154
  "print(\"\\nSearching for optimal designs...\")\n",
155
155
  "try:\n",
156
- " magnetics = PyOpenMagnetics.calculate_advised_magnetics(\n",
156
+ " result = PyOpenMagnetics.calculate_advised_magnetics(\n",
157
157
  " processed,\n",
158
158
  " max_results=5,\n",
159
159
  " core_mode=\"STANDARD_CORES\"\n",
160
160
  " )\n",
161
161
  " \n",
162
+ " # Extract magnetics list from result (v1.1.2+ format: {\"data\": [...]})\n",
163
+ " magnetics = result[\"data\"] if isinstance(result, dict) and \"data\" in result else result\n",
164
+ " \n",
162
165
  " print(f\"\\nFound {len(magnetics)} suitable designs:\")\n",
163
- " for i, result in enumerate(magnetics[:5]):\n",
164
- " if 'magnetic' in result:\n",
165
- " magnetic = result['magnetic']\n",
166
+ " for i, item in enumerate(magnetics[:5]):\n",
167
+ " # In v1.1.2+, each item has \"mas\" containing the magnetic data\n",
168
+ " mas = item.get(\"mas\", item) if isinstance(item, dict) else item\n",
169
+ " if isinstance(mas, dict) and 'magnetic' in mas:\n",
170
+ " magnetic = mas['magnetic']\n",
166
171
  " core = magnetic['core']['functionalDescription']\n",
167
172
  " shape_name = core['shape']['name'] if isinstance(core['shape'], dict) else core['shape']\n",
168
173
  " mat_name = core['material']['name'] if isinstance(core['material'], dict) else core['material']\n",
169
- " print(f\" {i+1}. {shape_name} / {mat_name}\")\n",
174
+ " score = item.get('scoring', 'N/A')\n",
175
+ " print(f\" {i+1}. {shape_name} / {mat_name} (score: {score})\")\n",
170
176
  "except Exception as e:\n",
171
177
  " print(f\"Adviser error (may need more compute time): {e}\")"
172
178
  ]
@@ -236,9 +242,14 @@
236
242
  " if 'magnetics' in dir() and len(magnetics) > 0:\n",
237
243
  " print(\"=== Best Design Analysis ===\\n\")\n",
238
244
  " \n",
239
- " best = magnetics[0]\n",
240
- " if 'magnetic' in best:\n",
241
- " magnetic = best['magnetic']\n",
245
+ " # Get best result (first in the list)\n",
246
+ " best_item = magnetics[0]\n",
247
+ " \n",
248
+ " # In v1.1.2+, each item has \"mas\" containing the magnetic data\n",
249
+ " best_mas = best_item.get(\"mas\", best_item) if isinstance(best_item, dict) else best_item\n",
250
+ " \n",
251
+ " if isinstance(best_mas, dict) and 'magnetic' in best_mas:\n",
252
+ " magnetic = best_mas['magnetic']\n",
242
253
  " core_fd = magnetic['core']['functionalDescription']\n",
243
254
  " \n",
244
255
  " # Extract shape and material names\n",
@@ -248,6 +259,10 @@
248
259
  " print(f\"Shape: {shape}\")\n",
249
260
  " print(f\"Material: {material}\")\n",
250
261
  " \n",
262
+ " # Show scoring if available (v1.1.2+)\n",
263
+ " if 'scoring' in best_item:\n",
264
+ " print(f\"Score: {best_item['scoring']:.3f}\")\n",
265
+ " \n",
251
266
  " # Check gapping\n",
252
267
  " gapping = core_fd.get('gapping', [])\n",
253
268
  " total_gap = sum(g.get('length', 0) for g in gapping) * 1000\n",
@@ -263,8 +278,8 @@
263
278
  " print(f\" Parallels: {winding.get('numberParallels', 1)}\")\n",
264
279
  " \n",
265
280
  " # Show outputs if available\n",
266
- " if 'outputs' in best:\n",
267
- " outputs = best['outputs']\n",
281
+ " if 'outputs' in best_mas:\n",
282
+ " outputs = best_mas['outputs']\n",
268
283
  " print(f\"\\nSimulation Results:\")\n",
269
284
  " if 'coreLosses' in outputs:\n",
270
285
  " print(f\" Core losses: {outputs['coreLosses']:.3f} W\")\n",
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "PyOpenMagnetics"
7
- version = "1.1.3"
7
+ version = "1.1.4"
8
8
  requires-python = ">=3.8"
9
9
  authors = [
10
10
  { name="Alfonso Martinez", email="Alfonso_VII@hotmail.com" },
@@ -56,11 +56,13 @@ before-all = [
56
56
  "npm --version",
57
57
  "npm install -g quicktype@23.0.170"
58
58
  ]
59
+ environment = { GIT_LFS_SKIP_SMUDGE=1, CMAKE_BUILD_PARALLEL_LEVEL="4" }
59
60
 
60
61
  [tool.cibuildwheel.macos]
61
62
  before-all = "npm --version && npm install -g quicktype@23.0.170"
62
- environment = { MACOSX_DEPLOYMENT_TARGET="14.0", GIT_LFS_SKIP_SMUDGE=1 }
63
+ environment = { MACOSX_DEPLOYMENT_TARGET="14.0", GIT_LFS_SKIP_SMUDGE=1, CMAKE_BUILD_PARALLEL_LEVEL="3" }
63
64
 
64
65
  [tool.cibuildwheel.windows]
65
66
  before-all = "rmdir /S /Q build && npm --version && npm install -g quicktype@23.0.170"
66
- archs = ["AMD64"]
67
+ archs = ["AMD64"]
68
+ environment = { GIT_LFS_SKIP_SMUDGE=1, CMAKE_BUILD_PARALLEL_LEVEL="2" }
@@ -17,6 +17,19 @@ def parse_json_result(result):
17
17
  return result
18
18
 
19
19
 
20
+ def extract_magnetics_list(result):
21
+ """
22
+ Extract list of magnetics from result.
23
+
24
+ In version 1.1.2+, the function returns {"data": [{"mas": {...}, "scoring": ..., ...}, ...]}
25
+ In version 1.1.0, it returned a list directly.
26
+ """
27
+ parsed = parse_json_result(result)
28
+ if isinstance(parsed, dict) and "data" in parsed:
29
+ return parsed["data"]
30
+ return parsed
31
+
32
+
20
33
  class TestMagneticAdviserBasic:
21
34
  """
22
35
  Basic magnetic adviser tests.
@@ -32,7 +45,7 @@ class TestMagneticAdviserBasic:
32
45
 
33
46
  # API: calculate_advised_magnetics(inputs, max_results, core_mode)
34
47
  result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
35
- results = parse_json_result(result_json)
48
+ results = extract_magnetics_list(result_json)
36
49
 
37
50
  assert isinstance(results, list)
38
51
  # Should return some results
@@ -45,15 +58,16 @@ class TestMagneticAdviserBasic:
45
58
  processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
46
59
 
47
60
  result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 3, "available cores")
48
- results = parse_json_result(result_json)
61
+ results = extract_magnetics_list(result_json)
49
62
 
50
63
  if len(results) > 0:
51
64
  for result in results:
52
65
  assert isinstance(result, dict)
53
- # Each result should be a valid Mas with magnetic
54
- # The Mas structure should contain magnetic, inputs, and optionally outputs
55
- if "magnetic" in result:
56
- assert "core" in result["magnetic"] or "coil" in result["magnetic"]
66
+ # Each result should have "mas" containing the magnetic data (v1.1.2+ format)
67
+ # or "magnetic" directly (v1.1.0 format)
68
+ mas = result.get("mas", result)
69
+ if isinstance(mas, dict) and "magnetic" in mas:
70
+ assert "core" in mas["magnetic"] or "coil" in mas["magnetic"]
57
71
 
58
72
 
59
73
  class TestMagneticAdviserCoreModes:
@@ -70,7 +84,7 @@ class TestMagneticAdviserCoreModes:
70
84
  processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
71
85
 
72
86
  result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
73
- results = parse_json_result(result_json)
87
+ results = extract_magnetics_list(result_json)
74
88
 
75
89
  assert isinstance(results, list)
76
90
 
@@ -82,7 +96,7 @@ class TestMagneticAdviserCoreModes:
82
96
  processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
83
97
 
84
98
  result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "standard cores")
85
- results = parse_json_result(result_json)
99
+ results = extract_magnetics_list(result_json)
86
100
 
87
101
  assert isinstance(results, list)
88
102
 
@@ -95,7 +109,7 @@ class TestMagneticAdviserInputTypes:
95
109
  processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
96
110
 
97
111
  result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
98
- results = parse_json_result(result_json)
112
+ results = extract_magnetics_list(result_json)
99
113
 
100
114
  assert isinstance(results, list)
101
115
 
@@ -108,7 +122,7 @@ class TestMagneticAdviserInputTypes:
108
122
  processed_inputs = PyOpenMagnetics.process_inputs(transformer_inputs)
109
123
 
110
124
  result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
111
- results = parse_json_result(result_json)
125
+ results = extract_magnetics_list(result_json)
112
126
 
113
127
  assert isinstance(results, list)
114
128
 
@@ -121,7 +135,7 @@ class TestMagneticAdviserInputTypes:
121
135
  processed_inputs = PyOpenMagnetics.process_inputs(high_frequency_inputs)
122
136
 
123
137
  result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
124
- results = parse_json_result(result_json)
138
+ results = extract_magnetics_list(result_json)
125
139
 
126
140
  assert isinstance(results, list)
127
141
 
@@ -134,7 +148,7 @@ class TestMagneticAdviserInputTypes:
134
148
  processed_inputs = PyOpenMagnetics.process_inputs(flyback_inputs)
135
149
 
136
150
  result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
137
- results = parse_json_result(result_json)
151
+ results = extract_magnetics_list(result_json)
138
152
 
139
153
  assert isinstance(results, list)
140
154
 
@@ -149,10 +163,10 @@ class TestMagneticAdviserFiltering:
149
163
  """
150
164
  processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
151
165
 
152
- results_5 = parse_json_result(
166
+ results_5 = extract_magnetics_list(
153
167
  PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 5, "available cores")
154
168
  )
155
- results_2 = parse_json_result(
169
+ results_2 = extract_magnetics_list(
156
170
  PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 2, "available cores")
157
171
  )
158
172
 
@@ -167,7 +181,7 @@ class TestMagneticAdviserFiltering:
167
181
  processed_inputs = PyOpenMagnetics.process_inputs(inductor_inputs)
168
182
 
169
183
  result_json = PyOpenMagnetics.calculate_advised_magnetics(processed_inputs, 1, "available cores")
170
- results = parse_json_result(result_json)
184
+ results = extract_magnetics_list(result_json)
171
185
 
172
186
  assert len(results) <= 1
173
187
 
File without changes
File without changes