Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions biosimdb_interface/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,8 @@ def inject_base_url():

app.register_blueprint(login_bp, url_prefix=app.config["APPLICATION_BASE"])

from .home import home_bp

app.register_blueprint(home_bp, url_prefix=app.config["APPLICATION_BASE"])

return app
2 changes: 1 addition & 1 deletion biosimdb_interface/form/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

form_bp = Blueprint("form", __name__)

from . import extract, home, webform # noqa: E402, F401
from . import extract, webform # noqa: E402, F401
86 changes: 52 additions & 34 deletions biosimdb_interface/form/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
"""

import os
import shutil

from biosim_extractor.metadata.populatemetadata import MetadataPopulator
from flask import jsonify, request
from flask import jsonify, request, session
from werkzeug.utils import secure_filename

from . import form_bp
from .upload import cache_extracted_files, cleanup_tmpdir
from .utils import make_upload_tmpdir


Expand Down Expand Up @@ -51,6 +52,7 @@ def extract_files_validate(top_file, traj_file):
@form_bp.route("/extract_metadata", methods=["POST"])
def extract_metadata():
"""Extract simulation metadata from uploaded topology and trajectory files.
This is where the tmpdir for the files is created.

Expects a multipart POST with:
- ``topology``: a single topology file.
Expand All @@ -65,49 +67,65 @@ def extract_metadata():
- ``{"simulation_metadata": ..., "validation_errors": [...]}`` if schema validation fails.
- ``{"error": "..."}`` with status 400 if files are missing, or 500 on unexpected error.
"""
# clear the existing tmpdir from previous extraction
tmpdir = session.get("submission_tmpdir")
if tmpdir:
cleanup_tmpdir(tmpdir)
session.pop("submission_tmpdir", None)
tmpdir = make_upload_tmpdir("biosimdb_submission_")
session["submission_tmpdir"] = tmpdir

try:
topology = request.files.get("topology")
trajectories = request.files.getlist("trajectory[]")

if not topology or not trajectories:
return jsonify({"error": "Simulation files are missing."}), 400

temp_dir = make_upload_tmpdir("biosimdb_extract_")
try:
topo_path = os.path.join(temp_dir, topology.filename)
topology.save(topo_path)
traj_files = []

for traj in trajectories:
traj_path = os.path.join(temp_dir, traj.filename)
traj.save(traj_path)
traj_files.append(traj_path)

result, validation_errors = extract_files_validate(topo_path, traj_files)

# Keep authoritative extracted payload on the server
# session["extracted_metadata"] = result

if len(validation_errors) > 0:
return jsonify(
{
"simulation_metadata": result,
"validation_errors": validation_errors,
}
)
else:
return jsonify(
{
"simulation_metadata": result,
"message": "Metadata extracted successfully.",
}
)
finally:
shutil.rmtree(temp_dir, ignore_errors=True)
topo_path = os.path.join(tmpdir, secure_filename(topology.filename))
topology.save(topo_path, buffer_size=16 * 1024 * 1024) # 16 MB chunks

traj_files = []
for traj in trajectories:
traj_path = os.path.join(tmpdir, secure_filename(traj.filename))
traj.save(traj_path, buffer_size=16 * 1024 * 1024)
traj_files.append(traj_path)

saved_files = {"topology": [topo_path], "trajectory": traj_files}
cache_extracted_files(tmpdir, saved_files)

result, validation_errors = extract_files_validate(topo_path, traj_files)

if len(validation_errors) > 0:
cleanup_tmpdir(tmpdir)
session.pop("submission_tmpdir", None)
return jsonify(
{
"simulation_metadata": result,
"validation_errors": validation_errors,
}
)
else:
return jsonify(
{
"simulation_metadata": result,
"message": "Metadata extracted successfully.",
}
)

except Exception as e:
print(f"ERROR: {e}")
import traceback

traceback.print_exc()
return jsonify({"error": str(e)}), 500


@form_bp.route("/clear_extraction", methods=["POST"])
def clear_extraction():
"""Discard extracted files and reset the pending submission tmpdir."""
tmpdir = session.get("submission_tmpdir")
cleanup_tmpdir(tmpdir)
for key in ("submission_tmpdir", "topo_path", "traj_files"):
session.pop(key, None)
return jsonify({"success": True})
Loading
Loading