function [cfg, artifact] = ft_artifact_tms(cfg, data)

% FT_ARTIFACT_TMS reads the data segments of interest from file and identifies artefacts in
% EEG recordings that were done during TMS stimulation.
%
% Use as
%   [cfg, artifact] = ft_artifact_tms(cfg)
% with the configuration options
%   cfg.dataset     = string with the filename
% or
%   cfg.headerfile  = string with the filename
%   cfg.datafile    = string with the filename
% and optionally
%   cfg.headerformat
%   cfg.dataformat
%
% Alternatively you can use it as
%   [cfg, artifact] = ft_artifact_tms(cfg, data)
% where the input data is a structure as obtained from FT_PREPROCESSING.
%
% In both cases the configuration should also contain
%   cfg.trl         = structure that defines the data segments of interest, see FT_DEFINETRIAL
%   cfg.continuous  = 'yes' or 'no' whether the file contains continuous data (default = 'yes')
% and
%   cfg.method      = 'detect' or 'marker', see below.
%   cfg.prestim     = scalar, time in seconds prior to onset of detected event to mark as artifactual (default = 0.005 seconds)
%   cfg.poststim    = scalar, time in seconds post onset of detected even to mark as artifactual (default = 0.010 seconds)
%
% The different methods are described in detail below.
%
% With cfg.method='detect', TMS-artifact are detected on basis of transient
% high-amplidude gradients that are typical for TMS-pulses. The data is preprocessed
% (again) with the following settings, which are optimal for identifying TMS-pulses.
% Artifacts are identified by means of thresholding the z-transformed value of the
% preprocessed data. This method acts as a wrapper around FT_ARTIFACT_ZVALUE.
%   cfg.artfctdef.tms.derivative  = 'yes'
%   cfg.artfctdef.tms.channel     = Nx1 cell-array with selection of channels, see FT_CHANNELSELECTION for details
%   cfg.artfctdef.tms.cutoff      = z-value at which to threshold (default = 4)
%   cfg.artfctdef.tms.trlpadding  = 0.1
%   cfg.artfctdef.tms.fltpadding  = 0.1
%   cfg.artfctdef.tms.artpadding  = 0.01
% Be aware that if one artifact falls within this specified range of another artifact, both
% artifact will be counted as one. Depending on cfg.prestim and cfg.poststim you may not mark
% enough data as artifactual.
%
% With cfg.method='marker', TMS-artifact onsets and offsets are based on markers/triggers that
% are written into the EEG dataset. This method acts as a wrapper around FT_DEFINETRIAL to
% determine on- and offsets of TMS pulses by reading markers in the EEG.
%   cfg.trialfun            = function name, see below (default = 'ft_trialfun_general')
%   cfg.trialdef.eventtype  = 'string'
%   cfg.trialdef.eventvalue = number, string or list with numbers or strings
% The cfg.trialfun option is a string containing the name of a function that you wrote
% yourself and that FT_ARTIFACT_TMS will call. The function should take the cfg-structure as
% input and should give a NxM matrix with M equal to or larger than 3) in the same format as
% "trl" as the output. You can add extra custom fields to the configuration structure to
% pass as arguments to your own trialfun.  Furthermore, inside the trialfun you can use the
% FT_READ_EVENT function to get the event information from your data file.
%
% The output argument "artifact" is a Nx2 matrix comparable to the
% "trl" matrix of FT_DEFINETRIAL. The first column of which specifying the
% beginsamples of an artifact period, the second column contains the
% endsamples of the artifactperiods.
%
% To facilitate data-handling and distributed computing with the peer-to-peer
% module, this function has the following option:
%   cfg.inputfile   =  ...
% If you specify this option the input data will be read from a *.mat
% file on disk. This mat files should contain only a single variable named 'data',
% corresponding to the input structure.
%
% See also FT_REJECTARTIFACT, FT_ARTIFACT_CLIP, FT_ARTIFACT_ECG, FT_ARTIFACT_EOG,
% FT_ARTIFACT_JUMP, FT_ARTIFACT_MUSCLE, FT_ARTIFACT_THRESHOLD, FT_ARTIFACT_ZVALUE

