-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Phase information in EigenChannel scattering wavefunctions #68
Comments
Hi @anshugaur, one possibility is to use |
It does not interface with py3Dmol for now, but it is something I want to do! (because plotly 3D engine is somewhat bad for big systems and blender is just for a definitive figure). I will probably use your example here as reference :) |
OK, but I was more thinking if your existing tools for showing isosurfaces with plotly could also handle complex wave functions (and thus could be used to also visualize eigenchannel scattering states)? |
Yes, that's for sure! If you have a sisl Grid in import sisl.viz
grid.plot(represent="deg_phase") # or rad_phase But you could also store the values of the phase in a cube file, right? import numpy as np
grid.apply(np.angle).write("Phase.cube") PS: If you want to visualize it in 2D/1D I actually recommend using sisl visualization directly, otherwise for now I think it's a better user experience to just write it to a cube file and visualize it with some other tool. |
Thanks @pfebrer, I was playing a bit around with this. I leave a few lines of code here that enabled me to generate some plots for a simple 1D Au chain: import numpy as np
import sisl
import sisl.viz
# read real and imaginary part of the scattering state from cube-format
wf_re = sisl.get_sile("Chain.EC.1L.Re.cube").read_grid()
wf_im = sisl.get_sile("Chain.EC.1L.Im.cube").read_grid().copy(dtype=np.complex128)
# construction of complex-valued grid + smoothening for nicer plots
wf = (wf_re + wf_im * 1j).smooth()
# density of scattering state
dens = wf.apply(np.abs).apply(np.square)
# phase of scattering state
phase = wf.apply(np.angle)
# two plots:
dens.plot(isos=[{"frac": 0.1}, {"frac": 0.02}], axes='zx', zsmooth="best", plot_geom=True, reduce_method="sum")
phase.plot(axes='zx', colorscale="Edge", zsmooth="best", plot_geom=True, reduce_method="average") In the latter plot we can roughly see how the traveling wave undergoes a phase shift of around pi/2 per site in the Au chain. This fits the simple picture of a half-filled s-band. |
Aaah ok so inelastica produces a |
It would be really cool if one could combine the above information into an isosurface contour of the density (top plot) with its surface colored according to the phase (bottom plot). Do you see a way to do this? |
Yes! You need to get the isosurface vertices for the density and then find out what the phase is at those vertices.This code snippet should do it in plotly: import sisl
import numpy as np
import plotly.graph_objects as go
# read real and imaginary part of the scattering state from cube-format
wf_re = sisl.get_sile("Chain.EC.1L.Re.cube").read_grid()
wf_im = sisl.get_sile("Chain.EC.1L.Im.cube").read_grid().copy(dtype=np.complex128)
# construction of complex-valued grid + smoothening for nicer plots
wf = (wf_re + wf_im * 1j).smooth()
# density of scattering state
dens = wf.apply(np.abs).apply(np.square)
# phase of scattering state
phase = wf.apply(np.angle)
# Get the vertices and faces of a given isosurface of the density
verts, faces, *_ = dens.isosurface(...) # Whatever arguments you want to pass
# These are the variables that plotly needs for plotting the isosurface
x, y, z = verts.T
i, j, k = faces.T
# Get the values of the phase at the vertices of the surface:
verts_indices = phase.index(verts)
color = phase.grid[tuple(verts_indices.T)]
# Build the plotly figure
fig = go.Figure(data=[
go.Mesh3d(
# Vertices and faces of the density isosurface
x=x, y=y, z=z,
i=i, j=j, k=k,
# Intensity of each vertex, which will be interpolated and color-coded
intensity = color,
# Pass whatever colorscale that you wish
colorscale="viridis",
)
])
# Make it have the appropiate proportions
fig.update_layout(scene_aspectmode="data")
fig.show() Looking forward to seeing what you produce with it! :) |
That looks great! It looks like a worm hahaha
Hmm that is tricky indeed. The default is that the intensity is applied to the vertices and then the color is interpolated between them, but there is also the possibility to use A bit more involved but it may be worth it (?) Although for the same grid precision the plot will look less smooth. |
Hahahah that looks beautiful indeed. That's what I was referring to, you need to then calculate the color of each face (triangle) which is not as straightforward as calculating the color of each vertex. Each face is defined by three indices (i,j,k as defined in the code), which contain the index of each vertex of the triangle. For each What you are doing here is retreiving the phase at the vertices and assigning these values to faces, that's why it doesn't make sense. |
Thanks for your explanations, I went too fast here. I'll leave the calculation of face values for another time. @anshugaur , I hope the above is useful for your purposes? |
By the way, perhaps making the grid finer in the Z direction (before computing the phase) is a good patch to make the discontinuity less visible and therefore less annoying? Something like: new_wf_shape = list(wf.shape)
new_wf_shape[2] *= 4 # Or some other factor.
wf = wf.interp(new_wf_shape) But I don't know how computationally expensive will things get in this particular case 😅. If you were to provide tools like these, another approach would be to detect the discontinuity and add extra very small faces so that there is no interpolation happening between the edges of the discontinuity, but that may be too hard to do. |
Dear Thomas,
Thanks a lot for your help. The exchanges between you and pfebrer have been enlightening and I will try to use some of it. Anshu (anshugaur) |
Nice! I would probably use cubic interpolation ( |
This is some nice tutorial material :) |
@anshugaur , based on the above solutions my recommendation would now be to first use the script |
If you use a symmetric colorbar, the discontinuity would be gone, regardless of the grid. |
Hmm I don't think so. Between two vertices, it seems to interpolate values, not colors. So it goes through the whole colorbar and even if it's symmetric you will see this weird feature. This is because I've seen in the docs that there is also If this were to be a provided script to visualize phases, it would not be that difficult to detect faces where these discontinuities happens and subdivide them until it becomes practically invisible. The other option is of course to plot just the absolute value if you don't care about the sign... |
Dear all,
Is there a way to visualize phase information of scattering wavefunctions using EigenChannel analysis? When I do EigenChannel analysis for a particular channel, I get "real", "imaginary", and "absolute" values of scattering wavefunctions in cube format. When I plot these using VESTA, I get "+ve" and "-ve" values of the wavefunctions (real, imaginary, or absolute), however, I do not get any phase information. Is there a way to find and visualize the phase of wavefunctions using these?
Thanks,
Anshu
The text was updated successfully, but these errors were encountered: