Skip to content

Commit

Permalink
Minor Bugfixes (#180)
Browse files Browse the repository at this point in the history
* Fix bug where imag always plots in auto mode #172

* Allow row vector for hkl for single point #179

* Fix inverted user colormap #131

* Refactor sw_plotspec to avoid recursive calls #132

* Add fitspec fixes suggested by K Richardson #98

* Add spinw obj to spec for twin cases in fitspec #158

* Fix spec spinw object issues in fitmode

spinwave() now creates a .obj field regardless
  When fitmode=true, this a barebones struct
  When fitmode=false, this is a full spinw object
Fix issue with sw_plotspec when using fastmode/fitmode
Add basic test for fitspec() to check twins handling

* Fix bug in sw_plotspec 'fastmode' handling

* Fix issues from review. Add change log.
  • Loading branch information
mducle committed May 20, 2024
1 parent c046e97 commit 3e8b492
Show file tree
Hide file tree
Showing 9 changed files with 247 additions and 186 deletions.
57 changes: 57 additions & 0 deletions +sw_tests/+unit_tests/unittest_spinw_fitspec.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
classdef unittest_spinw_fitspec < sw_tests.unit_tests.unittest_super
% Tests for fitspec - not strictly a unit test, but make sure it runs

properties
datafile = '';
swobj = [];
fitpar = struct();
end

methods (TestClassSetup)
function setup_model_and_fitpars(testCase)
% Writes out the mode data
testCase.datafile = fullfile(tempdir, 'triAF_modes.txt');
fid = fopen(testCase.datafile, 'w');
fprintf(fid, ' QH QK QL Elim1 Elim2 I1 EN1 sig1 I2 EN2 sig2\n');
fprintf(fid, ' 1 0.2 1 0.5 5.0 22.6 2.94 0.056 0 0 0\n');
fprintf(fid, ' 1 0.4 1 0.5 5.0 65.2 2.48 0.053 13.8 3.23 0.061\n');
fprintf(fid, ' 1 0.6 1 0.5 5.0 69.5 2.52 0.058 16.3 3.15 0.054\n');
fprintf(fid, ' 1 0.8 1 0.5 5.0 22.6 2.83 0.057 0 0 0\n');
fclose(fid);
testCase.swobj = sw_model('triAF', 0.7);
testCase.fitpar = struct('datapath', testCase.datafile, ...
'Evect', linspace(0, 5, 51), ...
'func', @(obj,p)matparser(obj,'param',p,'mat',{'J_1'},'init',1),...
'xmin', 0, 'xmax', 2, 'x0', 0.7, ...
'plot', false, 'hermit', true, ...
'optimizer', 'simplex', ...
'maxiter', 1, 'maxfunevals', 1, 'nMax', 1, 'nrun', 1);
end
end

methods (TestClassTeardown)
function del_mode_file(testCase)
try
delete(testCase.datafile); % Ignores errors if file already deleted
end
end
end

methods (Test)
function test_fitspec(testCase)
fitout = testCase.swobj.fitspec(testCase.fitpar);
testCase.verify_val(fitout.x, 1.0, 'abs_tol', 0.25);
testCase.verify_val(fitout.redX2, 0.0, 'abs_tol', 10);
end
function test_fitspec_twin(testCase)
% Checks that twins are handled correctly
swobj = copy(testCase.swobj);
% Adds a twin with very small volume so it doesn't affect original fit
% If twins not handled correctly, the fit will be bad.
swobj.addtwin('axis', [1 1 1], 'phid', 54, 'vol', 0.01);
fitout = swobj.fitspec(testCase.fitpar);
testCase.verify_val(fitout.x, 1.0, 'abs_tol', 0.25);
testCase.verify_val(fitout.redX2, 0.0, 'abs_tol', 10);
end
end
end
3 changes: 3 additions & 0 deletions +sw_tests/+unit_tests/unittest_spinw_spinwave.m
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ function test_sw_qh5_fitmode(testCase, mex)
% fitmode automatically turns off sortMode
expected_sw = testCase.swobj.spinwave(qpts, 'sortMode', false);
expected_sw = rmfield(expected_sw, {'obj', 'datestart', 'dateend'});
obj = testCase.swobj;
expected_sw.obj = struct('single_ion', obj.single_ion, 'twin', obj.twin, ...
'unit', obj.unit, 'basisvector', obj.basisvector, 'nmagext', obj.nmagext);
testCase.verify_spinwave(sw_out, expected_sw);
end
function test_incommensurate(testCase, mex)
Expand Down
77 changes: 75 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
# [v3.2.0](https://github.com/pace-neutrons/libpymcr/compare/0.0.1...v3.2.0)
# [Unreleased](https://github.com/spinw/spinw/compare/v3.2.0...master)

## New Features

- Add a function to output Mantid MDHistogramWorkspaces (`sw_spec2MDHisto`)
- Add Python plotting of magnetic structure using [vispy](https://vispy.org/)
- Add mex files to compute main loop in `spinwave()` enabling a 2x - 4x speed up depending on system size

## Improvements

- Replace `spinwavefast()` method with a new `fastmode` option in the main `spinwave()` method to reduce confusion
- Adds a `neutron_output` option to `spinwave()` to compute only the neutron (`Sperp`) cross-section and not the full spin-spin correlation tensor, saving memory

## Bug Fixes

- Corrects equation for Q-range from `thetaMin` in `sw_instrument` and add `thetaMax` option
- Fixes `sw_issymspec` to recognise powder spectra
- Fixes a parsing error in the `spinw.fourier` method if no sublat option given.
- Fixes several bugs in `sw_plotspec` where it ignores user options in `'auto'` mode, and where it inverts user supplied colormaps.
- Fixes several bugs in `.fitspec()` for handling twins and where it only outputs the final chi^2 values.


# [v3.2.0](https://github.com/spinw/spinw/compare/0.0.1...v3.2.0)

## Initial public beta of PySpinW

Expand Down Expand Up @@ -34,7 +56,6 @@ plt.show()

On Windows and Linux systems, as long as you're running PySpinW locally, Matlab plotting commands like `m.plot(swobj)` will work. This is not the case on MacOS (a known bug) and on remote systems (e.g. via JupyterHub).


# [v0.0.1](https://github.com/spinw/spinw/compare/v3.1.2...0.0.1)

## pySpinW
Expand Down Expand Up @@ -82,3 +103,55 @@ spec = m.spinwave(s, [q_start, q_end, pts])
### Known limitations

At the moment graphics will not work on macOS systems and is disabled.


# [v3.1.2](https://github.com/spinw/spinw/compare/v3.1.0...v3.1.2)

## Improvements

- Change to preallocation of output energies in `spinwave` to reduce memory usage and improve calculation speed
- Use a mex function (if mex is enabled) for matrix multiplication in `spinwave` with `hermit=false` that reduces memory usage and improves calculation speed for large magnetic cells (in an example with 216 magnetic atoms the execution time was reduced by ~65%)


## Bug Fixes

- Fix generation of lattice from basis vectors in `genlattice`, see issue [#28](https://github.com/SpinW/spinw/issues/28)
- `sortMode` in `spinwave` now correctly sorts the spin wave modes within each twin
- A `spinw` object can now be correctly created from a structure figure
- `.cif` files with a mixture of tabs and spaces or containing a `?` in the comments can now be read correctly
- Rotation matrix `rotC` in `addtwin` is now required to be a valid rotation or reflection matrix.
- Spin of atom in `addatom` must have `S>=0`.
- Anisotropic g-tensor in `addg` must be physically valid - i.e. :math:`g^\dagger.g` must be a symmetric positive definite matrix.
- Fix bug in addcoupling that did not allow user to supply 'atom' with numeric array of atom indices (previously only worked for string or cell of strings corresponding to atom labels).
- Renamed undocumented `gencoupling` parameter `tol` to `tolMaxDist` (see doc string of `gencoupling` for more details).
- Added validation to `gencoupling` to ensure `maxDistance > dMin`.
- Fixed uncaught error in `gencoupling` by checking if any bonds have length < `maxSym`
- A warning will now be emitted if `saveSabp` is requested in `spinwave` for a commensurate structure
- Fix bug in definition of rotation matrix transforming to spinw coordinate system when left-handed set of basis vectors supplied to `genlattice`, see issue [#57](https://github.com/SpinW/spinw/issues/57)
- Validation added for `perm` and `origin` arguments supplied to `genlattice` (and warn users that these will be ignored if no symmetry/spacegroup is supplied in the same function call).
- Deprecated `spgr` argument to `genlattice` (users should use `sym` instead).
- Fix `MATLAB:nonLogicalConditional` error raised when using multiple k in `genmagstr` with `helical` mode
- Raise error if invalid shape `S` or `k` is provided to `genmagstr`, previously they would be silently set to zero
- Raise error if wrong number of spins `S` is provided to `genmagstr` in `helical` mode. Previously the structure would be silently initialised to a random structure.
- Raise error if a complex spin `S` is provided to `genmagstr` in `helical` mode. Previously this meant it would silently ignore the `n` option, and behave exactly like `fourier` mode.
- Raise error if `rotate` mode is used without first initialising a magnetic structure
- Emit deprecation warning if the undocumented `extend` mode is used in `genmagstr`
- Raise error if the first spin is parallel to `n` and no rotation angle is provided in `rotate` mode in `genmagstr`. Previously this would silently result in `NaN`
- Raise error if `phi` or `phid` is not real in `rotate` mode in `genmagstr`. This was an undocumented feature which has been removed.
- Emit warning that the spin amplitude will be moderated if components of `S` are parallel to `n` in `helical` mode in `genmagstr`
- Emit warning if `nExt` is unnecessarily large compared to `k` in `helical` and `fourier` modes in `genmagstr`
- Emit warning if arguments that will be ignored are passed to a particular mode in `genmagstr` (e.g. `S` is passed to `random`)
- Raise error if complex values is provided for `n` in `genmagstr`. Previously this would've caused a crash.
- Fix error when plotting progress of `optmagsteep` without existing figure
- Correctly report magnetic moments in each iteration of `optmagsteep`.
- Fix errors when calling `intmatrix` with dipolar bonds and symbolic spinw object with fitmode true and false
- Ensure biquadratic exchange interactions are isotropic in `addcoupling` (previously checked in `intmatrix`)
- Raise error if invalid shape `kbase` is provided to `optmagk`, previously it would be silently set to empty
- Ensure varargin is correctly passed through to `ndbase.pso` from `optmagk`. Previously user provided `TolFun`, `TolX` and `MaxIter` would be overwritten by the defaults.
- Warn users that that the results of `spinwave` have not been scientifically validated for supercell structures with an incommensurate modulation.
- Emit warning if wrong length `xmin`, `xmax` or `x0` is passed to `optmagstr`. Previously they would be silently ignored.
- No longer require a magnetic structure be initialised with `genmagstr` before using `optmagstr`. If not intialised, a default `nExt` of `[1 1 1]` is used. This has also been clarified in the docstring.
- Fix bug where powder spectra was not recognised in `sw_plotspec`, introduced by a previous update to provide more helpful error messages.
- `sw_instrument` now calculates the limits for thetaMax, before it was using the continuation of the thetaMin line to high Q which is incorrect.
- Fixes a parsing error in the `spinw.fourier` method if no sublat option given.

98 changes: 0 additions & 98 deletions CHANGELOG.rst

This file was deleted.

6 changes: 3 additions & 3 deletions swfiles/@spinw/fitspec.m
Original file line number Diff line number Diff line change
Expand Up @@ -264,13 +264,13 @@
[x(idx,:),~, output(idx)] = ndbase.pso(dat,@(x,p)spec_fitfun(obj, data, param.func, p, param0),x0,'lb',param.xmin,'ub',param.xmax,...
'TolX',param.tolx,'TolFun',param.tolfun,'MaxIter',param.maxiter);

redX2(idx) = output.redX2;
redX2(idx) = output(idx).redX2;

case 'simplex'
[x(idx,:),~, output(idx)] = ndbase.simplex(dat,@(x,p)spec_fitfun(obj, data, param.func, p, param0),x0,'lb',param.xmin,'ub',param.xmax,...
'TolX',param.tolx,'TolFun',param.tolfun,'MaxIter',param.maxiter);

redX2(idx) = output.redX2;
redX2(idx) = output(idx).redX2;

case 'lm'
% does not work due to the binning of the spectrum
Expand Down Expand Up @@ -448,7 +448,7 @@
if param.plot
text(0.05,0.9,['x = [' sprintf('%6.4f ',x) sprintf(']\nRw = %6.4f',sqrt(R))],'Units','normalized','fontsize',12);
axis([0.5 Qc+0.5 param.Evect(1) param.Evect(end)]);
legend(pHandle(1:2),'simulation','data')
legend(pHandle([1, length(simE)+2]),'simulation','data')
xlabel('Scan index')
ylabel('Energy transfer (meV)')
title('Spin wave dispersion fit')
Expand Down
18 changes: 16 additions & 2 deletions swfiles/@spinw/spinwave.m
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,11 @@
% use mex file by default?
useMex = pref.usemex;

if isa(hkl, 'sym') && ~obj.symbolic
obj.symbolic(true);
setnosym = onCleanup(@()obj.symbolic(false));
end

% calculate symbolic spectrum if obj is in symbolic mode
if obj.symbolic
if numel(hkl) == 3
Expand All @@ -309,7 +314,7 @@
end
spectra = obj.spinwavesym(varargin{:});
else
spectra = obj.spinwavesym(varargin{:},'hkl',hkl);
spectra = obj.spinwavesym(varargin{:},'hkl',hkl(:));
end
return
end
Expand Down Expand Up @@ -399,6 +404,11 @@
'structure is commensurate so this will have no effect.']);
end

% If only one hkl value, convert to column vector
if numel(hkl) == 3
hkl = hkl(:);
end

% Transform the momentum values to the new lattice coordinate system
hkl = obj.unit.qmat*hkl;

Expand Down Expand Up @@ -1266,7 +1276,11 @@
spectra.title = param.title;
spectra.gtensor = param.gtensor;

if ~param.fitmode
if param.fitmode
% Copies only fields needed by downstream functions (sw_egrid, sw_neutron, sw_plotspec)
spectra.obj = struct('single_ion', obj.single_ion, 'twin', obj.twin, ...
'unit', obj.unit, 'basisvector', obj.basisvector, 'nmagext', obj.nmagext);
else
spectra.dateend = datestr(now);
spectra.obj = copy(obj);
end
Expand Down
2 changes: 1 addition & 1 deletion swfiles/@swpref/private/datastruct.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
20,...
12,...
1,...
@cm_inferno,...
@(x)flipud(cm_inferno(x)),...
false,...
'https://spinw.github.io/spinwdoc',...
-1,...
Expand Down
5 changes: 3 additions & 2 deletions swfiles/sw_egrid.m
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,8 @@
if param.T==0
nBose = double(ebin_cens>=0);
else
nBose = 1./(exp(abs(ebin_cens)./(spectra.obj.unit.kB*param.T))-1)+double(ebin_cens>=0);
kB = 0.086173324;
nBose = 1./(exp(abs(ebin_cens)./(kB*param.T))-1)+double(ebin_cens>=0);
end

% Sums up the intensities in DSF into swConv.
Expand Down Expand Up @@ -555,7 +556,7 @@
if isfield(spectra,'obj')
vol = spectra.obj.twin.vol/sum(spectra.obj.twin.vol);
else
vol = 1;
vol = ones(1,nTwin);
end
swConvT = cell(nConv,1);
DSFT = cell(nConv,1);
Expand Down
Loading

0 comments on commit 3e8b492

Please sign in to comment.