code: private SubstructureIdentifier toCanonical() {
  		StructureIdentifier real = getStructureIdentifier();
  		if(real != null) {
  			try {
  				return real.toCanonical();
  			} catch (StructureException e) {
  				// generate fake one if needed
  			}
  		}
  
  		// No identifier set, so generate based on residues present in the structure
  		List<ResidueRange> range = new ArrayList<>();
  		for (Chain chain : getChains()) {
  			List<Group> groups = chain.getAtomGroups();
  			ListIterator<Group> groupsIt = groups.listIterator();
  			if(!groupsIt.hasNext()) {
  				continue; // no groups in chain
  			}
  			Group g = groupsIt.next();
  			ResidueNumber first = g.getResidueNumber();
  
  			//TODO Detect missing intermediate residues -sbliven, 2015-01-28
  			//Already better than previous whole-chain representation
  
  			// get last residue
  			while(groupsIt.hasNext()) {
  				g = groupsIt.next();
  			}
  			ResidueNumber last = g.getResidueNumber();
  
  			range.add(new ResidueRange(chain.getName(),first,last));
  		}
  		return new SubstructureIdentifier(getPDBCode(),range);
  	}
docs: Creates a SubstructureIdentifier based on the residues in this Structure.
  
  Only the first and last residues of each chain are considered, so chains
  with gaps
  @return A {@link SubstructureIdentifier} with residue ranges constructed from each chain