<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _qmed_from_descriptors_2008(self, as_rural=False, donor_catchments=None):
 """ Return QMED estimation based on FEH catchment descriptors, 2008 methodology. Methodology source: Science Report SC050050, p. 36 :param as_rural: assume catchment is fully rural. Default: false. :type as rural: bool :param donor_catchments: override donor catchment to improve QMED catchment. If `None` (default), donor catchment will be searched automatically, if empty list, no donors will be used. :type donor_catchments: :class:`Catchment` :return: QMED in m³/s :rtype: float """

        try:
            # Basis rural QMED from descriptors
            lnqmed_rural = 2.1170 \
                           + 0.8510 * log(self.catchment.descriptors.dtm_area) \
                           - 1.8734 * 1000 / self.catchment.descriptors.saar \
                           + 3.4451 * log(self.catchment.descriptors.farl) \
                           - 3.0800 * self.catchment.descriptors.bfihost ** 2.0
            qmed_rural = exp(lnqmed_rural)

            # Log intermediate results
            self.results_log['qmed_descr_rural'] = qmed_rural

            if donor_catchments is None:
                # If no donor catchments are provided, find the nearest 25
                donor_catchments = self.find_donor_catchments()
            if donor_catchments:
                # If found multiply rural estimate with weighted adjustment factors from all donors

                weights = self._vec_alpha(donor_catchments)
                errors = self._vec_lnqmed_residuals(donor_catchments)
                correction = np.dot(weights, errors)

                lnqmed_rural += correction
                qmed_rural = exp(lnqmed_rural)

                # Log intermediate results
                self.results_log['donors'] = donor_catchments
                for i, donor in enumerate(self.results_log['donors']):
                    donor.weight = weights[i]
                    donor.factor = exp(errors[i])
                self.results_log['donor_adj_factor'] = exp(correction)
                self.results_log['qmed_adj_rural'] = qmed_rural

            if as_rural:
                return qmed_rural
            else:
                # Apply urbanisation adjustment
                urban_adj_factor = self.urban_adj_factor()

                # Log intermediate results
                self.results_log['qmed_descr_urban'] = self.results_log['qmed_descr_rural'] * urban_adj_factor
                return qmed_rural * urban_adj_factor
        except (TypeError, KeyError):
            raise InsufficientDataError("Catchment `descriptors` attribute must be set first.")