ClipRasterByMask.py

Added -multi option - Pedro Venâncio, 2019-02-13 03:50 PM

Download (11.1 KB)

 
1
# -*- coding: utf-8 -*-
2

    
3
"""
4
***************************************************************************
5
    ClipRasterByMask.py
6
    ---------------------
7
    Date                 : September 2013
8
    Copyright            : (C) 2013 by Alexander Bruy
9
    Email                : alexander bruy at gmail dot com
10
***************************************************************************
11
*                                                                         *
12
*   This program is free software; you can redistribute it and/or modify  *
13
*   it under the terms of the GNU General Public License as published by  *
14
*   the Free Software Foundation; either version 2 of the License, or     *
15
*   (at your option) any later version.                                   *
16
*                                                                         *
17
***************************************************************************
18
"""
19

    
20
__author__ = 'Alexander Bruy'
21
__date__ = 'September 2013'
22
__copyright__ = '(C) 2013, Alexander Bruy'
23

    
24
# This will get replaced with a git SHA1 when you do a git archive
25

    
26
__revision__ = '$Format:%H$'
27

    
28
import os
29

    
30
from qgis.PyQt.QtGui import QIcon
31

    
32
from qgis.core import (QgsRasterFileWriter,
33
                       QgsProcessing,
34
                       QgsProcessingException,
35
                       QgsProcessingParameterDefinition,
36
                       QgsProcessingParameterFeatureSource,
37
                       QgsProcessingParameterRasterLayer,
38
                       QgsProcessingParameterCrs,
39
                       QgsProcessingParameterEnum,
40
                       QgsProcessingParameterString,
41
                       QgsProcessingParameterNumber,
42
                       QgsProcessingParameterBoolean,
43
                       QgsProcessingParameterRasterDestination)
44
from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
45
from processing.algs.gdal.GdalUtils import GdalUtils
46

    
47
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
48

    
49

    
50
class ClipRasterByMask(GdalAlgorithm):
51

    
52
    INPUT = 'INPUT'
53
    MASK = 'MASK'
54
    SOURCE_CRS = 'SOURCE_CRS'
55
    TARGET_CRS = 'TARGET_CRS'
56
    NODATA = 'NODATA'
57
    ALPHA_BAND = 'ALPHA_BAND'
58
    CROP_TO_CUTLINE = 'CROP_TO_CUTLINE'
59
    KEEP_RESOLUTION = 'KEEP_RESOLUTION'
60
    SET_RESOLUTION = 'SET_RESOLUTION'
61
    X_RESOLUTION = 'X_RESOLUTION'
62
    Y_RESOLUTION = 'Y_RESOLUTION'
63
    OPTIONS = 'OPTIONS'
64
    DATA_TYPE = 'DATA_TYPE'
65
    MULTITHREADING = 'MULTITHREADING'
66
    OUTPUT = 'OUTPUT'
67

    
68
    TYPES = ['Use input layer data type', 'Byte', 'Int16', 'UInt16', 'UInt32', 'Int32', 'Float32', 'Float64', 'CInt16', 'CInt32', 'CFloat32', 'CFloat64']
69

    
70
    def __init__(self):
71
        super().__init__()
72

    
73
    def initAlgorithm(self, config=None):
74
        self.addParameter(QgsProcessingParameterRasterLayer(self.INPUT,
75
                                                            self.tr('Input layer')))
76
        self.addParameter(QgsProcessingParameterFeatureSource(self.MASK,
77
                                                              self.tr('Mask layer'),
78
                                                              [QgsProcessing.TypeVectorPolygon]))
79
        self.addParameter(QgsProcessingParameterCrs(self.SOURCE_CRS,
80
                                                    self.tr('Source CRS'),
81
                                                    optional=True))
82
        self.addParameter(QgsProcessingParameterCrs(self.TARGET_CRS,
83
                                                    self.tr('Target CRS'),
84
                                                    optional=True))
85
        self.addParameter(QgsProcessingParameterNumber(self.NODATA,
86
                                                       self.tr('Assign a specified nodata value to output bands'),
87
                                                       type=QgsProcessingParameterNumber.Double,
88
                                                       defaultValue=None,
89
                                                       optional=True))
90
        self.addParameter(QgsProcessingParameterBoolean(self.ALPHA_BAND,
91
                                                        self.tr('Create an output alpha band'),
92
                                                        defaultValue=False))
93
        self.addParameter(QgsProcessingParameterBoolean(self.CROP_TO_CUTLINE,
94
                                                        self.tr('Match the extent of the clipped raster to the extent of the mask layer'),
95
                                                        defaultValue=True))
96
        self.addParameter(QgsProcessingParameterBoolean(self.KEEP_RESOLUTION,
97
                                                        self.tr('Keep resolution of input raster'),
98
                                                        defaultValue=False))
99
        self.addParameter(QgsProcessingParameterBoolean(self.SET_RESOLUTION,
100
                                                        self.tr('Set output file resolution'),
101
                                                        defaultValue=False))
102
        self.addParameter(QgsProcessingParameterNumber(self.X_RESOLUTION,
103
                                                       self.tr('X Resolution to output bands'),
104
                                                       type=QgsProcessingParameterNumber.Double,
105
                                                       defaultValue=None,
106
                                                       optional=True))
107
        self.addParameter(QgsProcessingParameterNumber(self.Y_RESOLUTION,
108
                                                       self.tr('Y Resolution to output bands'),
109
                                                       type=QgsProcessingParameterNumber.Double,
110
                                                       defaultValue=None,
111
                                                       optional=True))
