Python Examples for ScientistCloud

This guide provides Python examples for interacting with the ScientistCloud Data Portal API.

Overview

These examples use the Python requests library. There is no separate published ScientistCloud pip SDK.

Prerequisites

pip install requests

Basic Authentication

Login and Get Token

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]}...")

Verify Token

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")

Upload File

Basic Upload

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']}")

Upload with Progress

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

Check Upload Status

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)

List Datasets

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')}")

Get Dataset Details

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']}")

Update Dataset

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" )

Complete Example

#!/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!")

Error Handling

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

Best Practices

  • Handle Errors: Always check response status codes
  • Use Context Managers: Use with statements for file operations
  • Token Management: Store tokens securely, refresh when expired
  • Progress Monitoring: Monitor upload progress for large files
  • Retry Logic: Implement retry logic for network errors

Next Steps