function map = tab20b(N)
% Qualitative colormap from MatPlotLib, for plots using the line ColorOrder.
% In MatPlotLib 2 it is named VEGA20b, for MatPlotLib 3 was renamed TAB20b.
%
% Copyright (c) 2017-2019 Stephen Cobeldick
%
%%% Syntax:
%  map = tab20b
%  map = tab20b(N)
%
% For MatPlotLib 2.0 improved colormaps were created for plot lines of
% categorical data. The new colormaps are introduced here:
% <http://matplotlib.org/2.0.0rc2/users/dflt_style_changes.html>
% VEGA10/TAB10 is the default Line Color Order for MatPlotLib 2 and 3.
%
% MATLAB axes ColorOrder (note that this is NOT the axes COLORMAP):
% <https://www.mathworks.com/help/matlab/creating_plots/defining-the-color-of-lines-for-plotting.html>
% <https://www.mathworks.com/help/matlab/graphics_transition/why-are-plot-lines-different-colors.html>
%
%% Examples %%
%
%%% PLOT using matrices:
% N = 20;
% axes('ColorOrder',tab20b(N),'NextPlot','replacechildren')
% X = linspace(0,pi*3,1000);
% Y = bsxfun(@(x,n)sqrt(n)*sin(x+2*n*pi/N), X(:), 1:N);
% plot(X,Y, 'linewidth',4)
%
%%% PLOT in a loop:
% N = 20;
% set(0,'DefaultAxesColorOrder',tab20b(N))
% X = linspace(0,pi*3,1000);
% Y = bsxfun(@(x,n)sqrt(n)*sin(x+2*n*pi/N), X(:), 1:N);
% for n = 1:N
%     plot(X(:),Y(:,n), 'linewidth',4);
%     hold all
% end
%
%%% LINE using matrices:
% N = 20;
% set(0,'DefaultAxesColorOrder',tab20b(N))
% X = linspace(0,pi*3,1000);
% Y = bsxfun(@(x,n)sqrt(n)*cos(x+2*n*pi/N), X(:), 1:N);
% line(X(:),Y)
%
%% Input and Output Arguments %%
%
%%% Inputs (*=default):
% N = NumericScalar, N>=0, an integer to define the colormap length.
%   = *[], use the length of the current figure's colormap (see COLORMAP).
%
%%% Outputs:
% map = NumericMatrix, size Nx3, a colormap of RGB values between 0 and 1.
%
% See also TAB10 TAB20 TAB20C SET TWILIGHT VIRIDIS LINES COLORMAP PARULA

if nargin<1
	N = size(get(gcf,'colormap'),1);
else
	assert(isscalar(N)&&isreal(N),'First argument must be a real numeric scalar.')
	assert(fix(N)==N&&N>=0,'First argument must be a positive integer.')
