You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Please really consider this as a tentative organisation - I did this as a summer job and as a large vibe-coding exercise, so no worries if it does not match what you would like, it can be redone with different principles.
The main points are:
switch to nanobind
objcryst++ as submodule and cctbx/newmat code directly embedded, so no more need of libobjcryst
pyproject.toml and cmake for compilation (I don't know if you want to stick with scons
so far only tested on mac and linux
Also see the extended migration notes (rationale for various implementation decisions, issues with inheritance, etc..)
Thanks @vincefn this is super-helpful. We haven't formulated specific standards for this migration and so lessons learned and recommendations from you are super helpful. As a general issue, moving to pyproject.toml/cmake builds seems like it is taking us in the right direction. I don't think there is any downside for us to drop scons, but as I said, I don't have tons of experience with that. Also, getting rid of the extra layer of libobjcryst seems like a win, so I don't object to that at all.
I will read the notes in detail with my c++ enabled folks and see if they have any feedback.
Ported and verified LSQ.GetRwHistory(), minRwpVar for Refine()/SafeRefine(), ReflectionProfilePseudoVoigtTCH, and silent-by-default PrepareRefParList(verbose=False) in the nanobind bindings.
Removed the libobjcryst and libboost-python dependencies. ObjCryst++ is vendored and built statically; only Boost headers remain required.
Built a wheel from the updated checkout and ran the complete suite: 172 tests passed. Existing nanobind reference-leak diagnostics still appear at interpreter shutdown.
Hi @sbillinge - do you have any update on this ? I'd really like to push this forward and get rid of libobjcryst, and simplify a lot the publication process, and also allow pure pip-installs. Of course it's a big change.
I am good with this. What do you need from us? I assumed you were just going ahead with this, but were you waiting from word from us? What would the biggest downstream impacts be?
We looked into also vendoring libdiffpy in a similar way but for us we have a fairly automated release cycle and releasing libdiffy updates and making them a dependency isn't such a big overhead for us and ensures we keep libdiffpy up to date. I need to understand if there are other benefits/downsides to doing it your way. It could, for example, require us to refactor our automated release scripts somewhat?
tl;dr: please go ahead with libobjcryst changes if you are ready.
What is proposed here for pyobjcryst completely refactors the library, including all the memory management - so it needs some intense testing to make sure there are no side effects. @clemisch will test this for large Rietveld refinements (>10k patterns in cluding parallel processing), but more tests are warranted in this case given the extensive changes. I don't know how it could affect you.
Main benefit (besides moving away from boost.python) is getting rid of libobjcryst, and greatly simplifying the release cycle.
I see. We would be super interested in that for what we can learn for libdiffpy. Shall we make a new migration branch and release and test that before merging into main?
Activity
sbillinge commentedon Aug 13, 2026
Thanks @vincefn this is super-helpful. We haven't formulated specific standards for this migration and so lessons learned and recommendations from you are super helpful. As a general issue, moving to pyproject.toml/cmake builds seems like it is taking us in the right direction. I don't think there is any downside for us to drop scons, but as I said, I don't have tons of experience with that. Also, getting rid of the extra layer of libobjcryst seems like a win, so I don't object to that at all.
I will read the notes in detail with my c++ enabled folks and see if they have any feedback.
vincefn commentedon Sep 1, 2026
nanobind branch update (September 2026)
The
nanobind_migration_testbranch has been updated and is now based on the currentmainHEAD.What was done
Submodule update
extern/objcrystupdated frombfdcfda→30fc8df(8 new upstream commits), addingGetRwHistory,minRwpVar,ReflectionProfilePseudoVoigtTCH,PowderPatternBackgroundHist, aniso PV constructor fix, etc.Translated from
mainbranch commits (boost.python → nanobind):makeNdArraymemory fix — N/A for nanobind (nobp::incref)lsq.GetVarianceCovarianceMap()#109:lsq.GetVarianceCovarianceMap()→ dict keyed by(param_name, param_name)tuplesEraseAllParamSetfix on compiledRefinableObj— already correct in nanobind via lambda; added testReflectionProfilePseudoVoigtandReflectionProfilePseudoVoigtAnisotropicas constructible classes; addIsAnisotropic()to basePowderPatternDiffraction.X2XCorrPhase()Translated from open PRs (#107, #113, #115, #116):
lsq.GetRwHistory()→list[float]of per-cycle Rw valuesminRwpVarargument added tolsq.Refine()andlsq.SafeRefine()ReflectionProfilePseudoVoigtTCH(TCH implicit-eta profile) with 8-parameterSetProfilePar()LSQ.PrepareRefParListsilent by default via newverboseargument #116:verboseoverload forLSQ.PrepareRefParList()Bug fixes in nanobind bindings:
nb_crystal.cpp: replaced non-existentnb::detail::keep_alive()free function (nanobind 3.x) withnb::keep_alive<1,2>()annotationCMakeLists.txt: added homebrew include paths for Boost headers on macOSSetProfile()toPowderPatternDiffraction(needed to install concrete profile objects)Tests: 171 tests, all passing.
vincefn commentedon Sep 24, 2026
Nanobind migration update:
mainchanges from Add method GetRwHistory to lsq #107, Add Rwp threshold minRwpVar for lsq.Refine() #113, Add profile ReflectionProfilePseudoVoigtTCH with TCH instead of explicit Eta mixing #115, and MakeLSQ.PrepareRefParListsilent by default via newverboseargument #116.LSQ.GetRwHistory(),minRwpVarforRefine()/SafeRefine(),ReflectionProfilePseudoVoigtTCH, and silent-by-defaultPrepareRefParList(verbose=False)in the nanobind bindings.libobjcrystandlibboost-pythondependencies. ObjCryst++ is vendored and built statically; only Boost headers remain required.vincefn commentedon Nov 2, 2026
Hi @sbillinge - do you have any update on this ? I'd really like to push this forward and get rid of libobjcryst, and simplify a lot the publication process, and also allow pure pip-installs. Of course it's a big change.
sbillinge commentedon Nov 2, 2026
I am good with this. What do you need from us? I assumed you were just going ahead with this, but were you waiting from word from us? What would the biggest downstream impacts be?
We looked into also vendoring libdiffpy in a similar way but for us we have a fairly automated release cycle and releasing libdiffy updates and making them a dependency isn't such a big overhead for us and ensures we keep libdiffpy up to date. I need to understand if there are other benefits/downsides to doing it your way. It could, for example, require us to refactor our automated release scripts somewhat?
tl;dr: please go ahead with
libobjcrystchanges if you are ready.vincefn commentedon Nov 2, 2026
What is proposed here for pyobjcryst completely refactors the library, including all the memory management - so it needs some intense testing to make sure there are no side effects. @clemisch will test this for large Rietveld refinements (>10k patterns in cluding parallel processing), but more tests are warranted in this case given the extensive changes. I don't know how it could affect you.
Main benefit (besides moving away from boost.python) is getting rid of libobjcryst, and greatly simplifying the release cycle.
sbillinge commentedon Nov 3, 2026
I see. We would be super interested in that for what we can learn for libdiffpy. Shall we make a new migration branch and release and test that before merging into main?
vincefn commentedon Nov 3, 2026
The https://github.com/diffpy/pyobjcryst/tree/nanobind_migration_test is already there for testing.
You can test it just using: