function fseries(action) % FSERIES is a function which allows the user to observe the convergence of % Fourier series. It is started with the command fseries at the % MATLAB prompt. This causes the FSERIES Setup window to appear. % In this window the user can enter the function that is to be % approximated. Since it is often the case that the function of % interest is discontinuous, it is possible to give different % definitions on up to four contiguous intervals. However, it is % important to choose the number of intervals used first. % % When the function is entered, clicking the Proceed button will % cause MATLAB to compute a large number of Fourier coefficients, % and to open the FSERIES Display window. In this window the % function will be plotted, along with the Fourier approximation % of order 0. The order of the approximation can be changed to % anything <= 1000 by changing the number in the edit box, and % hitting the Return or Enter keys. % % For many purposes, it is useful to use the MATLAB command ZOOM % with FSERIES. Use HELP ZOOM to get information about ZOOM. the % click and drag option for ZOOM is probably the most useful in % this case. % Copywright (c) John C. Polking, Rice University % Last modified: July 3, 1995 if nargin <1 action ='initialize'; end if strcmp(action,'initialize') % First we make sure that there is no other copy of FSERIES % running, since this causes problems. figs = findobj('tag','fseries'); if (~isempty(figs)) error('Only one copy of fseries can be open at one time.') end % Build the Setup window. N = 4096; % Number of data points. M = 2; % Default degree of approx. texth =20; % Height of text boxes. varw = 40; % Length of variable boxes. equalw =20; % Length of equals. eqlength = 250; % Length of right hand sides. space = 30; nw = 60; left =10; % Left margin. frw = 10+eqlength+space+2*nw+2*equalw+varw; NN = 2; separation = texth+3; % Separation between boxes. buttbott = 10; frbott = separation +2*buttbott; eqbott = frbott + buttbott + (fliplr(0:3))*separation; dirbott = eqbott(1)+separation; labelbott = dirbott + separation; frht = 2*buttbott + 6*separation; defigwidth =2*left + frw; % Width of the figure. defigureheight = frbott + frht + buttbott; % Height of the figure. defigurebot = 40; % Bottom of the figure. setpos = [20 defigurebot defigwidth defigureheight]; fourset = figure('pos',setpos,... 'resize','off','name','FSERIES Setup','numb','off',... 'visible','off','tag','fseries'); frame = uicontrol('style','frame',... 'pos',[left,frbott,frw,frht],... 'visible','off'); label=uicontrol('style','text',... 'pos',[left+5 labelbott frw-10 texth],... 'horizon','left',... 'string','The function may be defined differently on up to four contiguous intervals.',... 'visible','off'); dirlength = eqlength; directions=uicontrol('style','text',... 'pos',[left+5 dirbott dirlength texth],... 'horizon','left',... 'string','Choose the number of intervals.','visible','off'); radleft =left + dirlength + 10; radwidth = 40; rad(1) = uicontrol('style','radio',... 'pos',[radleft dirbott radwidth texth],... 'string','1','value',0,'visible','off'); rad(2) = uicontrol('style','radio',... 'pos',[radleft+radwidth dirbott radwidth texth],... 'string','2','value',2,'max',2,'visible','off'); rad(3) = uicontrol('style','radio',... 'pos',[radleft+2*radwidth dirbott radwidth texth],... 'string','3','value',0,'max',3,'visible','off'); rad(4) = uicontrol('style','radio',... 'pos',[radleft+3*radwidth dirbott radwidth texth],... 'string','4','value',0,'max',4,'visible','off'); for i=1:4 set(rad(i),'user',[rad(:,[1:(i-1),(i+1):4])]); end set(rad,'call','fseries(''callrad'')'); Xname = str2mat(' x + 1 ', ' x - 1 ','',''); lefts = str2mat(' -1 ',' 0 ','',''); rights = str2mat(' 0 ',' 1 ','',''); eqcall = ''; leftcall = ''; varcall = ''; rightcall = ''; forl = left +5 + eqlength; leftl = forl + space; leftr = leftl + nw; varl = leftr +equalw; rightl = varl + varw; rightr = rightl +equalw; for kk = 1:4 eqn(kk) = uicontrol('pos',[left+5 eqbott(kk) eqlength texth],... 'style','edit','tag',int2str(kk),... 'horizon','left','string',deblank(Xname(kk,:)),... 'call','fseries(''eqcall'')','visible','off'); forr(kk) = uicontrol('pos',[forl eqbott(kk) space texth],... 'style','text','tag',int2str(kk),... 'horizon','center','string','for',... 'visible','off'); leftw(kk) = uicontrol('pos',[leftl eqbott(kk) nw texth],... 'style','edit','tag',int2str(kk),... 'horizon','center','string',deblank(lefts(kk,:)),... 'call','fseries(''leftcall'')','visible','off'); lefteq(kk) = uicontrol('pos',[leftr eqbott(kk) equalw texth],... 'style','text','tag',int2str(kk),... 'horizon','center','string','<',... 'visible','off'); if kk ==1 varr(kk) = uicontrol('pos',[varl eqbott(kk) varw texth],... 'style','edit','tag',int2str(kk),... 'horizon','center','string',' x ',... 'call','fseries(''varcall'')','visible','off'); else varr(kk) = uicontrol('pos',[varl eqbott(kk) varw texth],... 'style','text','tag',int2str(kk),... 'horizon','left','string',' x ',... 'visible','off'); end righteq(kk) = uicontrol('pos',[rightl eqbott(kk) equalw texth],... 'style','text','tag',int2str(kk),... 'horizon','center','string','<',... 'visible','off'); rightw(kk) = uicontrol('pos',[rightr eqbott(kk) nw texth],... 'style','edit','tag',int2str(kk),... 'horizon','center','string',deblank(rights(kk,:)),... 'call','fseries(''rightcall'')','visible','off'); end butt(1) = uicontrol('style','push',... 'pos',[(defigwidth/4-35),buttbott,70,texth],... 'string','Quit',... 'call','fseries(''quit'')','visible','off'); butt(2) = 0; butt(3) = uicontrol('style','push','enable','on',... 'pos',[(3*defigwidth/4-35),buttbott,70,texth],... 'string','Proceed',... 'call','fseries(''proceed'')','visible','off'); butt(4) = 0; ud = [eqn,leftw,rightw,varr,butt,frame,NN,separation,N,0]; set(fourset,'resize','on'); hh = get(fourset,'child'); set(hh,'units','normal'); global FSSETPOS if all(size(FSSETPOS) == [1,4]) set(fourset,'pos',FSSETPOS); end set(fourset,'user',ud); set(fourset,'vis','on'); set(hh,'vis','on'); for kk = NN+1:4 set(findobj(hh,'tag',int2str(kk)),'vis','off'); end elseif strcmp(action,'proceed') ud = get(gcf,'user'); eqn = ud(1:4); leftw = ud(5:8); rightw = ud(9:12); var = ud(13); var = get(var,'string'); butt = ud(17:20); NN = ud(22); N = ud(24); fourdisp = ud(25); fourset = gcf; M = 0; mmmm = int2str(M); a = []; b = []; for kk = 1:NN aaa = str2num(get(leftw(kk),'string')); bbb = str2num(get(rightw(kk),'string')); ffcn = get(eqn(kk),'string'); l = length(ffcn); if ((l==0)|(isempty(aaa))|(isempty(bbb))) fseries('alert'); return; end a = [a,aaa]; b = [b,bbb]; eval([var,'=aaa;']); A(kk) = eval(ffcn); eval([var,'=bbb;']); B(kk) = eval(ffcn); for (k=fliplr(find((ffcn=='^')|(ffcn=='*')|(ffcn=='/')))) ffcn = [ffcn(1:k-1) '.' ffcn(k:l)]; l = l+1; end if kk ==1 fffcn = ffcn; else fffcn = str2mat(fffcn,ffcn); end end mmerr = abs(B(NN) - A(1)); for kk = 1:NN-1 mmerr = max(mmerr, abs(B(kk)-A(kk+1))); end mmerr = mmerr/2; aa = a(1); bb = b(NN); xx = aa +(0:N)*(bb-aa)/N; wf = NaN*ones(1,N+1); fm = wf; F1 = deblank(fffcn(1,:)); FN = deblank(fffcn(NN,:)); eval([var,'=xx(1);']); % x = xx(1); fm(1) = eval(F1); eval([var,'=xx(N+1);']); % x = xx(N+1); fm(1) = fm(1) + eval(FN); fm(1) = fm(1)/2; fm(N+1) = fm(1); FF = ''; for kk = 1:NN kkk = find((a(kk) 2 wf(kmin-1) = NaN; end end if (fourdisp == 0) ss = get(0,'screensize'); sw = ss(3); setpos = get(fourset,'pos'); setl = setpos(3); setw = setpos(3); displeft = min(setl+setw, sw -520); dispbott = 20; dispwidth = 550; dispht = 392; fourdisp = figure('pos',[displeft, dispbott, dispwidth, dispht],... 'resize','off','name','FSERIES Display','numb','off',... 'visible','off','tag','fseries'); ud(25) = fourdisp; set(fourset,'user',ud); texth =20; % Height of text boxes. space = 40; buttbott = 10; daxbott = 80/dispht; dxw = 450; daxw = dxw/dispwidth; dxleft = (dispwidth - dxw)/2; daxleft = dxleft/dispwidth; daxht = 281.25/dispht; diax = axes('pos',[daxleft, daxbott, daxw, daxht],'vis','off'); frame = uicontrol('pos',[dxleft,buttbott,dxw,texth+10],... 'style','frame'); degree = uicontrol('pos',[dxleft+5 buttbott+5 space texth],... 'style','edit','tag','deg',... 'horizon','center','string',mmmm,... 'call','fseries(''approx'')','visible','off'); degrlab = 'Enter the desired degree of approximation. ( <= 1000 )'; deglabw = dxw - space -20 -5; deglabel = uicontrol('pos',[dxleft+space+20 buttbott+5 deglabw texth],... 'style','text',... 'horizon','left','string',degrlab,... 'visible','off'); hh = get(fourdisp,'child'); set(findobj(fourdisp,'type','axes'),'units','normal'); set(findobj(fourdisp,'type','uicontrol'),'units','normal'); set(fourdisp,'resize','on'); global FSDISPPOS if all(size(FSDISPPOS) == [1,4]) set(fourdisp,'pos',FSDISPPOS); end set(fourdisp,'vis','on'); set(hh,'vis','on'); grid set(diax,'vis','on'); %,'xgrid','on','ygrid','on'); else figure(fourdisp); hh = get(fourdisp,'user'); degree = hh(4); set(degree,'string',mmmm); diax = gca; end aa = min(xx); bb = max(xx); cc = min(wf(finite(wf))); dd = max(wf(finite(wf))); ee = 0.05*(max((dd-cc),1)); cc = cc-ee; dd = dd+ee; hact = plot(xx,wf); axis([aa,bb,cc,dd]); set(hact,'user',fm); v = fft(fm(1:N)); set(diax,'user',v); w = v; w(M+2:N-M) = zeros(1,N-2*M-1); sfm = zeros(1,N+1); sfm(1:N) = real(ifft(w)); sfm(N+1) = sfm(1); cc = min(cc,min(sfm)); dd = max(dd,max(sfm)); hold on happ = plot(xx,sfm,'--r'); hold off axis([aa,bb,cc,dd]); set(fourdisp,'user',[hact,happ,mmerr,degree]); s2=['The Fourier series approximation of degree ',mmmm,'.']; title(s2); ferr=abs(fm-sfm); maxerr=max(max(ferr),mmerr); step = (xx(N+1)-xx(1))/N; L2err=norm(ferr)*sqrt(step); l2e=num2str(L2err); merr=num2str(maxerr); s3=['The maximum error is ',merr,'. The L2 error is ',l2e,'.']; xlabel(s3); hh = get(fourdisp,'child'); %set(hh,'vis','on'); elseif strcmp(action,'eqcall') ud = get(gcf,'user'); butt = ud(17:20); set(butt(3),'enable','on'); elseif strcmp(action,'leftcall') ud = get(gcf,'user'); butt = ud(17:20); rightw = ud(9:12); set(butt(3),'enable','on'); numb = get(gco,'tag'); N = str2num(numb); if N>1 bb = get(gco,'string'); nn = int2str(N-1); hh = findobj(rightw,'tag',nn); set(hh,'string',bb); end elseif strcmp(action,'rightcall') ud = get(gcf,'user'); butt = ud(17:20); leftw = ud(5:8); set(butt(3),'enable','on'); numb = get(gco,'tag'); N = str2num(numb); if N<4 bb = get(gco,'string'); nn = int2str(N+1); hh = findobj(leftw,'tag',nn); set(hh,'string',bb); end elseif strcmp(action,'varcall') ud = get(gcf,'user'); butt = ud(17:20); varr = ud(13:16); set(butt(3),'enable','on'); xx = get(gco,'string'); set(varr,'string',xx); elseif strcmp(action,'approx') mmax = 1000; hm = gco; v=get(gca,'user'); hh = get(gcf,'user'); hact = hh(1); happ = hh(2); mmerr = hh(3); xx = get(hact,'xdata'); fm = get(hact,'user'); mmmm = get(hm,'string'); M = str2num(mmmm); M = max(0,min(M,mmax)); mmmm = num2str(M); set(hm,'string',mmmm); w = v; N = length(xx) - 1; w(M+2:N-M) = zeros(1,N-2*M-1); sfm = zeros(1,N+1); sfm(1:N) = real(ifft(w)); sfm(N+1) = sfm(1); wf = get(hact,'ydata'); cc = min(wf(finite(wf))); dd = max(wf(finite(wf))); ee = 0.05* max((dd-cc),1); dd = max(max(sfm),dd)+ee; cc = min(min(sfm),cc)-ee; set(gca,'ylim',[cc,dd]); hold on set(happ,'ydata',sfm); hold off s2=['The Fourier series approximation of order ',mmmm,'.']; title(s2); ferr=abs(fm-sfm); maxerr=max(max(ferr),mmerr); step = (xx(N+1)-xx(1))/N; L2err=norm(ferr)*sqrt(step); l2e=num2str(L2err); merr=num2str(maxerr); s3=['The maximum error is ',merr,'. The L2 error is ',l2e,'.']; xlabel(s3); outdata =[xx;wf;sfm]; assignin('base','fsdata',outdata); elseif strcmp(action,'callrad') me = get(gcf,'currentobject'); vv = get(me,'value'); mm = get(me,'max'); if vv hand = get(me,'user'); set(hand(1:3),'value',0); end set(me,'value',mm); us = get(gcf,'user'); NN = us(22); if mm < NN us(22)=mm; set(gcf,'user',us); hh = get(gcf,'child'); % set(hh,'vis','on'); for kk = mm+1:NN set(findobj(hh,'tag',int2str(kk)),'vis','off'); end else us(22)=mm; set(gcf,'user',us); hh = get(gcf,'child'); % set(hh,'vis','on'); for kk = NN+1:mm set(findobj(hh,'tag',int2str(kk)),'vis','on'); end end elseif strcmp(action,'alert') ud = get(gcf,'user'); NN = ud(22); astr = ['All of the data for the ' num2str(NN) ' intervals must be provided.']; errh = errordlg(astr,'FSERIES data entry error'); elseif strcmp(action,'quit') h = findobj('tag','fseries'); close(h); end