Parse compartment information from model.

        Return tuple of: 1) iterator of
        :class:`psamm.datasource.entry.CompartmentEntry`; 2) Set of pairs
        defining the compartment boundaries of the model.

def parse_compartments(self):
        """Parse compartment information from model.

        Return tuple of: 1) iterator of
        :class:`psamm.datasource.entry.CompartmentEntry`; 2) Set of pairs
        defining the compartment boundaries of the model.
        """

        compartments = OrderedDict()
        boundaries = set()

        if 'compartments' in self._model:
            boundary_map = {}
            for compartment_def in self._model['compartments']:
                compartment_id = compartment_def.get('id')
                _check_id(compartment_id, 'Compartment')
                if compartment_id in compartments:
                    raise ParseError('Duplicate compartment ID: {}'.format(
                        compartment_id))

                props = dict(compartment_def)
                adjacent_to = props.pop('adjacent_to', None)
                if adjacent_to is not None:
                    if not isinstance(adjacent_to, list):
                        adjacent_to = [adjacent_to]
                    for other in adjacent_to:
                        boundary_map.setdefault(other, set()).add(
                            compartment_id)

                mark = FileMark(self._context, None, None)
                compartment = CompartmentEntry(props, mark)
                compartments[compartment_id] = compartment

            # Check boundaries from boundary_map
            for source, dest_set in iteritems(boundary_map):
                if source not in compartments:
                    raise ParseError(
                        'Invalid compartment {} referenced'
                        ' by compartment {}'.format(
                            source, ', '.join(dest_set)))
                for dest in dest_set:
                    boundaries.add(tuple(sorted((source, dest))))

        return itervalues(compartments), frozenset(boundaries)