예제 #1
0
파일: tasks.py 프로젝트: tarikakyol/WebODM
def execute_grass_script(script, serialized_context={}, out_key='output'):
    try:
        ctx = grass.create_context(serialized_context)
        return {out_key: ctx.execute(script), 'context': ctx.serialize()}
    except GrassEngineException as e:
        logger.error(str(e))
        return {'error': str(e), 'context': ctx.serialize()}
예제 #2
0
파일: api.py 프로젝트: silvrwolfboy/WebODM
    def post(self, request, pk=None):
        task = self.get_and_check_task(request, pk)
        if task.dsm_extent is None:
            return Response({
                'error':
                'No surface model available. From the Dashboard, select this task, press Edit, from the options make sure to check "dsm", then press Restart --> From DEM.'
            })

        serializer = GeoJSONSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        area = serializer['area'].value
        points = FeatureCollection([
            Feature(geometry=Point(coords))
            for coords in area['geometry']['coordinates'][0]
        ])
        dsm = os.path.abspath(task.get_asset_download_path("dsm.tif"))

        try:
            context = grass.create_context({'auto_cleanup': False})
            context.add_file('area_file.geojson', json.dumps(area))
            context.add_file('points_file.geojson', str(points))
            context.add_param('dsm_file', dsm)
            context.set_location(dsm)

            celery_task_id = execute_grass_script.delay(
                os.path.join(os.path.dirname(os.path.abspath(__file__)),
                             "calc_volume.grass"), context.serialize()).task_id

            return Response({'celery_task_id': celery_task_id},
                            status=status.HTTP_200_OK)
        except GrassEngineException as e:
            return Response({'error': str(e)}, status=status.HTTP_200_OK)
예제 #3
0
    def get(self, request, pk=None):
        print("TaskDSMCorrect")
        task = self.get_and_check_task(request, pk)
        if task.dsm_extent is None:
            return Response({'error': 'No surface model available. From the Dashboard, select this task, press Edit, from the options make sure to check "dsm", then press Restart --> From DEM.'})


        dsm = os.path.abspath(task.get_asset_download_path("dsm.tif"))

        try:
            context = grass.create_context()
            context.add_param('dsm_file', dsm)
            context.set_location(dsm)

            output = execute_grass_script.delay(os.path.join(
                os.path.dirname(os.path.abspath(__file__)),
                "dsm_correct.grass"
            ), context.serialize()).get()
            if isinstance(output, dict) and 'error' in output: raise GrassEngineException(output['error'])

            rows = output.split('\n')
            cols = rows[0].split('=')
            if len(cols) == 2:
                return Response({'max': str(float(cols[1]))
				}, status=status.HTTP_200_OK)
            else:
                raise GrassEngineException(output)
        except GrassEngineException as e:
            return Response({'error': str(e)}, status=status.HTTP_200_OK)
예제 #4
0
파일: api.py 프로젝트: WxDLR/WebODM
    def post(self, request, pk=None):
        task = self.get_and_check_task(request, pk)
        if task.dsm_extent is None:
            return Response({'error': 'No surface model available. From the Dashboard, select this task, press Edit, from the options make sure to check "dsm", then press Restart --> From DEM.'})

        serializer = GeoJSONSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        area = serializer['area'].value
        points = FeatureCollection([Feature(geometry=Point(coords)) for coords in area['geometry']['coordinates'][0]])
        dsm = os.path.abspath(task.get_asset_download_path("dsm.tif"))

        try:
            context = grass.create_context()
            context.add_file('area_file.geojson', json.dumps(area))
            context.add_file('points_file.geojson', str(points))
            context.add_param('dsm_file', dsm)
            context.set_location(dsm)

            output = execute_grass_script.delay(os.path.join(
                os.path.dirname(os.path.abspath(__file__)),
                "calc_volume.grass"
            ), context.serialize()).get()
            if isinstance(output, dict) and 'error' in output: raise GrassEngineException(output['error'])

            cols = output.split(':')
            if len(cols) == 7:
                return Response({'volume': str(abs(float(cols[6])))}, status=status.HTTP_200_OK)
            else:
                raise GrassEngineException(output)
        except GrassEngineException as e:
            return Response({'error': str(e)}, status=status.HTTP_200_OK)
예제 #5
0
파일: api.py 프로젝트: ywu453uoa/WebODM
    def post(self, request, pk=None):
        task = self.get_and_check_task(request, pk)
        plugin = get_current_plugin()

        if task.dsm_extent is None:
            return Response({'error': 'No DSM layer is available.'},
                            status=status.HTTP_400_BAD_REQUEST)

        reference = request.data.get('reference', 'global')
        if reference.lower() == 'ground' and task.dtm_extent is None:
            return Response(
                {
                    'error':
                    'No DTM layer is available. You need one to set the ground as reference.'
                },
                status=status.HTTP_400_BAD_REQUEST)

        try:
            context = grass.create_context({
                'auto_cleanup': False,
                'location': 'epsg:3857'
            })
            dsm = os.path.abspath(task.get_asset_download_path("dsm.tif"))
            dtm = os.path.abspath(task.get_asset_download_path(
                "dtm.tif")) if reference.lower() == 'ground' else None
            epsg = int(request.data.get('epsg', '3857'))
            interval = request.data.get('interval', '5')
            format = request.data.get('format', 'GPKG')
            supported_formats = ['GPKG', 'ESRI Shapefile', 'DXF', 'GeoJSON']
            if not format in supported_formats:
                raise GrassEngineException(
                    "Invalid format {} (must be one of: {})".format(
                        format, ",".join(supported_formats)))
            noise_filter_size = float(request.data.get('noise_filter_size', 2))

            current_dir = os.path.dirname(os.path.abspath(__file__))
            context.add_param('dsm_file', dsm)
            context.add_param('interval', interval)
            context.add_param('format', format)
            context.add_param('noise_filter_size', noise_filter_size)
            context.add_param('epsg', epsg)
            context.add_param('python_script_path',
                              os.path.join(current_dir, "elevationmap.py"))
            context.add_param('python_path', plugin.get_python_packages_path())

            if dtm != None:
                context.add_param('dtm', '--dtm {}'.format(dtm))
            else:
                context.add_param('dtm', '')
            context.set_location(dsm)

            celery_task_id = execute_grass_script.delay(
                os.path.join(current_dir, "calc_elevation_map.grass"),
                context.serialize()).task_id

            return Response({'celery_task_id': celery_task_id},
                            status=status.HTTP_200_OK)
        except GrassEngineException as e:
            return Response({'error': str(e)}, status=status.HTTP_200_OK)
예제 #6
0
파일: api.py 프로젝트: spacefan/WebODM
    def post(self, request, pk=None):
        task = self.get_and_check_task(request, pk)
        if task.dsm_extent is None:
            return Response({
                'error':
                'No surface model available. From the Dashboard, select this task, press Edit, from the options make sure to check "dsm", then press Restart --> From DEM.'
            })

        serializer = GeoJSONSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        area = serializer['area'].value
        points = FeatureCollection([
            Feature(geometry=Point(coords))
            for coords in area['geometry']['coordinates'][0]
        ])
        dsm = os.path.abspath(task.get_asset_download_path("dsm.tif"))

        try:
            context = grass.create_context()
            context.add_file('area_file.geojson', json.dumps(area))
            context.add_file('points_file.geojson', str(points))
            context.add_param('dsm_file', dsm)
            context.set_location(dsm)

            result = execute_grass_script.delay(
                os.path.join(os.path.dirname(os.path.abspath(__file__)),
                             "calc_volume.grass"), context.serialize()).get()

            if not isinstance(result, dict):
                raise GrassEngineException(
                    "Unexpected output from GRASS (expected dict)")
            if 'error' in result: raise GrassEngineException(result['error'])

            output = result.get('output', '')
            cols = output.split(':')
            if len(cols) == 7:
                # Correct scale measurement for web mercator
                # https://gis.stackexchange.com/questions/93332/calculating-distance-scale-factor-by-latitude-for-mercator#93335
                latitude = task.dsm_extent.centroid[1]
                scale_factor = math.cos(math.radians(latitude))**2

                volume = abs(float(cols[6]) * scale_factor)
                return Response({'volume': str(volume)},
                                status=status.HTTP_200_OK)
            else:
                raise GrassEngineException(output)
        except GrassEngineException as e:
            return Response({'error': str(e)}, status=status.HTTP_200_OK)