112
        multithreading_param = QgsProcessingParameterBoolean(self.MULTITHREADING,
113
                                                             self.tr('Use multithreaded warping implementation'),
114
                                                             defaultValue=False)
115
        multithreading_param.setFlags(multithreading_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
116
        self.addParameter(multithreading_param)
117
        options_param = QgsProcessingParameterString(self.OPTIONS,
118
                                                     self.tr('Additional creation options'),
119
                                                     defaultValue='',
120
                                                     optional=True)
121
        options_param.setFlags(options_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
122
        options_param.setMetadata({
123
            'widget_wrapper': {
124
                'class': 'processing.algs.gdal.ui.RasterOptionsWidget.RasterOptionsWidgetWrapper'}})
125
        self.addParameter(options_param)
126

    
127
        dataType_param = QgsProcessingParameterEnum(self.DATA_TYPE,
128
                                                    self.tr('Output data type'),
129
                                                    self.TYPES,
130
                                                    allowMultiple=False,
131
                                                    defaultValue=0)
132
        dataType_param.setFlags(dataType_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
133
        self.addParameter(dataType_param)
134

    
135
        self.addParameter(QgsProcessingParameterRasterDestination(self.OUTPUT,
136
                                                                  self.tr('Clipped (mask)')))
137

    
138
    def name(self):
139
        return 'cliprasterbymasklayer'
140

    
141
    def displayName(self):
142
        return self.tr('Clip raster by mask layer')
143

    
144
    def icon(self):
145
        return QIcon(os.path.join(pluginPath, 'images', 'gdaltools', 'raster-clip.png'))
146

    
147
    def group(self):
148
        return self.tr('Raster extraction')
149

    
150
    def groupId(self):
151
        return 'rasterextraction'
152

    
153
    def commandName(self):
154
        return 'gdalwarp'
155

    
156
    def getConsoleCommands(self, parameters, context, feedback, executing=True):
157
        inLayer = self.parameterAsRasterLayer(parameters, self.INPUT, context)
158
        if inLayer is None:
159
            raise QgsProcessingException(self.invalidRasterError(parameters, self.INPUT))
160

    
161
        maskLayer, maskLayerName = self.getOgrCompatibleSource(self.MASK, parameters, context, feedback, executing)
162

    
163
        sourceCrs = self.parameterAsCrs(parameters, self.SOURCE_CRS, context)
164
        targetCrs = self.parameterAsCrs(parameters, self.TARGET_CRS, context)
165

    
166
        if self.NODATA in parameters and parameters[self.NODATA] is not None:
167
            nodata = self.parameterAsDouble(parameters, self.NODATA, context)
168
        else:
169
            nodata = None
170
        options = self.parameterAsString(parameters, self.OPTIONS, context)
171
        out = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
172
        self.setOutputValue(self.OUTPUT, out)
173

    
174
        arguments = []
175

    
176
        if sourceCrs.isValid():
177
            arguments.append('-s_srs')
178
            arguments.append(GdalUtils.gdal_crs_string(sourceCrs))
179

    
180
        if targetCrs.isValid():
181
            arguments.append('-t_srs')
182
            arguments.append(GdalUtils.gdal_crs_string(targetCrs))
183

    
184
        data_type = self.parameterAsEnum(parameters, self.DATA_TYPE, context)
185
        if data_type:
186
            arguments.append('-ot ' + self.TYPES[data_type])
187

    
188
        arguments.append('-of')
189
        arguments.append(QgsRasterFileWriter.driverForExtension(os.path.splitext(out)[1]))
190

    
191
        if self.parameterAsBool(parameters, self.KEEP_RESOLUTION, context):
192
            arguments.append('-tr')
193
            arguments.append(str(inLayer.rasterUnitsPerPixelX()))
194
            arguments.append(str(-inLayer.rasterUnitsPerPixelY()))
195
            arguments.append('-tap')
196

    
197
        if self.parameterAsBool(parameters, self.SET_RESOLUTION, context):
198
            arguments.append('-tr')
199
            if self.X_RESOLUTION in parameters and parameters[self.X_RESOLUTION] is not None:
200
                xres = self.parameterAsDouble(parameters, self.X_RESOLUTION, context)
201
                arguments.append('{}'.format(xres))
202
            else:
203
                arguments.append(str(inLayer.rasterUnitsPerPixelX()))
204
            if self.Y_RESOLUTION in parameters and parameters[self.Y_RESOLUTION] is not None:
205
                yres = self.parameterAsDouble(parameters, self.Y_RESOLUTION, context)
206
                arguments.append('{}'.format(yres))
207
            else:
208
                arguments.append(str(-inLayer.rasterUnitsPerPixelY()))
209
            arguments.append('-tap')
210

    
211
        arguments.append('-cutline')
212
        arguments.append(maskLayer)
213

    
214
        if self.parameterAsBool(parameters, self.CROP_TO_CUTLINE, context):
215
            arguments.append('-crop_to_cutline')
216

    
217
        if self.parameterAsBool(parameters, self.ALPHA_BAND, context):
218
            arguments.append('-dstalpha')
219

    
220
        if nodata is not None:
221
            arguments.append('-dstnodata {}'.format(nodata))
222

    
223
        if self.parameterAsBool(parameters, self.MULTITHREADING, context):
224
            arguments.append('-multi')
225

    
226
        if options:
227
            arguments.extend(GdalUtils.parseCreationOptions(options))
228

    
229
        arguments.append(inLayer.source())
230
        arguments.append(out)
231

    
232
        return [self.commandName(), GdalUtils.escapeAndJoin(arguments)]