Exemplo n.º 1
0
def test_delete_point_cloud(projects_fixture):
    u1 = db_session.query(User).get(1)

    point_cloud = PointCloudService.create(projectId=projects_fixture.id,
                                           data=POINT_CLOUD_DATA,
                                           user=u1)
    PointCloudService.delete(pointCloudId=point_cloud.id)
    assert db_session.query(PointCloud).count() == 0
    assert db_session.query(Feature).count() == 0
    assert len(os.listdir(get_project_asset_dir(point_cloud.project_id))) == 0
Exemplo n.º 2
0
    def post(self, projectId: int, pointCloudId: int):
        u = request.current_user
        files = request.json["files"]
        logger.info("Import file(s) to a point cloud:{} in project:{} for user:{}: {}".format(
            pointCloudId, projectId, request.current_user.username, files))

        for file in files:
            PointCloudService.check_file_extension(file["path"])

        external_data.import_point_clouds_from_agave.delay(u.id, files, pointCloudId)
        return {"message": "accepted"}
Exemplo n.º 3
0
def test_delete_point_cloud_feature(celery_task_always_eager, projects_fixture,
                                    point_cloud_fixture,
                                    lidar_las1pt2_file_fixture):
    PointCloudService.fromFileObj(point_cloud_fixture.id,
                                  lidar_las1pt2_file_fixture,
                                  lidar_las1pt2_file_fixture.name)
    point_cloud = db_session.query(PointCloud).get(1)
    feature_asset_path = get_asset_path(point_cloud.feature.assets[0].path)

    FeaturesService.delete(point_cloud.feature.id)
    assert db_session.query(PointCloud).count() == 1
    assert db_session.query(PointCloud).get(1).feature is None
    assert db_session.query(Feature).count() == 0
    assert db_session.query(FeatureAsset).count() == 0
    assert os.path.exists(
        get_asset_path(point_cloud.path, PointCloudService.ORIGINAL_FILES_DIR))
    assert not os.path.exists(feature_asset_path)
Exemplo n.º 4
0
 def wrapper(*args, **kwargs):
     point_cloud_id = kwargs.get("pointCloudId")
     point_cloud = PointCloudService.get(point_cloud_id)
     if point_cloud.task \
             and point_cloud.task.status not in ["FINISHED", "FAILED"]:
         logger.info("point cloud:{} is not in terminal state".format(
             point_cloud_id))
         abort(404, "Point cloud is currently being updated")
     return fn(*args, **kwargs)
Exemplo n.º 5
0
 def post(self, projectId: int, pointCloudId: int):
     """
     :raises InvalidCoordinateReferenceSystem: in case  file missing coordinate reference system
     """
     f = request.files['file']
     file_name = secure_filename(f.filename)
     logger.info("Add a file to a point cloud:{} in project:{} for user:{}: {}".format(
         pointCloudId, projectId, request.current_user.username, file_name))
     pc_task = PointCloudService.fromFileObj(pointCloudId, f, file_name)
     return pc_task
Exemplo n.º 6
0
def test_update_point_cloud(projects_fixture, point_cloud_fixture,
                            convert_to_potree_mock):
    data = {
        'description': "new description",
        'conversion_parameters': "--scale 5.0"
    }
    point_cloud = PointCloudService.update(point_cloud_fixture.id, data=data)
    convert_to_potree_mock.apply_async.assert_called_once()
    assert point_cloud.description == "new description"
    assert point_cloud.conversion_parameters == "--scale 5.0"
Exemplo n.º 7
0
def test_add_point_cloud(projects_fixture):
    u1 = db_session.query(User).get(1)

    point_cloud = PointCloudService.create(projectId=projects_fixture.id,
                                           data=POINT_CLOUD_DATA,
                                           user=u1)
    assert point_cloud.description == "description"
    assert point_cloud.conversion_parameters == "--scale 2.0"
    assert not point_cloud.feature
    assert point_cloud.project_id == projects_fixture.id
    assert db_session.query(PointCloud).count() == 1