예제 #7
0
파일: api.py 프로젝트: ywu453uoa/WebODM
    def post(self, request, pk=None):
        task = self.get_and_check_task(request, pk)

        layer = request.data.get('layer', None)
        if layer == 'DSM' and task.dsm_extent is None:
            return Response({'error': 'No DSM layer is available.'})
        elif layer == 'DTM' and task.dtm_extent is None:
            return Response({'error': 'No DTM layer is available.'})

        try:
            if layer == 'DSM':
                dem = os.path.abspath(task.get_asset_download_path("dsm.tif"))
            elif layer == 'DTM':
                dem = os.path.abspath(task.get_asset_download_path("dtm.tif"))
            else:
                raise GrassEngineException(
                    '{} is not a valid layer.'.format(layer))

            context = grass.create_context({
                'auto_cleanup': False,
                'location': 'epsg:3857'
            })
            epsg = int(request.data.get('epsg', '3857'))
            interval = float(request.data.get('interval', 1))
            format = request.data.get('format', 'GPKG')
            supported_formats = ['GPKG', 'ESRI Shapefile', 'DXF', 'GeoJSON']
            if not format in supported_formats:
                raise GrassEngineException(
                    "Invalid format {} (must be one of: {})".format(
                        format, ",".join(supported_formats)))
            simplify = float(request.data.get('simplify', 0.01))

            context.add_param('dem_file', dem)
            context.add_param('interval', interval)
            context.add_param('format', format)
            context.add_param('simplify', simplify)
            context.add_param('epsg', epsg)

            celery_task_id = execute_grass_script.delay(
                os.path.join(os.path.dirname(os.path.abspath(__file__)),
                             "calc_contours.grass"), context.serialize(),
                'file').task_id

            return Response({'celery_task_id': celery_task_id},
                            status=status.HTTP_200_OK)
        except GrassEngineException as e:
            return Response({'error': str(e)}, status=status.HTTP_200_OK)
예제 #8
0
    def test_grass_engine(self):
        cwd = os.path.dirname(os.path.realpath(__file__))
        grass_scripts_dir = os.path.join(cwd, "grass_scripts")

        ctx = grass.create_context()
        ctx.add_file(
            'test.geojson', """{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          13.770675659179686,
          45.655328041141374
        ]
      }
    }
  ]
}""")
        ctx.set_location("EPSG:4326")

        output = execute_grass_script.delay(
            os.path.join(grass_scripts_dir, "simple_test.grass"),
            ctx.serialize()).get()
        self.assertTrue("Number of points:       1" in output)

        error = execute_grass_script.delay(
            os.path.join(grass_scripts_dir, "nonexistant_script.grass"),
            ctx.serialize()).get()
        self.assertIsInstance(error, dict)
        self.assertIsInstance(error['error'], str)

        with self.assertRaises(GrassEngineException):
            ctx.execute(
                os.path.join(grass_scripts_dir, "nonexistant_script.grass"))
