Mercurial > repos > public > sbplib
changeset 691:527a7b954f26 feature/quantumTriangles
Merge with default
author | Ylva Rydin <ylva.rydin@telia.com> |
---|---|
date | Thu, 14 Sep 2017 16:00:36 +0200 |
parents | f235284e2eb1 (current diff) bcddbc2beef4 (diff) |
children | dd3e9a0f5032 |
files | textTable.m |
diffstat | 20 files changed, 759 insertions(+), 89 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Cell.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,88 @@ +% Cell is a reimplementation of matlabs cell array with the benefit that it is subclassable +% It might be used for giving a typename to a cellarray to increase readability of the code. +classdef Cell + properties + data + end + + methods + function obj = Cell(data) + default_arg('data', {}); + if ~iscell(data) + error('Input argument to Cell must be a cell array'); + end + + obj.data = data; + end + + function str = toString(obj) + str = sprintf('%s%s', class(obj), toString(obj.data)); + end + + function s = size(A) + s = size(A.data); + end + + function l = length(A) + l = length(A.data); + end + + function ind = end(A,k,n) + ind = builtin('end',A.data, k, n); + end + + function B = transpose(A) + b = A.data.'; + B = callConstructor(A, b); + end + + function B = ctranspose(A) + b = A.data'; + B = callConstructor(A, b); + end + + function A = subsasgn(A, S, B) + a = subsasgn(A.data, S, B); + A = callConstructor(A, a); + end + + function B = subsref(A, S) + switch S(1).type + case '()' + b = subsref(A.data, S(1)); + B = callConstructor(A, b); + if length(S) > 1 + B = subsref(B,S(2:end)); + end + case '{}' + B = subsref(A.data, S); + case '.' + B = builtin('subsref',A, S); + otherwise + error('unreachable'); + end + end + + function C = horzcat(varargin) + dataArray = cell(1, length(varargin)); + + for i = 1:length(varargin) + dataArray{i} = varargin{i}.data; + end + + c = horzcat(dataArray{:}); + C = callConstructor(varargin{1}, c); + end + + function C = vertcat(varargin) + dataArray = cell(1, length(varargin)); + + for i = 1:length(varargin) + dataArray{i} = varargin{i}.data; + end + + c = vertcat(dataArray{:}); + C = callConstructor(varargin{1}, c); + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CellTest.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,264 @@ +function tests = CellTest() + tests = functiontests(localfunctions); +end + +function testSize(testCase) + cases = { + {{}, [0, 0]}, + {{1}, [1, 1]}, + {{1, 2}, [1, 2]}, + {{1; 2}, [2, 1]}, + {{1, 2; 3, 4}, [2,2]}, + }; + + for i = 1:length(cases) + A = Cell(cases{i}{1}); + expected = cases{i}{2}; + + testCase.verifyEqual(size(A),expected); + end +end + +function testLength(testCase) + cases = { + {{}, 0}, + {{1}, 1}, + {{1, 2}, 2}, + {{1; 2}, 2}, + {{1, 2; 3, 4}, 2}, + }; + + for i = 1:length(cases) + A = Cell(cases{i}{1}); + expected = cases{i}{2}; + + testCase.verifyEqual(length(A),expected); + end +end + +function testTranspose(testCase) + testCase.verifyEqual(Cell({1i, 2}).', Cell({1i; 2})); + testCase.verifyEqual(Cell({1i; 2}).', Cell({1i, 2})); +end + +function testCtranspose(testCase) + testCase.verifyEqual(Cell({1i, 2})', Cell({1i; 2})); + testCase.verifyEqual(Cell({1i; 2})', Cell({1i, 2})); +end + +function testRoundIndexWithProperty(testCase) + A = Cell({3,2,1}); + + result = A([1,3]).data; + testCase.verifyEqual(result, {3, 1}); +end + +function testSubAssignmentRound(testCase) + cases = { + % { + % lArray, + % index, + % rhs, + % expectedResult + % }, + { + {}, + 1, + {'a'}, + {'a'}, + }, + { + {1}, + 1, + {'a'}, + {'a'}, + }, + { + {1,2,3}, + 2, + {'a'}, + {1,'a',3}, + }, + { + {1,2,3}, + 2, + [], + {1,3}, + }, + }; + + for i = 1:length(cases) + lArray = Cell(cases{i}{1}); + index = cases{i}{2}; + rhs = cases{i}{3}; + expectedResult = cases{i}{4}; + + lArray(index) = rhs; + + testCase.verifyEqual(lArray.data, expectedResult) + end +end + +function testSubAssignmentCurly(testCase) + cases = { + % { + % lArray, + % index, + % rhs, + % expectedResult + % }, + { + {}, + 1, + 'a', + {'a'}, + }, + { + {1}, + 1, + 'a', + {'a'}, + }, + { + {1,2,3}, + 2, + 'a', + {1,'a',3}, + }, + }; + + for i = 1:length(cases) + lArray = Cell(cases{i}{1}); + index = cases{i}{2}; + rhs = cases{i}{3}; + expectedResult = cases{i}{4}; + + lArray{index} = rhs; + + testCase.verifyEqual(lArray.data, expectedResult) + end +end + +function testIndexreferenceRound(testCase) + cases = { + % { + % array, + % index, + % roundResult + % }, + { + {1,2,3}, + 1, + {1}, + }, + { + {1,3,2}, + 2, + {3}, + }, + { + {1,3,2}, + [1 3], + {1, 2}, + }, + }; + + + for i = 1:length(cases) + array = Cell(cases{i}{1}); + index = cases{i}{2}; + expected = cases{i}{3}; + + result = array(index); + + testCase.verifyTrue(isa(result, 'Cell')); + testCase.verifyEqual(result.data, expected); + end +end + +function testEndIndexing(testCase) + C = Cell({1,2,3}); + + testCase.verifyEqual(C(end), Cell({3})); + testCase.verifyEqual(C{end}, 3); +end + +function testColonIndexing(testCase) + C = Cell({1, 2, 3}); + D = Cell({1; 2; 3}); + + testCase.verifyEqual(C(:), D); + testCase.verifyEqual(D(:), D); +end + +function testIndexreferenceCurly(testCase) + cases = { + % { + % array, + % index, + % curlyResult + % }, + { + {1,2,3}, + 1, + 1 + }, + { + {1,3,2}, + 2, + 3 + }, + }; + + + for i = 1:length(cases) + array = Cell(cases{i}{1}); + index = cases{i}{2}; + expected = cases{i}{3}; + + result = array{index}; + + testCase.verifyEqual(result, expected); + end +end + +function testConcat(testCase) + cases = { + {{},{}}, + {{1},{}}, + {{},{1}}, + {{1},{2}}, + {{1, 2},{3, 4}}, + {{1; 2},{3; 4}}, + }; + + horzCat = { + {}, + {1}, + {1}, + {1,2}, + {1, 2, 3, 4}, + {1, 3; 2, 4}, + }; + + vertCat = { + {}, + {1}, + {1}, + {1; 2}, + {1, 2; 3, 4}, + {1; 2; 3; 4}, + }; + + for i = 1:length(cases) + A = Cell(cases{i}{1}); + B = Cell(cases{i}{2}); + + C_horz = [A, B]; + C_vert = [A; B]; + + testCase.verifyEqual(C_horz.data, horzCat{i}); + testCase.verifyEqual(C_vert.data, vertCat{i}); + + end +end
--- a/Color.m Mon Aug 07 13:20:48 2017 +0200 +++ b/Color.m Thu Sep 14 16:00:36 2017 +0200 @@ -10,6 +10,26 @@ black = [0.000 0.000 0.000]; white = [1.000 1.000 1.000]; colors = { Color.blue, Color.red, Color.yellow, Color.green, Color.purple, Color.lightblue, Color.darkred, Color.black, Color.white}; + + notabilityYellow = [100.0 99.0 22.0 ]/100; + notabilityOrange = [97.0 61.0 15.0 ]/100; + notabilityRed = [92.0 22.0 18.0 ]/100; + + notabilityLightGreen = [67.0 99.0 22.0 ]/100; + notabilityGreen = [39.0 72.0 30.0 ]/100; + notabilityDarkGreen = [5.0 45.0 24.0 ]/100; + + notabilityLightBlue = [8.0 45.0 98.0 ]/100; + notabilityBlue = [11.0 30.0 69.0 ]/100; + notabilityDarkBlue = [7.0 5.0 46.0 ]/100; + + notabilityPink = [99.0 13.0 82.0 ]/100; + notabilityPurple = [64.0 11.0 77.0 ]/100; + notabilityDarkPurple = [38.0 19.0 56.0 ]/100; + + notabilityBrown = [58.0 40.0 22.0 ]/100; + notabilityGrey = [59.0 59.0 59.0 ]/100; + notabilityBlack = [0.0 0.0 0.0 ]/100; end methods(Static)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TextTable.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,122 @@ +classdef TextTable < handle + properties + data + fmtArray + vertDiv + horzDiv + + nCols + nRows + end + + methods + function obj = TextTable(data, vertDiv, horzDiv); + default_arg('vertDiv', []); + default_arg('horzDiv', []); + + + obj.data = data; + obj.vertDiv = vertDiv; + obj.horzDiv = horzDiv; + + [obj.nRows, obj.nCols] = size(data); + obj.fmtArray = cell(size(data)); + obj.formatAll('%s'); + + end + + function formatAll(obj, fmt) + obj.fmtArray(:,:) = {fmt}; + end + + function formatCell(obj, i, j, fmt) + obj.fmtArray{i,j} = fmt; + end + + function formatRow(obj, i, fmt) + obj.fmtArray(i,:) = {fmt}; + end + + function formatColumn(obj, j, fmt) + obj.fmtArray(:,j) = {fmt}; + end + + function widths = getWidths(obj) + strArray = obj.getStringArray(); + + widths = zeros(1,obj.nCols); + for j = 1:obj.nCols + for i = 1:obj.nRows + widths(j) = max(widths(j), length(strArray{i,j})); + end + end + end + + function str = toString(obj) + strArray = obj.getStringArray(); + widths = obj.getWidths(); + + str = ''; + + % First horzDiv + if ismember(0, obj.horzDiv) + str = [str, obj.getHorzDiv(widths)]; + end + + for i = 1:obj.nRows + str = [str, TextTable.rowToString(strArray(i,:), widths, obj.vertDiv, obj.horzDiv)]; + + % Interior horzDiv + if ismember(i, obj.horzDiv) + str = [str, obj.getHorzDiv(widths)]; + end + end + end + + function str = getHorzDiv(obj, widths) + str = TextTable.rowToString(cell(1,obj.nCols), widths, obj.vertDiv, obj.horzDiv); + str(find(' ' == str)) = '-'; + str(find('|' == str)) = '+'; + end + + function strArray = getStringArray(obj) + strArray = cell(size(obj.data)); + + for i = 1:obj.nRows + for j = 1:obj.nCols + strArray{i,j} = sprintf(obj.fmtArray{i,j}, obj.data{i,j}); + end + end + end + end + + methods (Static) + function str = rowToString(strs, widths, vertDiv, horzDiv) + % First vertDiv + if ismember(0, vertDiv) + str = '| '; + else + str = ' '; + end + + % Interior cols + for j = 1:length(strs) - 1 + str = [str, sprintf('%*s ', widths(j), strs{j})]; + + % Interior vertDiv + if ismember(j, vertDiv) + str = [str, '| ']; + end + end + + % Last col + str = [str, sprintf('%*s ', widths(end), strs{end})]; + + if ismember(length(strs), vertDiv) + str = [str, '|']; + end + + str = [str, sprintf('\n')]; + end + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/assertType.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,5 @@ +function assertType(obj, type) + if ~isa(obj, type) + error('sbplib:assertType:wrongType', '"%s" must have type "%s", found "%s"', inputname(1), type, class(obj)); + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/callConstructor.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,6 @@ +% Calls the constructor of an object. +% Might be usefull to call the constructor of a subclass object in the superclass +function obj = callConstructor(subclassObj, varargin) + fun = str2func(class(subclassObj)); + obj = fun(varargin{:}); +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/checkAllCode.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,6 @@ +% Run matlabs checkcode on all files in current folder including subfolders +function checkAllCode(d) + default_arg('d','') + files = findMfiles(d); + checkcode(files) +end
--- a/convergenceTable.m Mon Aug 07 13:20:48 2017 +0200 +++ b/convergenceTable.m Thu Sep 14 16:00:36 2017 +0200 @@ -1,15 +1,15 @@ -function convergenceTable(methodName, T, orders, m, e, q, tableType) +function convergenceTable(caption, orders, m, e, q, tableType) default_arg('tableType','plaintext') switch tableType case {'plaintext','text','plain'} - plainTextTable(methodName, T, orders, m, e, q); + plainTextTable(caption, orders, m, e, q); case {'tex', 'latex'} - latexTable(methodName, T, orders, m, e, q); + latexTable(caption, orders, m, e, q); end end -function plainTextTable(methodName, T, orders, m, e, q) +function plainTextTable(caption, orders, m, e, q) eW = 0; @@ -23,7 +23,7 @@ mW = findFieldWidth('%d',m); orderHeaderWidth = eW + qW + 1; - fprintf('method: %s\nT: %d\n',methodName, T); + fprintf('%s\n',caption); % Print order headers fprintf(' %*s |',mW,'') @@ -69,7 +69,7 @@ end -function latexTable(methodName, T, orders, m, e, q) +function latexTable(caption, orders, m, e, q) nOrders = length(orders); @@ -85,7 +85,7 @@ footer = { '\end{tabular}' - '\caption{Error $l_2$, and convergence rate, $q$, for SBP operators of orders 4 and 6 at different grid densities $N$. PROBLEM DESCRIPTION.}' + ['\caption{' caption '}'] '\label{table:LABEL}' '\end{table}' };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/findMfiles.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,14 @@ +% Find all m files reachable from folder d +function files = findMfiles(d) + contents = what(d); + + files = {}; + for i = 1:length(contents.m) + files{end+1} = fullfile(d, contents.m{i}); + end + + for i = 1:length(contents.packages) + packagePath = fullfile(d,['+' contents.packages{i}]); + files = [files, findMfiles(packagePath)]; + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/isEquidistant.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,19 @@ +% Tests if consecutive elements of vector v are euidistant +function b = isEquidistant(v) + if length(v) < 2 + error('sbplib:isEquidistant:inputTooShort', 'Input vector is too short'); + end + + tol = 1e-8; + + d = v(2:end) - v(1:end-1); + err = abs(d - d(1)); + + relErr = err./abs(d); + + I_zero = find(d < tol); + + relErr(I_zero) = err(I_zero); + + b = all(relErr < tol); +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/isEquidistantTest.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,31 @@ +function tests = isEquidistantTest() + tests = functiontests(localfunctions); +end + +function testTooShortInput(testCase) + testCase.verifyError(@()isEquidistant([]), 'sbplib:isEquidistant:inputTooShort') +end + +function testCorrectOutput(testCase) + cases = { + % {input, expected}, + {[0,0,0,0,0], true}, + {[1,1,1,1,1], true}, + {[1,2,3,4,5], true}, + {[1,3,4,5], false}, + {[1,2,3,5], false}, + {[1,2,4,5], false}, + {linspace(0,pi, 3), true}, + {linspace(0,1, 4), true}, + {linspace(0,1, 4123), true}, + {linspace(0,sin(1), 123), true}, + }; + + for i = 1:length(cases) + input = cases{i}{1}; + expected = cases{i}{2}; + result = isEquidistant(input); + + testCase.verifyEqual(result,expected); + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/logsurf.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,19 @@ +function [srfHandle, cbHandle] = logsurf(X,Y,Z, lim) + absLogZ = log10(abs(Z)); + srfHandle = surf(X,Y,absLogZ); + + cbHandle = colorbar(); + colormap(hot(256)); + ah = gca(); + ah.CLim = lim; + + oldTickLabels = cbHandle.TickLabels; + + newTickLabels = {}; + + for i = 1:length(oldTickLabels) + newTickLabels{i} = sprintf('10^{%s}',oldTickLabels{i}); + end + + cbHandle.TickLabels = newTickLabels; +end \ No newline at end of file
--- a/plotConvergenceFit.m Mon Aug 07 13:20:48 2017 +0200 +++ b/plotConvergenceFit.m Thu Sep 14 16:00:36 2017 +0200 @@ -1,16 +1,45 @@ -% Draws a line in a loglog plot with slope `slope` and position `pos` -% and `width` orders of magnitude wide. -% ex: pos = [1e-1 1e-4] +% Draws a line in a loglog plot with slope `slope` fitted to the data in `x` +% and `y`. `xlength` scales how much of the interval [x(1) x(end)] is coverd +% by the line. `offset` is a multiplicative offset to where the line is drawn +% relative to the data. +function hand = plotConvergenceFit(slope, x, y, xlength, offset) + default_arg('xlength', 0.8) + default_arg('offset', 1); + + % Optimise for log(y) = p*log(x) + q + + p = slope; -function hand = plotConvergenceFit(slope, pos, width) - x0 = pos(1); - y0 = pos(2); + logx = log(x); + logy = log(y); + + N = length(logx); + + q = 1/N*sum(logy-p*logx); - x = [x0*10^-(width/2) x0*10^(width/2)]; - y = x.^slope * x0^-slope * y0; + logxlength = xlength * abs(logx(end)-logx(1)); + logxends = (logx(1)+logx(end))/2 + [-logxlength/2, logxlength/2]; - hand = line(x,y); + xends = exp(logxends); + yends = exp(q)*xends.^p; + + hand = line(xends, yends); hand.Color = Color.black; hand.LineStyle = '--'; hand.LineWidth = 2; -end \ No newline at end of file +end + + + +% function hand = plotConvergenceFit(slope, pos, width) +% x0 = pos(1); +% y0 = pos(2); + +% x = [x0*10^-(width/2) x0*10^(width/2)]; +% y = x.^slope * x0^-slope * y0; + +% hand = line(x,y); +% hand.Color = Color.black; +% hand.LineStyle = '--'; +% hand.LineWidth = 2; +% end \ No newline at end of file
--- a/runtestsAll.m Mon Aug 07 13:20:48 2017 +0200 +++ b/runtestsAll.m Thu Sep 14 16:00:36 2017 +0200 @@ -1,6 +1,8 @@ function res = runtestsAll() l = dir(); + warning('Simplify using the ''what'' command') + dirNames = {l([l.isdir]).name}; packages = {};
--- a/savepng.m Mon Aug 07 13:20:48 2017 +0200 +++ b/savepng.m Thu Sep 14 16:00:36 2017 +0200 @@ -11,11 +11,7 @@ h.PaperUnits = 'centimeters'; h.PaperPosition(3:4) = h.Position(3:4); - % Save as a bugged eps file. print(h,filename,'-dpng',sprintf('-r%d',dpi)); h.Units = handle_units; % Restore the old units - - - end
--- a/spyh.m Mon Aug 07 13:20:48 2017 +0200 +++ b/spyh.m Thu Sep 14 16:00:36 2017 +0200 @@ -3,10 +3,14 @@ [n,m] = size(A); [I,J] = find(A); - h = plot(J,I); - h.LineStyle = 'none'; - h.Marker = '.'; - h.MarkerSize = 14; + if ~isempty(J) + h = plot(J,I); + h.LineStyle = 'none'; + h.Marker = '.'; + h.MarkerSize = 14; + else + h = []; + end a = gca; xlim([0 m+1]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spzeros.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,18 @@ +function S = spzeros(varargin) + switch length(varargin) + case 2 + S = sparse(varargin{1}, varargin{2}); + case 1 + v = varargin{1}; + switch length(v) + case 1 + S = sparse(v,v); + case 2 + S = sparse(v(1), v(2)); + otherwise + error('Input must be either one integer, two integers or a vector with two integers'); + end + otherwise + error('Too many input arguments.'); + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/surfSym.m Thu Sep 14 16:00:36 2017 +0200 @@ -0,0 +1,54 @@ +function h = surfSym(X,Y,Z) + if isvector(X) && isvector(Y) + [X,Y] = meshgrid(X,Y); + end + + V_nodes = [X(:), Y(:), Z(:)]; + + X_centers = neighbourMean(X); + Y_centers = neighbourMean(Y); + Z_centers = neighbourMean(Z); + V_centers = [X_centers(:), Y_centers(:), Z_centers(:)]; + + + N = prod(size(X)); + nodeIndecies = reshape(1:N, size(X)); + centerIndecies = reshape(N+(1:prod(size(X)-[1,1])), size(X) - [1,1]); + + % figure() + % h = line(V_nodes(:,1),V_nodes(:,2),V_nodes(:,3)); + % h.LineStyle = 'none'; + % h.Marker = '.'; + % h = line(V_centers(:,1),V_centers(:,2),V_centers(:,3)); + % h.LineStyle = 'none'; + % h.Marker = '.'; + % h.Color = Color.red; + % axis equal + + + I_0 = nodeIndecies(1:end-1, 1:end-1); + I_1 = nodeIndecies(2:end, 1:end-1); + I_2 = nodeIndecies(2:end, 2:end); + I_3 = nodeIndecies(1:end-1, 2:end); + I_C = centerIndecies; + + S.Vertices = [ + V_nodes; + V_centers; + ]; + + S.Faces = [ + I_0(:), I_1(:), I_C(:); + I_1(:), I_2(:), I_C(:); + I_2(:), I_3(:), I_C(:); + I_3(:), I_0(:), I_C(:); + ]; + + % figure() + h = patch(S, 'FaceVertexCData', S.Vertices(:,3),'FaceColor','flat'); +end + +% Calculate the mean of four neighbours around a patch +function M = neighbourMean(A) + M = (A(1:end-1, 1:end-1) + A(2:end, 1:end-1) + A(1:end-1, 2:end) + A(2:end, 2:end))/4; +end
--- a/textTable.m Mon Aug 07 13:20:48 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ - -% data -- cell array of numbers -% leftColstrings -- cell array of strings, for left column -% topRowStrings -- cell array of strings, for top row -% dataFormat -- (optional) format specifier, e.g. '%.2f' -function textTable(data, leftColStrings, topRowStrings, dataFormat) - - default_arg('dataFormat','%.2f') - - nRows = length(leftColStrings); - nCols = length(topRowStrings); - [m,n] = size(data); - - if(m ~= nRows || n ~=nCols) - error('Data dimensions must match labels'); - end - - % Find column widths - headerLength = 0; - for i = 1:nCols - headerLength = max(headerLength, length(topRowStrings{i} )); - end - - dataLength = 0; - for i = 1:nRows - for j = 1:nCols - temp = length(sprintf(dataFormat, data{i,j})); - dataLength = max(dataLength, temp); - end - end - dataLength = length(sprintf(dataFormat, data{1,1})); - - colWidth = max(headerLength,dataLength); - - % Print headers - fprintf(' %*s |',colWidth,'') - for i = 1:nCols - fprintf(' %-*s |', colWidth, topRowStrings{i}); - end - fprintf('\n'); - - % Print divider - m_dev = repmat('-',1,colWidth); - column_dev = repmat('-',1,colWidth); - fprintf('-%s-+',m_dev); - for i = 1:nCols - fprintf('-%s-+', column_dev); - end - fprintf('\n'); - - - % Print each row - dataFormat = ['%*' dataFormat(2:end)]; - for i = 1:nRows - fprintf(' %*s |',colWidth,leftColStrings{i}); - for j = 1:nCols - fprintf([' ' dataFormat ' |'], colWidth, data{i,j}); - end - fprintf('\n'); - end - - fprintf('\n'); - -end \ No newline at end of file
--- a/toString.m Mon Aug 07 13:20:48 2017 +0200 +++ b/toString.m Thu Sep 14 16:00:36 2017 +0200 @@ -51,6 +51,14 @@ end function str = struct2string(s) + if isscalar(s) + str = structScalar2string(s); + else + str = structArray2string(s); + end +end + +function str = structScalar2string(s) fn = fieldnames(s); if length(fn) == 0 @@ -68,3 +76,32 @@ str = [str sprintf('%s: %s}',fn{end}, value2string(value))]; end +function str = structArray2string(s) + fn = fieldnames(s); + + if length(fn) == 0 + str = '{}'; + return + end + + stringArray = cell(length(s)+1, length(fn)+1); + + stringArray(1,2:end) = fn; + + for i = 1:length(s) + stringArray{i+1,1} = i; + for j = 1:length(fn) + valueStr = value2string(s(i).(fn{j})); + stringArray{i+1,j+1} = valueStr; + end + end + + tt = TextTable(stringArray); + tt.fmtArray(2:end, 1) = {'%d'}; + tt.vertDiv = [1]; + tt.horzDiv = [1]; + str = tt.toString(); +end + + +