Skip to content

Enhancements to biplanar coil workflow, optimization robustness, and manufacturable outputs (STL/Gerber + tube visualization)#82

Open
sairamgeethanath wants to merge 9 commits intokev-m:masterfrom
sairamgeethanath:master
Open

Enhancements to biplanar coil workflow, optimization robustness, and manufacturable outputs (STL/Gerber + tube visualization)#82
sairamgeethanath wants to merge 9 commits intokev-m:masterfrom
sairamgeethanath:master

Conversation

@sairamgeethanath
Copy link
Copy Markdown

Summary

This PR introduces a set of improvements to biplanar coil design workflows, optimization robustness, and manufacturing-ready outputs in pyCoilGen.

The changes are based on extended development in my fork and aim to make the pipeline more reliable for practical fabrication (3D printing + PCB workflows) while preserving compatibility with the original architecture.


Key Contributions

1. Improved Biplanar Coil Example

  • Refactored and stabilized the biplanar gradient example

  • Improved handling of:

    • Plate geometry consistency
    • Path validity across both planes
    • Alignment between generated wire paths and physical plates
  • Eliminated failure modes where one plate would generate empty or invalid geometry

Impact:
The biplanar example is now a reliable reference for users working on planar gradient coils or similar hardware.


2. Optimization Refinements

  • Improved robustness of the optimization pipeline:

    • Better handling of edge cases in path generation
    • Reduced occurrence of invalid or degenerate wire paths
  • More stable convergence behavior in practical scenarios

Impact:
Improves reproducibility and reduces manual intervention when generating coil layouts.


3. Manufacturing-Ready Gerber Output

  • Added/updated support for:

    • Complement Gerber generation (solid copper regions instead of just traces)
    • Cleaner, fabrication-friendly geometry
  • Ensures outputs are directly usable for PCB manufacturing workflows

Impact:
Bridges the gap between simulation and real-world PCB fabrication.


4. Robust STL Generation for 3D Printing

  • Reworked STL generation pipeline to:

    • Reliably convert coil geometries into printable solids
    • Ensure correct unit handling (mm scaling)
    • Avoid null/invalid geometries during export
  • Improved handling of:

    • Plate extrusion
    • Groove/channel generation
    • Boolean operations

Impact:
Users can now directly move from coil design to 3D printing (e.g., groove plates, formers) without extensive post-processing.


5. Tube-Based Wire Visualization

  • Introduced tube-based 3D visualization of wire paths:

    • Uses actual 3D geometry instead of line plots
    • Aligns with manufacturing representation
  • Can be reused for:

    • Visualization
    • STL generation pipelines

Impact:
Provides an intuitive and physically meaningful representation of coil windings.


6. Geometry & Scaling Fixes

  • Fixed inconsistencies between:

    • Internal units (meters)
    • Export units (millimeters)
  • Ensured consistent scaling across:

    • STL exports
    • Visualization
    • Plate geometry

Impact:
Eliminates a major source of fabrication errors.


7. Pythonic Input STL Generation

  • Replaced the previous approach of storing static STL files under data/pyCoilGenData/Geometry_Data with a fully Pythonic geometry generation workflow

  • Input geometries are now:

    • Programmatically defined
    • Parameterizable
    • Easier to modify and extend
  • Eliminates reliance on pre-generated STL assets

Impact:
Improves transparency, reproducibility, and flexibility of the geometry pipeline, making it easier for users to define and customize coil form factors directly in code.


Implementation Notes

  • Changes are largely modular and focus on:

    • Geometry generation
    • Export pipelines
    • Example workflows
  • Existing APIs are preserved where possible

  • New logic is primarily integrated into:

    • Gradient former generation
    • Gerber export pipeline
    • Visualization utilities

Testing

  • Validated using:

    • Biplanar gradient example (primary test case)
    • STL inspection in slicers (e.g., Bambu Studio)
    • Gerber inspection in standard viewers

Confirmed:

  • No empty geometries
  • Correct scaling
  • Manufacturable outputs

Motivation

The original pyCoilGen provides a strong foundation for coil design, but bridging the gap to fabrication-ready outputs required additional robustness in geometry handling and export workflows.

This PR aims to:

  • Make the tool more useful for experimental MRI / gradient coil prototyping
  • Enable direct transition from design → fabrication
  • Provide a more stable baseline for future extensions

Future Work (Optional)

  • Parametric control of groove dimensions
  • Multi-layer routing support
  • Integration with open hardware MRI workflows (e.g., PyPulseq-based pipelines)
  • Validation on additional coil geometries beyond biplanar

Request for Feedback

I would especially appreciate feedback on:

  • Integration with existing geometry/optimization modules
  • Preferred defaults for manufacturing outputs
  • Whether to generalize the biplanar improvements into a broader planar framework

Here’s a drop-in “Before vs After” section you can paste directly into your PR description:


Before vs After section follows

