xtb_step Phase D – File Drop Notes#
This drop addresses the six items from your last review:
Top-level
xtb.pyno longer setsself._metadata– you already have that fix in place.energy_parameters.pynow has"extra keywords"declared – you already have that fix; this drop additionally dropschargeandmultiplicityper items 3 below.Net charge and spin multiplicity moved off the parameters and onto the configuration – now read via
configuration.chargeandconfiguration.spin_multiplicityinsubstep.base_xtb_args.The Energy dialog now hides the
solventwidget whensolvation model == "none"and indents it under the solvation row when shown.setup.pygot aconsole_scriptsentry for the installer – you already added that.Results are now reported as a tabulated summary (Gaussian-style), with the table accumulated through the inheritance chain.
Files in this drop#
Replace existing#
xtb_step/energy_parameters.pyDrops
chargeandmultiplicityfrom the parameter set. Keepsextra keywords,method,accuracy,solvation model,solvent,results. The class docstring explains the convention.xtb_step/substep.pybase_xtb_args(P, configuration)now reads charge and multiplicity from the configuration:charge = int(configuration.charge) mult = int(configuration.spin_multiplicity)
Same as MOPAC’s
mopac.py:run(). No other changes to this file.xtb_step/metadata.pyAdds
"format"strings to the scalar float results so the table can format them sensibly:total / electronic / electronic energy and ZPE / G(T):
.6fHOMO / LUMO / gap:
.4fdipole moment:
.4ftemperature:
.2f
No structural changes – the same 17 results, same property names, same dimensionalities.
xtb_step/energy.pyTwo visible changes:
description_textno longer mentions charge or multiplicity. Otherwise unchanged.analyzenow builds atabulate-formatted summary withProperty | Value | Unitscolumns, takes an optionaltable=argument so subclasses can prepend rows, prints the result with a centered title, and gracefully handles missing results.runreadsextra keywordsfromPand appends them after the substep-specific args (so users can override / add to xTB’s CLI flags).
xtb_step/frequencies.pyThe
analyzemethod replaces the old_post_run_thermo_and_freqs. It re-parses the JSON / vibspectrum / thermo block, callsstore_resultsfor the new fields, and builds a single ordered table:Frequency-count summary rows (“Number of frequencies”, “Imaginary frequencies”).
Energy / orbital / dipole rows (same set as Energy.analyze).
Thermochemistry rows (ZPE, H, T*S, G(T), total free energy, temperature).
The table is printed with a “Frequencies / Thermochemistry” title.
xtb_step/tk_energy.pyDynamic dialog. The solvation-model widget is bound to a
reset_energy_framemethod (modeled onmopac_step.tk_energy). When the model changes, the frame is re-laid out:solventappears in column 1 (indented) only when the model is not"none". The labels in each column are aligned withsw.align_labelsseparately so they read cleanly.
Not in this drop#
xtb_step/optimization.pyUnchanged from Phase B. It does not need to override
analyze: whenEnergy.run()callsself.analyze(data, P=P)on anOptimizationinstance, Python’s MRO picks up the inheritedEnergy.analyzeautomatically. If you ever want optimization-specific rows (“Convergence: …”, “Max gradient: …”), the simplest pattern is to overrideanalyzeto add rows then callsuper().analyze(data=data, table=table, P=P).xtb_step/xtb.py,xtb_step/__init__.py,xtb_step/setup.pyUse the versions you uploaded.
xtb_step/xtb_parameters.pyFrom the Phase C drop. With the working no-
self._metadata-at-top-level approach you found, this file is no longer referenced byxtb.pyand could be removed. If you remove it, also remove thefrom .xtb_parameters import xTBParametersline from__init__.py. (Leaving it in is harmless – the class just sits there unused.)
Open issues / risk register for this drop#
Configuration attribute names. I’m assuming
configuration.chargeandconfiguration.spin_multiplicityare the right attribute names on a molsystemConfiguration, based on the MOPAC code I quoted. If a different attribute name is used in the version of molsystem you have, you’ll see anAttributeErrorand we’ll need to adjust.Dialog widget API.
self["solvation model"].combobox.bind(...)is the pattern frommopac_step.tk_energy. If the seamm-widgets version installed in your env exposes the underlying widget differently (some plug-ins useself[key].bind(...)directly, without.combobox), the bind will fail at dialog-creation time. If that happens, changesmodel.combobox.bindtosmodel.bind.store_results called twice in Frequencies. Energy.run() calls
store_resultsonce with the JSON-derived data, thenFrequencies.analyzecalls it again with the freq + thermo additions. SEAMM’sstore_resultsis idempotent for repeated calls with the same property name, but if you see duplicate property entries in the database, this is where to look.Frequencies.analyze duplicates the Energy.analyze table-build loop. This is intentional but not pretty: I needed to interleave the freq-count rows BEFORE the energy rows but the thermo rows AFTER, which the simple “subclass adds then super() prints” pattern in Gaussian doesn’t quite handle. If we ever want a cleaner factoring, the right move is to add a helper method on Energy like
_append_energy_rows(table, data)thatFrequencies.analyzecan call between its own pre- and post- sections.
What to test#
make lint && make install && make test– still passes.Open the Energy substep dialog. The solvent widget should be hidden when “Implicit solvation” is “none”. Pick “ALPB” – solvent should appear, indented. Pick “none” again – solvent disappears.
Run a simple Energy job (e.g. methane). The job.out should contain a tabulated summary like:
xTB (GFN2-xTB) Results ╭─────────────────────────────────────┬───────────┬───────╮ │ Property │ Value │ Units │ ├─────────────────────────────────────┼───────────┼───────┤ │ The total energy │ -4.174678 │ E_h │ │ The HOMO orbital energy │ -13.4827 │ eV │ │ The LUMO orbital energy │ 2.4567 │ eV │ │ The HOMO-LUMO gap │ 15.9394 │ eV │ │ The molecular dipole moment ... │ 0.0000 │ debye │ ╰─────────────────────────────────────┴───────────┴───────╯
(Exact wording and number of rows depends on which keys xTB actually emitted in xtbout.json.)
Run an Optimization job. Same table; geometry updated.
Run a Frequencies job on water. Table should now include “Number of frequencies”, “Imaginary frequencies”, and the thermochemistry rows beneath the energy rows.
Run on O2 in its triplet state and on O2- (a stored configuration with charge -1, multiplicity 2). xTB should pick up the charge and multiplicity from the configuration without any per-step parameter editing – demonstrating the SEAMM convention for high-throughput.
Code style#
All files compile cleanly. All lines are <= 88 characters. I have
not been able to run black --check here, so a first
make format may produce small whitespace adjustments – those
should be one pass and then stable.