Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add reva file endpoints #250

Merged
merged 2 commits into from
Jan 7, 2025
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
2 changes: 2 additions & 0 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ class Config(object):
HUBSPOT_CLIENT_SECRET = os.environ.get("HUBSPOT_CLIENT_SECRET")
EMAIL_OCTOPUS_API_KEY = os.environ.get("EMAIL_OCTOPUS_API_KEY")
LOG_LEVEL = os.environ.get("LOG_LEVEL", "WARNING")
REVA_3D_TRACING_PRIMARY_FOLDER_COLLECTION_ID = os.environ.get("REVA_3D_TRACING_PRIMARY_FOLDER_COLLECTION_ID")
REVA_MICRO_CT_PRIMARY_FOLDER_COLLECTION_ID = os.environ.get("REVA_MICRO_CT_PRIMARY_FOLDER_COLLECTION_ID")
# Metrics
GOOGLE_API_GA_SCOPE = os.environ.get("GOOGLE_API_GA_SCOPE", "https://www.googleapis.com/auth/analytics.readonly")
GOOGLE_API_GA_KEY_PATH = os.environ.get("GOOGLE_API_GA_KEY_PATH")
Expand Down
106 changes: 106 additions & 0 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
from flask_cors import CORS
from flask_marshmallow import Marshmallow
from pennsieve import Pennsieve
from pennsieve2 import Pennsieve as Pennsieve2
from pennsieve2.direct import new_client
from pennsieve.base import UnauthorizedException as PSUnauthorizedException
from PIL import Image
from requests.auth import HTTPBasicAuth
Expand Down Expand Up @@ -152,6 +154,13 @@ def connect_to_pennsieve():
logging.error("Unknown Error")
logging.error(err)

@app.before_first_request
def connect_to_pennsieve2():
global ps2
try:
ps2 = new_client(api_key=Config.PENNSIEVE_API_TOKEN, api_secret=Config.PENNSIEVE_API_SECRET, api_host=Config.PENNSIEVE_API_HOST, api2_host=None)
except Exception as err:
logging.error(f"Error connecting to pennsieve 2 agent: {err}")

viewers_scheduler = BackgroundScheduler()
metrics_scheduler = BackgroundScheduler()
Expand Down Expand Up @@ -935,6 +944,103 @@ def get_featured_dataset():
logging.error(f"Could not get featured dataset {featured_dataset_id}", ex)
abort(404, description="An error occured while fetching the resource")

@app.route("/reva/subject-ids", methods=["GET"])
def getRevaSubjectIds():
try:
primary_folder = ps2.get(f'/packages/{Config.REVA_3D_TRACING_PRIMARY_FOLDER_COLLECTION_ID}')
primary_children = primary_folder['children']
subject_ids = []
for child in primary_children:
if child['content']['packageType'] == 'Collection':
subject_ids.append(child['content']['name'])
return jsonify({"status": "success", "ids": subject_ids}), 200
except Exception as e:
logging.error(f"Error while getting REVA subject id files: {e}")
return jsonify({"status": "Error while getting REVA subject id files: ", "message": e}), 500

@app.route("/reva/tracing-files/<subject_id>", methods=["GET"])
def getRevaTracingFiles(subject_id):
coordinates_folder_name = 'Coordinates-Data'
in_situ_folder_name = 'InSitu'
vagus_nerve_folder_name = 'Vagus-nerve'

try:
primary_folder = ps2.get(f'/packages/{Config.REVA_3D_TRACING_PRIMARY_FOLDER_COLLECTION_ID}')
primary_children = primary_folder['children']
subject_child = next((child for child in primary_children if child['content']['name'] == subject_id), None)
if subject_child is None:
logging.error(f"REVA tracing folder not found with subject id: {subject_id}")
return jsonify({"status": "ERROR", "message": f"Folder not found with subject id: {subject_id}"}), 404
subject_folder = ps2.get(f"/packages/{subject_child['content']['id']}")
subject_children = subject_folder['children']
coordinates_child = next((child for child in subject_children if child['content']['name'] == coordinates_folder_name), None)
if coordinates_child is None:
logging.error(f"REVA tracing folder {coordinates_folder_name} not found for subject: {subject_id}")
return jsonify({"status": "ERROR", "message": f"{coordinates_folder_name} folder not found for subject: {subject_id}"}), 404
coordinates_folder = ps2.get(f"/packages/{coordinates_child['content']['id']}")
coordinates_children = coordinates_folder['children']
in_situ_child = next((child for child in coordinates_children if child['content']['name'] == in_situ_folder_name), None)
if in_situ_child is None:
logging.error(f"REVA tracing folder {in_situ_folder_name} not found for subject: {subject_id}")
return jsonify({"status": "ERROR", "message": f"{in_situ_folder_name} folder not found for subject: {subject_id}"}), 404
in_situ_folder = ps2.get(f"/packages/{in_situ_child['content']['id']}")
in_situ_children = in_situ_folder['children']
vagus_nerve_child = next((child for child in in_situ_children if child['content']['name'] == vagus_nerve_folder_name), None)
if vagus_nerve_child is None:
logging.error(f"REVA tracing folder {vagus_nerve_folder_name} not found for subject: {subject_id}")
return jsonify({"status": "ERROR", "message": f"{vagus_nerve_folder_name} folder not found for subject: {subject_id}"}), 404
vagus_nerve_folder = ps2.get(f"/packages/{vagus_nerve_child['content']['id']}")
vagus_nerve_children = vagus_nerve_folder['children']
vagus_tracing_files = []
for vagus_region_child in vagus_nerve_children:
vagus_region_folder = ps2.get(f"/packages/{vagus_region_child['content']['id']}")
# get file and use id and package id for getting the presigned url https://api.pennsieve.io/packages/{id}/view
vagus_region_children = vagus_region_folder['children']
for vagus_file_child in vagus_region_children:
file_package_id = vagus_file_child['content']['id']
vagus_file = ps2.get(f"/packages/{file_package_id}/view")
vagus_file_id = vagus_file[0]['content']['id']
vagus_file_presigned_url = ps2.get(f"/packages/{file_package_id}/files/{vagus_file_id}")['url']
vagus_tracing_files.append({'name':str(vagus_file_child['content']['name']), 's3Url':str(vagus_file_presigned_url)})
return jsonify({"status": "success", "files": vagus_tracing_files}), 200
except Exception as e:
logging.error(f"Error while getting REVA tracing files {e}")
return jsonify({"status": "Error while getting tracing files: ", "message": e}), 500

