def test_drainage_areas(): """Test drainage area functions and methods.""" jim = pj.Jim(tiles[0]) d8 = pj.demops.flowDirectionD8(jim) cda = pj.demops.contribDrainArea(d8, 8) destructive_object = pj.Jim(d8) destructive_object.demops.contribDrainArea(8) assert destructive_object.properties.isEqual(cda), \ 'Error in demops.contribDrainArea()' assert destructive_object.stats.getStats(band=0)['min'] >= 1, \ 'Error in demops.contribDrainArea()' thresh = pj.Jim(jim) thresh.pixops.setData(5) strat = pj.demops.contribDrainAreaStrat(cda, thresh, d8) destructive_object.demops.contribDrainAreaStrat(thresh, d8) stats = destructive_object.stats.getStats(band=0) assert destructive_object.properties.isEqual(strat), \ 'Error in demops.contribDrainAreaStrat()' assert stats['min'] == 0, 'Error in demops.contribDrainAreaStrat()' assert stats['max'] == 1, 'Error in demops.contribDrainAreaStrat()' inf = pj.demops.flowDirectionDInf(jim) # TODO: Suppress output originating in mialib (flag `quiet`, please?) cda_inf = pj.demops.contribDrainAreaInf(inf) inf.demops.contribDrainAreaInf() assert inf.properties.isEqual(cda_inf), \ 'Error in demops.contribDrainAreaInf()' assert abs(inf.stats.getStats(band=0)['min']) == 1, \ 'Error in demops.contribDrainAreaInf()'
def test_getStatProfile(): """Test if values from getStatProfile are not wrong.""" jim1 = pj.Jim(tiles[0]) jim2 = pj.Jim(tiles[1]) jiml = pj.JimList([jim1, jim2]) stats1 = jiml.stats.getStats(['min', 'max'], band=0) stats2 = jim2.stats.getStats(band=0) min = stats1['min'] if stats2['min'] < min: min = stats2['min'] max = stats1['max'] if stats2['max'] > max: max = stats2['max'] # TODO: Suppress output originating in jiplib (flag `quiet`, please?) min_profile = jiml.stats.getStatProfile('min') max_profile = jiml.stats.getStatProfile('max') assert min_profile.stats.getStats(band=0)['min'] == min, \ 'Error in stats.getStatProfile()' assert max_profile.stats.getStats(band=0)['max'] == max, \ 'Error in stats.getStatProfile()'
def test_sml(): """Test the Symbolic Machine Learning classifier.""" class_dict = { 'urban': 2, 'agriculture': 12, 'forest': 25, 'water': 41, 'rest': 50 } class_from = range(0, 50) class_to = [50] * 50 for i in range(0, 50): if 1 <= i < 10: class_to[i] = class_dict['urban'] elif 11 <= i < 22: class_to[i] = class_dict['agriculture'] elif 23 <= i < 25: class_to[i] = class_dict['forest'] elif 40 <= i < 45: class_to[i] = class_dict['water'] else: class_to[i] = class_dict['rest'] jim_ref = pj.Jim(clc, dx=1000, dy=1000) jim_ref.classify.reclass(classes=list(class_from), reclasses=class_to) bbox = [4246000, 2547000, 4349500, 2441000] jim = pj.Jim(testFile, band2plane=True, ulx=bbox[0], uly=bbox[1], lrx=bbox[2], lry=bbox[3]) jim_ref.geometry.warp(jim.properties.getProjection()) reflist = pj.JimList([jim_ref]) jim.classify.trainSML(reflist, output=model, classes=sorted(class_dict.values())) sml = pj.classify.sml(jim, model=model) sml.geometry.band2plane() sml.np()[:] = np.argmax(sml.np(), axis=0) sml.properties.clearNoData() sml.classify.reclass(classes=[0, 1, 2, 3, 4], reclasses=[2, 12, 25, 41, 50]) stats = sml.stats.getStats('histogram') assert 6605.0 < stats['histogram'][stats['bin'].index(2)] < 6610.0,\ 'Error in class 2' assert 23500.0 < stats['histogram'][stats['bin'].index(12)] < 23510.0,\ 'Error in class 12' assert 6285.0 < stats['histogram'][stats['bin'].index(25)] < 6295.0,\ 'Error in class 25' assert 960.0 < stats['histogram'][stats['bin'].index(41)] < 975.0,\ 'Error in class 41' assert 6510.0 < stats['histogram'][stats['bin'].index(50)] < 6520.0,\ 'Error in class 50' os.remove(model)
def test_flows(): """Test DEM flow functions and methods.""" jim = pj.Jim(tiles[0]) destructive_object = pj.Jim(jim) flow = pj.demops.flowDirectionD8(destructive_object) stats = flow.stats.getStats(band=0) assert stats['max'] <= 8, \ 'Error in demops.flowDirectionD8()' assert stats['min'] >= 0, \ 'Error in demops.flowDirectionD8()' destructive_object.demops.flowDirectionD8() assert destructive_object.properties.isEqual(flow), \ 'Error in demops.flowDirectionD8()' flow_2 = pj.demops.flow(destructive_object, 8) stats = flow_2.stats.getStats(band=0) assert stats['min'] >= 1, \ 'Error in demops.flowDirectionD8()' destructive_object.demops.flow(8) assert destructive_object.properties.isEqual(flow_2), \ 'Error in demops.flowDirectionD8()' destructive_object = pj.Jim(jim) flow_new = pj.demops.flowNew(destructive_object, flow, 8) destructive_object.demops.flowNew(flow, 8) assert destructive_object.properties.isEqual(flow_new), \ 'Error in demops.flowNew()' assert flow_new.stats.getStats(band=0)['min'] > 0, \ 'Error in demops.flowNew()' assert destructive_object.properties.getDataType() == \ flow_new.properties.getDataType(), \ 'Error in demops.flowNew() (changed data type of object)' flow = pj.demops.flowDirectionDInf(jim) jim.demops.flowDirectionDInf() stats = jim.stats.getStats(band=0) assert jim.properties.isEqual(flow), \ 'Error in demops.demFlowDirectionDInf()' assert stats['min'] >= -1, \ 'Error in demops.demFlowDirectionDInf()' assert stats['max'] < 6.5, \ 'Error in demops.demFlowDirectionDInf()' # jim2 = pj.Jim(tiles[0][:-8] + 'nir' + tiles[0][-5:]) destructive_object = pj.Jim(jim) destructive_object[25:30, 25:30] = 65533
def test_histograms(): """Test that values of histograms are not suspicious.""" jim1 = pj.Jim(tiles[0]) jim1_rows = jim1.properties.nrOfRow() jim1_cols = jim1.properties.nrOfCol() # Test getHisto1d() histo1d = jim1.stats.getHisto1d() assert histo1d.stats.getStats(band=0)['min'] >= 0, \ 'Error in computing 1D histogram' assert histo1d.stats.getStats(band=0)['max'] <= jim1_rows * jim1_cols,\ 'Error in computing 1D histogram' assert histo1d.properties.isEqual(pj.stats.getHisto1d(jim1)), \ 'Function and method getHisto1d() return different results' jim2 = pj.Jim(tiles[0][:-8] + 'nir' + tiles[0][-5] + '.tif') # Test getHisto2d() histo2d = jim1.stats.getHisto2d(jim2) assert histo2d.stats.getStats(band=0)['min'] >= 0, \ 'Error in computing 2D histogram' assert histo2d.stats.getStats(band=0)['max'] <= jim1_rows * jim1_cols,\ 'Error in computing 2D histogram' assert histo2d.properties.isEqual(pj.stats.getHisto2d(jim1, jim2)), \ 'Function and method getHisto2d() return different results' # TODO: Cover histo3d() # Test getHistoCumulative try: _ = jim1.stats.getHistoCumulative() raised = False except pj.exceptions.JimInnerParametersError: raised = True assert raised, 'Error in catching wrong data type in ' \ 'stats.getHistoCumulative()' # histo_cumul = pj.pixops.convert(jim1, 4).stats.getHistoCumulative() jim2 = pj.pixops.convert(jim1, 'Int32') histo_cumul = jim2.stats.getHistoCumulative() assert histo_cumul.properties.nrOfCol() == jim1_rows * jim1_cols + 1, \ 'Error in stats.getHistoCumulative() ' \ '(nrOfCol != nrOfRow*Col of original)'
def slopeDInf(jim_object): """Output the slope along the dinf drainage directions. :param jim_object: a Jim object :return: a Jim object """ return _pj.Jim(jim_object._jipjim.demSlopeDInf())
def test_NDVI(): """Test computing NDVI in different ways.""" jim = pj.Jim(testFile, band=[0, 1]) jim_red = pj.geometry.cropBand(jim, 0) jim_nir = pj.geometry.cropBand(jim, 1) # TODO: Suppress output originating in jiplib (flag `quiet`, please?) ndvi = pj.pixops.NDVI(jim, 0, 1) jim.pixops.NDVI(0, 1) assert jim.properties.isEqual(ndvi), 'Error in computing NDVI' ndvi = pj.pixops.NDVISeparateBands(jim_red, jim_nir) jim_red.pixops.NDVISeparateBands(jim_nir) assert jim_red.properties.isEqual(ndvi), 'Error in computing ' \ 'NDVISeparateBands' assert jim_red.properties.isEqual(jim), 'Error in computing NDVI or ' \ 'NDVISeparateBands' jim_nir.pixops.convert('Float32') ndvi = pj.pixops.NDVISeparateBands(jim_red, jim_nir) assert not jim.properties.isEqual(ndvi), 'Error in computing NDVI'
def getHisto1d(jim_object): """Compute the frequency distribution of the grey levels of im. :param jim_object: a Jim object :return: a Jim object """ return _pj.Jim(jim_object._jipjim.histo1d())
def test_stretch(): """Test stretch function.""" for tile in tiles: jim = pj.Jim(tile) stretched = pj.pixops.stretch(jim, otype='GDT_Byte', dst_min=0, dst_max=255, cc_min=2, cc_max=98) stretched_eq = pj.pixops.stretch(jim, otype='GDT_Byte', dst_min=0, dst_max=255, cc_min=2, cc_max=98, eq=True) jim.pixops.stretch(otype='GDT_Byte', dst_min=0, dst_max=255, cc_min=2, cc_max=98) assert jim.properties.isEqual(stretched), \ 'Inconsistency in pixops.stretch() ' \ '(method returns different result than function)' stats = stretched_eq.stats.getStats(['min', 'max', 'histogram'], src_min=1, src_max=254) assert stats['min'] == 1, \ 'Error in pixops.stretch(): min is not 1' assert stats['max'] == 254, \ 'Error in pixops.stretch(): max is not 254' assert max(stats['histogram']) <= 1150, \ 'Error in pixops.stretch(): max is not < 1150' assert min(stats['histogram']) >= 850, \ 'Error in pixops.stretch(): max is not >= 850'
def histoCompress(jim_object, band: int = None): """Redistribute the intensity of histogram to fit full range of values. Redistributes the intensity values of im in such a way that the minimum value is zero and that all subsequent intensity values are used until the maximum value (i.e. no gaps). :param jim_object: Jim object to be used for the histoCompress :param band: from which to get the histogram :return: a Jim object """ if band is not None: return _pj.Jim(jim_object._jipjim.histoCompress(band)) else: return _pj.Jim(jim_object._jipjim.histoCompress())
def flow(jim_object, graph: int): """Compute the contributing drainage areas using D8 drainage directions. :param jim_object: a Jim object :param graph: integer for number of nearest neighbours to consider :return: a Jim object """ return _pj.Jim(jim_object._jipjim.demFlow(graph))
def catchmentBasinOutlet(jim_object, d8): """Compute the catchment basin outlet. :param jim_object: an image node holding labelled outlets :param d8: an image node holding d8 flow directions :return: a Jim object """ return _pj.Jim(jim_object._jipjim.demCatchmentBasinOutlet(d8._jipjim))
def getHisto2d(self, jim_object2): """Compute the frequency distribution of the grey levels pairs. :param jim_object2: a Jim object :return: a Jim object """ return _pj.Jim(self._jim_object._jipjim.histo2d(jim_object2._jipjim))
def strahler(jim_object): """Compute the Strahler thing. :param jim_object: an image node holding d8 directions on river networks, 0 elsewhere :return: a Jim object """ return _pj.Jim(jim_object._jipjim.demStrahlerOrder())
def getStatProfile(self, function: str, **kwargs): """Get statistic profile. :param function: string naming a statistical function """ kwargs.update({'function': function}) return _pj.Jim(self._jim_list._jipjimlist.statProfile(kwargs))
def catchmentBasinConfluence(jim_object, d8): """Compute the catchment basin confluence. :param jim_object: an image node holding labelled outlet pixels with value 1 and river pixels with value 2 :param d8: an image node holding d8 flow directions :return: a Jim object """ return _pj.Jim(jim_object._jipjim.demCatchmenBasinOutlet(d8._jipjim))
def test_pit_removals(): """Test functions and methods for pit removals.""" jim = pj.Jim(tiles[0]) label = pj.ccops.labelPixels(jim) unpit = pj.demops.pitRemovalCarve(label, jim, 8, 212) pit_label = pj.Jim(label) pit_label.demops.pitRemovalCarve(jim, 8, 212) assert unpit.properties.isEqual(pit_label), \ 'Error in demops.pitRemovalCarve()' # TODO: Suppress output originating in mialib (flag `quiet`, please?) unpit = pj.demops.pitRemovalOptimal(label, jim, 8, 212, 0) label.demops.pitRemovalOptimal(jim, 8, 212, 0) assert unpit.properties.isEqual(label), \ 'Error in demops.pitRemovalOptimal()'
def slopeD8(jim_object): """Compute the steepest slope within a 3x3 neighbourhood for each pixel. It corresponds to the slope along the D8 direction. :param jim_object: a Jim object :return: a Jim object """ return _pj.Jim(jim_object._jipjim.demSlopeD8())
def stretch(jim_object, **kwargs): """Stretch Jim. :param jim_object: :param kwargs: :return: """ return _pj.Jim(jim_object._jipjim.stretch(kwargs))
def slope(jim_object, scale: float = 1.0, zscale: float = 1.0, percent: bool = False): """Compute the slope of a Jim object. :param jim_object: Jim :param scale: horizontal scale :param zscale: vertical scale :param percent: if True, return value in percents, degrees otherwise :return: a Jim object representing the slope """ tapsdx = _np.array([[-1.0, 0.0, 1.0], [-2.0, 0.0, 2.0], [-1.0, 0.0, 1.0]]) tapsdy = _np.array([[-1.0, -2.0, -1.0], [0.0, 0.0, 0.0], [1.0, 2.0, 1.0]]) tapsdx *= zscale tapsdy *= zscale jimdx = _pj.Jim(jim_object) jimdy = _pj.Jim(jim_object) if jim_object.properties.getDataType() != 'Float32' and \ jim_object.properties.getDataType() != 'Float64': jimdx.pixops.convert(otype="Float32") jimdy.pixops.convert(otype="Float32") jimdx.ngbops.firfilter2d(tapsdx, nodata=jim_object.properties.getNoDataVals(), norm=True) jimdx = abs(jimdx) jimdx /= jimdx.properties.getDeltaX() * scale jimdx *= jimdx jimdy.ngbops.firfilter2d(tapsdy, nodata=jim_object.properties.getNoDataVals(), norm=True) jimdy = abs(jimdy) jimdy /= jimdy.properties.getDeltaX() * scale jimdy *= jimdy rad2deg = 180.0 / _np.pi jimdx += jimdy jimdx.np()[:] = _np.sqrt(jimdx.np()) if percent: jimdx *= 100 else: jimdx.np()[:] = _np.arctan(jimdx.np()) jimdx *= rad2deg return jimdx
def simpleBitwiseOp(jim, another_jim, op: int, *args): """Create Jim composed using a simple bitwise operation (coded with op). :param jim: Jim object :param another_jim: Jim object (to be sure that at least one is provided) :param op: integer for operation type :param args: Jim objects :return: Jim holding specified bitwise operation with from provided Jim objects """ jout = _pj.Jim(jim) jims = [another_jim] jims.extend(args) for newJim in jims: jout._jipjim.d_pointOpBitwise(newJim._jipjim, op) return _pj.Jim(jout)
def simpleArithOp(jim1, jim2, op: int, *args): """Create Jim composed using a simple arithmetic operation (coded with op). :param jim1: Jim object :param jim2: Jim object (to be sure that at least one is provided) :param op: integer for operation type :param args: Jim objects :return: Jim holding specified arithmetic operation with from provided Jim objects """ jout = _pj.Jim(jim1) jims = [jim2] jims.extend(args) for jim in jims: jout._jipjim.d_pointOpArith(jim._jipjim, op) return _pj.Jim(jout)
def setThreshold(jim_object, **kwargs): """Apply min and max threshold to pixel values in raster dataset. :param jim_object: the Jim object on which to set threshold :param kwargs: See table :py:meth:`~pixops._PixOps.setThreshold`. for help, please refer to the corresponding method :py:meth:`~pixops._PixOps.setThreshold`. """ return _pj.Jim(jim_object._jipjim.setThreshold(kwargs))
def NDVISeparateBands(jim_red, jim_nir): """Compute NDVI from two Jim objects. Values in both red and NIR equal to 0 will obtain an NDVI value of -2) :param jim_red: Jim object with values of red :param jim_nir: Jim object with values of NIR :return: a Jim object with values of NDVI """ return _pj.Jim(jim_nir._jipjim.pointOpNDI(jim_red._jipjim))
def getStatProfile(jim_object, function: str, **kwargs): """Get statistic profile. :param jim_object: a Jim object :param function: string naming a statistical function :return: a Jim object """ kwargs.update({'function': function}) return _pj.Jim(jim_object._jipjim.statProfile(kwargs))
def getHistoCumulative(self): """Compute the cumulative frequency distribution of the grey levels. :return: a Jim object """ if self._jim_object.properties.getDataType() not in ['UInt32', 'Int32']: raise _pj.exceptions.JimInnerParametersError( 'Object the method is called on must be of type UInt32 or ' 'Int32') return _pj.Jim(self._jim_object._jipjim.histo1dCumulative())
def test_simple_op(): """Test simpleArithOp() and simpleBitwiseOp() functions and methods.""" jim = pj.Jim(tiles[0]) # Test simpleArithOp() ones = pj.pixops.setData(jim, 1) jim_plus_one = jim + 1 jim_plus_one_arith = pj.pixops.simpleArithOp(jim, ones, 0) jim.pixops.simpleArithOp(ones, 0) assert jim.properties.isEqual(jim_plus_one_arith), \ 'Inconsistency in pixops.simpleArithOp() ' \ '(method returns different result than function)' assert jim.properties.isEqual(jim_plus_one), \ 'Error in pixops.simpleArithOp(op=0) or Jim + int ' \ '(Results not equal)' jim_minus_one = jim - 1 jim_minus_one_arith = pj.pixops.simpleArithOp(jim, ones, 1) jim.pixops.simpleArithOp(ones, 1) assert jim.properties.isEqual(jim_minus_one_arith), \ 'Inconsistency in pixops.simpleArithOp() ' \ '(method returns different result than function)' assert jim.properties.isEqual(jim_minus_one), \ 'Error in pixops.simpleArithOp(op=1) or Jim - int ' \ '(Results not equal)' # Test simpleBitwiseOp() jim_and = jim & ones jim_and_bitwise = pj.pixops.simpleBitwiseOp(jim, ones, 10) jim.pixops.simpleBitwiseOp(ones, 10) assert jim.properties.isEqual(jim_and_bitwise), \ 'Inconsistency in pixops.simpleBitwiseOp() ' \ '(method returns different result than function)' assert jim.properties.isEqual(jim_and), \ 'Error in pixops.simpleBitwiseOp(op=10) or Jim & Jim ' \ '(Results not equal)' jim_or = jim | jim_minus_one jim_or_bitwise = pj.pixops.simpleBitwiseOp(jim, jim_minus_one, 11) jim.pixops.simpleBitwiseOp(jim_minus_one, 11) assert jim.properties.isEqual(jim_or_bitwise), \ 'Inconsistency in pixops.simpleBitwiseOp() ' \ '(method returns different result than function)' assert jim.properties.isEqual(jim_or), \ 'Error in pixops.simpleBitwiseOp(op=11) or Jim & Jim ' \ '(Results not equal)'
def test_histoCompress(): """Test histoCompress() function and method.""" jim = pj.Jim(tiles[0]) destructive_object = pj.Jim(jim) compressed = pj.pixops.histoCompress(destructive_object) destructive_object.pixops.histoCompress() assert destructive_object.properties.isEqual(compressed), \ 'Error in pixops.histoCompress()' assert destructive_object.stats.getStats(band=0)['min'] == 0, \ 'Error in pixops.histoCompress() (minimum value not 0)' compressed = pj.pixops.histoCompress(jim, 0) jim.pixops.histoCompress(0) assert jim.properties.isEqual(compressed), \ 'Error in pixops.histoCompress()' assert jim.stats.getStats(band=0)['min'] == 0, \ 'Error in pixops.histoCompress() (minimum value not 0)'
def test_slopes(): """Test demSlopeD8() function and method.""" jim = pj.Jim(tiles[0]) destructive_object = pj.Jim(jim) slope = pj.demops.slopeD8(destructive_object) stats = slope.stats.getStats(band=0) assert stats['min'] >= 0, \ 'Error in demops.slopeD8()' destructive_object.demops.slopeD8() assert destructive_object.properties.isEqual(slope), \ 'Error in demops.slopeD8()' inf = pj.demops.slopeDInf(jim) jim.demops.slopeDInf() assert jim.properties.isEqual(inf), 'Error in demops.slopeDInf()' assert inf.stats.getStats(band=0)['min'] >= 0, \ 'Error in demops.slopeDInf()'
def test_slope(): """Test DEM flow functions and methods.""" jim = pj.Jim(tiles[0]) slope = pj.demops.slope(jim) stats = slope.stats.getStats(band=0) assert stats['max'] <= 90, \ 'Error: max>90 in demops.slope()' assert stats['min'] >= 0, \ 'Error: min<0 in demops.slope()'