This guide provides Python examples for interacting with the ScientistCloud Data Portal API.
These examples use the Python requests library. There is no separate published ScientistCloud pip SDK.
pip install requests
import requests
import json
def login(email):
"""Login and get access token"""
url = "https://scientistcloud.com/api/auth/login"
response = requests.post(
url,
json={"email": email}
)
if response.status_code == 200:
data = response.json()
return data['data']['access_token']
else:
print(f"Login failed: {response.text}")
return None
# Usage
token = login("user@example.com")
print(f"Token: {token[:20]}...")
def verify_token(token):
"""Verify token is valid"""
url = "https://scientistcloud.com/api/auth/status"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers)
return response.status_code == 200
# Usage
if verify_token(token):
print("Token is valid")
def upload_file(token, file_path, dataset_name, **kwargs):
"""Upload a file to ScientistCloud"""
url = "https://scientistcloud.com/api/upload/upload"
headers = {"Authorization": f"Bearer {token}"}
# Prepare file
with open(file_path, 'rb') as f:
files = {'file': f}
# Prepare form data
data = {
'user_email': kwargs.get('user_email', ''),
'dataset_name': dataset_name,
'sensor': kwargs.get('sensor', '4D_NEXUS'),
'convert': str(kwargs.get('convert', True)).lower(),
'is_public': str(kwargs.get('is_public', False)).lower(),
}
# Add optional parameters
if 'folder' in kwargs:
data['folder'] = kwargs['folder']
if 'tags' in kwargs:
data['tags'] = kwargs['tags']
if 'team_uuid' in kwargs:
data['team_uuid'] = kwargs['team_uuid']
# Reset file pointer
f.seek(0)
# Upload
response = requests.post(url, headers=headers, files=files, data=data)
if response.status_code == 200:
return response.json()
else:
print(f"Upload failed: {response.text}")
return None
# Usage
result = upload_file(
token,
"/path/to/file.nxs",
"My Dataset",
user_email="user@example.com",
sensor="4D_NEXUS",
folder="CHESS_4D",
tags="nexus,4d,chess"
)
if result:
print(f"Upload started! Job ID: {result['job_id']}")
import os
from tqdm import tqdm
def upload_file_with_progress(token, file_path, dataset_name, **kwargs):
"""Upload file with progress bar"""
url = "https://scientistcloud.com/api/upload/upload"
headers = {"Authorization": f"Bearer {token}"}
file_size = os.path.getsize(file_path)
with open(file_path, 'rb') as f:
files = {'file': f}
data = {
'user_email': kwargs.get('user_email', ''),
'dataset_name': dataset_name,
'sensor': kwargs.get('sensor', '4D_NEXUS'),
'convert': str(kwargs.get('convert', True)).lower(),
'is_public': str(kwargs.get('is_public', False)).lower(),
}
if 'folder' in kwargs:
data['folder'] = kwargs['folder']
if 'tags' in kwargs:
data['tags'] = kwargs['tags']
f.seek(0)
# Upload with progress
with tqdm(total=file_size, unit='B', unit_scale=True) as pbar:
response = requests.post(
url,
headers=headers,
files=files,
data=data,
stream=True
)
# Note: requests doesn't support progress for multipart uploads
# This is a simplified version
pbar.update(file_size)
if response.status_code == 200:
return response.json()
else:
print(f"Upload failed: {response.text}")
return None
import time
def check_upload_status(token, job_id):
"""Check upload job status"""
url = f"https://scientistcloud.com/api/upload/status/{job_id}"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()
else:
print(f"Status check failed: {response.text}")
return None
def wait_for_completion(token, job_id, timeout=3600):
"""Wait for upload to complete"""
start_time = time.time()
while time.time() - start_time < timeout:
status = check_upload_status(token, job_id)
if status:
job_status = status.get('status')
progress = status.get('progress_percentage', 0)
print(f"Status: {job_status} ({progress}%)")
if job_status == 'completed':
print("Upload completed!")
return status
elif job_status == 'failed':
print("Upload failed!")
return status
time.sleep(5)
print("Timeout waiting for upload")
return None
# Usage
job_id = result['job_id']
final_status = wait_for_completion(token, job_id)
def list_datasets(token, user_email, folder=None, team_uuid=None):
"""List user's datasets grouped as my / shared / team"""
url = "https://scientistcloud.com/api/v1/datasets/by-user"
headers = {"Authorization": f"Bearer {token}"}
params = {"user_email": user_email}
if folder:
params['folder'] = folder
if team_uuid:
params['team_uuid'] = team_uuid
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
return response.json()
print(f"Failed to list datasets: {response.text}")
return None
# Usage
payload = list_datasets(token, "user@example.com", folder="CHESS_4D")
if payload and payload.get("datasets"):
for dataset in payload["datasets"].get("my", []):
print(f"{dataset.get('name')} - {dataset.get('status')}")
def get_dataset_details(token, dataset_uuid, user_email):
"""Get dataset details"""
url = f"https://scientistcloud.com/api/v1/datasets/{dataset_uuid}"
headers = {"Authorization": f"Bearer {token}"}
params = {"user_email": user_email}
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
return response.json()
print(f"Failed to get dataset details: {response.text}")
return None
# Usage
details = get_dataset_details(token, "550e8400-e29b-41d4-a716-446655440000", "user@example.com")
if details:
print(f"Dataset: {details['dataset']['name']}")
print(f"Status: {details['dataset']['status']}")
def update_dataset(token, dataset_uuid, user_email, **kwargs):
"""Update dataset metadata"""
url = f"https://scientistcloud.com/api/v1/datasets/{dataset_uuid}"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
params = {"user_email": user_email}
data = {}
# Add update fields
if 'name' in kwargs:
data['name'] = kwargs['name']
if 'tags' in kwargs:
data['tags'] = kwargs['tags']
if 'folder' in kwargs:
data['folder'] = kwargs['folder']
if 'team_uuid' in kwargs:
data['team_uuid'] = kwargs['team_uuid']
if 'dimensions' in kwargs:
data['dimensions'] = kwargs['dimensions']
if 'preferred_dashboard' in kwargs:
data['preferred_dashboard'] = kwargs['preferred_dashboard']
response = requests.put(url, headers=headers, params=params, json=data)
if response.status_code == 200:
return response.json()
print(f"Update failed: {response.text}")
return None
# Usage
result = update_dataset(
token,
"550e8400-e29b-41d4-a716-446655440000",
"user@example.com",
name="Updated Name",
tags="updated, tags"
)
#!/usr/bin/env python3
"""Complete example: Upload file and monitor progress"""
import requests
import time
import sys
# Configuration
EMAIL = "user@example.com"
FILE_PATH = "/path/to/file.nxs"
DATASET_NAME = "My Dataset"
FOLDER = "CHESS_4D"
# 1. Login
print("Logging in...")
login_response = requests.post(
"https://scientistcloud.com/api/auth/login",
json={"email": EMAIL}
)
if login_response.status_code != 200:
print(f"Login failed: {login_response.text}")
sys.exit(1)
token = login_response.json()['data']['access_token']
print(f"ā
Token obtained: {token[:20]}...")
# 2. Upload file
print(f"\nUploading {FILE_PATH}...")
with open(FILE_PATH, 'rb') as f:
files = {'file': f}
data = {
'user_email': EMAIL,
'dataset_name': DATASET_NAME,
'sensor': '4D_NEXUS',
'convert': 'true',
'is_public': 'false',
'folder': FOLDER,
'tags': 'nexus,4d'
}
f.seek(0)
upload_response = requests.post(
"https://scientistcloud.com/api/upload/upload",
headers={"Authorization": f"Bearer {token}"},
files=files,
data=data
)
if upload_response.status_code != 200:
print(f"Upload failed: {upload_response.text}")
sys.exit(1)
result = upload_response.json()
job_id = result['job_id']
dataset_uuid = result['dataset_uuid']
print(f"ā
Upload started! Job ID: {job_id}")
print(f"š Dataset UUID: {dataset_uuid}")
# 3. Monitor progress
print("\nš Monitoring upload progress...")
while True:
status_response = requests.get(
f"https://scientistcloud.com/api/upload/status/{job_id}",
headers={"Authorization": f"Bearer {token}"}
)
if status_response.status_code == 200:
status = status_response.json()
job_status = status.get('status')
progress = status.get('progress_percentage', 0)
print(f"Status: {job_status} ({progress}%)")
if job_status == 'completed':
print("ā
Upload completed!")
break
elif job_status == 'failed':
print("ā Upload failed!")
sys.exit(1)
time.sleep(5)
# 4. Get dataset details
print("\nš Getting dataset details...")
details_response = requests.get(
f"https://scientistcloud.com/api/v1/datasets/{dataset_uuid}",
headers={"Authorization": f"Bearer {token}"},
params={"user_email": EMAIL}
)
if details_response.status_code == 200:
details = details_response.json()
dataset = details.get("dataset") or details
print(f"Dataset: {dataset.get('name')}")
print(f"Status: {dataset.get('status')}")
print(f"Created: {dataset.get('created_at')}")
print("\nā
Done!")
def safe_upload(token, file_path, dataset_name):
"""Upload with error handling"""
try:
result = upload_file(token, file_path, dataset_name)
if result and 'job_id' in result:
return result
else:
print("Upload failed: No job_id in response")
return None
except FileNotFoundError:
print(f"File not found: {file_path}")
return None
except requests.exceptions.RequestException as e:
print(f"Request error: {e}")
return None
except Exception as e:
print(f"Unexpected error: {e}")
return None
with statements for file operations