function glout = geolist(match) %stage info = geolist(matching string) % %This function uses the geologicstages.m database and attempts to locate those %stage names that most closely match the specified "matching string". % %It starts this by trying to find all the stages names or aliases that start %with exactly the characters in matching string. If exactly one stage is found %that starts with the requested characters then geowhen is called to give a %detailed description of that stage. Otherwise it lists all the stages that %begin with that string. Should no stage start with the requested string, this %function returns a list of the stages which are alphabetically closest. % %If output arguments are requested, similar content as shown to the screen is %also returned in a cell array. The columns of which are "stage name", "start %date", "end date" and "duration". % %Note that if geolist is called with no arguments, all stages are listed. %Created by Robert A. Rohde (geowhen@robertrohde.com) %Last Modified August 26, 2003 %load the geological database structure stages= geologicstages; %index counter for number of names, starts at 1. c = 1; %loop over all stages in data structure. for a = 1:length(stages); %create Names array with the vital info for the list. Names{c,1} = stages(a).Name; Names{c,2} = stages(a).Start; Names{c,3} = stages(a).End; Names{c,4} = stages(a).Start-stages(a).End; %numerical representation of a stage's name, used for sorting. gls{c} = lower(stages(a).Name')-'a'; %increment the counter. c = c + 1; %Do the same for each name in the AKA list. for b = 1:length(stages(a).AKA) Names{c,1} = stages(a).AKA{b}; Names{c,2} = stages(a).Start; Names{c,3} = stages(a).End; Names{c,4} = stages(a).Start-stages(a).End; gls{c} = lower(stages(a).AKA{b}')-'a'; c = c +1; end end %create a single numeric value associated with each string. %note: this section can misfire on some special characters. for a = 1:length(gls) t(a) = 0; for b = 1:length(gls{a}) t(a) = t(a) + gls{a}(b)/26^(b-1); end end %sort the numbers to figure out the appropriate order for the list. [t,re] = sort(t'); t = [t,re]; %if called with arguments, perform the matching ritual and throw away those %which don't conform. if (nargin > 0) %matching is not case sensitive, so lower it. match = lower(match); %length of the matching string lm = length(match); %nt array will hold the indices to the names that start with the matching string. nt = []; %loop over all possible names. for a =1:length(t) if (strncmp(lower(Names{t(a,2),1}),match,lm)) nt = [nt;t(a,:)]; end end %if no names start with it, then find the names which are closest alphabetically if isempty(nt) %ts will be a unique number associated to the matching string. %a similar number is associated with each element from computing t above. ts = 0; match = match - 'a'; for a = 1:lm ts = ts + match(a)/26^(a-1); end %figure out where it fits in t. k = findk(t(:,1),ts); %select adjacent elements, and perform bounds checking. mn = k - 8; mx = k + 8; if (mn < 1) mn = 1; mx = 16; end if (mx > length(t)) mx = length(t); mn = length(t) - 16; end %set nt to be the ones selected nt = t(mn:mx,:); end %else if only one element matched call geowhen to display the %details of that stage. if (length(nt(:,1)) == 1) geowhen(Names{nt(1,2),1}); return; end %truncate t to just the elements selected. t = nt; end %reuse variable name for new purpose because everyone enjoys recycling. %gls will now be used to collect the outputs that are returned if output %was requested. gls = {[],[],[],[]}; nmax = 0; ymax = 0; %figure out the maximum length needed for certain strings. for a = 1:length(t) if (length(Names{t(a,2),1})>nmax) nmax = length(Names{t(a,2),1}); end yl = length(num2str(Names{t(a,2),4})); if (yl>ymax) ymax = yl; end end %since most durations are short, don't allow more than 5 spaces if (ymax > 5) ymax = 5; end disp(' '); %display the list for a = 1:length(t) %prepare the output returns gls{a,1} = Names{t(a,2),1}; gls{a,2} = Names{t(a,2),3}; gls{a,3} = Names{t(a,2),2}; gls{a,4} = Names{t(a,2),4}; %prepare formatted output for display. str = [' ' gls{a,1} blanks(nmax-length(gls{a,1})) ' (' num2str(gls{a,2}) ' - ' num2str(gls{a,3}) ')']; str = [str, blanks(nmax + 20 - length(str)), ' ', num2str(gls{a,4})]; str = [str, blanks(ymax - length(num2str(gls{a,4}))), ' Myr']; disp(str); %make a note if any stage has negative duration if (gls{a,4} < 0) disp(' ---- BAD DATES HERE ---- '); end end %note how many stages displayed disp(' '); disp([' ' num2str(length(t)), ' Stages Displayed']); disp(' '); %return output, if requested. if nargout > 0 glout = gls; end function k = findk(value,vector); % function k = findk(value,vector); % finds the k such that vector(k) is closest to value [val,k] = min(abs(vector-value));