def test_manyTargets_consistentOutput(feature): target_point_cloud = copy_point_cloud(_PC_260807) compute_features(copy_point_cloud(_PC_10), _260807_NEIGHBORHOODS_IN_10, target_point_cloud, [feature], volume=_CYLINDER) _assert_consistent_attribute_length(target_point_cloud)
def test_completeTile_consistentOutput(feature): target_point_cloud = copy_point_cloud(_PC_1000) compute_features(copy_point_cloud(_PC_260807), _1000_NEIGHBORHOODS_IN_260807, target_point_cloud, [feature], volume=_CYLINDER) _assert_consistent_attribute_length(target_point_cloud)
def test_entropy_in_cylinders(self): """Test computing of eigenvalues in cylinder.""" num_all_pc_points = len(self.point_cloud[keys.point]["x"]["data"]) rand_indices = [ random.randint(0, num_all_pc_points) for p in range(20) ] target_point_cloud = utils.copy_point_cloud(self.point_cloud, rand_indices) n_targets = len(target_point_cloud[keys.point]["x"]["data"]) radius = 25 neighbors = compute_neighbors.compute_cylinder_neighborhood( self.point_cloud, target_point_cloud, radius) target_idx_base = 0 for x in neighbors: feature_extractor.compute_features(self.point_cloud, x, target_idx_base, target_point_cloud, ["entropy_z"], InfiniteCylinder(5), layer_thickness=0.1) target_idx_base += len(x) for i in range(n_targets): H = utils.get_attribute_value(target_point_cloud, i, "entropy_z") self.assertTrue(H >= 0) self.assertEqual( "laserchicken.feature_extractor.entropy_feature_extractor", target_point_cloud[keys.provenance][0]["module"]) self.assertEqual([0.1], target_point_cloud[keys.provenance][0]["parameters"])
def _get_random_targets(self): """Get a random target pc.""" num_all_pc_points = len(self.point_cloud[keys.point]["x"]["data"]) rand_indices = [ random.randint(0, num_all_pc_points) for _ in range(20) ] return utils.copy_point_cloud(self.point_cloud, rand_indices)
def setUp(self): """ Set up the test. Load in a bunch of real data from AHN3. """ np.random.seed(1234) _TEST_FILE_NAME = 'AHN3.las' _TEST_DATA_SOURCE = 'testdata' _CYLINDER = InfiniteCylinder(4) _PC_260807 = load(os.path.join(_TEST_DATA_SOURCE, _TEST_FILE_NAME)) _PC_1000 = copy_point_cloud( _PC_260807, array_mask=(np.random.choice(range( len(_PC_260807[keys.point]['x']['data'])), size=1000, replace=False))) _1000_NEIGHBORHOODS_IN_260807 = list( compute_neighbors.compute_neighborhoods(_PC_260807, _PC_1000, _CYLINDER)) self.point_cloud = _PC_260807 self.neigh = _1000_NEIGHBORHOODS_IN_260807
def test_inputNotChanged(feature): original_environment = _PC_260807 environment = copy_point_cloud(original_environment) original_targets = _PC_10 targets = copy_point_cloud(original_targets) original_neighborhoods = _10_NEIGHBORHOODS_IN_260807 neighborhoods = [[e for e in l] for l in original_neighborhoods] compute_features(environment, neighborhoods, targets, [feature], volume=_CYLINDER) _assert_attributes_not_changed(original_environment, environment) _assert_attributes_not_changed(original_targets, targets) assert json.dumps(original_neighborhoods) == json.dumps(neighborhoods)
def test_CopyEmptyPointCloud(self): """ Should not raise exception. """ pc = test_tools.generate_tiny_test_point_cloud() pc[keys.point]["x"]["data"] = np.array([]) pc[keys.point]["y"]["data"] = np.array([]) pc[keys.point]["z"]["data"] = np.array([]) copypc = utils.copy_point_cloud(pc) self.assertEqual(0, len(copypc[keys.point]["x"]["data"]))
def test_CopyNonEmptyPointCloud(self): """ Test whether coordinates are copied """ pc = test_tools.generate_tiny_test_point_cloud() x = pc[keys.point]["x"]["data"] y = pc[keys.point]["y"]["data"] z = pc[keys.point]["z"]["data"] copypc = utils.copy_point_cloud(pc) self.assertTrue(all(x == copypc[keys.point]["x"]["data"])) self.assertTrue(all(y == copypc[keys.point]["y"]["data"])) self.assertTrue(all(z == copypc[keys.point]["z"]["data"]))
def test_AddToPointCloud(self): test_data = test_tools.ComplexTestData() pc_source = test_data.get_point_cloud() pc_dest = utils.copy_point_cloud(pc_source) utils.add_to_point_cloud(pc_dest, pc_source) for key in pc_source.keys(): self.assertIn(key, pc_dest) for attr in pc_source[keys.point].keys(): self.assertEqual(len(pc_dest[keys.point][attr]['data']), 2 * len(pc_source[keys.point][attr]['data'])) self.assertEqual(pc_dest[keys.provenance][-1]['module'], 'laserchicken.utils')
def select_below(point_cloud, attribute, threshold): """ Return the selection of the input point cloud that contains only points with a given attribute below some value. :param point_cloud: Input point cloud :param attribute: The attribute name used for selection :param threshold: The threshold value used for selection :return: A new point cloud containing only the selected points """ _check_valid_arguments(attribute, point_cloud) mask = point_cloud[point][attribute]['data'] < threshold return copy_point_cloud(point_cloud, mask)
def select_equal(point_cloud, attribute, value): """ Return the selection of the input point cloud that contains only points with a given attribute equal to some value. :param point_cloud: Input point cloud. :param attribute: The attribute name used for selection :param value: The value to compare the attribute to :return: A new point cloud containing only the selected points """ _check_valid_arguments(attribute, point_cloud) mask = point_cloud[point][attribute]['data'] == value return copy_point_cloud(point_cloud, mask)
def test_CopyNonEmptyPointCloudBoolMask(self): """ Test whether coordinates are copied with boolean mask """ pc = test_tools.generate_tiny_test_point_cloud() x = pc[keys.point]["x"]["data"][2] y = pc[keys.point]["y"]["data"][2] z = pc[keys.point]["z"]["data"][2] copypc = utils.copy_point_cloud(pc, array_mask=np.array( [False, False, True])) self.assertTrue(all(np.array([x]) == copypc[keys.point]["x"]["data"])) self.assertTrue(all(np.array([y]) == copypc[keys.point]["y"]["data"])) self.assertTrue(all(np.array([z]) == copypc[keys.point]["z"]["data"]))
def test_CopyPointCloudMetaData(self): """ Test whether metadata are copied """ pc = test_tools.generate_tiny_test_point_cloud() pc["log"] = [{ "time": datetime.datetime(2018, 1, 23, 12, 15, 59), "module": "filter", "parameters": [("z", "gt", 0.5)] }] copypc = utils.copy_point_cloud(pc) self.assertEqual(datetime.datetime(2018, 1, 23, 12, 15, 59), copypc["log"][0]["time"]) self.assertEqual("filter", copypc["log"][0]["module"]) self.assertEqual([("z", "gt", 0.5)], copypc["log"][0]["parameters"])
def test_CopyNonEmptyPointCloudIntMask(self): """ Test whether coordinates are copied with array indexing """ pc = test_tools.generate_tiny_test_point_cloud() x0, x1 = pc[keys.point]["x"]["data"][0], pc[keys.point]["x"]["data"][1] y0, y1 = pc[keys.point]["y"]["data"][0], pc[keys.point]["y"]["data"][1] z0, z1 = pc[keys.point]["z"]["data"][0], pc[keys.point]["z"]["data"][1] copypc = utils.copy_point_cloud(pc, array_mask=np.array([1, 0])) self.assertTrue( all(np.array([x1, x0]) == copypc[keys.point]["x"]["data"])) self.assertTrue( all(np.array([y1, y0]) == copypc[keys.point]["y"]["data"])) self.assertTrue( all(np.array([z1, z0]) == copypc[keys.point]["z"]["data"]))
def points_in_polygon_wkt(pc, polygons_wkt): if pc is None: raise ValueError('Input point cloud cannot be None.') if polygons_wkt is None: raise ValueError('Polygons wkt cannot be None.') try: polygon = loads(polygons_wkt) except WKTReadingError: raise ValueError('Polygon is invalid.') if isinstance(polygon, shapely.geometry.polygon.Polygon) and polygon.is_valid: points_in = _contains(pc, polygon) else: raise ValueError('It is not a Polygon.') return copy_point_cloud(pc, points_in)
def points_in_polygon_shp_file(pc, polygons_shp_path): if pc is None: raise ValueError('Input point cloud cannot be None.') if polygons_shp_path is None: raise ValueError('Polygons shp file path cannot be None.') try: polygon = read_shp_file(polygons_shp_path) except: raise if isinstance(polygon, shapely.geometry.polygon.Polygon) and polygon.is_valid: points_in = _contains(pc, polygon) else: raise ValueError('It is not a Polygon.') return copy_point_cloud(pc, points_in)
def _find_neighbors_for_random_targets_and_compute_entropy(self): num_all_pc_points = len(self.point_cloud[keys.point]["x"]["data"]) rand_indices = [ random.randint(0, num_all_pc_points) for _ in range(20) ] target_point_cloud = utils.copy_point_cloud(self.point_cloud, rand_indices) radius = 25 neighborhoods = list( compute_cylinder_neighborhood(self.point_cloud, target_point_cloud, radius)) compute_features(self.point_cloud, neighborhoods, target_point_cloud, ["entropy_z"], InfiniteCylinder(5), layer_thickness=0.1) return target_point_cloud
def _assert_all_points_within_cylinder(self, index_sets, target_point_cloud, radius): point_clouds = [ utils.copy_point_cloud(self.point_cloud, indices) for indices in index_sets ] n_targets = len(target_point_cloud[keys.point]["x"]["data"]) assert_equal(n_targets, len(point_clouds)) for i in range(n_targets): target_x = target_point_cloud[keys.point]["x"]["data"][i] target_y = target_point_cloud[keys.point]["y"]["data"][i] for j in range(len(point_clouds[i][keys.point]["x"]["data"])): neighbor_x = point_clouds[i][keys.point]["x"]["data"][j] neighbor_y = point_clouds[i][keys.point]["y"]["data"][j] dist = np.sqrt((neighbor_x - target_x)**2 + (neighbor_y - target_y)**2) self.assertTrue(dist <= radius)
def select_polygon(point_cloud, polygon_string, read_from_file=False, return_mask=False): """ Return the selection of the input point cloud that contains only points within a given polygon. :param point_cloud: Input point cloud :param polygon_string: Polygon, either defined in a WKT string or in a file (WKT and ESRI formats supported) :param read_from_file: if true, polygon is expected to be the name of the file where the polygon is defined :param return_mask: if true, return a mask of selected points, rather than point cloud :return: """ if point_cloud is None: raise ValueError('Input point cloud cannot be None.') if not isinstance(polygon_string, str): raise ValueError('Polygon (or its filename) should be a string') if read_from_file: format = os.path.splitext(polygon_string)[1].lower() reader = _get_polygon_reader(format) polygon = reader(polygon_string) else: polygon = _load_polygon(polygon_string) if isinstance(polygon, shapely.geometry.polygon.Polygon) and polygon.is_valid: points_in = _contains(point_cloud, polygon) elif isinstance(polygon,shapely.geometry.multipolygon.MultiPolygon) and polygon.is_valid: points_in = [] count=1 for poly in polygon: if not(count%200) or count==len(polygon): print('Checking polygon {}/{}...'.format(count, len(polygon))) points_in.extend(_contains(point_cloud, poly)) count=count+1 print('{} points found in {} polygons.'.format(len(points_in), len(polygon))) else: raise ValueError('It is not a Polygon or Multipolygon.') if return_mask: mask = np.zeros(len(point_cloud['vertex']['x']['data']), dtype=bool) mask[points_in] = True return mask else: point_cloud_filtered = copy_point_cloud(point_cloud, points_in) add_metadata(point_cloud_filtered, sys.modules[__name__], {'polygon_string': polygon_string, 'read_from_file': read_from_file}) return point_cloud_filtered
def select_below(point_cloud, attribute, threshold, return_mask=False): """ Return the selection of the input point cloud that contains only points with a given attribute below some value. :param point_cloud: Input point cloud :param attribute: The attribute name used for selection :param threshold: The threshold value used for selection :param return_mask: If true, return the mask corresponding to the selection :return: """ _check_valid_arguments(attribute, point_cloud) mask = point_cloud[point][attribute]['data'] < threshold if return_mask: return mask point_cloud_filtered = copy_point_cloud(point_cloud, mask) add_metadata(point_cloud_filtered, sys.modules[__name__], {'attribute': attribute, 'threshold': threshold}) return point_cloud_filtered
def _assert_all_points_within_sphere(self, index_sets, target_point_cloud, radius): point_clouds = [ utils.copy_point_cloud(self.point_cloud, indices) for indices in index_sets ] n_targets = len(target_point_cloud[keys.point]["x"]["data"]) assert_equal(n_targets, len(point_clouds)) for i in range(n_targets): target_x, target_y, target_z = utils.get_point( target_point_cloud, i) for j in range(len(point_clouds[i][keys.point]["x"]["data"])): neighbor_x, neighbor_y, neighbor_z = utils.get_point( point_clouds[i], j) dist = np.sqrt((neighbor_x - target_x)**2 + (neighbor_y - target_y)**2 + (neighbor_z - target_z)**2) self.assertTrue(dist <= radius)
def setUp(self): # read the data self.point_cloud = read_las.read( os.path.join(self._test_data_source, self._test_file_name)) # get the target point clouds random.seed(102938482634) self.target_pc_sequential = self._get_random_targets() self.target_pc_vector = utils.copy_point_cloud( self.target_pc_sequential) self.target_pc_index = 0 # volume descriptions radius = 0.5 self.cyl = InfiniteCylinder(radius) self.neighbors = compute_neighborhoods(self.point_cloud, self.target_pc_sequential, self.cyl) self.cylinder_index = [] for x in self.neighbors: self.cylinder_index += x
def test_eigenvalues_in_cylinders(self): """Test provenance added (This should actually be part the general feature extractor test suite).""" random.seed(102938482634) point_cloud = load(os.path.join('testdata', 'AHN3.las')) num_all_pc_points = len(point_cloud[keys.point]["x"]["data"]) rand_indices = [ random.randint(0, num_all_pc_points) for _ in range(20) ] target_point_cloud = utils.copy_point_cloud(point_cloud, rand_indices) radius = 2.5 neighbors = compute_neighbors.compute_cylinder_neighborhood( point_cloud, target_point_cloud, radius) compute_features(point_cloud, neighbors, target_point_cloud, ["eigenv_1", "eigenv_2", "eigenv_3"], InfiniteCylinder(5)) self.assertEqual( "laserchicken.feature_extractor.eigenvals_feature_extractor", target_point_cloud[keys.provenance][-1]["module"])
def select_equal(point_cloud, attribute, value, return_mask=False): """ Return the selection of the input point cloud that contains only points with a given attribute equal to some value. If a list of values is given, select the points corresponding to any of the provided values. :param point_cloud: Input point cloud. :param attribute: The attribute name used for selection :param value: The value(s) to compare the attribute to :param return_mask: If true, return the mask corresponding to the selection :return: """ _check_valid_arguments(attribute, point_cloud) # broadcast using shape of the values mask = point_cloud[point][attribute]['data'] == np.array(value)[..., None] if mask.ndim > 1: mask = np.any(mask, axis=0) # reduce if return_mask: return mask point_cloud_filtered = copy_point_cloud(point_cloud, mask) add_metadata(point_cloud_filtered, sys.modules[__name__], {'attribute': attribute, 'value': value}) return point_cloud_filtered
from laserchicken.utils import copy_point_cloud from laserchicken.volume_specification import InfiniteCylinder, Cell from . import compute_features from .feature_map import create_default_feature_map, _create_name_extractor_pairs np.random.seed(1234) _TEST_FILE_NAME = 'AHN3.ply' _TEST_NEIGHBORHOODS_FILE_NAME = 'AHN3_1000_random_neighbors.json' _TEST_DATA_SOURCE = 'testdata' _CYLINDER = InfiniteCylinder(4) _PC_260807 = read_ply.read(os.path.join(_TEST_DATA_SOURCE, _TEST_FILE_NAME)) _PC_1000 = copy_point_cloud(_PC_260807, array_mask=(np.random.choice(range( len(_PC_260807[keys.point]['x']['data'])), size=1000, replace=False))) _PC_10 = copy_point_cloud(_PC_260807, array_mask=(np.random.choice(range( len(_PC_260807[keys.point]['x']['data'])), size=10, replace=False))) _1000_NEIGHBORHOODS_IN_260807 = next( compute_neighbors.compute_neighborhoods(_PC_260807, _PC_1000, _CYLINDER, sample_size=500)) _10_NEIGHBORHOODS_IN_260807 = next( compute_neighbors.compute_neighborhoods(_PC_260807, _PC_10,
def _get_central_point(self): """Get the central point.""" return utils.copy_point_cloud(self.point_cloud, [0])