Exemplo n.º 8
0
 def wrapper(*args, **kwargs):
     projectId = kwargs.get("projectId")
     proj = ProjectsService.get(projectId)
     if not proj:
         abort(404, "No project found")
     pointCloudId = kwargs.get("pointCloudId")
     point_cloud = PointCloudService.get(pointCloudId)
     if not point_cloud:
         abort(404, "No point cloud found!")
     if point_cloud.project_id != projectId:
         abort(404, "Point cloud not part of project")
     return fn(*args, **kwargs)
Exemplo n.º 9
0
def get_point_cloud_info(pointCloudId: int) -> dict:
    """
    Get info on las files
    :param pointCloudId: int
    :return: None
    """
    from geoapi.services.point_cloud import PointCloudService

    point_cloud = PointCloudService.get(pointCloudId)
    path_to_original_point_clouds = get_asset_path(
        point_cloud.path, PointCloudService.ORIGINAL_FILES_DIR)
    input_files = get_point_cloud_files(path_to_original_point_clouds)

    return [{'name': os.path.basename(f)} for f in input_files]
Exemplo n.º 10
0
def test_add_point_cloud_file(projects_fixture, point_cloud_fixture,
                              lidar_las1pt2_file_fixture,
                              convert_to_potree_mock, check_point_cloud_mock,
                              get_point_cloud_info_mock):

    filename = os.path.basename(lidar_las1pt2_file_fixture.name)
    task = PointCloudService.fromFileObj(point_cloud_fixture.id,
                                         lidar_las1pt2_file_fixture, filename)

    assert task.status == "RUNNING"
    assert point_cloud_fixture.task_id == task.id
    # load updated point cloud
    point_cloud = db_session.query(PointCloud).get(1)
    las_files = os.listdir(
        get_asset_path(point_cloud.path, PointCloudService.ORIGINAL_FILES_DIR))
    assert len(las_files) == 1
    assert las_files[0] == os.path.basename(filename)
    original_file_size = os.fstat(lidar_las1pt2_file_fixture.fileno()).st_size
    asset_file_path = os.path.join(
        get_asset_path(point_cloud.path, PointCloudService.ORIGINAL_FILES_DIR),
        filename)
    assert os.path.getsize(asset_file_path) == original_file_size

    # run conversion tool (that we had mocked)
    _, convert_kwargs = convert_to_potree_mock.apply_async.call_args
    assert projects_fixture.id == convert_kwargs['args'][0]
    convert_to_potree(projects_fixture.id)

    # load updated point cloud
    point_cloud = db_session.query(PointCloud).get(1)

    assert point_cloud.task.status == "FINISHED"
    assert db_session.query(Feature).count() == 1
    assert db_session.query(FeatureAsset).count() == 1
    assert len(os.listdir(get_project_asset_dir(point_cloud.project_id))) == 2
    assert len(os.listdir(get_asset_path(point_cloud.feature.assets[0].path))
               ) == 5  # index.html, preview.html, pointclouds, libs, logo
    assert os.path.isfile(
        os.path.join(get_asset_path(point_cloud.feature.assets[0].path),
                     "preview.html"))
    with open(
            os.path.join(get_asset_path(point_cloud.feature.assets[0].path),
                         "preview.html"), 'r+') as f:
        preview = f.read()
        assert "nsf_logo" not in preview
        assert "$('.potree_menu_toggle').hide()" in preview
Exemplo n.º 11
0
def point_cloud_fixture():
    u1 = db_session.query(User).filter(User.username == "test1").first()
    data = {"description": "description"}
    point_cloud = PointCloudService.create(projectId=1, data=data, user=u1)
    yield point_cloud
