Skip to content

Conversation

@RobBuchananCompPhys
Copy link
Collaborator

@RobBuchananCompPhys RobBuchananCompPhys commented Sep 25, 2025

Description of work
Currently, the Job tab info does not render the embedded LaTex expression strings, which can look less informative and cluttered. This PR proposes an enhancement in which images (rendered in a simple matplotlib figure) of the expression are inserted into the html of the Job tab, allowing mathematical expressions to be displayed in the text.

Fixes
Before:
Screenshot 2025-09-26 094524

After:
Screenshot 2025-09-26 094921

To test
Please describe the tests that were run to verify the changes.

@MBartkowiakSTFC
Copy link
Collaborator

Looks like it's almost there. A few possible points that could still be worked on:

  1. If an equation is not inline, it is not picked up:
Screenshot 2025-09-26 at 10 58 32
  1. The ignored expressions still affect the line breaks:
Screenshot 2025-09-26 at 10 58 13
  1. In principle, it may be worthwhile to try to inline the images. With some tweaking, I got to the stage where it looked like this:
Screenshot 2025-09-26 at 11 18 37 But if the vertical alignment cannot be corrected easily and the whole thing looks to awkward, then it should be fine to stick to the current version with a line break per maths symbol.

@RobBuchananCompPhys RobBuchananCompPhys marked this pull request as ready for review September 29, 2025 08:17
Copy link
Collaborator

@ChiCheng45 ChiCheng45 left a comment

Choose a reason for hiding this comment

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

Just a few things.

Image

White background with dark mode theme, and the inline equations' font size is very large. For the white background, I guess we could make the text white and the background transparent. The font size issue might be trickier. I wonder if we should latex the whole thing?

@RobBuchananCompPhys
Copy link
Collaborator Author

Just a few things.
Image

White background with dark mode theme, and the inline equations' font size is very large. For the white background, I guess we could make the text white and the background transparent. The font size issue might be trickier. I wonder if we should latex the whole thing?

Good question - we may be able to get away with transparency and white font when in dark mode.

Copy link
Collaborator

@oerc0122 oerc0122 left a comment

Choose a reason for hiding this comment

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

I think the MathRenderer can be simplified by using REs to their full extent. Though you may have to be careful and make a copy of the text since replace may disrupt finditer.

from matplotlib import pyplot as plt


class MathRenderer:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Really, this would be an ideal use-case of 3.14's t-strings

Comment on lines 67 to 78
def processInlineExpressions(text: str) -> list[tuple[str, bool]]:
pattern = r"(:math:`.*?`)"
substrings = re.split(pattern, text)
scanned = []
for s in substrings:
if s.startswith(":math:"):
expr = s[len(":math:`") : -1]
scanned.append((expr, True))
else:
scanned.append((s, False))

return scanned
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is a somewhat strange way to do this. The usual way would be to use Regular expression groups.

Suggested change
def processInlineExpressions(text: str) -> list[tuple[str, bool]]:
pattern = r"(:math:`.*?`)"
substrings = re.split(pattern, text)
scanned = []
for s in substrings:
if s.startswith(":math:"):
expr = s[len(":math:`") : -1]
scanned.append((expr, True))
else:
scanned.append((s, False))
return scanned
def processInlineExpressions(text: str) -> list[tuple[str, bool]]:
pattern = r"(:math:`(.*?)`)" # <-- Should really be class-level constant
last = 0
for match in re.finditer(pattern, text):
scanned.append((text[last:match.start], False))
scanned.append((match.group(1), True))
last = match.end
scanned.append((text[last:], False))
return scanned

Although I'm still not sure whether you really want to capture the non-converting bits or whether you just want to substitute the matches in-place for their image equivalents, which simplifies the logic massively.

