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 trainSML(self, reference, output: str = None, **kwargs): """Train a supervised symbolic machine learning (SML) classifier. Train it based on a reference :py:class:`JimList` object :param reference: (list of) Jim objects containing reference raster dataset(s) :param output: output filepath where trained model will be written (leave empty to return as a string) :param kwargs: See below keyword arguments: ========= ============================================================ band (list of) band index (indices) (starting from 0) classes list of classes to extract from reference. Leave empty to extract two classes only: 1 against rest srcnodata No data value in source (do not consider for training) ========= ============================================================ Example: train a Jim object (jim) with four Sentinel-2 bands using a single reference image (e.g., corine land cover):: corine = pj.Jim('/path/to/corine.tif') jim.classify.trainSML( corine, output='/path/to/model.txt', classes=[12, 40]) Use :py:meth:`~_Classify.sml` to perform the classification Typically, the SML algorithm performs a discretization, in order to reduce the dynamic range of the input and limit the number of unique sequences. For instance, to reduce the dynamic range of the input to NBIT bits:: NBIT=3 jim += 2 ** (8 - NBIT) - jim.stats.getStats(['min'])['min'] jim *= (2 ** 8 - 1) / jim.stats.getStats(['max'])['max'] jim >>= 8-NBIT """ # convert list of Jim to JimList if not isinstance(reference, _pj.JimList): reference = _pj.JimList([reference]) kwargs.update({'method': "sml"}) if 'classes' in kwargs: kwargs.update({'class': kwargs.pop('classes')}) if output: kwargs.update({'model': str(output)}) self._jim_object._jipjim.trainSML(reference._jipjimlist, kwargs) else: raise _pj.exceptions.JimIllegalArgumentError( 'output for model not set')
def test_jimlist_creations(): """Test different ways to create JimList.""" jim1 = pj.Jim(tiles[0]) # Test JimList creation from a list of jims jiml = pj.JimList([jim1, jim1]) assert len(jiml) == 2, 'Error in JimList creation from a list of ' \ 'Jims (wrong number of items afterwards)' assert jiml[0].properties.isEqual(jim1) and \ jiml[1].properties.isEqual(jim1), \ 'Error in JimList creation from a list of Jims ' \ '(items at positions do not correspond with the used ones)' # Test JimList creation from a JimList jiml2 = pj.JimList(jiml) assert len(jiml2) == 2, 'Error in JimList creation from a JimList ' \ '(wrong number of items afterwards)' assert jiml2[0].properties.isEqual(jim1) and \ jiml2[1].properties.isEqual(jim1), \ 'Error in JimList creation from a JimList object ' \ '(items at positions do not correspond with the used ones)' # Test JimList creation from a Jim jiml = pj.JimList(jim1) assert len(jiml) == 1, 'Error in JimList creation from a Jim object ' \ '(wrong number of items afterwards)' assert jiml[0].properties.isEqual(jim1), \ 'Error in JimList creation from a Jim object ' \ '(item at position 0 does not correspond with the used Jim)' # Test wrong creation of a JimList (integer used as an argument) try: jiml = pj.JimList(1) raised = False except pj.exceptions.JimListIllegalArgumentError: raised = True assert raised, \ 'Error in catching a call of JimList creation with wrong value ' \ 'parsed (integer used instead of allowed argument types)'
def test_supremum_infimum(): """Test picking up supremum and infimum from computed NDVIs.""" for tile in tiles: jim4 = pj.Jim(tile) jim8 = pj.Jim(tile[:-8] + 'nir' + tile[-5] + '.tif') if 'max_ndvi' and 'min_ndvi' in locals(): b = pj.pixops.NDVISeparateBands(jim4, jim8) max_ndvi[b > max_ndvi] = b max_ndvi_func = pj.pixops.supremum(max_ndvi, b) max_ndvi2.pixops.supremum(b) max_ndvi3 = pj.pixops.supremum(pj.JimList([max_ndvi2, b])) max_ndvi4 = pj.Jim(max_ndvi2) max_ndvi4.pixops.supremum(pj.JimList([b, max_ndvi2])) max_ndvi5 = pj.JimList([max_ndvi2, b]).pixops.supremum() assert max_ndvi.properties.isEqual(max_ndvi2), \ 'Inconsistency in pixops.supremum() ' \ '(method returns different result than function)' assert max_ndvi.properties.isEqual(max_ndvi_func), \ 'Error in pixops.supremum or jim[a>jim] = a' assert max_ndvi.properties.isEqual(max_ndvi3), \ 'Error in pixops.supremum JimList 3' assert max_ndvi.properties.isEqual(max_ndvi4), \ 'Error in pixops.supremum JimList 4' assert max_ndvi.properties.isEqual(max_ndvi5), \ 'Error in pixops.supremum JimList 5' min_ndvi[b < min_ndvi] = b min_ndvi_func = pj.pixops.infimum(min_ndvi, b) min_ndvi2.pixops.infimum(b) min_ndvi3 = pj.pixops.infimum(pj.JimList([min_ndvi2, b])) min_ndvi4 = pj.Jim(min_ndvi2) min_ndvi4.pixops.infimum(pj.JimList([b, min_ndvi2])) min_ndvi5 = pj.JimList([min_ndvi2, b]).pixops.infimum() assert min_ndvi.properties.isEqual(min_ndvi2), \ 'Inconsistency in pixops.infimum() ' \ '(method returns different result than function)' assert min_ndvi.properties.isEqual(min_ndvi_func), \ 'Error in pixops.infimum or jim[a<jim] = a' assert min_ndvi.properties.isEqual(min_ndvi3), \ 'Error in pixops.infimum JimList 3' assert min_ndvi.properties.isEqual(min_ndvi4), \ 'Error in pixops.infimum JimList 4' assert min_ndvi.properties.isEqual(min_ndvi5), \ 'Error in pixops.infimum JimList 5' else: max_ndvi = pj.pixops.NDVISeparateBands(jim4, jim8) max_ndvi2 = pj.Jim(max_ndvi) min_ndvi = pj.Jim(max_ndvi) min_ndvi2 = pj.Jim(min_ndvi)
class BadPropsLists(unittest.TestCase): """Test JimList funcs and methods for getting and setting properties.""" jim1 = pj.Jim(testFile, band=[0, 1]) jim2 = pj.Jim(tiles[1]) jim3 = pj.Jim(tiles[0]) jiml = pj.JimList([jim1, jim2]) ulx = jiml.properties.getUlx() uly = jiml.properties.getUly() lrx = jiml.properties.getLrx() lry = jiml.properties.getLry() jiml2 = pj.JimList([jim2, jim3]) ulx2 = jiml2.properties.getUlx() uly2 = jiml2.properties.getUly() lrx2 = jiml2.properties.getLrx() lry2 = jiml2.properties.getLry() def test_no_data_vals(self): """Test JimList methods connected to no data values.""" self.jiml.properties.clearNoData() self.jiml.properties.pushNoDataVal(0) assert self.jiml.properties.getNoDataVals() == [0], \ 'Error in properties.pushNoDataVal() or getNoDataVals for JimList' self.jiml.properties.pushNoDataVal(1) assert self.jiml.properties.getNoDataVals() == [0, 1], \ 'Error in properties.pushNoDataVal() for JimList' self.jiml.properties.clearNoData() assert self.jiml.properties.getNoDataVals() == [], \ 'Error in properties.clearNoData() for JimList' def test_covers(self): """Test JimList properties.covers() method.""" assert self.jiml.properties.covers(self.ulx + 0.1, self.uly - 0.1), \ 'Error in properties.covers(), getUlx() or getUly()' assert self.jiml.properties.covers(self.lrx - 0.1, self.lry + 0.1), \ 'Error in properties.covers(), getLrx() or getLry()' assert not self.jiml.properties.covers(self.lrx + 0.1, self.lry), \ 'Error in properties.covers(), getLrx() or getLry()' def test_bbox(self): """Test JimList properties.getBBox() method.""" bbox = self.jiml2.properties.getBBox() assert bbox == [self.ulx2, self.uly2, self.lrx2, self.lry2], \ 'Error in properties.getBBox()' """Test JimList properties.getBBox() method at target projection.""" assert bbox == self.jiml2.properties.getBBox( t_srs=self.jiml2[0].properties.getProjection()),\ 'Error in properties getBBox() with projection ' """Test JimList properties.getBBox() method at target projection.""" bbox = self.jiml2.properties.getBBox(t_srs = 4326) assert bbox[0] > 7.70 and bbox[0] < 7.71, \ "Error in properties.getBBox() with projection [0]: {}".format(bbox[0]) assert bbox[1] > 46.04 and bbox[1] < 46.05, \ "Error in properties.getBBox() with projection [1]: {}".format(bbox[1]) assert bbox[2] > 7.77 and bbox[2] < 7.78, \ "Error in properties.getBBox() with projection [2]: {}".format(bbox[2]) assert bbox[3] > 46.00 and bbox[3] < 46.01, \ "Error in properties.getBBox() with projection [3]: {}".format(bbox[3]) def test_selectGeo(self): """Test JimList properties.selectGeo() function and method.""" self.jiml.properties.selectGeo(self.ulx + 0.1, self.uly - 0.1) assert len(self.jiml) == 1, 'Error in properties.selectGeo()' self.jiml.properties.selectGeo(0, 0) assert len(self.jiml) == 0, 'Error in properties.selectGeo()'
def test_getStats(): """Test if values from getStats are not suspicious.""" jim1 = pj.Jim(tiles[0]) jim2 = pj.Jim(tiles[1]) jiml = pj.JimList([jim1, jim2]) stats = jiml.stats.getStats(band=0) stats2 = pj.stats.getStats(jiml, band=0) assert stats == stats2, \ 'Inconsistency in JimList.stats.getStats() ' \ '(method returns different result than function)' max = stats['max'] min = stats['min'] mean = stats['mean'] jim_minmax_dict = jiml.stats.getStats(function=['min', 'max'], band=0) assert jim_minmax_dict['min'] == min, \ 'Error in getting statistics with JimList.stats.getStats()' \ '(min value from getStats() and ' \ 'getStats(function=["min", "max"]) do not correspond)' assert jim_minmax_dict['max'] == max, \ 'Error in getting statistics with JimList.stats.getStats()' \ '(max value from getStats() and ' \ 'getStats(function=["min", "max"]) do not correspond)' assert min < mean < max, \ 'Error in getting statistics with JimList.stats.getStats()' jiml.properties.clearNoData() stats = jiml.stats.getStats('median,invalid', band=0) stats2 = pj.stats.getStats(jiml, 'median,invalid', band=0) assert stats == stats2, \ 'Inconsistency in JimList.stats.getStats() ' \ '(method returns different result than function)' assert stats['ninvalid'] == 0, \ 'Error in JimList.properties.clearNoData() or ' \ 'JimList.stats.getStats(function="invalid") ' \ '(nodata detected after clearing)' stats = jiml.stats.getStats(['max', 'median', 'invalid'], nodata=max, band=0) stats2 = pj.stats.getStats(jiml, ['max', 'median', 'invalid'], nodata=max, band=0) assert stats == stats2, \ 'Inconsistency in JimList.stats.getStats() ' \ '(method returns different result than function)' assert stats['max'] < max, \ 'Error in using nodata kwarg for JimList.stats.getStats()' assert stats['max'] > stats['median'] > min, \ 'Suspicious value of median with JimList.stats.getStats() ' \ '(not smaller than max or not bigger than min)' assert stats['ninvalid'] > 0, \ 'Error in JimList.stats.getStats(function="invalid") ' \ '(no nodata detected, but should be)'
def test_list_methods(): """Test basic methods originating in list() inheritance.""" jim1 = pj.Jim(tiles[0]) jim2 = pj.Jim(tiles[1]) jim3 = pj.Jim(testFile, band=[0, 1]) jiml1 = pj.JimList([jim1, jim2]) jiml2 = pj.JimList([jim1, jim2, jim3]) assert len(jiml1) == 2, 'Error in len(JimList)' jiml1.append(jim1) assert len(jiml1) == 3, 'Error in len(JimList) or JimList.append()' assert len(jiml1) == jiml1._jipjimlist.getSize(), \ 'Error in JimList._set() with argument from_list=True' image2 = pj.Jim(jiml1._jipjimlist.getImage(2)) assert jiml1[2].properties.isEqual(jiml1[0]), \ 'Error in JimList.append()' assert not jiml1[2].properties.isEqual(jiml1[1]), \ 'Error in JimList[index]' assert jiml1[2].properties.isEqual(image2),\ 'Error in JimList.append()' assert jiml1.count(jim1) == 2, 'Error in JimList.count(Jim)' jiml1.extend(jiml2) assert len(jiml1) == 6, 'Error in JimList.extend()' assert len(jiml1) == jiml1._jipjimlist.getSize(), \ 'Error in JimList._set() with argument from_list=True' image4 = pj.Jim(jiml1._jipjimlist.getImage(4)) assert jiml1.count(jim1) == 3, 'Error in JimList.count(Jim)' assert jiml1[4].properties.isEqual(image4),\ 'Error in JimList.extend()' jiml1.insert(1, jim3) assert len(jiml1) == 7, 'Error in JimList.insert()' assert len(jiml1) == jiml1._jipjimlist.getSize(), \ 'Error in JimList._set() with argument from_list=True' image1 = pj.Jim(jiml1._jipjimlist.getImage(1)) # TODO: the following line results in segmentation fault... # assert jiml1.count(jim3) == 2, 'Error in JimList.insert(Jim)' assert jiml1[1].properties.isEqual(image1),\ 'Error in JimList.insert()' assert jiml1.index(jim3) == 1, 'Error in JimList.index() or insert()' popped = jiml1.pop(jiml1.index(jim3)) assert len(jiml1) == 6, 'Error in JimList.pop()' assert len(jiml1) == jiml1._jipjimlist.getSize(), \ 'Error in JimList._set() with argument from_list=True' assert jiml1.count(jim3) == 1, 'Error in JimList.pop(Jim)' assert popped.properties.isEqual(jim3), 'Error in JimList.pop()' jiml1.remove(jim3) assert len(jiml1) == 5, 'Error in JimList.remove()' assert len(jiml1) == jiml1._jipjimlist.getSize(), \ 'Error in JimList._set() with argument from_list=True' assert jiml1.count(jim3) == 0, 'Error in JimList.remove(Jim)' jiml2.reverse() image1 = pj.Jim(jiml1._jipjimlist.getImage(1)) assert jiml2.index(jim1) == 2, 'Error in JimList.reverse()' assert jiml1[1].properties.isEqual(image1),\ 'Error in JimList.reverse()'