Before

  • Biplanar example could produce:

    • Empty or invalid geometry on one plate
    • Misalignment between wire paths and physical plates
  • Optimization occasionally resulted in:

    • Degenerate or unusable paths
  • STL export:

    • Inconsistent scaling (meters vs mm)
    • Frequent failures due to invalid/empty geometries
    • Limited direct usability in slicers
  • Gerber output:

    • Trace-only representation (not fabrication-ready in many cases)
  • Geometry inputs:

    • Static STL files stored under data/Geometry
    • Difficult to modify or parameterize
  • Visualization:

    • Line-based wire paths (limited physical intuition)

After

  • Biplanar example is:

    • Stable and reproducible
    • Generates valid geometry on both plates
    • Properly aligned with physical plate definitions
  • Optimization:

    • More robust to edge cases
    • Produces valid, manufacturable wire paths consistently
  • STL export:

    • Consistent mm-scale outputs
    • Reliable solid generation (plates, grooves, channels)
    • Directly usable in slicers (e.g., Bambu Studio)
  • Gerber output:

    • Supports complement Gerbers (solid copper regions)
    • Cleaner, fabrication-ready outputs
  • Geometry inputs:

    • Fully Pythonic, programmatic STL generation
    • Parameterizable and easier to extend
    • No reliance on pre-generated assets
  • Visualization:

    • Tube-based 3D wire rendering
    • Matches physical realizations and can feed into STL generation

Net Effect

This PR transitions pyCoilGen from a primarily design/prototyping tool to a more end-to-end pipeline that supports:

  • Design → Optimization → Visualization → Fabrication

with significantly improved robustness and reproducibility.

@kev-m
Copy link
Copy Markdown
Owner

kev-m commented Mar 19, 2026

Hello and thank you for the PR.
Since this is a large PR, I will need some time to establish a suitable testing protocol, to ensure compatibility with the existing outputs.

@kev-m
Copy link
Copy Markdown
Owner

kev-m commented Mar 19, 2026

I presume that you used AI assistance to generate or assist with these changes. Please can you provide some details, especially which models where used, and the level of guidance that you provided.
Thank you!

Copy link
Copy Markdown
Owner

@kev-m kev-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contributions.

Unfortunately, I can not accept the PR as provided.

Please can you take care of the following and resubmit:

  1. Exclude all non-project binary files from the commit (.DS_Store)
  2. Move helpers or plotting-only modules out of the sub_functions module into a more appropriate place, e.g. pyCoilGen\plotting or pyCoilGen\helpers.
  3. Ensure that all functions used by the main calling path are documented with Google-style docstrings (see the CONTRIBUTING.md document).
  4. Provide updated project documentation in docs\source, describing all new parameters and functionality. This is critical to help users understand the changes and new functions that you are introducing.
  5. Ensure that all modules in pyCoilGen\sub_functions are single-function (the current project convention).
  6. Any tests or verification scripts (such as pyCoilGen/sub_functions/test_stl_generation.py) are in an appropriate place, and that all referenced resources are included in the PR.

@imr-framework
Copy link
Copy Markdown

I presume that you used AI assistance to generate or assist with these changes. Please can you provide some details, especially which models where used, and the level of guidance that you provided. Thank you!

yes, I used chatgpt 5.4 and 5.3 for code generation of certain aspects related to wire extraction and stl printing in particular. These code snippets went through multiple iterations and debugs. I am not sure how I would answer your question on the level of guidance but I would put it down as atleast 30 to 40 iterations per snippet to ensure the correct libraries and bug free/minimized code was generated and pruned. I did prune code subsequently to fit it into the pycoilgen frramework as well. Ofcourse, I need to cleanup/refactor some of the code still - especially related to imports and docstrings.

@imr-framework
Copy link
Copy Markdown

Thank you for your contributions.

Unfortunately, I can not accept the PR as provided.
Understood, let me work on the comments. I plan to get back to this sometime next week or so. I will ping you once I am done with the six comments, and some of my TODOs as well. Maybe a month or so, given the other balls to juggle :)

Please can you take care of the following and resubmit:

  1. Exclude all non-project binary files from the commit (.DS_Store)
  2. Move helpers or plotting-only modules out of the sub_functions module into a more appropriate place, e.g. pyCoilGen\plotting or pyCoilGen\helpers.
  3. Ensure that all functions used by the main calling path are documented with Google-style docstrings (see the CONTRIBUTING.md document).
  4. Provide updated project documentation in docs\source, describing all new parameters and functionality. This is critical to help users understand the changes and new functions that you are introducing.
  5. Ensure that all modules in pyCoilGen\sub_functions are single-function (the current project convention).
  6. Any tests or verification scripts (such as pyCoilGen/sub_functions/test_stl_generation.py) are in an appropriate place, and that all referenced resources are included in the PR.

@kev-m
Copy link
Copy Markdown
Owner

kev-m commented Mar 24, 2026

Hello!

Thank you for the time and enthusiasm you've put into this contribution. It's great to see interest in expanding the functionality of pyCoilGen.

I've reviewed the PR, and while the underlying ideas are interesting, I'm not able to merge it in its current state. To maintain the project's stability and ensure your work is actually usable by others, we need to bring the PR in line with the project's standards.

