Skip to content

fsdb_rest_api

FSDB REST API - Serve Plant Database through RESTful Endpoints

This module provides a RESTful API server for interacting with a local plant database (FSDB). It is designed for the ROMI project and facilitates efficient data handling and retrieval of plant-related datasets. The server enables users to query and manage plant scans, images, point clouds, and other related data files.

Key Features
  • Serve a local plant database (FSDB) through RESTful API endpoints.
  • Manage plant scans and related data, including images, point clouds, and meshes.
  • Retrieve and manage dataset files with various configurations.
  • Run in test mode with optional preconfigured datasets or an empty test database.
  • Lightweight server setup using Flask, with options for debugging and CORS support.
Usage Examples

To start the REST API server for a local plant database:

python fsdb_rest_api.py --db_location /path/to/your/database --host 127.0.0.1 --port 8080 --debug

To run the server with a temporary test database in debug mode:

python fsdb_rest_api.py --test --debug

RESTful endpoints include: - /scans: List all scans available in the database. - /files/<path:path>: Retrieve files from the database. - /image/<scan_id>/<fileset_id>/<file_id>: Access specific images. - /pointcloud/<scan_id>/<fileset_id>/<file_id>: Access specific point clouds. - /mesh/<scan_id>/<fileset_id>/<file_id>: Retrieve related meshes.

For detailed command-line parameters, use the --help flag:

python fsdb_rest_api.py --help

main() Link

Main function to initialize and execute the REST API server.

This function utilizes argument parsing to extract user-provided input values for configuring and running the REST API server.

Source code in plantdb/cli/fsdb_rest_api.py
235
236
237
238
239
240
241
242
243
def main():
    """Main function to initialize and execute the REST API server.

    This function utilizes argument parsing to extract user-provided input values
    for configuring and running the REST API server.
    """
    parser = parsing()
    args = parser.parse_args()
    rest_api(args.db_location, args.host, args.port, args.debug, args.test, args.empty, args.models, args.log_level)

rest_api(db_location, host='0.0.0.0', port=5000, debug=False, test=False, empty=False, models=False, log_level=DEFAULT_LOG_LEVEL) Link

Initialize and configure a RESTful API server for Plant Database querying.

This function sets up a Flask application with various RESTful endpoints to enable interaction with a local Plant Database (FSDB). RESTful routes are added for managing and retrieving various datasets and configurations, providing an interface for working with plant scans and related files. The application can be run in test mode with optional configurations for using sample datasets.

Parameters:

Name Type Description Default
db_location str

The path to the local plant database to be served. If set to "/none", the server will raise an error and terminate unless the path is appropriately overridden in test mode.

required
host str

The hostname or IP address on which the Flask application will listen for incoming requests. Defaults to "0.0.0.0".

'0.0.0.0'
port int

The port number to bind the Flask application for incoming HTTP requests. Defaults to 5000.

5000
debug bool

A boolean flag indicating whether Flask debugging mode should be enabled. Useful for debugging during development. Defaults to False.

False
test bool

A boolean flag to specify if the application should run in test mode. When enabled, a test database will be instantiated with sample datasets or an empty configuration if specified. Defaults to False.

False
empty bool

A boolean flag to specify whether the test database should be instantiated without any datasets or configurations. Defaults to False.

False
models bool

A boolean flag to specify whether the test database should be populated with trained CNN models. Defaults to False.

False
log_level str

The logging level to use for the application. Defaults to DEFAULT_LOG_LEVEL.

DEFAULT_LOG_LEVEL
Source code in plantdb/cli/fsdb_rest_api.py
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
def rest_api(db_location, host="0.0.0.0", port=5000, debug=False, test=False, empty=False, models=False, log_level=DEFAULT_LOG_LEVEL):
    """Initialize and configure a RESTful API server for Plant Database querying.

    This function sets up a Flask application with various RESTful endpoints to enable interaction with a
    local Plant Database (FSDB).
    RESTful routes are added for managing and retrieving various datasets and configurations, providing
    an interface for working with plant scans and related files. The application can be run in test
    mode with optional configurations for using sample datasets.

    Parameters
    ----------
    db_location : str
        The path to the local plant database to be served. If set to "/none", the server will raise
        an error and terminate unless the path is appropriately overridden in test mode.
    host : str, optional
        The hostname or IP address on which the Flask application will listen for incoming requests.
         Defaults to ``"0.0.0.0"``.
    port : int, optional
        The port number to bind the Flask application for incoming HTTP requests.
         Defaults to ``5000``.
    debug : bool, optional
        A boolean flag indicating whether Flask debugging mode should be enabled.
        Useful for debugging during development. Defaults to ``False``.
    test : bool, optional
        A boolean flag to specify if the application should run in test mode. When enabled, a test
        database will be instantiated with sample datasets or an empty configuration if specified.
         Defaults to ``False``.
    empty : bool, optional
        A boolean flag to specify whether the test database should be instantiated without any
        datasets or configurations. Defaults to ``False``.
    models : bool, optional
        A boolean flag to specify whether the test database should be populated with trained CNN models.
        Defaults to ``False``.
    log_level : str, optional
        The logging level to use for the application. Defaults to ``DEFAULT_LOG_LEVEL``.

    """
    # Instantiate the Flask application:
    app = Flask(__name__)
    CORS(app)
    api = Api(app)
    # Instantiate the logger:
    wlogger = logging.getLogger('werkzeug')
    logger = get_logger('fsdb_rest_api', log_level=log_level)

    if test:
        if empty:
            db_location = test_database(None).path()
        else:
            db_location = test_database(DATASET, with_configs=True, with_models=models).path()
        # Register cleanup if a temporary database was created
        def cleanup():
            logger.info(f"Cleaning up temporary database directory at '{db_location}'...")
            try:
                shutil.rmtree(db_location)
                logger.info(f"Successfully removed temporary directory at '{db_location}'.")
            except OSError as e:
                logger.error(f"Error removing temporary directory: {e}.")

        atexit.register(cleanup)

    if db_location == "/none":
        logger.error("Can't serve a local PlantDB as no path to the database was specified!")
        logger.info(
            "To specify the location of the local database to serve, either set the environment variable 'ROMI_DB' or use the `-db` or `--db_location` option.")
        sleep(1)
        sys.exit("Wrong database location!")

    # Connect to the database:
    db = FSDB(db_location)
    logger.info(f"Connecting to local plant database located at '{db.path()}'...")
    db.connect(unsafe=True)  # to avoid locking the database
    logger.info(f"Found {len(db.list_scans(owner_only=False))} scans dataset to serve in local plant database.")

    # Initialize RESTful resources to serve:
    api.add_resource(ScansList, '/scans',
                     resource_class_args=tuple([db]))
    api.add_resource(ScansTable, '/scans_info',
                     resource_class_args=tuple([db, logger]))
    api.add_resource(Scan, '/scans/<string:scan_id>',
                     resource_class_args=tuple([db, logger]))
    api.add_resource(File, '/files/<path:path>',
                     resource_class_args=tuple([db]))
    api.add_resource(DatasetFile, '/files/<string:scan_id>',
                     resource_class_args=tuple([db]))
    api.add_resource(Refresh, '/refresh',
                     resource_class_args=tuple([db]))
    api.add_resource(Image, '/image/<string:scan_id>/<string:fileset_id>/<string:file_id>',
                     resource_class_args=tuple([db]))
    api.add_resource(PointCloud, '/pointcloud/<string:scan_id>/<string:fileset_id>/<string:file_id>',
                     resource_class_args=tuple([db]))
    api.add_resource(PointCloudGroundTruth, '/pcGroundTruth/<string:scan_id>/<string:fileset_id>/<string:file_id>',
                     resource_class_args=tuple([db]))
    api.add_resource(Mesh, '/mesh/<string:scan_id>/<string:fileset_id>/<string:file_id>',
                     resource_class_args=tuple([db]))
    api.add_resource(CurveSkeleton, '/skeleton/<string:scan_id>',
                     resource_class_args=tuple([db]))
    api.add_resource(Sequence, '/sequence/<string:scan_id>',
                     resource_class_args=tuple([db]))
    api.add_resource(Archive, '/archive/<string:scan_id>',
                     resource_class_args=tuple([db, logger]))

    # Start the Flask application:
    app.run(host=host, port=port, debug=debug)