Read characteristic lengths from the given file.

        The file is expected to have either 1 or 4 entries/lines with
        characteristic lengths > 0 (floats). If only one value is encountered,
        it is used for all four entities. If four values are encountered, they
        are assigned, in order, to:

            1) electrode nodes
            2) boundary nodes
            3) nodes from extra lines
            4) nodes from extra nodes

        Note that in case one node belongs to multiple entities, the smallest
        characteristic length will be used.

        If four values are used and the electrode length is negative, then the
        electrode positions will be read in (todo: we open the electrode.dat
        file two times here...) and the minimal distance between all electrodes
        will be multiplied by the absolute value of the imported value, and
        used as the characteristic length:

        .. math::

            l_{electrodes} = min(pdist(electrodes)) * |l_{electrodes}^{from
            file}|

        The function scipy.spatial.distance.pdist is used to compute the global
        minimal distance between any two electrodes.

        It is advisable to only used values in the range [-1, 0) for the
        automatic char length option.

def read_char_lengths(self, filename, electrode_filename):
        """Read characteristic lengths from the given file.

        The file is expected to have either 1 or 4 entries/lines with
        characteristic lengths > 0 (floats). If only one value is encountered,
        it is used for all four entities. If four values are encountered, they
        are assigned, in order, to:

            1) electrode nodes
            2) boundary nodes
            3) nodes from extra lines
            4) nodes from extra nodes

        Note that in case one node belongs to multiple entities, the smallest
        characteristic length will be used.

        If four values are used and the electrode length is negative, then the
        electrode positions will be read in (todo: we open the electrode.dat
        file two times here...) and the minimal distance between all electrodes
        will be multiplied by the absolute value of the imported value, and
        used as the characteristic length:

        .. math::

            l_{electrodes} = min(pdist(electrodes)) * |l_{electrodes}^{from
            file}|

        The function scipy.spatial.distance.pdist is used to compute the global
        minimal distance between any two electrodes.

        It is advisable to only used values in the range [-1, 0) for the
        automatic char length option.
        """

        if os.path.isfile(filename):
            data = np.atleast_1d(np.loadtxt(filename))
            if data.size == 4:
                characteristic_length = data
                # check sign of first (electrode) length value
                if characteristic_length[0] < 0:
                    try:
                        elec_positions = np.loadtxt(electrode_filename)
                    except:
                        raise IOError(
                            'The was an error opening the electrode file')
                    import scipy.spatial.distance
                    distances = scipy.spatial.distance.pdist(elec_positions)
                    characteristic_length[0] = min(distances) * np.abs(
                        characteristic_length[0])
                    if characteristic_length[0] == 0:
                        raise Exception(
                            'Error computing electrode ' +
                            'distances (got a minimal distance of zero')

            else:
                characteristic_length = np.ones(4) * data[0]
        else:
            characteristic_length = np.ones(4)

        if np.any(characteristic_length <= 0):
            raise Exception('No negative characteristic lengths allowed ' +
                            '(except for electrode length')

        self.char_lengths = {}
        for key, item in zip(('electrode',
                              'boundary',
                              'extra_line',
                              'extra_node'),
                             characteristic_length):
            self.char_lengths[key] = item