A5 Scripts
A5A
% Script A5A % Examines ConicFit bigscreen % The unperturbed data... x = [ 1.02 .95 .87 .77 .67 .56 .44 .30 .16 .01]'; y = [ 0.39 .32 .27 .22 .18 .15 .13 .12 .13 .15]'; n = 10; % We'll contaminate with scaled versions of these noise vectors rand('seed',0) xrand = -1+2*rand(n,1); yrand = -1+2*rand(n,1); for noise = [0 .0001 .001 .01 .1] [a,b,c,d,e] = ConicFit(x+noise*xrand,y+noise*yrand); xmin = -1; xmax = 2 ; deltax = .02; ymin = -1; ymax = 1.5 ; deltay = .02; [X,Y] = meshgrid(xmin:deltax:xmax,ymin:deltay:ymax); Z = a*X.^2 + b*X.*Y + c*Y.^2 + d*X + e*Y + 1; contour(X,Y,Z,[0 0],'k') hold on plot(x,y,'*') hold off title(sprintf('a = %9.6f b = %9.6f c = %9.6f d = %9.6f e = %9.6f',a,b,c,d,e)) shg pause end %%%%%%%%%% Sensitivity study %%%%%%% % Examine how small changes in the data affect the outcome. % Here are two data sets. % One is best approximated with an ellipse, the other by a hyperbola. xEllipse = [1.0144 0.9409 0.8736 0.7736 0.6787 0.5577 0.4404 0.3066 0.1507 0.0011]'; yEllipse = [0.3906 0.3234 0.2602 0.2177 0.1713 0.1483 0.1337 0.1218 0.1386 0.1569]'; xHyperb = [0.9638 0.8594 0.9058 0.8059 0.7569 0.5367 0.4439 0.3662 0.0669 -0.0793]'; yHyperb = [0.3959 0.3542 0.1715 0.1967 0.0934 0.1335 0.1674 0.1378 0.2161 0.2192]'; % Here is a measure of the separation of the two data sets sep = norm(xEllipse-xHyperb,1)+norm(yEllipse-yHyperb,1); while sep >.00001 % Look at midpoint of the datasets and approximate with a conic xMid = (xEllipse+xHyperb)/2; yMid = (yEllipse+yHyperb)/2; [a,b,c,d,e] = ConicFit(xMid,yMid); if c < 0 % A hyperbola renders the best fit at the midpoint xHyperb = xMid; yHyperb = yMid; else % An ellipse renders the best fit at the midpoint xEllipse = xMid; yEllipse = yMid; end % Plot the "endpoint" conics [a,b,c,d,e] = ConicFit(xEllipse,yEllipse); [X,Y] = meshgrid(-1:.02:2,-1:.02:1.5); Z = a*X.^2 + b*X.*Y + c*Y.^2 + d*X + e*Y + 1; contour(X,Y,Z,[0 0],'k') hold on text(-.9,-.6,sprintf('Ellipse: a = %9.6f b = %9.6f c = %9.6f d = %9.6f e = %9.6f',a,b,c,d,e)) plot(xEllipse,yEllipse,'*k') [a,b,c,d,e] = ConicFit(xHyperb,yHyperb); text(-.9,-.7,sprintf('Hyperbola: a = %9.6f b = %9.6f c = %9.6f d = %9.6f e = %9.6f',a,b,c,d,e)) Z = a*X.^2 + b*X.*Y + c*Y.^2 + d*X + e*Y + 1; contour(X,Y,Z,[0 0],'r') plot(xHyperb,yHyperb,'or') hold off sep = norm(xEllipse-xHyperb,1)+norm(yEllipse-yHyperb,1); title(sprintf('Ellipse is black, Hyperbola is red, Data Separation = %5.2e',sep)) pause end
A5C
% A5C % Examines Update close all % Using fmin which is soon to disappear ... warning off matlab:fmin:ObsoleteFunction % Season length data... sA = [92.7556 93.6507 89.8424 88.9938]; % Initial guess.. d = 0; alpha = 0; kMax = 6; for k = 1:kMax [dnext,alphanext] = Update(d,alpha); d = dnext; alpha = alphanext; sE = SeasonLength(d,alpha); DrawEccentric(d,alpha,sE,sA) pause end
CirclePoints
function [x,y] = CirclePoints(d,alpha) % Determines the equinox and solstice points for the eccentric model % with displacement d and rotation alpha. % % x and y are row 4-vectors with the property that % % (x(1),y(1)) = coordinate of the Vernal Equinox point % (x(2),y(2)) = coordinate of the Summer Solstice point % (x(3),y(3)) = coordinate of the Autumnal Equinox point % (x(4),y(4)) = coordinate of the Winter Solstice point c = cos(alpha); s = sin(alpha); tau = sqrt(1-(s*d)^2); xV = d*s^2 + c*tau; yV = s*(-d*c + tau); xA = d*s^2 - c*tau; yA = s*(-d*c - tau); c = cos(alpha+pi/2); s = sin(alpha+pi/2); tau = sqrt(1-(s*d)^2); xS = d*s^2 + c*tau; yS = s*(-d*c + tau); xW = d*s^2 - c*tau; yW = s*(-d*c - tau); x = [xV xS xA xW]; y = [yV yS yA yW];
DrawEccentric
function DrawEccentric(d,alpha,sE,sA) % Displays the eccentric model with displacement d and rotation % alpha. % sE is a row 4-vector of estimated season lengths (in days). % sA is a row 4-vector of actual season lengths (in days). % Both sE and sA specify these lengths in Spring-Summer-Fall-Winter order. % Plot Circle and coordinate axes theta = linspace(0,2*pi); plot(cos(theta),sin(theta),'k') axis([-1.2 1.2 -1.2 1.2]) axis equal off hold on plot(linspace(-1.1,1.1),zeros(1,100),':k') plot(zeros(1,100),linspace(-1.1,1.1),':k') hold on [x,y] = CirclePoints(d,alpha); % Plot the equinox connector xV = x(1); yV = y(1); xA = x(3); yA = y(3); plot([xV xA],[yV yA]) text(1.1*xV,1.1*yV,'V') text(1.1*xA,1.1*yA,'A') plot(xV,yV,'m*',xA,yA,'m*') % Plot the solstice connector xS = x(2); yS = y(2); xW = x(4); yW = y(4); plot([xS xW],[yS yW]) text(1.1*xS,1.1*yS,'S') text(1.1*xW,1.1*yW,'W') plot(xS,yS,'m*',xW,yW,'m*') % Display the estimated and actual season lengths text( 1.0,1.15,'\bfSpring'); text( 1.0, 1.0,pretty(sE(1))); text( 1.0, .85,pretty(sA(1))) text(-1.5,1.15,'\bfSummer'); text(-1.5, 1.0,pretty(sE(2))); text(-1.5, .85,pretty(sA(2))) text(-1.5,-.85,'\bfAutumn'); text(-1.5,-1.0,pretty(sE(3))); text(-1.5,-1.15,pretty(sA(3))) text( 1.0,-.85,'\bfWinter'); text( 1.0,-1.0,pretty(sE(4))); text( 1.0,-1.15,pretty(sA(4))) % Display the error and the parameter values title( ['Error = ' pretty(max(abs(sE-sA)))]) text(-.8,-1.3,sprintf('d = %10.6f alpha = %10.6f',d,alpha)) hold off
Pretty
function s = Pretty(d) % % s = Pretty(d) converts a decimal number assumed to specify time in days % into a string that indicates the time in days, hours, and minutes. % % Input: % % d A nonnegative real number (Earth Days) % % Output: % % s s string that reports d in days, hours, and minutes. % For example, if % % days = 92 + 34*(1/24) + 21*(1/(24*60)), % % then s would be the string '92d 34m 21s'. % % % ------------------------------------------------------------------------- % Convert days to numerical d-h-m form. days = floor(d); hrs = (d-days)*24; h = floor(hrs); m = round((hrs-h)*60); % Adjust so that 0<=m<60 and 0<=h<24 if m==60 m = 0; h = h+1; end if h==24 h = 0; days = days+1; end % Convert d, h, and m to strings. sd = [num2str(days) 'd ']; if days<=9 sd = ['0' sd]; end if h<=9 sh = ['0' num2str(h) 'h ']; else sh = [num2str(h) 'h ']; end if m<=9 sm = ['0' num2str(m) 'm']; else sm = [num2str(m) 'm']; end % Concatenate s = [sd sh sm];