Get a demo

Get in touch

Prefer using email? Write us at hello@moveshelf.com

Developer – Example scripts

    Search Knowledge Base
Getting started
  • Setting up the environment
  • Setting up a GitHub repository
  • Setting up the Moveshelf API
  • Recording - Intro to Moveshelf API
  • Using the API
  • Moveshelf API documentation
  • Configuration and authentication
  • Use built-in functions
  • Examples provided by Moveshelf
  • Importing data
  • Create subject
  • Import subject metadata
  • Create session
  • Import session metadata
  • Create trial
  • Upload data files
  • Create interactive reports
  • Querying data
  • Retrieve a filtered subset of subjects
  • Retrieve a filtered subset of sessions
  • Retrieve a subject
  • Retrieve subject metadata
  • Retrieve session
  • Retrieve session metadata
  • Export metadata to Excel
  • Retrieve trials
  • Retrieve data files
  • Deleting data
  • Delete a subject
  • Delete multiple subjects
  • Delete a session
  • Delete a trial
  • Delete all trials within a condition
  • Delete a data file
  • Example scripts
  • Public repository
  • Download data
  • Download large data sets
  • Batch upload data
  • Pre vs post intervention data export
  • Extending the Moveshelf API
  • Extending the Moveshelf API
  • Complete example processing scripts that combine import and query steps into custom workflows.



    Public repository
    Moveshelf provides a public GitHub repository that contains several complete example scripts that are ready to be used. To use these example scripts, clone Moveshelf's public GitHub repository to your local machine. You can do this by following these steps.

    The sections below explain how to run the different examples scripts, e.g. to query and download or upload data.


     

    Download data
    The example script download_data.py can be used when you want to query and download data from the Moveshelf platform.
    Prerequisites
    Before implementing this example, ensure that you have performed all necessary setup steps. In particular, you should have:
    Run download_data.py
    • Open download_data.py in Visual Studio Code, follow the instructions, add all relevant information to the script and save the file
    • To run the script, insert python scripts/download_data.py in the terminal and press 'Enter'



     

    Download large data sets
    This section explains how to retrieve data (files) for all subjects in a project on Moveshelf using the Moveshelf API in an efficient way. The key points to speed up execution in this use case are:
    • Reduce the number of API calls to retrieve data
    • Download data in parallel

    When to use parallel retrieval by Subject or Session ID: Use this pattern when (1) you already have a list of specific IDs to retrieve, (2) you need to perform multiple filtering iterations before downloading data, or (3) you need to programmatically select which items to download. For simple "filter once and download all" workflows, using include_additional_data=True directly in getFilteredProjectSubjects or getFilteredProjectSessions is more efficient with fewer API calls.
    Prerequisites
    Before implementing these examples, ensure that your processing script includes all necessary setup steps. In particular, you should have:
    Implementation
    Below are two recommended patterns for retrieving large numbers of files in parallel. Use whichever matches your workflow.
    Example 1: Retrieve subject data in parallel (from a list of subject IDs)
    Use this pattern when you have a list of subject IDs and need to retrieve full subject data with all sessions, clips, and additional data files. Subject IDs can be obtained from filtered subjects, manual selection, or other custom sources.

    import os, sys, json
    parent_folder = os.path.dirname(os.path.dirname(__file__))
    sys.path.append(parent_folder)
    import requests
    from moveshelf_api.api import MoveshelfApi
    from concurrent.futures import ThreadPoolExecutor
    
    # Use a requests.Session for connection pooling
    MAX_WORKERS = 5 # Number of threads for parallel processing.
    POOL_MAXSIZE = MAX_WORKERS + 2  # Set slightly higher than max_workers to avoid connection issues
    requests_session = requests.Session()
    adapter = requests.adapters.HTTPAdapter(pool_maxsize=POOL_MAXSIZE)
    requests_session.mount('https://', adapter)
    
    def download_with_session(url: str) -> dict | None:
        return download_json_file(url, session=requests_session)
    
    def download_json_file(url: str, session: requests.Session | None = None) -> dict | None:
        try:
            response = session.get(url) if session else requests.get(url)
            decoded_content = response.content.decode()
            return json.loads(decoded_content)
        except Exception as e:
            print(f"Failed to download or parse {url}: {e}")
            return None
       
    ## Setup the API
    # Load config
    personal_config = os.path.join(parent_folder, "mvshlf-config.json")
    if not os.path.isfile(personal_config):
        raise FileNotFoundError(
            f"Configuration file '{personal_config}' is missing.\n"
            "Ensure the file exists with the correct name and path."
        )
    
    with open(personal_config, "r") as config_file:
        data = json.load(config_file)
    
    api = MoveshelfApi(
        api_key_file=os.path.join(parent_folder, data["apiKeyFileName"]),
        api_url=data["apiUrl"],
    )
    
    # Increase connection pool size globally for urllib3 to match MAX_WORKERS thread workers
    api.http.connection_pool_kw['maxsize'] = POOL_MAXSIZE
    
    ## Get available projects
    projects = api.getUserProjects()
    project_names = [project['name'] for project in projects if len(projects) > 0]
    
    my_project = "<organizationName/projectName>"  # e.g. support/demoProject
    idx_my_project = project_names.index(my_project)
    my_project_id = projects[idx_my_project]["id"]
    file_extension_to_download = '.json'  # Only download json files
    
    # Example: List of subject IDs (see note below on how to obtain these through filtering)
    subject_ids = [
        "<subjectId_1>",
        "<subjectId_2>",
        "<subjectId_3>"
    ]
    print(f"Processing {len(subject_ids)} subjects")
    
    # Step 1: Retrieve full subject data in parallel
    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        subjects_with_clips = list(executor.map(api.getSubjectData, subject_ids))
    
    ## Extract URLs and file paths for additional data
    URLs = []
    for subject_details in subjects_with_clips:
        for session in subject_details.get("sessions", []):
            for clip in session.get("clips", []):
                for ad in clip.get("additionalData", []):
                    if ad["originalDataDownloadUri"].endswith(file_extension_to_download):
                        URLs.append(ad["originalDataDownloadUri"])
    
    print(f"Found {len(URLs)} files to download")
    
    # Step 2: Download additional data files in parallel
    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        additional_data = list(executor.map(download_with_session, URLs))
    
    print(f"Downloaded {sum(1 for data in additional_data if data is not None)} files successfully")

    How to obtain subject IDs: You can retrieve subject IDs by using getFilteredProjectSubjects with include_additional_data=False for fast filtering, then extract the IDs with: subject_ids = [subject['id'] for subject in filtered_subjects]. This is useful when you need to iterate through multiple filters or programmatically select which subjects to download before retrieving their data.

    Example 2: Retrieve session data in parallel (from a list of session IDs)
    Use this pattern when you have a list of session IDs and need to retrieve session data with clips and additional data files. Session IDs can be obtained from filtered sessions, manual selection, or other custom sources.

    import os, sys, json
    parent_folder = os.path.dirname(os.path.dirname(__file__))
    sys.path.append(parent_folder)
    import requests
    from moveshelf_api.api import MoveshelfApi
    from concurrent.futures import ThreadPoolExecutor
    
    # Use a requests.Session for connection pooling
    MAX_WORKERS = 5 # Number of threads for parallel processing.
    POOL_MAXSIZE = MAX_WORKERS + 2  # Set slightly higher than max_workers to avoid connection issues
    requests_session = requests.Session()
    adapter = requests.adapters.HTTPAdapter(pool_maxsize=POOL_MAXSIZE)
    requests_session.mount('https://', adapter)
    
    def download_with_session(url: str) -> dict | None:
        return download_json_file(url, session=requests_session)
    
    def download_json_file(url: str, session: requests.Session | None = None) -> dict | None:
        try:
            response = session.get(url) if session else requests.get(url)
            decoded_content = response.content.decode()
            return json.loads(decoded_content)
        except Exception as e:
            print(f"Failed to download or parse {url}: {e}")
            return None
       
    ## Setup the API
    # Load config
    personal_config = os.path.join(parent_folder, "mvshlf-config.json")
    if not os.path.isfile(personal_config):
        raise FileNotFoundError(
            f"Configuration file '{personal_config}' is missing.\n"
            "Ensure the file exists with the correct name and path."
        )
    
    with open(personal_config, "r") as config_file:
        data = json.load(config_file)
    
    api = MoveshelfApi(
        api_key_file=os.path.join(parent_folder, data["apiKeyFileName"]),
        api_url=data["apiUrl"],
    )
    
    # Increase connection pool size globally for urllib3 to match MAX_WORKERS thread workers
    api.http.connection_pool_kw['maxsize'] = POOL_MAXSIZE
    
    ## Get available projects
    projects = api.getUserProjects()
    project_names = [project['name'] for project in projects if len(projects) > 0]
    
    my_project = "<organizationName/projectName>"  # e.g. support/demoProject
    idx_my_project = project_names.index(my_project)
    my_project_id = projects[idx_my_project]["id"]
    file_extension_to_download = '.json'  # Only download json files
    
    # Example: List of session IDs (see note below on how to obtain these through filtering)
    session_ids = [
        "<sessionId_1>",
        "<sessionId_2>",
        "<sessionId_3>"
    ]
    
    print(f"Processing {len(session_ids)} sessions")
    
    # Step 1: Retrieve session data with additional data in parallel
    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        sessions_with_data = list(executor.map(
            lambda sid: api.getSessionById(sid, include_additional_data=True),
            session_ids
        ))
    
    ## Extract URLs and file paths for additional data
    URLs = []
    for session in sessions_with_data:
        for clip in session.get("clips", []):
            for ad in clip.get("additionalData", []):
                if ad["originalDataDownloadUri"].endswith(file_extension_to_download):
                    URLs.append(ad["originalDataDownloadUri"])
    
    print(f"Found {len(URLs)} files to download")
    
    # Step 2: Download additional data files in parallel
    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        additional_data = list(executor.map(download_with_session, URLs))
    
    print(f"Downloaded {sum(1 for data in additional_data if data is not None)} files successfully")

    How to obtain session IDs: You can retrieve session IDs by using getFilteredProjectSessions with include_additional_data=False for fast filtering, then extract the IDs with: session_ids = [session['id'] for session in filtered_sessions]. This is useful when you need to iterate through multiple filters or programmatically select which sessions to download before retrieving their data.


     

    Batch upload data
    The example script batchUpload.py can be used when you want to upload data for multiple subjects / sessions to the Moveshelf platform.
    Prerequisites
    Before implementing this example, ensure that you have performed all necessary setup steps. In particular, you should have:
    Run batchUpload.py
    • Open batchUpload.py in Visual Studio Code, follow the instructions, add all relevant information to the script and save the file
    • To run the script, insert python scripts/batchUpload.py in the terminal and press 'Enter'


     

    Pre vs post intervention data export
    In this example we provide a complete workflow for analyzing intervention effects. This includes defining clear inclusion and exclusion criteria for subjects, sessions, and clips/trials, applying efficient server-side filtering to narrow down relevant data, and performing additional local filtering in Python for more advanced logic. The script also demonstrates how to identify and extract consecutive sessions surrounding a specific intervention (e.g., sessions immediately before and after), and how to organize and export the resulting dataset to an Excel file for further analysis or reporting. Refer to the script's README section for detailed instructions and explanation.
    Prerequisites
    Before implementing this example, ensure that you have performed all necessary setup steps. In particular, you should have:
    Run pre_vs_post_intervention_query_example.py
    • Open pre_vs_post_intervention_query_example.py in Visual Studio Code, follow the instructions detailed in the README section, add all relevant information to the script and save the file
    • To run the script, press F5 or type python scripts/pre_vs_post_intervention_query_example.py in the terminal and press 'Enter'