Suggested change
def processInlineExpressions(text: str) -> list[tuple[str, bool]]:
pattern = r"(:math:`.*?`)"
substrings = re.split(pattern, text)
scanned = []
for s in substrings:
if s.startswith(":math:"):
expr = s[len(":math:`") : -1]
scanned.append((expr, True))
else:
scanned.append((s, False))
return scanned
def processInlineExpressions(self, text: str) -> None:
pattern = r"(:math:`(.*?)`)" # <-- Should really be class-level constant
for match in re.finditer(pattern, text):
text.replace(match[0], self.render(match[1]))

Comment on lines 46 to 64
@staticmethod
def processMultiLineBlockExpression(
strings: list[str], n: int
) -> tuple[list[tuple[str, bool]], int]:
substrings = strings[n + 1 :]
group = []
for s in substrings:
if (not s) or (s == r"<br /><br />"):
break
group.append(s)

group = [s.replace(r"<br />", "") for s in group]
total = "".join(group)
if total.startswith(r"<br />") and total.endswith(r"<br />"):
result = total.split(r"<br />")[1]
else:
result = total.split(r"<br /><br />")[0]

return [(result, True)], n + len(group) + 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

Again, you can use pattern matching here.

Suggested change
@staticmethod
def processMultiLineBlockExpression(
strings: list[str], n: int
) -> tuple[list[tuple[str, bool]], int]:
substrings = strings[n + 1 :]
group = []
for s in substrings:
if (not s) or (s == r"<br /><br />"):
break
group.append(s)
group = [s.replace(r"<br />", "") for s in group]
total = "".join(group)
if total.startswith(r"<br />") and total.endswith(r"<br />"):
result = total.split(r"<br />")[1]
else:
result = total.split(r"<br /><br />")[0]
return [(result, True)], n + len(group) + 1
def processMultiLineBlockExpression(
self, strings: str
) -> None:
pattern = r".. math::\s*\n(?:\s*\n)?(\s+)(.+)\n(\1.+\n)*" # <- Should be class level variable
for match in re.finditer(pattern, text):
if match[3] is not None:
body = "".join(more_itertools.prepend(match[2], match[3].splitlines()))
else:
body = match[2]
text.replace(match[0], self.render(body))

Comment on lines 42 to 44
@staticmethod
def processBlockExpression(text: str) -> list[tuple[str, bool]]:
return [(text[len(".. math:: ") :], True)]
Copy link
Collaborator

Choose a reason for hiding this comment

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

As above, we can use pattern matching:

Suggested change
@staticmethod
def processBlockExpression(text: str) -> list[tuple[str, bool]]:
return [(text[len(".. math:: ") :], True)]
def processBlockExpression(text: str) -> list[tuple[str, bool]]:
pattern = ".. math::\s*(.+)"
for match in re.finditer(pattern, text):
text.replace(match[0], self.render(match[1]))

for token, is_expression in scanned:
if is_expression:
image = MathRenderer.from_cache(token)
if len(token) < 10:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Bear in mind that latex tokens may not correspond to large images:

\underbrace{\mathbf{x}} = \mathbf{3}

$\underbrace{\mathbf{x}} = \mathbf{3}$

@ChiCheng45
Copy link
Collaborator

ChiCheng45 commented Oct 22, 2025

I don't think this needs to be fix here but something I discover in #1038 which also will happen for the equation images.

auto-dark-light-new

@ChiCheng45
Copy link
Collaborator

ChiCheng45 commented Nov 12, 2025

I don't think this needs to be fix here but something I discover in #1038 which also will happen for the equation images.

I've been able to fix some dark light mode system change GUI issues. See #1062 might be worth trying to add a similar fix here I think.

@ChiCheng45
Copy link
Collaborator

A few more things. Some text has been dropped. The "for a set of atoms" is missing. Also the equations are on their own line, I think it would be nice if you could inline them.

image image

here is the text on protos.

image

@RobBuchananCompPhys Can you resolve the merge conflict, I can have a look to see if dark/light mode change can be fixed for the equation images.

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.

5 participants