Skip to content

Commit ee03b75

Browse files
andyclaude
andcommitted
MO diagram: room for the labels in a fragment column
Nitrite's oxygen set has six symmetry orbitals inside a tenth of a Hartree. Drawn strictly to scale their rows overlapped and their labels printed on top of one another -- "2x A1 (2p)" over "A2 (2p)" over "2x B2 (2p)", phase sketches in the same place -- and the whole construction the diagram exists to show was unreadable. A fragment level is not AT its drawn energy anyway: it is placed at the mean of the orbitals it became. So a fragment column may be opened out to leave a row's height between its levels, which is what a person draws. The molecular column is never touched: its energies are the measurement. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EFMUNbw2UpRPmgsqviAowb
1 parent bd23c21 commit ee03b75

1 file changed

Lines changed: 56 additions & 17 deletions

File tree

‎src/apps/builder/MoDiagramCanvas.H‎

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,8 @@ class MoDiagramCanvas : public wxPanel
282282
*/
283283
void drawColumn(wxDC& dc, const MoColumn& column, int x, int width,
284284
const wxRect& plot, bool withOccupancy,
285-
vector<Hit>* hits, int outward = -1)
285+
vector<Hit>* hits, int outward = -1,
286+
bool spread = false)
286287
{
287288
// Which side this column's labels and sketches go. Outward, so
288289
// nothing is written over the correlation lines in the middle --
@@ -296,21 +297,60 @@ class MoDiagramCanvas : public wxPanel
296297

297298
const int lineGap = 4;
298299

299-
for (size_t first = 0; first < column.levels.size(); ) {
300-
301-
// How many levels share this energy?
302-
size_t last = first;
303-
int lines = column.levels[first].degeneracy > 0
304-
? column.levels[first].degeneracy : 1;
305-
while (last + 1 < column.levels.size() &&
306-
fabs(column.levels[last+1].energy
307-
- column.levels[first].energy) < 1.0e-9) {
308-
last++;
309-
lines += column.levels[last].degeneracy > 0
310-
? column.levels[last].degeneracy : 1;
300+
// ROOM FOR THE LABELS IN A FRAGMENT COLUMN.
301+
//
302+
// Nitrite's oxygen set has six symmetry orbitals inside a tenth
303+
// of a Hartree, so drawn strictly to scale their rows overlap
304+
// and their labels print on top of one another -- "2x A1 (2p)"
305+
// over "A2 (2p)" over "2x B2 (2p)", with the phase sketches in
306+
// the same place. A fragment level is not AT its drawn energy
307+
// anyway: it is placed at the mean of the orbitals it became.
308+
// So these columns may be opened out to leave a row's height
309+
// between them, which is what a person draws. The molecular
310+
// column is never touched: its energies are the measurement.
311+
vector< std::pair<size_t,size_t> > groups;
312+
for (size_t a = 0; a < column.levels.size(); ) {
313+
size_t b = a;
314+
while (b + 1 < column.levels.size() &&
315+
fabs(column.levels[b+1].energy - column.levels[a].energy)
316+
< 1.0e-9) {
317+
b++;
318+
}
319+
groups.push_back(std::make_pair(a, b));
320+
a = b + 1;
321+
}
322+
323+
vector<int> groupY;
324+
for (size_t g = 0; g < groups.size(); g++) {
325+
groupY.push_back(yFor(column.levels[groups[g].first].energy, plot));
326+
}
327+
if (spread && groupY.size() > 1) {
328+
dc.SetFont(*wxSMALL_FONT);
329+
const int minGap = dc.GetTextExtent(wxT("Xg")).y + 8;
330+
// Ascending energy, so descending y.
331+
for (size_t g = 1; g < groupY.size(); g++) {
332+
if (groupY[g - 1] - groupY[g] < minGap) {
333+
groupY[g] = groupY[g - 1] - minGap;
334+
}
335+
}
336+
// Slid back down if the stack ran off the top.
337+
const int over = plot.y + 6 - groupY[groupY.size() - 1];
338+
if (over > 0) {
339+
for (size_t g = 0; g < groupY.size(); g++) groupY[g] += over;
340+
}
341+
}
342+
343+
for (size_t gi = 0; gi < groups.size(); gi++) {
344+
345+
const size_t first = groups[gi].first;
346+
const size_t last = groups[gi].second;
347+
int lines = 0;
348+
for (size_t i = first; i <= last; i++) {
349+
lines += column.levels[i].degeneracy > 0
350+
? column.levels[i].degeneracy : 1;
311351
}
312352

313-
const int y = yFor(column.levels[first].energy, plot);
353+
const int y = groupY[gi];
314354
const int slot = (lines > 0) ? (width + lineGap)/lines : width;
315355
const int lineWidth = max(8, slot - lineGap);
316356

@@ -361,7 +401,6 @@ class MoDiagramCanvas : public wxPanel
361401
}
362402
drawn += count;
363403
}
364-
first = last + 1;
365404
}
366405
}
367406

@@ -841,10 +880,10 @@ class MoDiagramCanvas : public wxPanel
841880
// occupancy now, and a diagram that does not draw it does not
842881
// say which combinations are filled -- which is half of what
843882
// it is for. The offline renderer draws them; this did not.
844-
drawColumn(dc, p_left, xLeft, levelWidth, plot, true, 0);
883+
drawColumn(dc, p_left, xLeft, levelWidth, plot, true, 0, -1, true);
845884
p_placed.clear();
846885
p_notes.clear();
847-
drawColumn(dc, p_right, xRight, levelWidth, plot, true, 0, +1);
886+
drawColumn(dc, p_right, xRight, levelWidth, plot, true, 0, +1, true);
848887
p_placed.clear();
849888
p_notes.clear();
850889
}

0 commit comments

Comments
 (0)