function [mix,rix] = build_index(string,seg,rmin,rmax,ixmin,ixmax)
%
%  This function builds a valid matrix index from the input string
%  The input string has the form  SEG range  SEG range
%  where SEG is one of the members of seg and the range is a
%  valid range of residues bounded by rmin and rmax
%
%  It also returns a residue index to help with annotation.
%
   mix = '';
   rix = '';
   prefix = '[';
%
%  Copy the input string
   a = string;
%
%  Loop until the string is parsed
   while (1)
      [s,a] = strtok(a);
      if (isempty(s)); break; end
      n = 1;
      while ( n < length(seg) )
         if (strcmp(s,seg(n))); break; end
         n = n + 1;
      end  
%  Invalid segment id      
      if (n > length(seg) )
         sprintf('%s is not a valid segment id',s);
         return
      end
%  Get the requested range
      [r,a] = strtok(a);
%
%  Is this a compound range request?
%  e.g., 200:230,240:250, 261  (with/without intruding whitespace)
%
      k = findstr(r,',');
      if (isempty(k))
%
%  Simple range request
%
         [istr,rstr] = range_str(r,rmin(n),rmax(n),ixmin(n),ixmax(n));
         mix = [mix prefix istr];
         rix = [rix prefix rstr];
      else
%  Compound range request
         lk = length(k);
         lr = length(r);
%  Does this token end with a comma?
%  If so, append the next token.
         if ( k(lk) == lr ) 
            while (1)
               [r2,a] = strtok(a);
               r = strcat(r,r2);
               lk = length(k);
               lr = length(r);
               kk = findstr(r2,',');
               if (isempty(kk)); break; end
               k = findstr(r,',');
               if ( k(lk) < lr ) ; break; end
            end
         end
%
%  Commas delineate the ranges
%  e.g. 200:230,250
         r0 = 1;
         for jj = 1:lk
            [istr,rstr] = range_str(r(r0:k(jj)-1),rmin(n),rmax(n),ixmin(n),ixmax(n));
            mix = [mix prefix istr];
            rix = [rix prefix rstr];
            r0 = k(jj) + 1;
            prefix = ',';
         end
         [istr,rstr] = range_str(r(r0:lr),rmin(n),rmax(n),ixmin(n),ixmax(n));
         mix = [mix prefix istr];
         rix = [rix prefix rstr];
      end
      prefix = ',';
   end
   mix = [mix ']'];
   rix = [rix ']'];
return


function [index_str,resid_str] = range_str(token,rmin,rmax,ixmin,ixmax)
%
%  Create the index string for the specified range
%  e.g.,  200   200:210   200:10:220
%
%  Handle the wildcards * and :
   switch token 
    case {'*',':'}
      index_str = [int2str(ixmin) ':' int2str(ixmax)];
      resid_str = [int2str(rmin) ':' int2str(rmax)];
    otherwise
      m = findstr(token,':');
      lm = length(m);
      lt = length(token);
      switch lm
%
%  Single values, no range:    200   
%
       case 0
         i0 = sscanf(token,'%d');
         if (i0 < rmin); i0 = rmin ; end
         if (i0 > rmax); i0 = rmax ; end
         index_str = [int2str(ixmin+i0-rmin)];
         resid_str = [int2str(i0)];
%
%  Two values:   200:210  or possibly  :210 or  200:
%  the second form implies beginning:210  or  200:end
%
       case 1
%  Is the : the first entry in the token?
         if (m(1) == 1)
            i0 = rmin;
         else
            i0 = sscanf(token(1:m(1)-1),'%d');
            if (i0 < rmin); i0 = rmin ; end
            if (i0 > rmax); i0 = rmax ; end
         end
%  Is the : the last entry in the token?
         if (m(1) == lt) 
            i1 = rmax;
         else
            i1 = sscanf(token(m(1)+1:lt),'%d');
            if (i1 < rmin); i1 = rmin ; end
            if (i1 > rmax); i1 = rmax ; end
         end
         index_str = [int2str(ixmin+i0-rmin) ':' int2str(ixmax+i1-rmax)];
         resid_str = [int2str(i0) ':' int2str(i1)];
%
%  Three values:    200:5:250  or possibly :5:250 or 200:5:
%  the second form implies beginning:5:250 or 200:5:end
%
       case 2
%  Is the : the first entry in the token?
         if (m(1) == 1)
            i0 = rmin;
         else
            i0 = sscanf(token(1:m(1)-1),'%d');
            if (i0 < rmin); i0 = rmin ; end
            if (i0 > rmax); i0 = rmax ; end
         end
         istep = sscanf(token(m(1)+1:m(2)-1),'%d');
%  Is the : the last entry in the token?
         if (m(2) == lt) 
            i1 = rmax;
         else
            i1 = sscanf(token(m(2)+1:lt),'%d');
            if (i1 < rmin); i1 = rmin ; end
            if (i1 > rmax); i1 = rmax ; end
         end
         index_str = [int2str(ixmin+i0-rmin) ':' int2str(istep) ':' int2str(ixmax+i1-rmax)];
         resid_str = [int2str(i0) ':' int2str(istep) ':' int2str(i1)];
       otherwise
         sprintf('%s is not a valid range',token);    
         return
      end
   end
return

