<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def moresane_by_scale(self, start_scale=1, stop_scale=20, subregion=None, sigma_level=4, loop_gain=0.1, tolerance=0.75, accuracy=1e-6, major_loop_miter=100, minor_loop_miter=30, all_on_gpu=False, decom_mode="ser", core_count=1, conv_device='cpu', conv_mode='linear', extraction_mode='cpu', enforce_positivity=False, edge_suppression=False, edge_offset=0, flux_threshold=0, neg_comp=False, edge_excl=0, int_excl=0):
 """ Extension of the MORESANE algorithm. This takes a scale-by-scale approach, attempting to remove all sources at the lower scales before moving onto the higher ones. At each step the algorithm may return to previous scales to remove the sources uncovered by the deconvolution. INPUTS: start_scale (default=1) The first scale which is to be considered. stop_scale (default=20) The maximum scale which is to be considered. Optional. subregion (default=None):
 Size, in pixels, of the central region to be analyzed and deconvolved. sigma_level (default=4) Number of sigma at which thresholding is to be performed. loop_gain (default=0.1):
 Loop gain for the deconvolution. tolerance (default=0.75):
 Tolerance level for object extraction. Significant objects contain wavelet coefficients greater than the tolerance multiplied by the maximum wavelet coefficient in the scale under consideration. accuracy (default=1e-6):
 Threshold on the standard deviation of the residual noise. Exit main loop when this threshold is reached. major_loop_miter (default=100):
 Maximum number of iterations allowed in the major loop. Exit condition. minor_loop_miter (default=30):
 Maximum number of iterations allowed in the minor loop. Serves as an exit condition when the SNR does not reach a maximum. all_on_gpu (default=False):
 Boolean specifier to toggle all gpu modes on. decom_mode (default='ser'):
 Specifier for decomposition mode - serial, multiprocessing, or gpu. core_count (default=1):
 In the event that multiprocessing, specifies the number of cores. conv_device (default='cpu'):
 Specifier for device to be used - cpu or gpu. conv_mode (default='linear'):
 Specifier for convolution mode - linear or circular. extraction_mode (default='cpu'):
 Specifier for mode to be used - cpu or gpu. enforce_positivity (default=False):
 Boolean specifier for whether or not a model must be strictly positive. edge_suppression (default=False):
 Boolean specifier for whether or not the edges are to be suprressed. edge_offset (default=0):
 Numeric value for an additional user-specified number of edge pixels to be ignored. This is added to the minimum suppression. OUTPUTS: self.model (no default):
 Model extracted by the algorithm. self.residual (no default):
 Residual signal after deconvolution. """


        # The following preserves the dirty image as it will be changed on every iteration.

        dirty_data = self.dirty_data

        scale_count = start_scale


        while not (self.complete):

            logger.info("MORESANE at scale {}".format(scale_count))

            self.moresane(subregion=subregion, scale_count=scale_count, sigma_level=sigma_level, loop_gain=loop_gain,
                          tolerance=tolerance, accuracy=accuracy, major_loop_miter=major_loop_miter,
                          minor_loop_miter=minor_loop_miter, all_on_gpu=all_on_gpu, decom_mode=decom_mode,
                          core_count=core_count, conv_device=conv_device, conv_mode=conv_mode,
                          extraction_mode=extraction_mode, enforce_positivity=enforce_positivity,
                          edge_suppression=edge_suppression, edge_offset=edge_offset,
                          flux_threshold=flux_threshold, neg_comp=neg_comp,
                          edge_excl=edge_excl, int_excl=int_excl)

            self.dirty_data = self.residual

            scale_count += 1

            if (scale_count>(np.log2(self.dirty_data.shape[0]))-1):
                logger.info("Maximum scale reached - finished.")
                break

            if (scale_count>stop_scale):
                logger.info("Maximum scale reached - finished.")
                break

        # Restores the original dirty image.

        self.dirty_data = dirty_data
        self.complete = False