예제 #9
0
    def test_grass_engine(self):
        cwd = os.path.dirname(os.path.realpath(__file__))
        grass_scripts_dir = os.path.join(cwd, "grass_scripts")

        ctx = grass.create_context()
        ctx.add_file('test.geojson', """{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          13.770675659179686,
          45.655328041141374
        ]
      }
    }
  ]
}""")
        ctx.set_location("EPSG:4326")

        output = execute_grass_script.delay(
                os.path.join(grass_scripts_dir, "simple_test.grass"),
                ctx.serialize()
            ).get()
        self.assertTrue("Number of points:       1" in output)

        error = execute_grass_script.delay(
                os.path.join(grass_scripts_dir, "nonexistant_script.grass"),
                ctx.serialize()
            ).get()
        self.assertIsInstance(error, dict)
        self.assertIsInstance(error['error'], str)

        with self.assertRaises(GrassEngineException):
            ctx.execute(os.path.join(grass_scripts_dir, "nonexistant_script.grass"))
예제 #10
0
파일: api.py 프로젝트: AIALab/WebODM-1
    def post(self, request, pk=None):
        task = self.get_and_check_task(request, pk)
        if task.dsm_extent is None:
            return Response({'error': 'No surface model available'})

        serializer = GeoJSONSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        area = serializer['area'].value
        points = FeatureCollection([
            Feature(geometry=Point(coords))
            for coords in area['geometry']['coordinates'][0]
        ])
        dsm = os.path.abspath(task.get_asset_download_path("dsm.tif"))

        try:
            context = grass.create_context()
            context.add_file('area_file.geojson', json.dumps(area))
            context.add_file('points_file.geojson', str(points))
            context.add_param('dsm_file', dsm)
            context.set_location(dsm)

            output = execute_grass_script.delay(
                os.path.join(os.path.dirname(os.path.abspath(__file__)),
                             "calc_volume.grass"), context.serialize()).get()
            if isinstance(output, dict) and 'error' in output:
                raise GrassEngineException(output['error'])

            cols = output.split(':')
            if len(cols) == 7:
                return Response({'volume': str(abs(float(cols[6])))},
                                status=status.HTTP_200_OK)
            else:
                raise GrassEngineException(output)
        except GrassEngineException as e:
            return Response({'error': str(e)}, status=status.HTTP_200_OK)
예제 #11
0
    def test_grass_engine(self):
        cwd = os.path.dirname(os.path.realpath(__file__))
        grass_scripts_dir = os.path.join(cwd, "grass_scripts")

        ctx = grass.create_context()
        points = """{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Point",
        "coordinates": [
          13.770675659179686,
          45.655328041141374
        ]
      }
    }
  ]
}"""
        ctx.add_file('test.geojson', points)
        ctx.set_location("EPSG:4326")

        result = execute_grass_script.delay(
                os.path.join(grass_scripts_dir, "simple_test.grass"),
                ctx.serialize()
            ).get()
        self.assertTrue("Number of points:       1" in result.get('output'))

        self.assertTrue(result.get('context') == ctx.serialize())

        # Context dir has been cleaned up automatically
        self.assertFalse(os.path.exists(ctx.get_cwd()))

        error = execute_grass_script.delay(
                os.path.join(grass_scripts_dir, "nonexistant_script.grass"),
                ctx.serialize()
            ).get()
        self.assertIsInstance(error, dict)
        self.assertIsInstance(error['error'], str)

        with self.assertRaises(GrassEngineException):
            ctx.execute(os.path.join(grass_scripts_dir, "nonexistant_script.grass"))

        ctx = grass.create_context({"auto_cleanup": False})
        ctx.add_file('test.geojson', points)
        ctx.set_location("EPSG:4326")

        result = execute_grass_script.delay(
            os.path.join(grass_scripts_dir, "simple_test.grass"),
            ctx.serialize()
        ).get()
        self.assertTrue("Number of points:       1" in result.get('output'))

        # Path still there
        self.assertTrue(os.path.exists(ctx.get_cwd()))

        ctx.cleanup()

        # Cleanup worked
        self.assertFalse(os.path.exists(ctx.get_cwd()))
