pymatgen
pymatgen copied to clipboard
Highlight selected points in plotly PDPlotter
Sometimes I want to plot a phase diagram and highlight points that are not on the convex hull. It would be nice to be able to give a list of entry names that would then be highlighted in a separate list to "stable" and "above hull".
@mattmcdermott Is this something that seems reasonable to be able to add?
Would also be nice to be able to pass in additional information for the hover labels i.e. a DOI for the entry etc
Additionally if using PDEntry
entry_id = getattr(entry, "entry_id", "no ID")
doesn't grab the name as PDEntry
calls the identifier name
Sometimes I want to plot a phase diagram and highlight points that are not on the convex hull. It would be nice to be able to give a list of entry names that would then be highlighted in a separate list to "stable" and "above hull".
This should be doable, but I don't yet know a clean way to do it in Plotly. The most straightforward approach would be to define a new trace that would correspond to "Highlighted" points, but because the stable and unstable entries are already split into two traces, you would need to create four separate traces now: 1) Highlighted - Stable, 2) Highlighted - Unstable, 3) Unhighlighted - Stable, 4) Unhighlighted - Unstable. Since this is kind of gross I'd rather not do it that way. However, if you think this would be okay (or even preferred?) let me know.
I think the better way is probably to add a Button
in plotly, so that you can restyle the phase diagram. The issue with that is there doesn't seem to be way to hide specific points without leaving some weird stuff behind. I tried setting their opacity to zero, but it leaves behind some artifacts that look kind of gross. (See picture where I try to hide all but one stable point and one unstable point). For the stable points, it seems to leave behind gray lines that I can't get rid of, and the legend labels also get messed up.
Would also be nice to be able to pass in additional information for the hover labels i.e. a DOI for the entry etc
Additionally if using PDEntry entry_id = getattr(entry, "entry_id", "no ID") doesn't grab the name as PDEntry calls the identifier name
^ I should be able to address these!
@janosh does the stuff you were doing with groups for the frontier plot offer any nice solutions for highlighting here?
@CompRhys I don't see how without changes to PDPlotter
which might turn into a mess.
But since PDPlotter
returns a Plotly figure object, you can just apply changes to any of its traces as you see fit:
from pymatgen.analysis.phase_diagram import PDPlotter, PhaseDiagram
from pymatgen.ext.matproj import MPRester
entries = MPRester().get_entries("Fe-O")
entries += MPRester().get_entries("Fe")
entries += MPRester().get_entries("O")
pd = PhaseDiagram(entries)
fig = PDPlotter(pd).get_plot()
unstable = [trace for trace in fig.data if trace.name == "Above Hull"][0]
unstable["marker"]["size"] = [10] * (len(unstable["x"]) - 1) + [40]
The issue with that is there doesn't seem to be way to hide specific points without leaving some weird stuff behind.
@mattmcdermott I assume you could zip
over the x
, y
and hovertext
attributes of a trace and populate new lists with the existing points based on conditions, then overwrite the existing attributes with the new lists. Something like:
trace = [trace for trace in fig.data if trace.name == "Above Hull"][0]
new_x, new_y, new_hover = [], [], []
for x, y, h in zip(trace.x, trace.y, trace.hovertext):
if (x < 0.5) and (y > 1):
new_x.append(x)
new_y.append(y)
new_hover.append(h)
trace.x = new_x
trace.y = new_y
trace.hovertext = new_hover
Haven't tried it though. And it's a lot of work too.
@CompRhys FYI, I finally added this feature in https://github.com/materialsproject/pymatgen/pull/3032.