Exemplo n.º 12
0
def convert_to_potree(self, pointCloudId: int) -> None:
    """
    Use the potree converter to convert a LAS/LAZ file to potree format
    :param pointCloudId: int
    :return: None
    """
    from geoapi.models import Feature, FeatureAsset
    from geoapi.services.point_cloud import PointCloudService

    point_cloud = PointCloudService.get(pointCloudId)

    path_to_original_point_clouds = get_asset_path(
        point_cloud.path, PointCloudService.ORIGINAL_FILES_DIR)
    path_temp_processed_point_cloud_path = get_asset_path(
        point_cloud.path, PointCloudService.PROCESSED_DIR)

    input_files = [
        get_asset_path(path_to_original_point_clouds, file)
        for file in os.listdir(path_to_original_point_clouds)
        if pathlib.Path(file).suffix.lstrip('.').lower() in
        PointCloudService.LIDAR_FILE_EXTENSIONS
    ]

    outline = get_bounding_box_2d(input_files)

    command = [
        "PotreeConverter", "--verbose", "-i", path_to_original_point_clouds,
        "-o", path_temp_processed_point_cloud_path, "--overwrite",
        "--generate-page", "index"
    ]
    if point_cloud.conversion_parameters:
        command.extend(point_cloud.conversion_parameters.split())
    logger.info("Processing point cloud (#{}):  {}".format(
        pointCloudId, " ".join(command)))
    subprocess.run(command, check=True, capture_output=True, text=True)

    # Create preview viewer html (with no menu and now nsf logo)
    with open(
            os.path.join(path_temp_processed_point_cloud_path, "preview.html"),
            'w+') as preview:
        with open(
                os.path.join(path_temp_processed_point_cloud_path,
                             "index.html"), 'r') as viewer:
            content = viewer.read()
            content = re.sub(r"<div class=\"nsf_logo\"(.+?)</div>",
                             '',
                             content,
                             flags=re.DOTALL)
            content = content.replace("viewer.toggleSidebar()",
                                      "$('.potree_menu_toggle').hide()")
            preview.write(content)

    if point_cloud.feature_id:
        feature = point_cloud.feature
    else:
        feature = Feature()
        feature.project_id = point_cloud.project_id

        asset_uuid = uuid.uuid4()
        base_filepath = make_project_asset_dir(point_cloud.project_id)
        asset_path = os.path.join(base_filepath, str(asset_uuid))
        fa = FeatureAsset(uuid=asset_uuid,
                          asset_type="point_cloud",
                          path=get_asset_relative_path(asset_path),
                          feature=feature)
        feature.assets.append(fa)
        point_cloud.feature = feature

    feature.the_geom = from_shape(geometries.convert_3D_2D(outline), srid=4326)
    point_cloud.task.status = "FINISHED"
    point_cloud.task.description = ""

    point_cloud_asset_path = get_asset_path(feature.assets[0].path)
    shutil.rmtree(point_cloud_asset_path, ignore_errors=True)
    shutil.move(path_temp_processed_point_cloud_path, point_cloud_asset_path)

    try:
        db_session.add(point_cloud)
        db_session.add(feature)
        db_session.commit()
    except:
        db_session.rollback()
        raise
Exemplo n.º 13
0
 def get(self, projectId: int):
     return PointCloudService.list(projectId)
Exemplo n.º 14
0
def test_update_point_cloud_without_changing_conversion_parameters(
        projects_fixture, point_cloud_fixture, convert_to_potree_mock):
    data = {'description': "new description"}
    point_cloud = PointCloudService.update(point_cloud_fixture.id, data=data)
    convert_to_potree_mock.apply_async.assert_not_called()
    assert point_cloud.description == "new description"
Exemplo n.º 15
0
 def delete(self, projectId: int, pointCloudId: int):
     logger.info("Delete point cloud:{} in project:{} for user:{}".format(
         pointCloudId, projectId, request.current_user.username))
     return PointCloudService.delete(pointCloudId)
Exemplo n.º 16
0
 def put(self, projectId: int, pointCloudId: int):
     # TODO consider adding status to point cloud as we aren't returning task
     return PointCloudService.update(pointCloudId=pointCloudId,
                                     data=api.payload)
Exemplo n.º 17
0
 def get(self, projectId: int, pointCloudId: int):
     return PointCloudService.get(pointCloudId)
Exemplo n.º 18
0
 def post(self, projectId: int):
     logger.info("Add point cloud to project:{} for user:{}".format(
         projectId, request.current_user.username))
     return PointCloudService.create(projectId=projectId,
                                     user=request.current_user,
                                     data=api.payload)