end
%
hex = ['#393b79';'#5254a3';'#6b6ecf';'#9c9ede';'#637939';'#8ca252';'#b5cf6b';'#cedb9c';'#8c6d31';'#bd9e39';'#e7ba52';'#e7cb94';'#843c39';'#ad494a';'#d6616b';'#e7969c';'#7b4173';'#a55194';'#ce6dbd';'#de9ed6'];
raw = sscanf(hex.','#%2x%2x%2x',[3,Inf]).';
%
map = raw(1+mod(0:N-1,size(raw,1)),:) / 255;
%
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%tab20b


function value = p20_r8 ( action, name, value )

%*****************************************************************************80
%
%% P20_R8 sets or gets R8 parameters for problem 20.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 March 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string ACTION,
%    'D' sets the parameter to its default value;
%    'G' gets a parameter.
%    'R' sets the parameter to a random value.
%    'S' sets a parameter,
%
%    Input, string NAME, the name of the parameter.
%    'A' is the value of all lower integral bounds.
%    'B' is the value of all upper integral bounds.
%    'P' is the value of the exponent in the integrand.
%
%    Input/output, real VALUE.
%    * If ACTION = 'S', then VALUE is an input quantity, and is the
%      new value to be assigned to NAME.
%    * If ACTION = 'G' or 'R', then VALUE is an output quantity,
%      and is the current value of NAME.
%
  persistent a;
  persistent b;
  persistent p;

  if ( action == 'D' | action == 'd' )

    if ( name == 'A' | name == 'a' | name == '*' )
      a = 0.0;
    end

    if ( name == 'B' | name == 'b' | name == '*' )
      b = 1.0;
    end

    if ( name == 'P' | name == 'p' | name == '*' )
      p = 2.0;
    end

  elseif ( action == 'G' | action == 'g' )

    if ( name == 'A' | name == 'a' )
      value = a;
    elseif ( name == 'B' | name == 'b' )
      value = b;
    elseif ( name == 'P' | name == 'p' )
      value = p;
    else
      fprintf ( 1, '\n' );
      fprintf ( 1, 'P20_R8 - Fatal error!\n' );
      fprintf ( 1, '  Unrecognized name = "%s".\n', name );
      error ( 'P20_R8 - Fatal error!' );
    end

  elseif ( action == 'R' | action == 'r' )

    if ( name == 'A' | name == 'a' )
      a = rand ( 1, 1 );
      value = a;
    elseif ( name == 'B' | name == 'b' )
      b = rand ( 1, 1 );
      value = b;
    elseif ( name == 'P' | name == 'p' )
      p = rand ( 1, 1 );
      value = p;
    else
      fprintf ( 1, '\n' );
      fprintf ( 1, 'P20_R8 - Fatal error!\n' );
      fprintf ( 1, '  Unrecognized name = "%s".\n', name );
      error ( 'P20_R8 - Fatal error!' );
    end

  elseif ( action == 'S' | action == 's' )

    if ( name == 'A' | name == 'a' )
      a = value;
    elseif ( name == 'B' | name == 'b' )
      b = value;
    elseif ( name == 'P' | name == 'p' )
      p = value;
    else
      fprintf ( 1, '\n' );
      fprintf ( 1, 'P20_R8 - Fatal error!\n' );
      fprintf ( 1, '  Unrecognized name = "%s".\n', name );
      error ( 'P20_R8 - Fatal error!' );
    end

  else

    fprintf ( 1, '\n' );
    fprintf ( 1, 'P20_R8 - Fatal error!\n' );
    fprintf ( 1, '  Unrecognized action = "%s".\n', action );
    error ( 'P20_R8 - Fatal error!' );

  end

  return
end


function [S] = cell2nestedstruct(C)
%
%  S = CELL2NESTEDSTRUCT(C) converts an MxN cell array C into a
%     nested 1x1 structure array S
%
%     Examples:
%
%       C = {'a','b',1;  'qqq','',cell(6,2);   'aa','',[1 3]};
%       [S] = cell2nestedstruct(C)
%
%       S =
%           a: [1x1 struct]
%           qqq: {6x2 cell}
%           aa: [1 3]
%
%
%       C = {'water'    'a'     ''     ''     ''    111;...
%            'water'    'b'     ''     ''     ''    222;...
%            'melon'     ''     ''     ''     ''    [];...
%            'a'        'b'    'c'    'd'    'e'    'aaa';...
%            'q'        'r'     ''     ''     ''    cell(6,2)};
%       [S] = cell2nestedstruct(C);
%       [C2] = nestedstruct2cell(S);
%       isequal(C,C2)
%
%       ans =
%
%           1
%
%
%     Notes:
%       1. The fields in the first N-1 rows of C must be be left-justified.
%       2. The data must be in the right-most column.
%       3. The structure is produced row-by-row using the general syntax:
%                   S.row1.row2. ... rowN-1 = rowN;
%           which means that a sigle row, for example:
%                   {'water'    'a'     ''     ''     ''    111}
%           is equivalent to entering:
%                   S.water.a = 111;
%
%
%
%     See also CELL2STRUCT, STRUCT2CELL
%
%     See also NESTEDSTRUCT2CELL (available at Matlab
%     Central File Exchange)
%
%Author:
%
% Todd C Pataky (0todd0@gmail.com)  26-May-2006

%Programming notes:
%1. Currently working on implementating of MxN structural array, but
%   blank fields, for example, make the N-D case difficult to deal with.
%   Suggestions appreciated.

%%%%%%%%%%%%%%%%%%%%
%DATA ORGANIZATION CHECKS
%%%%%%%%%%%%%%%%%%%%
if ~iscell(C) | ndims(C)~=2 | size(C,2)<2
    error('Must input an MxN cell array (N>1).')
end
if ~iscellstr(C(:,1:end-1))
    error('First %.0f columns of cell array must contain strings.',size(C,2)-1)
end
%%%%%%%%%%%%%%%%%%%%
%check that empty cells are to the right
%%%%%%%%%%%%%%%%%%%%
c = C(:,1:end-1);
L = ones(size(c));
ind = strmatch({' '},c);
L(ind) = 0;   %logical array indicating non-blank entries
for k=1:size(L,1)
    f = find(L(k,:));
    if ~isequal(f,1:length(f))
        error('All non-blank cells in row %.0f must be left-justified',k)
    end
end
%%%%%%%%%%%%%%%%%%%%
%check that there are no duplicate rows
%%%%%%%%%%%%%%%%%%%%
for k = 1:size(C,1)-1
    c = C(k,1:end-1);
    for kk = (k+1):size(C,1);
        cc = C(kk,1:end-1);
        if isequal(c,cc)
            error('Rows %.0f and %.0f are identical branches',k,kk);
        end
    end
end
%%%%%%%%%%%%%%%%%%%%
%check that branches go to the same depth (i.e. check for branch overwriting)
%%%%%%%%%%%%%%%%%%%%
hereCheckOverWrite(C(:,1:end-1));    %see subfunction below

%%%%%%%%%%%%%%%%%%%%
%ASSEMBLE STRUCTURE ROW-BY-ROW
%%%%%%%%%%%%%%%%%%%%
for k=1:size(C,1)
    a = C(k,:);
    ind = strmatch('',a(1:end-1),'exact');
    a(ind) = [];

    s = a(1:end-1);
    data = a{end};

    s = [s; repmat({'.'},size(s))];
    s = s(:)';
    s = cat(2,s{1:end-1});

    eval(['S.',s,'= data;']);
end

%%%%%%%%%%%%%%%%%%%%
%SUBFUNCTIONS
%%%%%%%%%%%%%%%%%%%%
function hereCheckOverWrite(C)
%%%%%%%%%%%%%%%%%%%%
if size(C,2)==1
    return
end
%%%%%%%%%%%%%%%%%%%%
%if a zero stem has the same root as any other branch, error
%%%%%%%%%%%%%%%%%%%%
row = strmatch({' '},C(:,end));
for k=1:length(row)
    root0 = C(row(k),1:end-1);
    for kk=1:size(C,1)
        if kk~=row(k)
            root1 = C(kk,1:end-1);
            if isequal(root0,root1)
                error('Overwriting error. A stem from row %.0f is empty, but rows %.0f and %.0f have the same roots.',...
                    row(k) , min(row(k),kk) , max(row(k),kk) );
            end
        end
    end
end
hereCheckOverWrite(C(:,1:end-1));   %recurse


% ConvertToGray.m
% -------------------------------------------------------------------
%
% Authors: Sun Li
% Date:    05/05/2013
% Last modified: 05/05/2013
% -------------------------------------------------------------------

function imgGray = ConvertToGray(img)
    if size(img, 3) == 3,
        imgGray = RGBTOGRAY(img);
    else
        imgGray = img;
    end
end


function value = p26_autonomous ( )

%*****************************************************************************80
%
%% P26_AUTONOMOUS reports whether problem P26 is autonomous.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 February 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, integer VALUE, is 1 if the equation is autonomous.
%
  value = 1;

  return
end


function G = exchangenode(G,a,b)

%Exchange element at column a with element at column b;
buffer=G(:,a);
G(:,a)=G(:,b);
G(:,b)=buffer;

%Exchange element at row a with element at row b;
buffer=G(a,:);
G(a,:)=G(b,:);
G(b,:)=buffer;


function snakedisp(x,y,style)
%--------Display the snake model contour-----------

hold on

% convert to column data
x = x(:); y = y(:);

if nargin == 3          %nargin returns the number of input arguments specified for a function
   plot([x;x(1,1)],[y;y(1,1)],style);
   hold off
else
   disp('snakedisp.m: The input parameter is not correct!');
end


function map = tab10(N)
% Qualitative colormap from MatPlotLib, for plots using the line ColorOrder.
% In MatPlotLib 2 it is named VEGA10, for MatPlotLib 3 was renamed TAB10.
%
% Copyright (c) 2017-2020 Stephen Cobeldick
%
%%% Syntax:
%  map = tab10
%  map = tab10(N)
%
% For MatPlotLib 2.0 improved colormaps were created for plot lines of
% categorical data. The new colormaps are introduced here:
% <http://matplotlib.org/2.0.0rc2/users/dflt_style_changes.html>
% VEGA10/TAB10 is the default Line Color Order for MatPlotLib 2 and 3.
%
% MATLAB axes ColorOrder (note that this is NOT the axes COLORMAP):
% <https://www.mathworks.com/help/matlab/creating_plots/defining-the-color-of-lines-for-plotting.html>
% <https://www.mathworks.com/help/matlab/graphics_transition/why-are-plot-lines-different-colors.html>
%
%% Examples %%
%
%%% PLOT using matrices:
% N = 10;
% axes('ColorOrder',tab10(N),'NextPlot','replacechildren')
% X = linspace(0,pi*3,1000);
% Y = bsxfun(@(x,n)sqrt(n)*sin(x+2*n*pi/N), X(:), 1:N);
% plot(X,Y, 'linewidth',4)
%
%%% PLOT in a loop:
% N = 10;
% set(0,'DefaultAxesColorOrder',tab10(N))
% X = linspace(0,pi*3,1000);
% Y = bsxfun(@(x,n)sqrt(n)*sin(x+2*n*pi/N), X(:), 1:N);
% for n = 1:N
%     plot(X(:),Y(:,n), 'linewidth',4);
%     hold all
% end
%
%%% LINE using matrices:
% N = 10;
% set(0,'DefaultAxesColorOrder',tab10(N))
% X = linspace(0,pi*3,1000);
% Y = bsxfun(@(x,n)sqrt(n)*cos(x+2*n*pi/N), X(:), 1:N);
% line(X(:),Y)
%
%% Input and Output Arguments %%
%
%%% Inputs (*=default):
% N = NumericScalar, N>=0, an integer to define the colormap length.
%   = *[], use the length of the current figure's colormap (see COLORMAP).
%
%%% Outputs:
% map = NumericMatrix, size Nx3, a colormap of RGB values between 0 and 1.
%
% See also TAB20 TAB20B TAB20C SET VIRIDIS TWILIGHT LINES COLORMAP PARULA

if nargin<1 || isnumeric(N)&&isequal(N,[])
	N = size(get(gcf,'colormap'),1);
else
	assert(isscalar(N)&&isfinite(N)&&isreal(N),...
		'SC:tab10:N:NotRealFiniteScalarNumeric',...
		'First argument <N> must be a real finite numeric scalar.')
end
%
hex = ['#1f77b4';'#ff7f0e';'#2ca02c';'#d62728';'#9467bd';'#8c564b';'#e377c2';'#7f7f7f';'#bcbd22';'#17becf'];
raw = sscanf(hex.','#%2x%2x%2x',[3,Inf]).';
%
map = raw(1+mod(0:N-1,size(raw,1)),:) / 255;
%
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%tab10


		% Incarcarea continutului fisierului
load patrmag.dat
		% Alocarea variabilei B continutul fisierului
B=patrmag


function [map_osm] = load_osm_xml(filename)
% load OpenStreetMap XML file contents as a MATLAB structure
%
% download OpenStreetMap XML Data file to be parsed from:
%   http://www.openstreetmap.org/
%
% dependency
%   xml2struct, File Exchange ID = 28518, (c) 2010 by Wouter Falkena
%   http://www.mathworks.com/matlabcentral/fileexchange/28518-xml2struct
%
% note
%   xml2struct renamed to xml2struct_fex28518 to avoid name conflicts
%   with matlab bioinformatics toolbox
%
% 2010.11.06 (c) Ioannis Filippidis, jfilippidis@gmail.com
%
% See also PARSE_OPENSTREETMAP, PARSE_OSM.

if ~ischar(filename)
    error('Filename should be a string.')
end

if ~strfind(filename, '.osm')
    warning('Filename does not have the extension .osm')
end

map_osm = xml2struct_fex28518(filename); % downloaded osm file


function [glyphImage]=textImage(varargin)

% function [glyphImage]=textImage(textInput,FontName,FontSize,padAmount)
% ------------------------------------------------------------------------
% This function generates a 2D image containing text as provided in the
% input. The text is of high intensity while the background is of low
% intensity. The font type and font size can be specified allong with the
% amount of padding around the text.
%
%
% ------------------------------------------------------------------------

%%

switch nargin
    case 0
        textInput='GIBBON';
        FontName=vision.internal.getDefaultFont();
        FontSize=50;
        padAmount=0;
    case 1
        textInput=varargin{1};
        FontName=vision.internal.getDefaultFont();
        FontSize=50;
        padAmount=0;
    case 2
        textInput=varargin{1};
        FontName=varargin{2};
        FontSize=50;
        padAmount=0;
    case 3
        textInput=varargin{1};
        FontName=varargin{2};
        FontSize=varargin{3};
        padAmount=0;
    case 4
        textInput=varargin{1};
        FontName=varargin{2};
        FontSize=varargin{3};
        padAmount=varargin{4};
end

position=[0 0];

if isa(textInput,'cell')
    textString=char(textInput);
else
    textString=textInput;
end

if isempty(FontName)
    FontName=vision.internal.getDefaultFont();
end

%%
FONT=listTrueTypeFonts(FontName);

try
[glyphBitmapArray, ...
    glyphIdxFromCharcode, ...
    glyphBitmapStartIdx, ...
    glyphWidths, ...
    glyphHeights, ...
    glyphXAdvances, ...
    glyphLeftBearings, ...
    glyphTopBearings, ...
    fontAscend, ...
    fontDescend, ...
    fontLinespace, ...
    maxBitmapSize]=visionPopulateGlyphBuffer(FONT.fileName,FONT.faceIndex, ...
    FontSize,false);
catch ME
    warning(['Check if ',FontName,' is a valid font use listTrueTypeFonts to see available fonts']);
    rethrow(ME);
end

glyphStruct.glyphBitmapArray     = glyphBitmapArray;
glyphStruct.glyphIdxFromCharcode = glyphIdxFromCharcode;
glyphStruct.glyphBitmapStartIdx  = glyphBitmapStartIdx;
glyphStruct.glyphWidths          = glyphWidths;
glyphStruct.glyphHeights         = glyphHeights;
glyphStruct.glyphXAdvances       = glyphXAdvances;
glyphStruct.glyphLeftBearings    = glyphLeftBearings;
glyphStruct.glyphTopBearings     = glyphTopBearings;
%
glyphStruct.fontAscend            = fontAscend;
glyphStruct.fontDescend           = fontDescend;
glyphStruct.fontLinespace         = fontLinespace;

fontStruct.fontAscend            = fontAscend;
fontStruct.fontDescend           = fontDescend;
fontStruct.fontLinespace         = fontLinespace;

glyphStruct.maxBitmapSize         = maxBitmapSize;

%%

glyphIdxFromCharcode=glyphStruct.glyphIdxFromCharcode;
glyphXAdvances=glyphStruct.glyphXAdvances;
fontHeightWLinegap  = fontStruct.fontLinespace;
fontHeightWOLinegap = fontStruct.fontAscend - fontStruct.fontDescend;

b1 = 1; % for converting 0-based to 1-based
spaceGlyphIdx = glyphIdxFromCharcode(32+b1);
if (spaceGlyphIdx==0)
    spaceCharWidth = int32(fontHeightWOLinegap/4);
else
    spaceCharWidth = int32(glyphXAdvances(spaceGlyphIdx+b1));
end

MARGIN_LeftOrRight = spaceCharWidth; % used 3 before
MARGIN_TopOrBottom = spaceCharWidth; % used 3 before

%%

position = int32(position);

tbLocationXY = int32(position);

tbLocationX = tbLocationXY(1);
tbLocationY = tbLocationXY(2);

tbTopLeftY = tbLocationY;
tbTopLeftX = tbLocationX;

textLocationXY.x = tbTopLeftX + int32(MARGIN_LeftOrRight);
textLocationXY.y = tbTopLeftY + int32(MARGIN_TopOrBottom);

%%

textStringU16 = uint16(textString);

penX = int32(textLocationXY.x);

% go to reference baseline (near the middle of the glyph)
penY = int32(textLocationXY.y) + fontStruct.fontAscend;

oneI32 = int32(1);

isNewLineChar = (textStringU16 == uint16(10));

numChars = numel(textStringU16);

glyphImages=cell(1,numChars);
glyph_I=zeros(numChars,2);
glyph_J=zeros(numChars,2);
q=1;
for ii=1:size(textStringU16,1)
    %Set position
    if ii>1
        penY = penY + fontHeightWLinegap; % go to next line
    end
    penX = textLocationXY.x;
    for jj=1:size(textStringU16,2)

        %see logic in mdlOutputs of sviptextrender.cpp

        % reset x position to the beginning on a line

        thisCharcode = textStringU16(ii,jj);
        thisCharcode_1b = thisCharcode+b1;
        thisGlyphIdx = glyphStruct.glyphIdxFromCharcode(thisCharcode_1b);
        thisGlyphIdx_1b = thisGlyphIdx + b1;
        glyphExists = (thisGlyphIdx ~= 0);
        if ~glyphExists
            penX = penX + int32(spaceCharWidth);
        else
            thisGlyphW = glyphStruct.glyphWidths(thisGlyphIdx_1b);
            thisGlyphH = glyphStruct.glyphHeights(thisGlyphIdx_1b);

            xx=penX+int32(glyphStruct.glyphLeftBearings(thisGlyphIdx_1b));
            yy=penY-int32(glyphStruct.glyphTopBearings(thisGlyphIdx_1b));

            start_I = yy;
            end_I = yy+int32(thisGlyphH)- oneI32;
            start_J = xx;
            end_J = xx+int32(thisGlyphW)- oneI32;

            bitmapStartIdx_1b = glyphStruct.glyphBitmapStartIdx(thisGlyphIdx_1b) + b1;
            bitmapEndIdx_1b =  bitmapStartIdx_1b + uint32(thisGlyphW*thisGlyphH) - uint32(1);
            thisGlyphBitmap = glyphStruct.glyphBitmapArray(bitmapStartIdx_1b:bitmapEndIdx_1b);
            thisGlyphBitmap = reshape(thisGlyphBitmap,[thisGlyphW thisGlyphH])';

            glyphImages{q}=thisGlyphBitmap;
            glyph_I(q,:)=[start_I end_I];
            glyph_J(q,:)=[start_J end_J];

            % update X position for next character
            penX=penX+int32(glyphStruct.glyphXAdvances(thisGlyphIdx_1b));

        end
        q=q+1;
    end
end

%Crop around text
glyph_I=glyph_I-min(glyph_I(:))+1;
glyph_J=glyph_J-min(glyph_J(:))+1;

%% Create image

glyphImage=zeros(max(glyph_I(:))+min(glyph_I(:))-1,max(glyph_J(:))+min(glyph_J(:))-1);
for q=1:1:numChars
    glyphImage(glyph_I(q,1):glyph_I(q,2),glyph_J(q,1):glyph_J(q,2))=glyphImages{q};
end
glyphImage=double(glyphImage);

if padAmount>0
    siz=size(glyphImage)+2*padAmount;
    glyphImagePad=zeros(siz);
    glyphImagePad(padAmount+1:padAmount+size(glyphImage,1),padAmount+1:padAmount+size(glyphImage,2))=glyphImage;
    glyphImage=glyphImagePad;
end

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


% GETPROBLEM  Script for locating, reading and convert to SeDuMi, a problem
%   with the name specified by the variable `pname'. You have to define the
%   variable 'pname' before using this script.
%
% Usage: pname = 'problemname'; getproblem
%   Problem returned in (At,b,c,K).
%
% IMPORTANT
%   1. If you have an environment variable named SDPPACK, containing
%   the directory name of SDPPACK, then this searches in SDPPACK/problems.
%   2. If you have an environment variable named SDPLIB, then it searches
%   for problems in the directory SDPLIB/. These problems should be in
%   sparse SDPA format, with extension ".dat-s".
%   3. If LIPSOL is installed as a MATLAB Toolbox, then LIPSOL's  `findprob'
%   is used for searching MPS-type models.
%   4. Files with extension ".gz" are also recognized, so that you can
%   store your problem libraries more efficiently.
%
% See also  fromsdpa, frompack, prelp, feasreal, feascpx, sedumi,
%   postprocess (LIPSOL).

%
% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA  (since 1.1)
%
% Copyright (C) 2001 Jos F. Sturm (up to 1.05R5)
%   Dept. Econometrics & O.R., Tilburg University, the Netherlands.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% Affiliation SeDuMi 1.03 and 1.04Beta (2000):
%   Dept. Quantitative Economics, Maastricht University, the Netherlands.
%
% Affiliations up to SeDuMi 1.02 (AUG1998):
%   CRL, McMaster University, Canada.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
% 02110-1301, USA%

global PROBDIR

% ----------------------------------------
% status = {0 don't know yet, 1 SDPPack, 2 MPS, 3 SDPA}
% ----------------------------------------
status = 0;
PROBDIR = str2mat([]);
% ----------------------------------------
% Try to get problem in SDPA format, from SDPLIB
% ----------------------------------------
if status == 0
    SDPAPATH = getenv('SDPLIB');
    if ~isempty(SDPAPATH)
        MATNAME = [SDPAPATH '/' pname '.dat-s'];
        if exist(MATNAME,'file')
            [At,b,c,K] = fromsdpa(MATNAME); status = 3;
        elseif exist([MATNAME '.gz'],'file')
            unix(['gunzip -c ' MATNAME '.gz > /tmp/default.mat']);
            [At,b,c,K] = fromsdpa('/tmp/default.mat'); status = 3;
        end
    end
    clear SDPAPATH
end
% ----------------------------------------
% Try to get problem in SDPPACK format
% ----------------------------------------
if status == 0
    PACKPATH = getenv('SDPPACK');
    if ~isempty(PACKPATH)
        MATNAME = [PACKPATH '/problems/' pname '.mat'];
        if exist(MATNAME,'file')
            unix(['/bin/cp ' MATNAME ' /tmp/default.mat']); status = 1;
        elseif exist([MATNAME '.gz'],'file')
            unix(['gunzip -c ' MATNAME '.gz > /tmp/default.mat']); status = 1;
        end
    end
    clear PACKPATH
end
% ----------------------------------------
% Try to get problem in LIPSOL format
% ----------------------------------------
if(status == 0)
    if(exist('findprob','file') > 1)
        if (findprob([],pname) == 1)
            status = 2;
        end
    end
end
% ----------------------------------------
% Move the problem into [At,b,c,K] structure
% ----------------------------------------
if(status==0)
    error('Problem not found.  Check spelling?')
elseif(status==1)
    load /tmp/default
    % ----------------------------------------
    % In SDPPACK, 0s are sometimes used  as emptyset and vice versa.
    % ----------------------------------------
    if isempty(blk.l)
        blk.l = 0;
    end
    if ~isempty(blk.q)
        if(blk.q == 0)
            blk.q = [];
        end
    end
    if ~isempty(blk.s)
        if(blk.s == 0)
            blk.s = [];
        end
    end
    [At,c] = frompack(A,b,C,blk);
    if isempty(blk.l)
        blk.l = 0;
    end
    K = blk;
    % ----------------------------------------
    % LP problem: preprocess using LIPSOL.
    % ----------------------------------------
elseif(status==2)
    [At,b,c,nx,lbs] = prelp([]);
    At = At';
    clear K;
    K.l = length(c);
end
clear status
% clear global PROBDIR   %would disable LIPSOL.


%% Reads ECG recordings in Mortara format.
% Reads ECG recordings in Mortara format.
%
% Arguments:
%   + filename: recording to be read or folder containing HourXXRawData.bin
%   files.
%   + start_sample: (opt) start sample to read. Default 1.
%   + end_sample: (opt) end sample to read. Default min(All recording, ECG block of 200 Mbytes)
%
% Output:
%   + ECG: the ECG block
%   + heasig: header with the ECG properties.
%   + ann: annotations for the ECG recordings.
%
% Limits:
% This routine is limited to read blocks smaller than 200 Mbytes for
% performance reasons. You can disable this limit by doing:
% MaxIOread = Inf; %megabytes
%
% See also read_Mortara_header, read_ECG, ECGwrapper
%
% Author: Mariano Llamedo Soria
% <matlab:web('mailto:llamedom@electron.frba.utn.edu.ar','-browser') (email)>
% Version: 0.1 beta
% Birthdate: 29/05/2014
% Last update: 19/11/2014
% Copyright 2008-2015
%
function [ECG heasig end_sample] = read_Mortara_format( filename, start_sample, end_sample )

heasig.freq = 1000; %Hz
heasig.desc = char({'I','II','V1','V2','V3','V4','V5','V6'});
leads_in_mortara_files = 8;

ECG = [];
last_sample = [];

%No leer bloques mas grandes de 200 megabytes
MaxIOread = 200; %megabytes

if( nargin < 2 || isempty( start_sample ) )
    start_sample = 1;
else
    start_sample = max(1,start_sample);
end

if( isdir(filename) )
    rec_path = filename;
else
    [rec_path, rec_name] = fileparts(filename);
end

hours_files = dir([rec_path filesep 'Hour*.bin' ]);

hours_available = length(hours_files);

samples_per_hour = zeros(hours_available,1);

expected_samples = 60*60*heasig.freq;

for ii = 1:hours_available

    hour_filename = [rec_path filesep 'Hour' num2str(ii) 'RawData.bin' ];
    fid = fopen(hour_filename);

    if( fid > 0 )
        fseek(fid, 0, 'eof');
        bytes_totales = ftell(fid);
        samples_per_hour(ii) = bytes_totales / 2 / leads_in_mortara_files;
        fclose(fid);
        if( ii ~= expected_samples && samples_per_hour(ii) ~= expected_samples)
            error('read_Mortara_format:Impossible2read', 'Not enough samples in %s. Expected %d - found %d. Problem copying ?\n', hour_filename, expected_samples, samples_per_hour(ii));
        end
    else
        error('read_Mortara_format:Impossible2read', 'Problem opening %s.\n', hour_filename);
    end

end

total_samples = sum(samples_per_hour);

if( nargin < 3 || isempty( end_sample ) )
    %Intento la lectura total por defecto
    end_sample = total_samples;
end

samples2read = end_sample - start_sample + 1;

if( (samples2read*leads_in_mortara_files*2) > (MaxIOread * 1024^2) )
    samples2read = (MaxIOread * 1024^2) / leads_in_mortara_files / 2;
    end_sample = start_sample + samples2read - 1;
    warning(['No es recomendable leer mas de ' num2str(MaxIOread) ' Mb. Realice varias lecturas.'])
end

end_samples = cumsum(samples_per_hour);
start_samples = [1; end_samples(1:end-1)+1 ];
files2read = find(start_sample <= end_samples & end_sample >= start_samples );

for ii = rowvec(files2read)

    hour_filename = [rec_path filesep 'Hour' num2str(ii) 'RawData.bin' ];
    fidECG = fopen( hour_filename, 'r');

    if( fidECG > 0 )

        aux_offset = 0;

        if(ii == files2read(1))

            aux_offset = start_sample - start_samples(ii);
            fseek(fid, aux_offset * 2 * leads_in_mortara_files, 'cof');

        end

        if(ii == files2read(end))

            if( length(files2read) == 1 )
                % read samples from a single file
                this_samples2read = samples2read;
            else
                % read samples from several files
                this_samples2read = end_sample - start_samples(ii) + 1;
            end

        else

            if( aux_offset == 0)
                this_samples2read = samples_per_hour(ii);
            else
                this_samples2read = samples_per_hour(ii) - aux_offset;
            end

        end

        ECG = [ECG; fread(fid, [leads_in_mortara_files this_samples2read], '*int16')'];

        fclose(fid);
    else
        error('read_Mortara_format:Impossible2read', 'Problem opening %s.\n', hour_filename);
    end

end

[heasig.nsamp, heasig.nsig] = size(ECG);

if( abs(heasig.nsamp - samples2read) > 1 )
    warning('read_Mortara_format:ReadError', 'Problem reading %s. Required %d samples, and only read %d.\n', filename, samples2read, heasig.nsamp);
end

heasig.adczero = zeros(heasig.nsig,1);
heasig.gain = ones(heasig.nsig,1);
heasig.units = repmat('uV',heasig.nsig,1);

if( rec_path(end) == filesep )
    rec_path = rec_path(1:end-1);
end
[~, rec_name] = fileparts(rec_path);

heasig.recname = rec_name;
heasig.btime = calc_btime( start_sample, heasig.freq );
heasig.bdate = '01/01/2000';


function region = p11_region ( )

%*****************************************************************************80
%
%% P11_REGION returns the name of the integration region for problem 11.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 March 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, string REGION, the name of the integration region.
%
  region = 'box';

  return
end


function [ddtData] = get_all_from_ddt(filename)

ddtData  =[];
[dirstr, name, ext] = fileparts(filename);
ddtData.FileName = [name ext];

[ddtData.raw.nch, ddtData.raw.npoints, ddtData.raw.freq, ddtData.raw.d] = ddt(filename);
[ddtData.v.nch, ddtData.v.npoints, ddtData.v.freq, ddtData.v.d] = ddt_v(filename);


classdef TonemapDrago < handle
    %TONEMAPDRAGO  Tonemapping algorithm used to map HDR image to 8-bit range
    %
    % Adaptive logarithmic mapping is a fast global tonemapping algorithm that
    % scales the image in logarithmic domain.
    %
    % Since it's a global operator the same function is applied to all the
    % pixels, it is controlled by the bias parameter.
    %
    % Optional saturation enhancement is possible as described in [FL02].
    %
    % For more information see [DM03].
    %
    % ## References
    % [FL02]:
    % > Raanan Fattal, Dani Lischinski, and Michael Werman.
    % > "Gradient domain high dynamic range compression". In ACM Transactions
    % > on Graphics (TOG), volume 21, pages 249-256. ACM, 2002.
    %
    % [DM03]:
    % > Frederic Drago, Karol Myszkowski, Thomas Annen, and Norishige Chiba.
    % > "Adaptive logarithmic mapping for displaying high contrast scenes".
    % > In Computer Graphics Forum, volume 22, pages 419-426. Wiley Online
    % > Library, 2003.
    %
    % See also: cv.Tonemap, cv.TonemapDurand, cv.TonemapReinhard,
    %  cv.TonemapMantiuk, tonemap
    %

    properties (SetAccess = private)
        % Object ID
        id
    end

    properties (Dependent)
        % positive value for gamma correction.
        %
        % Gamma value of 1.0 implies no correction, gamma equal to 2.2 is
        % suitable for most displays. Generally gamma > 1 brightens the image
        % and gamma < 1 darkens it.
        Gamma
        % positive saturation enhancement value.
        %
        % 1.0 preserves saturation, values greater than 1 increase saturation
        % and values less than 1 decrease it.
        Saturation
        % value for bias function in [0, 1] range.
        %
        % Values from 0.7 to 0.9  usually give best results, default value
        % is 0.85
        Bias
    end

    %% TonemapDrago
    methods
        function this = TonemapDrago(varargin)
            %TONEMAPDRAGO  Creates TonemapDrago object
            %
            %     obj = cv.TonemapDrago()
            %     obj = cv.TonemapDrago('OptionName',optionValue, ...)
            %
            % ## Options
            % * __Gamma__ default 1.0
            % * __Saturation__ default 1.0
            % * __Bias__ default 0.85
            %
            % See also: cv.TonemapDrago.process
            %
            this.id = TonemapDrago_(0, 'new', varargin{:});
        end

        function delete(this)
            %DELETE  Destructor
            %
            %     obj.delete()
            %
            % See also: cv.TonemapDrago
            %
            if isempty(this.id), return; end
            TonemapDrago_(this.id, 'delete');
        end
    end

    %% Tonemap
    methods
        function dst = process(this, src)
            %PROCESS  Tonemaps image
            %
            %     dst = obj.process(src)
            %
            % ## Input
            % * __src__ source RGB image, 32-bit `single` 3-channel array.
            %
            % ## Output
            % * __dst__ destination image of same size as `src`, 32-bit
            %   `single` 3-channel array with values in [0,1] range.
            %
            % See also: cv.TonemapDrago.TonemapDrago
            %
            dst = TonemapDrago_(this.id, 'process', src);
        end
    end

    %% Algorithm
    methods (Hidden)
        function clear(this)
            %CLEAR  Clears the algorithm state
            %
            %     obj.clear()
            %
            % See also: cv.TonemapDrago.empty, cv.TonemapDrago.load
            %
            TonemapDrago_(this.id, 'clear');
        end

        function b = empty(this)
            %EMPTY  Returns true if the algorithm is empty
            %
            %     b = obj.empty()
            %
            % ## Output
            % * __b__ Returns true if the object is empty (e.g in the
            %   very beginning or after unsuccessful read).
            %
            % See also: cv.TonemapDrago.clear, cv.TonemapDrago.load
            %
            b = TonemapDrago_(this.id, 'empty');
        end

        function name = getDefaultName(this)
            %GETDEFAULTNAME  Returns the algorithm string identifier
            %
            %     name = obj.getDefaultName()
            %
            % ## Output
            % * __name__ This string is used as top level XML/YML node tag
            %   when the object is saved to a file or string.
            %
            % See also: cv.TonemapDrago.save, cv.TonemapDrago.load
            %
            name = TonemapDrago_(this.id, 'getDefaultName');
        end

        function save(this, filename)
            %SAVE  Saves the algorithm parameters to a file
            %
            %     obj.save(filename)
            %
            % ## Input
            % * __filename__ Name of the file to save to.
            %
            % This method stores the algorithm parameters in the specified
            % XML or YAML file.
            %
            % See also: cv.TonemapDrago.load
            %
            TonemapDrago_(this.id, 'save', filename);
        end

        function load(this, fname_or_str, varargin)
            %LOAD  Loads algorithm from a file or a string
            %
            %     obj.load(fname)
            %     obj.load(str, 'FromString',true)
            %     obj.load(..., 'OptionName',optionValue, ...)
            %
            % ## Input
            % * __fname__ Name of the file to read.
            % * __str__ String containing the serialized model you want to
            %   load.
            %
            % ## Options
            % * __ObjName__ The optional name of the node to read (if empty,
            %   the first top-level node will be used). default empty
            % * __FromString__ Logical flag to indicate whether the input is a
            %   filename or a string containing the serialized model.
            %   default false
            %
            % This method reads algorithm parameters from the specified XML or
            % YAML file (either from disk or serialized string). The previous
            % algorithm state is discarded.
            %
            % See also: cv.TonemapDrago.save
            %
            TonemapDrago_(this.id, 'load', fname_or_str, varargin{:});
        end
    end

    %% Getters/Setters
    methods
        function value = get.Gamma(this)
            value = TonemapDrago_(this.id, 'get', 'Gamma');
        end
        function set.Gamma(this, value)
            TonemapDrago_(this.id, 'set', 'Gamma', value);
        end

        function value = get.Saturation(this)
            value = TonemapDrago_(this.id, 'get', 'Saturation');
        end
        function set.Saturation(this, value)
            TonemapDrago_(this.id, 'set', 'Saturation', value);
        end

        function value = get.Bias(this)
            value = TonemapDrago_(this.id, 'get', 'Bias');
        end
        function set.Bias(this, value)
            TonemapDrago_(this.id, 'set', 'Bias', value);
        end
    end

end


function up = setup_universal_params(period_orig)
% SETUP_UNIVERSAL_PARAMS sets the universal parameters for use throughout
% "RRest".
%
%               setup_universal_params('mimic')
%
%	Inputs:
%		period_orig - the period of Vortal recording on which to do the
%		analysis, e.g. 'mimic'
%
%	Outputs:
%       up      - a struct of universal parameters
%
%   Context:    called by "RRest.m"
%
%   Further Information:
%       This version is specifically designed to facilitate reproduction of
%       the analysis performed in:
%           Charlton P.H. et al., "Waveform Analysis to Estimate
%           Respiratory Rate" [In Press]
%       Further information on this study can be obtained at:
%           http://peterhcharlton.github.io/RRest/waveform_analysis.html
%       In addition, further information on RRest, including future
%       versions, can be obtained at:
%           http://peterhcharlton.github.io/RRest/index.html
%
%   Comments, Questions, Criticisms, Feedback, Contributions:
%       See: http://peterhcharlton.github.io/RRest/contributions.html
%
%   Version:
%       v.1 - published on 23rd Feb 2016 by Peter Charlton
%
%   Licence:
%       please see the accompanying file named "LICENSE"
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%% FILE PATHS TO BE SPECIFIED %%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%% (requires editing) %%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Please note that your system may require the slashes in file paths to be
% of the opposite direction. In which case, change the following:
up.paths.slash_direction = '\';     % usually a backslash for Windows, forward slash for Linux

% Specify path of data root folder. For instance, if you specify
% "up.paths.root_folder = 'C:\Documents\Data\';", then data will be saved
% in the directory located at 'C:\Documents\Data\DATASETNAME\', where
% "DATASETNAME" is the name of the dataset being analysed, e.g. "MIMICII".
up.paths.root_folder = 'C:\Documents\Data\';

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%% LOAD PREVIOUS UNIVERSAL PARAMETERS %%%%%%%%
%%%%%%%%%%%%%%%% (no editing required) %%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Provide licence details
provide_licence_details
% set current directory to that of this file
cd(fileparts(mfilename('fullpath')))
% Add all functions corresponding to options for each component to the path
addpath(genpath(fileparts(mfilename('fullpath'))));
% Specify name of universal params file:
up_foldername = 'universal_params';
up_filename = 'up';
up_path = [fileparts(mfilename('fullpath')), up.paths.slash_direction, up_foldername, up.paths.slash_direction, up_filename];
% Specify whether or not to re-make the universal_params (needs to be
% remade if any settings have changed)
redo_up = true;
% Don't remake the universal_params file unless needed:
if exist([up_filename, '.mat'], 'file') && ~redo_up
    fprintf('\n--- Loading Universal Parameters ');
    load(up_filename);
    return
end
% Otherwise make the universal_params file:
fprintf('\n--- Creating Universal Parameters ');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%% ALGORITHMS %%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%% (edit if you wish) %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Specify the stages of the algorithms (best left alone):
up.al.key_components = {'extract_resp_sig', 'estimate_rr', 'fuse_rr'};      %   % To run the analysis in full this should be: {'extract_resp_sig', 'estimate_rr', 'fuse_rr'}
% Specify methods for extraction of respiratory signals (feature / filter, ecg / ppg):
up.al.options.extract_resp_sig = {'ppg_feat', 'ekg_feat'};
% Specify the components for feature-based extraction of respiratory signals:
up.al.sub_components.ppg_feat = {'EHF', 'PDt', 'FPt', 'FMe', 'RS', 'ELF'};  % Should read: {'EHF', 'PDt', 'FPt', 'FMe', 'RS', 'ELF'}
up.al.sub_components.ekg_feat = {'EHF', 'RDt', 'FPt', 'FMe', 'RS', 'ELF'};  % Should read: {'EHF', 'RDt', 'FPt', 'FMe', 'RS', 'ELF'}
% Specify the interchangeable technique(s) to be used for each component of feature-based extraction of respiratory signals:
up.al.options.PDt = {'IMS'};                                                % Possible methods: 'DCl', 'COr', 'IMS'
up.al.options.RDt = {'GC'};                                                 % Possible methods: 'GC', 'ME'
up.al.options.FMe = {'am', 'fm', 'bw'};                                     % Possible methods: 'pulW', 'am', 'fm', 'bw', 'pk', 'on', 'bwm', 'qrsW', 'qrsA', 'pca'
up.al.options.RS = {'linB'};                                                % Possible methods: 'cub', 'cubB', 'brg', 'lin', 'brgB', 'linB'
% Specify the interchangeable technique(s) to be used for filter-based respiratory signal extraction:
up.al.options.ekg_filt = {'Wfm', 'Wam', 'CCF', 'BFi'};                      % Possible methods: 'Wfm', 'Wam', 'CCF', 'BFi'
up.al.options.ppg_filt = {'Wfm', 'Wam', 'CCF', 'BFi'};                      % Possible methods: 'Wfm', 'Wam', 'CCF', 'BFi'
% Specify the interchangeable technique(s) for RR Estimation
up.al.options.estimate_rr = {'FTS', 'CtO'};
% Different methods for fusion of RR estimates:
up.al.options.fuse_rr = {'fus_mod'};                                        % Possible methods: 'fus_mod', 'fus_temp'
% Components for each method of extraction of RR fusion:
up.al.sub_components.fus_mod = {'SFu'};                                     % Possible methods: 'SFu', 'PMC', 'PRC', 'SPA'
up.al.sub_components.fus_temp = {'TFu'};                                    % Possible methods: 'TFu'

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%% DIRECTORIES %%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%% (no editing required) %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Specify the folders in which to save results files
up.paths.root_data_folder = [up.paths.root_folder, period_orig, up.paths.slash_direction];
up.paths.data_load_filename = [period_orig, '_data'];

% Specify file paths
up.paths.data_load_folder = [up.paths.root_data_folder, 'Analysis_files', up.paths.slash_direction, 'Data_for_Analysis', up.paths.slash_direction];
up.paths.data_save_folder = [up.paths.root_data_folder, 'Analysis_files', up.paths.slash_direction, 'Component_Data', up.paths.slash_direction];
up.paths.results_folder = [up.paths.root_data_folder, 'Analysis_files' , up.paths.slash_direction, 'Results', up.paths.slash_direction];
up.paths.plots_save_folder = [up.paths.results_folder, 'Figures', up.paths.slash_direction];
up.paths.tables_save_folder = [up.paths.results_folder, 'Tables', up.paths.slash_direction];
up.paths.filenames.respSigs = '_respSigs.mat';
up.paths.filenames.int_respSigs = '_int_respSigs.mat';
up.paths.filenames.pulse_peaks = '_PDt';
up.paths.filenames.qrss = '_RDt';
up.paths.filenames.fid_pts = '_FPt';
up.paths.filenames.elim_vhf = '_EHF';
up.paths.filenames.feat_meas = '_FMe';
up.paths.filenames.resampler = '_RS';
up.paths.filenames.elim_vlf2 = '_ELF';
up.paths.filenames.filt = '_flt';
up.paths.filenames.rrEsts = '_rrEsts';
up.paths.filenames.fuse = 'fuse';
up.paths.filenames.ref_rrs = '_rrRef';
up.paths.filenames.sqi = '_sqi';
up.paths.filenames.stats = '_stats';
up.paths.filenames.win_timings = '_wins';
up.paths.filenames.global_stats = 'stats_global';
up.paths.filenames.ehv_stats = 'stats_ehv';
up.paths.filenames.yhv_stats = 'stats_yhv';
up.paths.filenames.group_stats = 'stats_';
up.paths.filenames.global_data = 'data_global';
up.paths.filenames.yhv_data = 'data_yhv';
up.paths.filenames.ehv_data = 'data_ehv';
up.paths.filenames.group_data = 'data_';
up.paths.filenames.global_BA = 'BA_global';
up.paths.filenames.imp_BA = 'BA_imp';
up.paths.filenames.yhv_BA = 'BA_yhv';
up.paths.filenames.ehv_BA = 'BA_ehv';
up.paths.filenames.group_BA = 'BA_';
up.paths.filenames.study_stats = 'study_stats';
up.paths.filenames.alg_names = 'alg_names';
up.paths.filenames.imp_alg_names = 'imp_alg_names';
up.paths.filenames.results_table = 'results_table';
up.paths.filenames.BA_results_table = 'BA_results_table';
up.paths.filenames.stats_results_table = 'stats_results_table';
up.paths.filenames.subj_results_table = 'subj_results_table';
up.paths.filenames.win_results_table = 'win_results_table';
up.paths.filenames.win_results_headers = 'win_results_headers';
up.paths.filenames.win_data = 'win_data';
up.paths.filenames.win_data_imp = 'win_data_imp';
up.paths.filenames.win_data_raw_clin = 'win_data_raw_clin';
up.paths.filenames.win_data_raw_clin_imp = 'win_data_raw_clin_imp';
up.paths.filenames.vortal_results = 'vortal_results';
up.paths.filenames.synth_results = 'synth_results';
up.paths.filenames.hr_rr_scatter = 'hr_rr_scatter';
up.paths.filenames.stacked_bar = 'stacked_bar';
up.paths.filenames.joint_vortal_BA = 'BA_rest_and_rec';
up.paths.filenames.rest_and_rec_win_data = 'rest_and_rec_win_data';
up.paths.filenames.temp_prec_plot ='temp_prec_plot';
up.paths.filenames.feat_filt_plot = 'feat_filt_plot';

% Make directories
directories_to_make = {up.paths.data_load_folder, up.paths.data_save_folder, up.paths.results_folder, up.paths.plots_save_folder, up.paths.tables_save_folder};
for s = 1 : length(directories_to_make)
    rel_path = directories_to_make{s};
    if ~exist(rel_path, 'dir')
        mkdir(rel_path)
    end
end
% Move data for processing into the relevant folder (you may wish to delete the original file)
data_orig_path = [up.paths.root_folder, up.paths.data_load_filename, '.mat'];
data_new_path = [up.paths.data_load_folder, up.paths.data_load_filename, '.mat'];
if exist(data_orig_path, 'file')
    copyfile(data_orig_path, data_new_path);
end

% path of the folder in which to store results figures. This can be
% wherever you like.
up.paths.paper_figures_folder = up.paths.plots_save_folder;   % in which to save eps figures for direct import into publication.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%% ANALYSIS PARAMETERS %%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%% (no editing required) %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Find out what subjects need processing
data_path = [up.paths.data_load_folder, up.paths.data_load_filename, '.mat'];
up.analysis.run_analysis = true;
if exist(data_path, 'file')
    load(data_path);
else
    warning('Note there was no raw data for this period...')
    path00 = [up.paths.root_folder, 'VORTAL_rest', up.paths.slash_direction];
    path0 = [path00, 'Analysis_files', up.paths.slash_direction, 'Data_for_Analysis', up.paths.slash_direction];
    path2 = 'VORTAL_rest_data';
    load([path0, path2]);
    up.analysis.run_analysis = false;
    up.paths.equipment_type = '';                                           % Possible equipment types: either '_clin' for clinical monitor, or empty, '', for raw signal acquisition
end
up.paramSet.subj_list = 1:length(data);
up.paramSet.groups = extractfield(data, 'group');

% window parameters
up.paramSet.winLeng = 32;                                                   % the duration of each window in secs
up.paramSet.winStep = 0;                                                    % the number of secs between each consecutive window
up.paramSet.buffer_period = 10;                                             % the number of secs to ignore at the start of each resp sig (since the filters might not have stabilised).

% Filter characteristics: Eliminate VHFs (above frequency content of signals)
up.paramSet.elim_vhf.ppg.Fpass = 38.5;  % in HZ
up.paramSet.elim_vhf.ppg.Fstop = 33.12;  % in HZ   (33.12 and 38.5 provide a -3 dB cutoff of 35 Hz)
up.paramSet.elim_vhf.ppg.Dpass = 0.05;
up.paramSet.elim_vhf.ppg.Dstop = 0.01;
up.paramSet.elim_vhf.ekg.Fpass = 103.7;  % in HZ
up.paramSet.elim_vhf.ekg.Fstop = 98;  % in HZ    (98 and 103.7 provide a -3 dB cutoff of 100 Hz)
up.paramSet.elim_vhf.ekg.Dpass = 0.05;
up.paramSet.elim_vhf.ekg.Dstop = 0.01;
% Filter characteristics: Eliminate Mains frequencies (50 Hz)
up.paramSet.elim_mains.fcuts = [41, 47.2, 52.8, 59];  % in HZ (41, 47.2, 52.8, 59 provide a -3 dB cutoff of 45-55 Hz)
up.paramSet.elim_mains.Dpass = 0.05;
up.paramSet.elim_mains.Dstop = 0.01;
% Filter characteristics: Eliminate HFs (above resp freqs)
up.paramSet.elim_hf.Fpass = 1.2;  % in Hz
up.paramSet.elim_hf.Fstop = 0.8899;  % in Hz     (1.2 and 0.8899 provide a -3dB cutoff of 1 Hz)
up.paramSet.elim_hf.Dpass = 0.05;
up.paramSet.elim_hf.Dstop = 0.01;
% Filter characteristics: Eliminate LFs (below cardiac freqs): For 30bpm cutoff
up.paramSet.elim_sub_cardiac.Fpass = 0.63;  % in Hz
up.paramSet.elim_sub_cardiac.Fstop = 0.43;  % in Hz     (0.63 and 0.43 provide a - 3dB cutoff of 0.5 Hz)
up.paramSet.elim_sub_cardiac.Dpass = 0.05;
up.paramSet.elim_sub_cardiac.Dstop = 0.01;
% Filter characteristics: Eliminate VLFs (below resp freqs): For 4bpm cutoff
up.paramSet.elim_vlf.Fpass = 0.157;  % in Hz
up.paramSet.elim_vlf.Fstop = 0.02;   % in Hz     (0.157 and 0.02 provide a - 3dB cutoff of 0.0665 Hz)
up.paramSet.elim_vlf.Dpass = 0.05;
up.paramSet.elim_vlf.Dstop = 0.01;
% Filter characteristics: duration of Tukey window taper in secs
up.paramSet.tukey_win_duration_taper = 2;

% frequency at which to resample feature-based respiratory signals
up.paramSet.resample_fs = 5;
% frequency at which to sample filter-based respiratory signals
up.paramSet.filt_resample_fs = 25;

% Plausible range of HRs [bpm]
up.paramSet.hr_range = [30, 220];

% Plausible range of plausible RRs [bpm]
up.paramSet.rr_range = [4 60];

% AR model order
up.paramSet.ar_model_order = 8;
up.paramSet.ar_resample_freq = 5;

% FFT downsample freq
up.paramSet.fft_resample_freq = 5;

% decide whether or not to redo stats
up.analysis.redo_stats = 1;

% QRS detection windows in secs
up.paramSet.qrs_detect.win_length = 10;
up.paramSet.qrs_detect.win_overlap = 5;

% PPG Peak Detector specifications
% CO
smooth_filt = load('parafilt'); % Load PPG smoothing filter
up.paramSet.CO_peak_det.PPG_smoother.coeffs = smooth_filt.parafiltPPG;
up.paramSet.CO_peak_det.PPG_smoother.details = smooth_filt.details;
up.paramSet.CO_peak_det.upctl = 0.9;
up.paramSet.CO_peak_det.lpctl = 0.1;

% Determine how to obtain reference RRs:
ref_fields = fieldnames(data(1).ref);
if sum(strcmp(ref_fields, 'resp_sig')) && sum(strcmp(fieldnames(data(1).ref.resp_sig), 'paw'))
    up.paramSet.ref_method = 'paw';
elseif sum(strcmp(ref_fields, 'resp_sig')) && sum(strcmp(fieldnames(data(1).ref.resp_sig), 'imp'))
    up.paramSet.ref_method = 'imp';
elseif sum(strcmp(ref_fields, 'breaths'))
    up.paramSet.ref_method = 'breaths';
elseif sum(strcmp(ref_fields, 'params')) && sum(strcmp(fieldnames(data(1).ref.params), 'rr'))
    up.paramSet.ref_method = 'rrs';
end

% Determine whether to calculate stats for impedance:
if sum(strcmp(fieldnames(data(1).ref), 'params')) && sum(strcmp(fieldnames(data(1).ref.params), 'rr')) ...
        && sum(strcmp(fieldnames(data(1).ref.params.rr), 'method')) && ~isempty(strfind(data(1).ref.params.rr.method, 'impedance'))
    up.analysis.imp_stats = true;
else
    up.analysis.imp_stats = false;
end
% Determine whether to calculate stats for synthetic data:
if ~isempty(strfind(up.paths.root_data_folder, 'synth'))
    up.analysis.calc_synth_stats = true;
else
    up.analysis.calc_synth_stats = false;
end
clear data

% Ref RR threshold
up.paramSet.resp_sig_thresh.paw = 0.42;                                     % thresh for use of paw (just a single paw, not 2*paw)
up.paramSet.resp_filter_roll_off = 1+(1/3);

% Paw SNR
up.paramSet.paw_snr_thresh = -8;

% Reference RR method
up.paramSet.ref_rr_method = 'paw_thresh';                                   % For Vortal: sum_both_thresh, imp_thresh, paw_thresh; For MIMIC: comb_imp; For CAPNOBASE: co2_zex

% Impedance RR methods
up.paramSet.imp_rr_method = 'num';   % num or thresh

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%% SAVE UNIVERSAL PARAMETERS %%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%% (no editing required) %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

save(up_path, 'up');
end

function provide_licence_details

licence_details = ['\n\n RRest  Copyright (C) 2016 King''s College London', ...
    '\n This program comes with ABSOLUTELY NO WARRANTY', ...
    '\n and is available under the GNU public license.', ...
    '\n For details see the accompanying LICENSE.txt file.\n\n'];

fprintf(licence_details)

end


function [y,fs,wmode,fidx]=readwav(filename,mode,nmax,nskip)
%READWAV  Read a .WAV format sound file [Y,FS,WMODE,FIDX]=(FILENAME,MODE,NMAX,NSKIP)
%
% Input Parameters:
%
%	FILENAME gives the name of the file (with optional .WAV extension) or alternatively
%                 can be the FIDX output from a previous call to READWAV
%	MODE		specifies the following (*=default):
%
%    Scaling: 's'    Auto scale to make data peak = +-1
%             'r'    Raw unscaled data (integer values)
%             'q'    Scaled to make 0dBm0 be unity mean square
%             'p' *	 Scaled to make +-1 equal full scale
%             'o'    Scale to bin centre rather than bin edge (e.g. 127 rather than 127.5 for 8 bit values)
%                     (can be combined with n+p,r,s modes)
%             'n'    Scale to negative peak rather than positive peak (e.g. 128.5 rather than 127.5 for 8 bit values)
%                     (can be combined with o+p,r,s modes)
%             'g'    Scale by the gain written by the "g" option in "writewav" to restore original level
%     Offset: 'y' *	 Correct for offset in <=8 bit PCM data
%             'z'    No offset correction
%   File I/O: 'f'    Do not close file on exit
%             'd'    Look in data directory: voicebox('dir_data')
%   Display;  'h'    Print header information
%             'w'    Plot waveform
%             'W'    Plot spectrogram
%             'a'    play audio (max 10 seconds)
%             'A'    play all audio even if very long
%
%	NMAX     maximum number of samples to read (or -1 for unlimited [default])
%	NSKIP    number of samples to skip from start of file
%               (or -1 to continue from previous read when FIDX is given instead of FILENAME [default])
%
% Output Parameters:
%
%	Y        data matrix of dimension (samples,channels)
%	FS       sample frequency in Hz
%	WMODE    mode string needed for WRITEWAV to recreate the data file
%	FIDX     Information row vector containing the element listed below.
%
%           (1)  file id
%		    (2)  current position in file
%           (3)  dataoff	byte offset in file to start of data
%           (4)  nsamp	number of samples
%           (5)  nchan	number of channels
%           (6)  nbyte	bytes per data value
%           (7)  bits	number of bits of precision
%           (8)  code	Data format: 1=PCM, 2=ADPCM, 3=floating point, 6=A-law, 7=Mu-law
%           (9)  fs	    sample frequency
%           (10) mask   channel mask
%           (11) gain   gain factor in dB
%
%   If no output parameters are specified, header information will be printed.
%
%   For stereo data, y(:,1) is the left channel and y(:,2) the right
%   The mask, if specified, is a bit field giving the channels present in the following order:
%   0=FL, 1=FR, 2=FC, 3=W, 4=BL, 5=BR, 6=FLC, 7=FRC, 8=BC, 9=SL, 10=SR, 11=TC, 12=TFL, 13=TFC, 14=TFR, 15=TBL, 16=TBC, 17=TBR
%   where F=front, L=left, C=centre, W=woofer (low frequency), B=back, LC=left of centre, RC=right of centre, S=side, T=top
%
%   See also WRITEWAV.

%   *** Note on scaling ***
%   If we want to scale signal values in the range +-1 to an integer in the
%   range [-128,127] then we have four plausible choices corresponding to
%   scale factors of (a) 127, (b) 127.5, (c) 128 or (d) 128.5 but each choice
%   has disadvantages.
%   For forward scaling: (c) and (d) cause clipping on inputs of +1.
%   For reverse scaling: (a) and (b) can generate output values < -1.
%   Any of these scalings can be selected via the mode input: (a) 'o', (b) default, (c) 'on', (d) 'n'

%	   Copyright (C) Mike Brookes 1998-2011
%      Version: $Id: readwav.m 713 2011-10-16 14:45:43Z dmb $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Bugs/suggestions:

if nargin<1
    error('Usage: [y,fs,wmode,fidx]=READWAV(filename,mode,nmax,nskip)'); end
if nargin<2
    mode='p';
else
    mode = [mode(:).' 'p'];
end
k=find((mode>='p') & (mode<='s'));
mno=all(mode~='o');                      % scale to input limits not output limits
sc=mode(k(1));
z=128*all(mode~='z');
info=zeros(1,11);
if ischar(filename)
    if any(mode=='d')
        filename=fullfile(voicebox('dir_data'),filename);
    end
    fid=fopen(filename,'rb','l');
    if fid == -1
        fn=[filename,'.wav'];
        fid=fopen(fn,'rb','l');
        if fid ~= -1
            filename=fn;
        end
    end
    if fid == -1
        error('Can''t open %s for input',filename);
    end
    info(1)=fid;
else
    info=filename;
    fid=info(1);
end
getdat= nargout>0 || any(lower(mode)=='w') || any(lower(mode)=='a');
mh=any(mode=='h') || ~getdat;
if ~info(3)
    fseek(fid,8,-1);						% read riff chunk
    header=fread(fid,4,'*char')';
    if ~strcmp(header,'WAVE')
        fclose(fid);
        error('File does not begin with a WAVE chunck');
    end
    if mh
        fprintf('\nWAVE file: %s\n',filename);
    end
    fmtlen=-1;
    datalen=-1;
    instlen=-1;
    factlen=-1;
    riffmt='e';  % default is original wave file format
    while datalen<0						% loop until FMT and DATA chuncks both found
        header=fread(fid,4,'*char');
        len=fread(fid,1,'ulong');
        if mh
            fprintf('  %s chunk: %d bytes\n',header,len);
        end
        if strcmp(header','fmt ')					% ******* found FMT chunk *********
            fmtlen=len;                             % remember the length
            if len>16
                riffmt='x';  % might be WAVEFORMATEX format
            end
            wavfmt=fread(fid,1,'short');			% format: 1=PCM, 6=A-law, 7-Mu-law
            info(8)=wavfmt;
            info(5)=fread(fid,1,'ushort');			% number of channels
            fs=fread(fid,1,'ulong');				% sample rate in Hz
            info(9)=fs;                             % sample rate in Hz
            rate=fread(fid,1,'ulong');				% average bytes per second (ignore)
            align=fread(fid,1,'ushort');			% block alignment in bytes (container size * #channels)
            bps=fread(fid,1,'ushort');			% bits per sample
            info(7)=bps;
            %             info(6)=ceil(info(7)/8);                % round up to a byte count
            info(6)=floor(align/info(5));                       % assume block size/channels = container size
            if info(8)==-2   % wave format extensible
                cb=fread(fid,1,'ushort');			% extra bytes must be >=22
                riffmt='X';                         % WAVEFORMATEXTENSIBLE format
                wfxsamp=fread(fid,1,'ushort');			% samples union
                if wfxsamp>0
                    info(7)=wfxsamp;     % valid bits per sample
                end
                info(10)=fread(fid,1,'ulong');				% channel mask
                wfxguida=fread(fid,1,'ulong');				% GUID
                wfxguidb=fread(fid,2,'ushort');				% GUID
                wfxguidc=fread(fid,8,'uchar');				% GUID
                if wfxguida<65536
                    info(8)=wfxguida; % turn it into normal wav format
                end
                fseek(fid,len-40,0);				    % skip to end of header
            else
                if align>0 && align<(info(6)+4)*info(5)
                    info(6)=ceil(align/info(5));
                end
                fseek(fid,len-16,0);				    % skip to end of header
            end
            if mh
                fmttypes={'?' 'PCM' 'ADPCM' 'IEEE-float' '?' '?' 'A-law' 'µ-law' '?'};
                fprintf('        Format: %d = %s',info(8),fmttypes{1+max(min(info(8),8),0)});
                if wavfmt==-2
                    fprintf(' (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)\n',wfxguida,wfxguidb,wfxguidc);
                else
                    fprintf('\n');
                end
                fprintf('        %d channels at %g kHz sample rate (%d kbytes/s)\n',info(5),fs/1000,rate/1000);
                fprintf('        Mask=%x:',info(10));
                spkpos={'FL' 'FR' 'FC' 'W' 'BL' 'BR' 'FLC' 'FRC' 'BC' 'SL' 'SR' 'TC' 'TFL' 'TFC' 'TFR' 'TBL' 'TBC' 'TBR'};
                for i=1:18
                    if mod(floor(info(10)*pow2(1-i)),2)
                        fprintf([' ' spkpos{i}]);
                    end
                end
                fprintf('\n        %d valid bits of %d per sample (%d byte block size)\n',info(7),bps,align);
            end
        elseif strcmp(header','fact')				% ******* found FACT chunk *********
            factlen=len;
            if len<4
                error('FACT chunk too short');
            end
            nsamp=fread(fid,1,'ulong');				% number of samples
            fseek(fid,len-4,0);                     % skip to end of header
            if mh
                fprintf('        %d samples = %.3g seconds\n',nsamp,nsamp/fs);
            end
        elseif strcmp(header','inst')				% ******* found INST chunk *********
            instlen=len;
            if len<7
                error('INST chunk too short');
            end
            inst=fread(fid,3,'schar');
            info(11)=double(inst(3));                          % gain in dB
            if mh
                fprintf('        Gain = %d dB\n',info(11));
            end
            fseek(fid,len-3,0);                     % skip to end of header
        elseif strcmp(header','data')				% ******* found DATA chunk *********
            if fmtlen<0
                fclose(fid);
                error('File %s does not contain a FMT chunck',filename);
            end
            if factlen>3 && nsamp >0
                info(4)=nsamp;   % take data length from FACT chunk
            else
                info(4) = fix(len/(info(6)*info(5)));  % number of samples
            end
            info(3)=ftell(fid);                    % start of data
            datalen=len;
            if mh
                fprintf('        %d samples x %d channels x %d bytes/samp',info(4:6));
                if prod(info(4:6))~=len
                    fprintf(' + %d padding bytes',len-prod(info(4:6)));
                end
                fprintf(' = %g sec\n',info(4)/fs);
            end
        else							% ******* found unwanted chunk *********
            fseek(fid,len,0);
        end
    end
else
    fs=info(9);
end
if nargin<4 || nskip<0
    nskip=info(2);  % resume at current file position
end

ksamples=info(4)-nskip; % number of samples remaining
if nargin>2
    if nmax>=0
        ksamples=min(nmax,ksamples);
    end
elseif ~getdat
    ksamples=min(5,ksamples); % just read 5 samples so we can print the first few data values
end
if ksamples>0
    info(2)=nskip+ksamples;
    fseek(fid,info(3)+info(6)*info(5)*nskip,-1);
    nsamples=info(5)*ksamples;
    if any(info(8)==3)  % floating point format
        pk=1;  % peak is 1
        switch info(6)
            case 4
                y=fread(fid,nsamples,'float32');
            case 8
                y=fread(fid,nsamples,'float64');
            otherwise
                error('cannot read %d-byte floating point numbers',info(6));
        end
    else
        if ~any(info(8)==[1 6 7])
            sc='r';  % read strange formats in raw integer mode
        end
        pk=pow2(0.5,8*info(6))*(1+(mno/2-all(mode~='n'))/pow2(0.5,info(7)));  % use modes o and n to determine effective peak
        switch info(6)
            case 1
                y=fread(fid,nsamples,'uchar');
                if info(8)==1
                    y=y-z;
                elseif info(8)==6
                    y=pcma2lin(y,213,1);
                    pk=4032+mno*64;
                elseif info(8)==7
                    y=pcmu2lin(y,1);
                    pk=8031+mno*128;
                end
            case 2
                y=fread(fid,nsamples,'short');
            case 3
                y=fread(fid,3*nsamples,'uchar');
                y=reshape(y,3,nsamples);
                y=([1 256 65536]*y-pow2(fix(pow2(y(3,:),-7)),24)).';
            case 4
                y=fread(fid,nsamples,'long');
            otherwise
                error('cannot read %d-byte integers',info(6));
        end
    end
    if sc ~= 'r'
        if sc=='s'
            sf=1/max(abs(y(:)));
        elseif sc=='p'
            sf=1/pk;
        else
            if info(8)==7
                sf=2.03761563/pk;
            else
                sf=2.03033976/pk;
            end
        end
        y=sf*y;
    else                             % mode = 'r' - output raw values
        if info(8)==1
            y=y*pow2(1,info(7)-8*info(6));  % shift to get the bits correct
        end
    end
    if any(mode=='g') && info(11)~=0
        y=y*10^(info(11)/20);   % scale by the gain
    end
    if info(5)>1
        y = reshape(y,info(5),ksamples).';
    end
else
    y=[];
end
if all(mode~='f')
    fclose(fid);
end
if nargout>2  % sort out the mode input for writing this format
    wmode=char([riffmt sc 'z'-z/128]);
    if factlen>0
        wmode=[wmode 'E'];
    end
    if info(6)>1 && info(6)<5
        cszc=' cCL';
        wmode=[wmode cszc(info(6))];
    end
    switch info(8)
        case 1                                    % PCM modes
            if ~mno
                wmode=[wmode 'o'];
            end
            if any(mode=='n')
                wmode=[wmode 'n'];
            end
            wmode=[wmode num2str(info(7))];
        case 3
            if info(7)<=32
                wmode = [wmode 'v'];
            else
                wmode = [wmode 'V'];
            end
        case 6
            wmode = [wmode 'a'];
        case 7
            wmode = [wmode 'u'];
    end
    fidx=info;
end
[ns,nchan]=size(y);
if mh && ns>0
    nsh=min(ns,5);  % print first few samples
    for i=1:nsh
        fprintf('        %d:',i);
        fprintf(' %.3g',y(i,:));
        fprintf('\n');
    end
end

if ns>0.01*fs
    if any(lower(mode)=='a')
        nsh=min(ns,10*fs+ns*any(mode=='A'));
        soundsc(y(1:nsh,1:min(nchan,2)),fs);
    end
    if any(mode=='W')
        spm='pJcbf ';
        if any(mode=='w')
            spm(end)='w';
        end
        clf;
        if nchan>1
            for i=nchan:-1:1
                subplot(nchan,1,i)
                spgrambw(y(:,i),fs,spm);
            end
        else
            spgrambw(y,fs,spm);
        end
    elseif any(mode=='w')
        clf;
        if nchan>1
            for i=nchan:-1:1
                subplot(nchan,1,i)
                plot((1:ns)/fs,y(:,i));
                ylabel(['Chan ' num2str(i)]);
                if i==nchan
                    xlabel('Time (s)');
                end
            end
        else
            plot((1:ns)/fs,y);
            xlabel('Time (s)');
        end

    end
end


function colorStr = getStringFromLineSpecColor(lineSpecColor)
    if(strcmpi(lineSpecColor,'r'))
        colorStr = 'Red';

    elseif((isnumeric(lineSpecColor) && all(lineSpecColor == [178,0,255]/255)) || (ischar(lineSpecColor) && strcmpi(lineSpecColor,'m')))
        colorStr = 'Magenta';

	elseif(lineSpecColor == [255,131,0]/255)
        colorStr = 'Orange';

    elseif((isnumeric(lineSpecColor) && all(lineSpecColor == [255,216,0]/255)) || (ischar(lineSpecColor) && strcmpi(lineSpecColor,'y')))
        colorStr = 'Yellow';

    elseif((isnumeric(lineSpecColor) && all(lineSpecColor == [76,220,0]/255)) || (ischar(lineSpecColor) && strcmpi(lineSpecColor,'g')))
        colorStr = 'Green';

    elseif((isnumeric(lineSpecColor) && all(lineSpecColor == [0,210,255]/255)) || (ischar(lineSpecColor) && strcmpi(lineSpecColor,'c')))
        colorStr = 'Cyan';

	elseif(strcmpi(lineSpecColor,'b'))
        colorStr = 'Blue';

	elseif(strcmpi(lineSpecColor,'k'))
        colorStr = 'Black';

	elseif(strcmpi(lineSpecColor,'w'))
        colorStr = 'White';

	elseif(lineSpecColor == [255,0,220]/255)
        colorStr = 'Pink';

	elseif(lineSpecColor == [139,69,19]/255)
        colorStr = 'Brown';

    else
        colorStr = 'Black';
        warning(['Did not recongize line spec color string: ', num2str(lineSpecColor)]);
    end
end