def woe(factor, sites, unit_cell=1): '''Weight of evidence method (multiclass form). @param factor Multiclass pattern array used for prediction of point objects (sites). @param sites Array layer consisting of the locations at which the point objects are known to occur. @param unit_cell Method parameter, pixelsize of resampled rasters. @return masked array Array of total weights of each factor. ''' # Get list of categories from the factor raster categories = get_gradations(factor.compressed()) # Try to binarize sites: sCategories = get_gradations(sites.compressed()) if len(sCategories) != 2: raise WoeError('Site raster must be binary!') sites = binaryzation(sites, [sCategories[1]]) # List of the weights of evidence: # weights[0] is (wPlus, wMinus) for the first category, weights[1] is (wPlus, wMinus) for the second category, ... weights = [] if len(categories) >= 2: for cat in categories: fct = binaryzation(factor, [cat]) weights.append(_binary_woe(fct, sites, unit_cell)) else: raise WoeError('Wrong count of categories in the factor raster!') wTotalMin = sum([w[1] for w in weights]) # List of total weights of evidence of the categories: # wMap[0] is the total weight of the first category, wMap[1] is the total weight of the second category, ... wMap = [w[0] + wTotalMin - w[1] for w in weights] # If len(categories) = 2, then [w[0] + wTotalMin - w[1] for w in weights] increases the answer. # In this case: if len(categories) == 2: wMap = [w/2 for w in wMap] resultMap =np.zeros(ma.shape(factor)) for i,cat in enumerate(categories): resultMap[factor==cat] = wMap[i] resultMap = ma.array(data=resultMap, mask=factor.mask) result = {'map': resultMap, 'categories': categories, 'weights': wMap} return result
def resetMask(self, maskVals = None): ''' Set mask of _ALL_ bands. maskVals is a list of masked values. ''' for i in range(self.getBandsCount()): r = self.getBand(i) if maskVals != None: mask = binaryzation(r, maskVals) else: mask = False r = ma.array(data = r, mask=mask) self.setBand(r, i)
def train(self): ''' Train the model ''' self.transitionPotentials = {} try: iterCount = len(self.codes)*len(self.factors) self.rangeChanged.emit(self.tr("Training WoE... %p%"), iterCount) changeMap = self.changeMap.getBand(1) for code in self.codes: sites = binaryzation(changeMap, [code]) # Reclass factors (continuous factor -> ordinal factor) wMap = np.ma.zeros(changeMap.shape) # The map of summary weight of the all factors self.weights[code] = {} # Dictionary for storing wheights of every raster's band for k in xrange(len(self.factors)): fact = self.factors[k] self.weights[code][k] = {} # Weights of the factor factorW = self.weights[code][k] if self.bins: # Get bins of the factor bin = self.bins[k] if (bin != None) and fact.getBandsCount() != len(bin): raise WoeManagerError("Count of bins list for multiband factor is't equal to band count!") else: bin = None for i in range(1, fact.getBandsCount()+1): band = fact.getBand(i) if bin and bin[i-1]: # band = reclass(band, bin[i-1]) band, sites = masks_identity(band, sites, dtype=np.uint8) # Combine masks of the rasters woeRes = woe(band, sites, self.unit_cell) # WoE for the 'code' (initState->finalState) transition and current 'factor'. weights = woeRes['map'] wMap = wMap + weights factorW[i] = woeRes['weights'] self.updateProgress.emit() # Reclassification finished => set WoE coefficients self.woe[code]=wMap # WoE for all factors and the transition code. # Potentials are WoE map rescaled to 0--100 percents band = (sigmoid(wMap)*100).astype(np.uint8) p = Raster() p.create([band], self.geodata) self.transitionPotentials[code] = p gc.collect() except MemoryError: self.errorReport.emit('The system out of memory during WoE trainig') raise except: self.errorReport.emit(self.tr("An unknown error occurs during WoE trainig")) raise finally: self.processFinished.emit()
def __init__ (self, referenceMap, simulatedMap): """ @param referenceMap Reference raster @param simulatedMap Simulated raster """ QObject.__init__(self) if referenceMap.getBandsCount() + simulatedMap.getBandsCount() !=2: raise EBError('The reference and simulated rasters must be 1-band rasters!') if not referenceMap.geoDataMatch(simulatedMap): raise EBError('Geometries of the reference and simulated rasters are different!') self.categories = referenceMap.getBandGradation(1) for s in simulatedMap.getBandGradation(1): if not s in self.categories: raise EBError('Categories in the reference and simulated rasters are different!') R = referenceMap.getBand(1) S = simulatedMap.getBand(1) self.shape = R.shape R, S = masks_identity(R,S, dtype=np.uint8) # Array for weight self.W = np.ones(self.shape) self.W = self.W - np.ma.getmask(R) R = np.ma.filled(R, 0) S = np.ma.filled(S, 0) # Proportion of category j in pixel n at the beginning resolution of the reference map self.Rj = {} for j in self.categories: self.Rj[j] = 1.0*binaryzation(R, [j]) # Proportion of category j in pixel n at the beginning resolution of the simulated map self.Sj = {} for j in self.categories: self.Sj[j] = 1.0*binaryzation(S, [j])
def _read(self): try: data = gdal.Open( self.filename ) except RuntimeError: raise ProviderError("Can't read the file '%s'" % self.filename) if data is None: raise ProviderError("Can't read the file '%s'" % self.filename) self.geodata = {} self.geodata['xSize'] = data.RasterXSize self.geodata['ySize'] = data.RasterYSize self.geodata['proj'] = data.GetProjection() self.geodata['transform'] = data.GetGeoTransform() # Get units of the projection sr = osr.SpatialReference() sr.ImportFromWkt(self.geodata['proj']) self.geodata['units'] = sr.GetLinearUnitsName() self.bands = np.ma.zeros((data.RasterCount,self.geodata['ySize'], self.geodata['xSize']), dtype=float) self.bandcount = data.RasterCount if self.maskVals != None and len(self.maskVals) != self.bandcount: raise ProviderError("Band count of the file '%s' does't match nodata values count" % self.filename) for i in range(1, data.RasterCount+1): r = data.GetRasterBand(i) nodataValue = r.GetNoDataValue() if nodataValue != None: nodataValues = [nodataValue] else: nodataValues = [] r = r.ReadAsArray() #self.bandgradation[i] = None try: userNodataValues = self.maskVals[i] except TypeError: userNodataValues = [] nodataValues += userNodataValues if nodataValues != []: mask = binaryzation(r, nodataValues) r = ma.array(data = r, mask=mask) else: r = ma.array(data = r, mask=False) self.bands[i-1, :, :] = r self.isNormalazed = False
def binaryzation(self, trueVals, bandNum): '''Reclass band bandNum to true/false mode. Set true for pixels from trueVals.''' r = self.getBand(bandNum) r = binaryzation(r, trueVals) self.setBand(r, bandNum)