예제 #12
0
def execute_grass_script(script, serialized_context={}):
    try:
        ctx = grass.create_context(serialized_context)
        return ctx.execute(script)
    except GrassEngineException as e:
        return {'error': str(e)}
예제 #13
0
    def post(self, request, pk=None):

        role = request.data.get('role', 'reference')
        if role == 'reference':
            reference_pk = pk
            compare_task_pk = request.data.get('other_task', None)
        else:
            reference_pk = request.data.get('other_task', None)
            compare_task_pk = pk

        reference_task = self.get_and_check_task(request, reference_pk)
        if compare_task_pk is None:
            return Response({'error': 'You must select a task to compare to.'},
                            status=status.HTTP_400_BAD_REQUEST)
        compare_task = self.get_and_check_task(request, compare_task_pk)

        reference_pc = os.path.abspath(
            reference_task.get_asset_download_path("georeferenced_model.laz"))
        reference_dsm = os.path.abspath(
            reference_task.get_asset_download_path("dsm.tif"))
        reference_dtm = os.path.abspath(
            reference_task.get_asset_download_path("dtm.tif"))

        compare_pc = os.path.abspath(
            compare_task.get_asset_download_path("georeferenced_model.laz"))
        compare_dsm = os.path.abspath(
            compare_task.get_asset_download_path("dsm.tif"))
        compare_dtm = os.path.abspath(
            compare_task.get_asset_download_path("dtm.tif"))

        plugin = get_current_plugin()

        # We store the aligned DEMs on the persistent folder, to avoid recalculating them in the future
        aligned_dsm = plugin.get_persistent_path("{}_{}_dsm.tif".format(
            pk, compare_task_pk))
        aligned_dtm = plugin.get_persistent_path("{}_{}_dtm.tif".format(
            pk, compare_task_pk))

        try:
            context = grass.create_context({
                'auto_cleanup':
                False,
                'location':
                'epsg:3857',
                'python_path':
                plugin.get_python_packages_path()
            })
            format = request.data.get('format', 'GPKG')
            epsg = int(request.data.get('epsg', '3857'))
            supported_formats = ['GPKG', 'ESRI Shapefile', 'DXF', 'GeoJSON']
            if not format in supported_formats:
                raise GrassEngineException(
                    "Invalid format {} (must be one of: {})".format(
                        format, ",".join(supported_formats)))
            min_area = float(request.data.get('min_area', 40))
            min_height = float(request.data.get('min_height', 5))
            resolution = float(request.data.get('resolution', 0.5))
            display_type = request.data.get('display_type', 'contour')
            can_align_and_rasterize = request.data.get('align', 'false')

            current_dir = os.path.dirname(os.path.abspath(__file__))
            context.add_param('reference_pc', reference_pc)
            context.add_param('compare_pc', compare_pc)
            context.add_param('reference_dsm', reference_dsm)
            context.add_param('reference_dtm', reference_dtm)
            context.add_param('compare_dsm', compare_dsm)
            context.add_param('compare_dtm', compare_dtm)
            context.add_param('aligned_dsm', aligned_dsm)
            context.add_param('aligned_dtm', aligned_dtm)
            context.add_param('format', format)
            context.add_param('epsg', epsg)
            context.add_param('display_type', display_type)
            context.add_param('resolution', resolution)
            context.add_param('min_area', min_area)
            context.add_param('min_height', min_height)
            context.add_param('can_align_and_rasterize',
                              can_align_and_rasterize)

            celery_task_id = execute_grass_script.delay(
                os.path.join(current_dir, "changedetection.py"),
                context.serialize()).task_id

            return Response({'celery_task_id': celery_task_id},
                            status=status.HTTP_200_OK)
        except GrassEngineException as e:
            return Response({'error': str(e)}, status=status.HTTP_200_OK)