SunnySuite / Sunny.jl

Spin dynamics and generalization to SU(N) coherent states
Other
65 stars 19 forks source link

Support more complicated `.nxs` in `load_nxs` #256

Closed Lazersmoke closed 2 months ago

Lazersmoke commented 3 months ago

This is required for the Shiver script, which can place the axes in any order (not just space,space,space,energy).

Also adds permutedims instance for BinningParameters, since some Sunny functions will expect you to be in the canonical space,space,space,energy order.

Lazersmoke commented 2 months ago

I chatted briefly with Steven Hahn about this: unfortunately, MDHistoWorkspace (the specific format of .nxs file exported by Mantid) is not particularly standardized, so there's not any standards doc to implement here, and the pragmatic approach of this PR (support as much as possible of commonly used files) is optimal

Lazersmoke commented 2 months ago

Previous to these latest commits, any Mantid histogram making a cut between certain low symmetry points was loaded incorrectly :(

The correct algorithm, implemented in that commit, is as follows: A Mantid histogram has a set of "axes labels" of the form [H,2H,0], [0,K,0], [0,L,-L], or similar. There must be exactly three of these. The semantics of these labels is that the numbers H, K, and L serve as the numbers reported by the tick marks on the histogram axes. So, a point (H,K,L) in histogram axis space corresponds to q = [1 0 0; 2 1 1; 0 0 -1] * [H,K,L], where the matrix is obtained by placing the axes labels as columns. The code in load_nxs now first loads this matrix of numbers (in the correct way for each of several possible sources within the .nxs file) into spatial_covectors. Now, to convert this matrix into the covectors required for binning, we need to invert the equation q = spatial_covectors * histogram_axes_numbers to find inv(spatial_covectors) * q = histogram_axes_numbers. This shows that inv(spatial_covectors) is the correct definition for the spatial part of the params.covectors matrix.

This has been tested by using it twice on the same data but prepared in different ways: once with the W_MATRIX available, and once reading from axes labels (the common case). With these changes, both result in the correct parameters being loaded, as confirmed by having the crystallographic features of a spin wave model match the data.

kbarros commented 2 months ago

I asked Sam "what are the spatial_covectors", and the response should probably live here as part of the documentation for this feature:

Yeah this is actually a bad variable name now because its meaning changes as a result of the PR. Its meaning is that it is the Mantid W_MATRIX. Pragmatically, it's a 3x3 matrix where each column corresponds to a Mantid-style axis label, e.g. [H,-H,0] is represented as a column [1;-1;0]. When the W_MATRIX is not available in the nxs, it instead gets computed by parsing the axes labels, which are always available in the nxs. The algorithm to convert such a matrix to the params.covectors matrix that is needed for Sunny to do binning is described in the PR comment The params.covectors matrix is much more intuitive to me: Each row of the matrix is a row vector associated with an axis on a histogram plot. If you have a neutron event labelled (qx,qy,qz,E), then the label it gets on the histogram axis is simply rowvector * (qx,qy,qz,E). So each event gets assigned a number along the axis in a straightforward way. Less intuitively, if you have the W_MATRIX of Mantid-style labels, you have to solve a system of equations in order to figure out which label to assign to a given event. (Conversely, if you already know the location of a point on the plot, e.g. if you're reading a plot in someone's paper, and if you only have params.covectors, you would have to solve a system of equations to determine the (qx,qy,qz,E) associated to that point. So: W_MATRIX is better suited for reading papers, covectors matrix is better suited for putting event data into bins) And one last fact: the rowvector is actually a real space vector (written as a linear combination of lattice vectors) that tells you the direction of motion of the dispersion of the quasiparticles as you move along that histogram axis. So it actually has a direct physical interpretation that's sometimes useful.