@app.route("/reva/micro-ct-files/<subject_id>", methods=["GET"])
def getRevaMicroCtFiles(subject_id):
micro_ct_visualization_folder_name = f'{subject_id}-MicroCTVisualization'

try:
primary_folder = ps2.get(f'/packages/{Config.REVA_MICRO_CT_PRIMARY_FOLDER_COLLECTION_ID}')
primary_children = primary_folder['children']
subject_child = next((child for child in primary_children if child['content']['name'] == subject_id), None)
if subject_child is None:
logging.error(f'REVA microCT folder not found with subject id: {subject_id}')
return jsonify({"status": "ERROR", "message": f"MicroCT folder not found with subject id: {subject_id}"}), 404
subject_folder = ps2.get(f"/packages/{subject_child['content']['id']}")
subject_children = subject_folder['children']
micro_ct_child = next((child for child in subject_children if child['content']['name'] == micro_ct_visualization_folder_name), None)
if micro_ct_child is None:
logging.error(f'REVA microCT {micro_ct_visualization_folder_name} folder not found for subject: {subject_id}')
return jsonify({"status": "ERROR", "message": f"{micro_ct_visualization_folder_name} folder not found for subject: {subject_id}"}), 404
micro_ct_visualization_folder = ps2.get(f"/packages/{micro_ct_child['content']['id']}")
micro_ct_children = micro_ct_visualization_folder['children']
micro_ct_files = []
for micro_child in micro_ct_children:
file_package_id = micro_child['content']['id']
micro_child_file = ps2.get(f"/packages/{file_package_id}/view")
micro_child_file_id = micro_child_file[0]['content']['id']
micro_file_presigned_url = ps2.get(f"/packages/{file_package_id}/files/{micro_child_file_id}")['url']
file_name = micro_child['content']['name']
file_size = micro_child['storage']
package_type = micro_child['content']['packageType']
file_type = micro_child_file[0]['content']['fileType']
micro_ct_files.append({'name':str(file_name), 's3Url':str(micro_file_presigned_url), 'type':str(file_type), 'packageType':str(package_type), 'size':str(file_size)})
return jsonify({"status": "success", "files": micro_ct_files}), 200
except Exception as e:
logging.error(f"Error while getting REVA microCT files {e}")
return jsonify({"status": "Error while getting microCT files: ", "message": e}), 500

@app.route("/get_owner_email/<int:owner_id>", methods=["GET"])
def get_owner_email(owner_id):
Expand Down
7 changes: 4 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
api==0.0.7
pennsieve==6.1.1
boto3==1.17.67
botocore==1.20.67
pennsieve2==0.1.2
boto3==1.26
botocore==1.29.0
certifi==2023.5.7
chardet==3.0.4
Click==7.1.2
Expand All @@ -27,7 +28,7 @@ python-dateutil==2.8.2
python-dotenv==0.10.3
query-string==2019.4.13
requests==2.31.0
s3transfer==0.4.2
s3transfer==0.6.0
sendgrid==6.9.7
six==1.13.0
SQLAlchemy==1.3.20
Expand Down
21 changes: 21 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,24 @@ def test_get_featured_datasets(client):
json = r.get_json()
assert 'identifiers' in json
assert type(json['identifiers']) == list

def test_get_reva_subject_ids(client):
r = client.get('/reva/subject-ids')
assert r.status_code == 200
json = r.get_json()
assert 'ids' in json
assert type(json['ids']) == list

def test_get_reva_tracing_files(client):
r = client.get('/reva/tracing-files/sub-SR005')
assert r.status_code == 200
json = r.get_json()
assert 'files' in json
assert type(json['files']) == list

def test_get_reva_micro_ct_files(client):
r = client.get('/reva/micro-ct-files/sub-SR005')
assert r.status_code == 200
json = r.get_json()
assert 'files' in json
assert type(json['files']) == list