Specifically, I'd like to see the following addressed:

  • Documentation: I place a high value on keeping the documentation comprehensive. Without corresponding updates in the docs/source directory, these new features will be "invisible" to users. Please ensure new functionality is documented in the same style as the existing modules.
  • Commit Structure: The current PR is a bit unwieldy. I recommend breaking your changes into smaller, logical "chunks." Well-organised commits with descriptive messages make the review process smoother and help maintain a clean ChangeLog.
  • Code Style & Dependencies: Please revisit the contributing guide regarding code style and commenting. Also, note that requirements.txt should only list top-level packages; we avoid listing nested or automatic dependencies to keep the environment clean.

Next Steps:

  1. Align the additions with existing code conventions and commenting styles.
  2. Refactor the submission into organised, incremental updates, following the project's module placement philosophy.
  3. Add the necessary documentation to make your contributions discoverable.

I'm happy to support you through these adjustments. Once the PR is tidied up and documented, I'll be in a much better position to do a final technical review for merging.

@sairamgeethanath
Copy link
Copy Markdown
Author

sairamgeethanath commented Mar 24, 2026

1. Exclude all non-project binary files from the commit (.DS_Store)

  • Removed all existing .DS_store from repo
  • Updated .gitignore

2. Move helpers or plotting-only modules out of the sub_functions module into a more appropriate place, e.g. pyCoilGen\plotting or pyCoilGen\helpers.

Refactored code to create single definition files and place in corresponding directories

  • sub_functions - extract_wire_paths
  • sub_functions - simulate_gradient_coil.py
  • sub_functions - gradient_former
  • helpers - metrics.py
  • plotting - plot_wire_loops
  • plotting - plot_field

3. Ensure that all functions used by the main calling path are documented with Google-style docstrings (see the CONTRIBUTING.md document).

  • All functions now include docstrings

4. Provide updated project documentation in docs\source, describing all new parameters and functionality. This is critical to help users understand the changes and new functions that you are introducing.

  • Updated - index.rst
  • Created - api_new_modules.rst
  • migration.rst
  • workflow.rst

5. Ensure that all modules in pyCoilGen\sub_functions are single-function (the current project convention).

The three functions are single-function implementations now:

  • pyCoilGen/sub_functions/extract_wire_paths.py
  • pyCoilGen/sub_functions/gradient_former.py
  • pyCoilGen/sub_functions/simulate_gradient_coil.py

6. Any tests or verification scripts (such as pyCoilGen/sub_functions/test_stl_generation.py) are in an appropriate place, and that all referenced resources are included in the PR.

  • Moved test_stl_generation.py to tests
  • Tested install with updated requirements.txt - Python 3.13.9

@kev-m
Copy link
Copy Markdown
Owner

kev-m commented Mar 24, 2026

A quick question: Are you a bot or a human?
I don't mind either way, it simply guides how I respond in the future.

@sairamgeethanath
Copy link
Copy Markdown
Author

sairamgeethanath commented Mar 24, 2026

Totally human :) Nice to meet you @kev-m
I basically took some time to format my answers from my notes here.
image

@kev-m
Copy link
Copy Markdown
Owner

kev-m commented Mar 24, 2026

Hi!
Since you're human, I'm going to propose the following:

  1. Close this PR.
  2. Create a new PR that targets the branch that I created. This way I can experiment and review your changes without affecting the current master.
  3. Clean up the requirements.txt to only contain the new high-level modules that your changes require. I'm expecting one or two new entries.
  4. Create a few commits that each capture the unique core functionality that you are introducing. My assumption is that you are introducing several, distinct, new ideas or concepts. Each one should be delivered in it's own individual commit.
    a. Ensure that each commit has a semver compatible commit message. See the examples for inspiration.
    b. I use auto-changelog to generate the next ChangeLog. Please ensure that the commit messages describe the new functionality in a way that is suitable for users to understand when they read the resulting content.
    c. Each individual commit should contain just the affected/relevant changes.
  5. We need to agree on how to describe your new functionality in the documentation.
    a. The documentation changes in this existing PR are not appropriate (index.rst is not the place for describing changes and the others do not fit with the existing structure) , and do not do your changes justice.
    b. It seems like you are proposing a new workflow for a particular type of coil solution, so that means we probably should add a top-level "Biplanar Alternative Workflow" document, e.g. docs\source\biplanar_alternative.md, and add it to the index.
    c. If the new target_field_weighting parameter that you added to parameters affects all existing code, then it should be described in the configuration.md using the same style as the existing documentation.

Does this sound reasonable to you?

Other observations:

  1. Documentation - I see that some functions are properly documented with Google-style DocStrings, but many are not.
  2. I see some plotting methods called in the middle of a workflow. I recommend to avoid this. If you find it useful to visualise data for debugging purposes, save an image file instead. Add additional visualisation functions to the helper, if the current ones are not suitable.

@sairamgeethanath
Copy link
Copy Markdown
Author

@kev-m - I should be able to work through the changes, except mapping 4 as multiple features might be required to make one part of the workflow work. So, I might end up bunching up a couple but I will try my best to be as modular as possible. Might take me a few days to get this sorted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants