code: public static ProteinSequence getProteinSequenceForStructure(Structure struct, Map<Integer,Group> groupIndexPosition ) {
  
  		if( groupIndexPosition != null) {
  			groupIndexPosition.clear();
  		}
  
  		StringBuilder seqStr = new StringBuilder();
  
  		for(Chain chain : struct.getChains()) {
  			List<Group> groups = chain.getAtomGroups();
  			Map<Integer,Integer> chainIndexPosition = new HashMap<Integer, Integer>();
  			int prevLen = seqStr.length();
  
  			// get the sequence for this chain
  			String chainSeq = SeqRes2AtomAligner.getFullAtomSequence(groups, chainIndexPosition, false);
  			seqStr.append(chainSeq);
  
  
  			// fix up the position to include previous chains, and map the value back to a Group
  			for(Integer seqIndex : chainIndexPosition.keySet()) {
  				Integer groupIndex = chainIndexPosition.get(seqIndex);
  				groupIndexPosition.put(prevLen + seqIndex, groups.get(groupIndex));
  			}
  		}
  
  		ProteinSequence s = null;
  		try {
  			s = new ProteinSequence(seqStr.toString());
  		} catch (CompoundNotFoundException e) {
  			// I believe this can't happen, please correct this if I'm wrong - JD 2014-10-24
  			// we can log an error if it does, it would mean there's a bad bug somewhere
  			logger.error("Could not create protein sequence, unknown compounds in string: {}", e.getMessage());
  		}
  
  		return s;
  	}
docs: Generates a ProteinSequence corresponding to the sequence of struct,
  and maintains a mapping from the sequence back to the original groups.
  
  Chains are appended to one another. 'X' is used for heteroatoms.
  
  @param struct Input structure
  @param groupIndexPosition An empty map, which will be populated with
  (residue index in returned ProteinSequence) -> (Group within struct)
  @return A ProteinSequence with the full sequence of struct. Chains are
  concatenated in the same order as the input structures
  
  @see {@link SeqRes2AtomAligner#getFullAtomSequence(List, Map)}, which
  does the heavy lifting.