% Copyright (C) 2003-2011, Jan-Mathijs Schoffelen & Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip 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.
%
%    FieldTrip 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 FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

% these are used by the ft_preamble/ft_postamble function and scripts
ft_revision = '$Id$';
ft_nargin   = nargin;
ft_nargout  = nargout;

% do the general setup of the function
ft_defaults
ft_preamble init

% ft_preamble provenance is not needed because just a call to ft_artifact_zvalue
% ft_preamble loadvar data is not needed because ft_artifact_zvalue will do this

% check if the input cfg is valid for this function
cfg = ft_checkconfig(cfg, 'renamed',    {'datatype', 'continuous'});
cfg = ft_checkconfig(cfg, 'renamedval', {'continuous', 'continuous', 'yes'});
cfg = ft_checkconfig(cfg, 'required', 'method');
cfg = ft_checkconfig(cfg, 'allowedval', {'method', 'detect', 'marker'});

% set default rejection parameters
if ~isfield(cfg, 'artfctdef'),                       cfg.artfctdef                   = [];        end
if ~isfield(cfg, 'method'),                          cfg.method                      = 'detect';  end
if ~isfield(cfg.artfctdef, 'tms'),                   cfg.artfctdef.tms               = [];        end
if ~isfield(cfg, 'prestim'),                         cfg.prestim                     = 0.005;     end
if ~isfield(cfg, 'poststim'),                        cfg.poststim                    = 0.010;     end

if isfield(cfg.artfctdef.tms, 'artifact')
  fprintf('tms artifact detection has already been done, retaining artifacts\n');
  artifact = cfg.artfctdef.tms.artifact;
  return
end

switch cfg.method
  case 'detect'
    % settings for preprocessing
    if ~isfield(cfg.artfctdef.tms, 'derivative'),   cfg.artfctdef.tms.derivative   = 'yes';    end
    % settings for the zvalue subfunction
    if ~isfield(cfg.artfctdef.tms, 'method'),     cfg.artfctdef.tms.method      = 'zvalue';    end
    if ~isfield(cfg.artfctdef.tms, 'channel'),    cfg.artfctdef.tms.channel     = 'all';       end
    if ~isfield(cfg.artfctdef.tms, 'trlpadding'), cfg.artfctdef.tms.trlpadding  = 0.1;         end
    if ~isfield(cfg.artfctdef.tms, 'fltpadding'), cfg.artfctdef.tms.fltpadding  = 0.1;         end
    if ~isfield(cfg.artfctdef.tms, 'artpadding'), cfg.artfctdef.tms.artpadding  = 0.01;        end
    if ~isfield(cfg.artfctdef.tms, 'cutoff'),     cfg.artfctdef.tms.cutoff      = 4;           end
    % construct a temporary configuration that can be passed onto artifact_zvalue
    tmpcfg                  = [];
    tmpcfg.trl              = cfg.trl;
    tmpcfg.artfctdef.zvalue = cfg.artfctdef.tms;
    if isfield(cfg, 'continuous'),   tmpcfg.continuous       = cfg.continuous;    end
    if isfield(cfg, 'dataformat'),   tmpcfg.dataformat       = cfg.dataformat;    end
    if isfield(cfg, 'headerformat'), tmpcfg.headerformat     = cfg.headerformat;  end
    % call the zvalue artifact detection function

    % the data is either passed into the function by the user or read from file with cfg.inputfile
    hasdata = exist('data', 'var');

    if hasdata
      % read the header
      cfg = ft_checkconfig(cfg, 'forbidden', {'dataset', 'headerfile', 'datafile'});
      fsample = data.fsample;
      [tmpcfg, artifact] = ft_artifact_zvalue(tmpcfg, data);
    else
      cfg = ft_checkconfig(cfg, 'dataset2files', 'yes');
      cfg = ft_checkconfig(cfg, 'required', {'headerfile', 'datafile'});
      hdr = ft_read_header(cfg.headerfile);
      fsample = hdr.Fs;
      tmpcfg.datafile    = cfg.datafile;
      tmpcfg.headerfile  = cfg.headerfile;
      [tmpcfg, artifact] = ft_artifact_zvalue(tmpcfg);
    end
    cfg.artfctdef.tms = tmpcfg.artfctdef.zvalue;

    % adjust artifact definition so that Nx2 matrix contains detected TMS
    % events with user-specified pre- and post stimulus period included.
    % The reason for this is that ft_artifact_zvalue centers the period
    % marked as artifactual around the detected event. In the case of a TMS
    % pulse the window you would like to mark as artifactual is not
    % symmetrical around the onset of the pulse.

    % get values and express in samples
    prestim = round(cfg.prestim * fsample);
    poststim = round(cfg.poststim * fsample);

    % adjust Nx2 artifact matrix to be centered non-symmetrically around
    % detected TMS-pulse
    artifact(:,1) = (artifact(:,1)+artifact(:,2))./2 - prestim;
    artifact(:,2) = artifact(:,1) + poststim;
    cfg.artfctdef.tms.artifact = artifact;

  case 'marker'
    % Check if the cfg is correct for this method
    cfg = ft_checkconfig(cfg, 'dataset2files', 'yes');
    ft_checkconfig(cfg, 'required', 'trialdef');
    cfg.trialfun = ft_getopt(cfg, 'trialfun', 'ft_trialfun_general');
    trialdef = cfg.trialdef;
    trialdef.prestim = cfg.prestim;
    trialdef.poststim = cfg.poststim;
    cfg.trialdef = ft_checkconfig(trialdef, 'required', {'eventvalue', 'eventtype'});

    % Get the trialfun
    cfg.trialfun = ft_getuserfun(cfg.trialfun, 'trialfun');

    % Evaluate the trialfun
    fprintf('evaluating trialfunction ''%s''\n', func2str(cfg.trialfun));
    trl   = feval(cfg.trialfun, cfg);

    % Prepare the found events for output
    artifact = trl(:,1:2);
    cfg.artfctdef.tms.artifact = artifact;
    fprintf('found %d events\n', size(artifact,1));

  otherwise
    % This should be redundant as ft_checkconfig does not allow other methods than the supported ones.
    ft_error('unsupported method');
end

% FIXME - not removing this causes problems when passing to ft_preprocessing
cfg = rmfield(cfg, 'method');


function varargout = wavf_gen(varargin)
% WAVF_GEN M-file for wavf_gen.fig
%      WAVF_GEN, by itself, creates a new WAVF_GEN or raises the existing
%      singleton*.
%
%      H = WAVF_GEN returns the handle to a new WAVF_GEN or the handle to
%      the existing singleton*.
%
%      WAVF_GEN('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in WAVF_GEN.M with the given input arguments.
%
%      WAVF_GEN('Property','Value',...) creates a new WAVF_GEN or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before wavf_gen_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to wavf_gen_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help wavf_gen

% Last Modified by GUIDE v2.5 02-Apr-2009 18:21:03

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @wavf_gen_OpeningFcn, ...
                   'gui_OutputFcn',  @wavf_gen_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before wavf_gen is made visible.
function wavf_gen_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to wavf_gen (see VARARGIN)

% Choose default command line output for wavf_gen
handles.output = hObject;

set(handles.axes1,'NextPlot','add');

global r xys sp iscnt p mth res hc f

f=440; % initial frequency
T=1/f;

mth='spline'; % intial method is spline

res=200; % curve resolution

iscnt=get(handles.cnt,'value');

r=0.015*T;

sp=1*r; % span between markers

% xys(:,1)=[0.5;
%           0.5];
% xys(:,2)=[0.5;
%           0.7];

% p(1)=create_marker(handles.axes1,xys(1,1),xys(2,1),r,[0 1 0],'a',1);
% p(2)=create_marker(handles.axes1,xys(1,2),xys(2,2),r,[1 0 0],'a',2);
nm=str2num(get(handles.nm,'string'));
p=zeros(1,nm);
%p=zeros(1,2);
xys=zeros(2,nm);
for n=1:nm
    stp=T/nm; % step
    xys(1,n)=stp/2+stp*(n-1);
    p(n)=create_marker(handles.axes1,xys(1,n),xys(2,n),r,[0 1 0],'a',n);
end

set(handles.axes1,'XLim',[0 T]);
set(handles.axes1,'YLim',[-1 1]);

% % axis equal:
% set(handles.axes1,'DataAspectRatio',[2 1 1]);
% set(handles.axes1,'DataAspectRatioMode','manual');
set(handles.axes1,'PlotBoxAspectRatio',[6 4 4]);
set(handles.axes1,'PlotBoxAspectRatioMode','manual');

for n=1:nm
    make_round(p(n),handles.axes1);
end

% get(handles.axes1,'DataAspectRatio')

% draw curve:
xl=get(handles.axes1,'Xlim');
yl=get(handles.axes1,'Ylim');
dxl=xl(2)-xl(1);
dyl=yl(2)-yl(1);

xc=xl(1):(dxl/res):xl(2);
yc=interp1(xys(1,:),xys(2,:),xc,mth,'extrap');
handles.cr=plot(xc,yc,'k-');
hc=handles.cr;
set(handles.cr,'hittest','off');

drawnow;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes wavf_gen wait for user response (see UIRESUME)
% uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = wavf_gen_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;

function nm_Callback(hObject, eventdata, handles)

global p xys r iscnt sp res hc mth

% delete old:
for pc=1:length(p)
    delete(p(pc));
end

ha=handles.axes1;
xl=get(ha,'Xlim');
dxl=xl(2)-xl(1);
yl=get(ha,'Ylim');

% create new:
nm=str2num(get(handles.nm,'string'));
p=zeros(1,nm);
%p=zeros(1,2);
xys=zeros(2,nm);
if iscnt
    stp=dxl/nm; % step
    for n=1:nm
        xys(1,n)=stp/2+stp*(n-1);
        p(n)=create_marker(handles.axes1,xys(1,n),xys(2,n),r,[0 1 0],'a',n);
    end
else
    stp=dxl/(nm-1); % step
    for n=1:nm
        xys(1,n)=stp*(n-1);
        p(n)=create_marker(handles.axes1,xys(1,n),xys(2,n),r,[0 1 0],'a',n);
    end
end

% set(handles.axes1,'XLim',[0 3]);
% set(handles.axes1,'YLim',[-1 1]);

% % axis equal:
% set(handles.axes1,'DataAspectRatio',[2 1 1]);
% set(handles.axes1,'DataAspectRatioMode','manual');
% set(handles.axes1,'PlotBoxAspectRatio',[6 4 4]);
% set(handles.axes1,'PlotBoxAspectRatioMode','manual');

for n=1:nm
    make_round(p(n),handles.axes1);
end

% update curve:
update_curve;

% --- Executes during object creation, after setting all properties.
function nm_CreateFcn(hObject, eventdata, handles)
% hObject    handle to nm (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in cnt.
function cnt_Callback(hObject, eventdata, handles)

global iscnt xys p sp res hc mth

iscnt=get(hObject,'Value');

ha=handles.axes1;
xl=get(ha,'Xlim');
dxl=xl(2)-xl(1);
yl=get(ha,'Ylim');

if iscnt
    % if from not continius to continius

    xdt=get(p(end),'XData');

    nm=length(xys(1,:));
    if (dxl-xys(1,nm-1))>sp
        dx=xl(2)-sp-xys(1,end);
    else
        sp1=(xys(1,nm)-xys(1,nm-1))/2;
        dx=xl(2)-sp1-xys(1,end);
    end

    xdt=xdt+dx;
    set(p(end),'XData',xdt);
    xys(1,end)=xys(1,end)+dx;

else
    % if from continius to not continius

    xdt=get(p(1),'XData');
    dx=xl(1)-xys(1,1);
    xdt=xdt+dx;
    set(p(1),'XData',xdt);
    xys(1,1)=xl(1);

    xdt=get(p(end),'XData');
    dx=xl(2)-xys(1,end);
    xdt=xdt+dx;
    set(p(end),'XData',xdt);
    xys(1,end)=xl(end);

    %xys(1,end)=xl(2);

end

update_curve;

% --- Executes when uipanel1 is resized.
function uipanel1_ResizeFcn(hObject, eventdata, handles)
% hObject    handle to uipanel1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% --- Executes when selected object is changed in uipanel1.
function uipanel1_SelectionChangeFcn(hObject, eventdata, handles)

global mth hc xys res iscnt

if get(handles.nearest,'value')
    mth='nearest';
end

if get(handles.linear,'value')
    mth='linear';
end

if get(handles.spline,'value')
    mth='spline';
end

xl=get(handles.axes1,'Xlim');
yl=get(handles.axes1,'Ylim');
dxl=xl(2)-xl(1);
dyl=yl(2)-yl(1);
update_curve;

function fr_Callback(hObject, eventdata, handles)

global f p xys r sp res mth hc iscnt

f_old=f; % old value of f
T_old=1/f_old;

frs=get(handles.fr,'string');
f=str2num(frs);
T=1/f;

xys(1,:)=T*xys(1,:)/T_old; % scretch data as T

r=0.015*T;

sp=1*r; % span between markers

set(handles.axes1,'XLim',[0 T]);
set(handles.axes1,'YLim',[-1 1]);

nm=length(xys(1,:));

for n=1:nm
    make_round(p(n),handles.axes1);
end

xl=get(handles.axes1,'Xlim');
yl=get(handles.axes1,'Ylim');
dxl=xl(2)-xl(1);
dyl=yl(2)-yl(1);
update_curve;

% --- Executes during object creation, after setting all properties.
function fr_CreateFcn(hObject, eventdata, handles)
% hObject    handle to fr (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function sl_Callback(hObject, eventdata, handles)
% hObject    handle to sl (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of sl as text
%        str2double(get(hObject,'String')) returns contents of sl as a double

% --- Executes during object creation, after setting all properties.
function sl_CreateFcn(hObject, eventdata, handles)
% hObject    handle to sl (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in pl.
function pl_Callback(hObject, eventdata, handles)

global xys iscnt mth f

prepare_signal;

sound(yc,Fs); % play

% --- Executes on button press in sv.
function sv_Callback(hObject, eventdata, handles)

[filename, pathname] = uiputfile(...
 {'*.wav'},...
 'Save sound as wav file');

filename1=[pathname filename];

global xys iscnt mth f

prepare_signal;

wavwrite(yc,Fs,filename1);

% --- Executes on selection change in prs.
function prs_Callback(hObject, eventdata, handles)
% hObject    handle to prs (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns prs contents as cell array
%        contents{get(hObject,'Value')} returns selected item from prs

global p xys r iscnt sp res hc mth f

spr=get(hObject,'Value'); % selected preset

T=1/f;

if spr~=1
    % delete old:
    for pc=1:length(p)
        delete(p(pc));
    end

    ha=handles.axes1;
    xl=get(ha,'Xlim');
    dxl=xl(2)-xl(1);
    yl=get(ha,'Ylim');
end

% create new:

switch spr
    case 1 % nothing

    case 2 % zero
        np=5; % number of points
        set(handles.nm,'string',num2str(np));
        stp=T/np;
        p=zeros(1,np);
        xys=zeros(2,np);
        for n=1:np
            xys(1,n)=(n-1)*stp;
            xys(2,n)=0;
        end

        % set continius:
        iscnt=true;
        set(handles.cnt,'value',iscnt);

        % set spline method:
        mth='spline';
        set(handles.nearest,'value',0);
        set(handles.linear,'value',0);
        set(handles.spline,'value',1);
    case 3 % sine
        snrs=8; % sine resolution
        set(handles.nm,'string',num2str(snrs));
        stp=T/snrs;
        p=zeros(1,snrs);
        xys=zeros(2,snrs);
        for n=1:snrs
            xys(1,n)=(n-1)*stp;
            xys(2,n)=0.9*sin(2*pi*f*xys(1,n));
        end

        % set continius:
        iscnt=true;
        set(handles.cnt,'value',iscnt);

        % set spline method:
        mth='spline';
        set(handles.nearest,'value',0);
        set(handles.linear,'value',0);
        set(handles.spline,'value',1);

    case 4 % square
        np=2; % number of points
        set(handles.nm,'string',num2str(np));
        stp=T/np;
        p=zeros(1,np);
        xys=zeros(2,np);
        for n=1:np
            xys(1,n)=(n-1)*stp+T/4;
            if n==1
                xys(2,n)=-0.9;
            else
                xys(2,n)=0.9;
            end
        end

        % set continius:
        iscnt=true;
        set(handles.cnt,'value',iscnt);

        % set nearest method:
        mth='nearest';
        set(handles.nearest,'value',1);
        set(handles.linear,'value',0);
        set(handles.spline,'value',0);

    case 5 % triangle
        np=2; % number of points
        set(handles.nm,'string',num2str(np));
        stp=T/np;
        p=zeros(1,np);
        xys=zeros(2,np);
        for n=1:np
            xys(1,n)=(n-1)*stp+T/4;
            if n==1
                xys(2,n)=-0.9;
            else
                xys(2,n)=0.9;
            end
        end

        % set continius:
        iscnt=true;
        set(handles.cnt,'value',iscnt);

        % set linear method:
        mth='linear';
        set(handles.nearest,'value',0);
        set(handles.linear,'value',1);
        set(handles.spline,'value',0);

    case 6 % sawtooth
        np=2; % number of points
        set(handles.nm,'string',num2str(np));
        stp=T/np;
        p=zeros(1,np);
        xys=zeros(2,np);

        xys(1,1)=0;
        xys(2,1)=-0.9;

        xys(1,2)=T;
        xys(2,2)=0.9;

        % set not continius:
        iscnt=false;
        set(handles.cnt,'value',iscnt);

        % set linear method:
        mth='linear';
        set(handles.nearest,'value',0);
        set(handles.linear,'value',1);
        set(handles.spline,'value',0);
end

if spr~=1

    nm=length(xys(1,:));
    for n=1:nm
        p(n)=create_marker(handles.axes1,xys(1,n),xys(2,n),r,[0 1 0],'a',n);
    end

    for n=1:nm
        make_round(p(n),handles.axes1); % use make_round to update circles positions
    end

    update_curve;
end

% --- Executes during object creation, after setting all properties.
function prs_CreateFcn(hObject, eventdata, handles)
% hObject    handle to prs (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in p3p.
function p3p_Callback(hObject, eventdata, handles)

global xys f res mth iscnt

plot_3p;


function alpha = p15_alpha ( )

%*****************************************************************************80
%
%% P15_ALPHA returns ALPHA for problem 15.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 August 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real ALPHA, the value of ALPHA.
%
  alpha = 0.0;

  return
end


 function mat_write(file, data, varargin)
%function mat_write(file, data,
%		['-check', '-nocheck', '-type', datatype, '-name', varname])
%
% Save matlab "data" to "file", first checking if "file" exists!
% If file suffix is .fld, then save as AVS .fld file in xdr_float.
%
% datatype can be 'xdr_float' 'xdr_int' ...
% Jeff Fessler, The University of Michigan

if nargin == 1 && streq(file, 'test'), mat_write_test, return, end
if nargin < 2, ir_usage, end

% use .fld file if filename ends in .fld, or if filename is t0, t1, ...
isfld = 0;
if length(file) > 4
	isfld = streq(file((end-3):end), '.fld');
elseif length(file) == 2 && file(1) == 't'
	isfld = true;
end

check1st = true;
if isfld
	varname = '';
	datatype = 'xdr_float';
else
	varname = 'data';
	datatype = '';
end

while length(varargin)
	if streq(varargin{1}, '-nocheck')
		check1st = 0;
		varargin = {varargin{2:end}};
	elseif streq(varargin{1}, '-check')
		check1st = 1;
		varargin = {varargin{2:end}};
	elseif streq(varargin{1}, '-type')
		if length(varargin) < 2
			error '-type needs arg'
		else
			datatype = varargin{2};
			varargin = {varargin{3:end}};
		end
	elseif streq(varargin{1}, '-name')
		if length(varargin) < 2
			error '-name needs arg'
		else
			varname = varargin{2};
			varargin = {varargin{3:end}};
		end
	else
		error(sprintf('bad arg "%s"', varargin{1}))
	end
end

if isfld && ~isempty(varname)
	warning('variable name for .fld file ignored')
end
if ~isfld && ~isempty(datatype)
	warning('datatype for .mat file ignored')
end

if 2==exist(file) && check1st
	if has_aspire
		if isfld
			os_run(['op range ' file])
		else
			os_run(['op -chat 0 matls ' file])
		end
	end
	t = sprintf('file "%s" exists.  overwrite? [y|n]: ', file);
	t = input(t, 's');
	if ~streq(t, 'y')
		return
	end
end

% avs file
if isfld
	if check1st
		fld_write(file, data, '-check', datatype)
	else
		fld_write(file, data, '-nocheck', datatype)
	end

% matlab file
else
	error 'writing to matlab file for reading by aspire no longer supported because mathworks changes the file format too often.  use fld_write'
	if ~streq(varname, 'data')
		eval([varname '= data'])	% caution: dangerous!
	end

	t = version;
	if t(1) == '4'
		save(file, varname)
	elseif t(1) == '5' || t(1) == '6'
		save(file, varname, '-v4')
	else
		error version
	end
end

printm('file "%s" written ok', file)

% mat_write_test()
function mat_write_test
dat = [5:8 1:4];
file = 'tmp.fld';
mat_write(file, dat, '-check', '-name', 'tester')
%d = load(file);
d = fld_read(file);
if any(d.tester ~= dat), error 'bug', else, printf('%s test ok', mfilename), end
delete(file)


%
%   FILE NAME:    HMR2Curation.m
%
%   PURPOSE: Curating HMR2 database model toward HMR3
%

% Load the original Matlab file of HMR2 database
load('HMRdatabase2_00.mat');

% Import HMR2 reactions from the Excel file 'RXNS' sheet that leave out
% the following five rows that represent reaction classes
% 7709: 'Exchange reactions';
% 8171: 'Fake reactions';
% 8176: 'Biomass reactions';
% 8177: 'HMR_biomass_Renalcancer';
% 8183: 'Included for connectivity for INIT'
T=readtable('HMRdatabase2_00.xlsx','Sheet','RXNS','ReadVariableNames',1);
HMR2=table2struct(T,'ToScalar',true);

% Adding reaction identifiers from external databases
% additional empty spaces were also removed druing this process
if isequal(ihuman.rxns,HMR2.RXNID)
	ihuman.rxnKEGGID=HMR2.KEGGID;              %KEGG
	ihuman.rxnEHMNID=HMR2.EHMNID;              %EHMN
	ihuman.rxnBiGGID=HMR2.BIGGDATABASEID;      %Recon
	ihuman.rxnHepatoNET1ID=HMR2.HEPATONET1ID;  %Hepatonet1
	ihuman.rxnREACTOMEID=HMR2.REACTOMEID;      %Reactome
	ihuman.rxnReferences=HMR2.REFERENCES;      %References
end

% Some errors were spotted and fixed:
% The reaction HMR_2190 was assocated to four REACTOM reactions.
% The first one (REACT_22270) is correect, the other three
% (REACT_22097; REACT_22133; REACT_22219) should be wrong because
% they are empty ids by searching reactom.org, and thus removed
index=find(strcmp('HMR_2190',ihuman.rxns));
ihuman.rxnREACTOMEID{index}='REACT_22270';

% The KEGG id of HMR_7709 was associated to 'R0302' that should be typo
% It was manually checked and corrected to R03027
index=find(strcmp('HMR_7709',ihuman.rxns));
ihuman.rxnKEGGID{index}='R03027';

% Save as version 2.0.1
save('HMRdatabase2_01.mat','ihuman'); %===2018-01-16