{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 3D Models\n", "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/VirtualBrainLab/urchin-examples/blob/main/basics/3D.ipynb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Install Urchin\n", "\n", "Urchin is a Python package stored on PyPI, the following code needs to be run the first time you use Urchin in a Python environment. \n", "\n", "Urchin's full documentation can be found [on our website](https://virtualbrainlab.org/urchin/installation_and_use.html)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Installing urchin\n", "!pip install oursin -U" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!pip install PyWavefront numpy-stl" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup Urchin and open the renderer webpage \n", "\n", "By default Urchin opens the 3D renderer in a webpage. Make sure pop-ups are enabled, or the page won't open properly. You can also open the renderer site yourself by replacing [ID here] with the ID that is output by the call to `.setup()` at https://data.virtualbrainlab.org/Urchin/?ID=[ID here]\n", "\n", "Note that Urchin communicates to the renderer webpage through an internet connection, we don't currently support offline use (we hope to add support in the future)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] } ], "source": [ "import oursin as urchin\n", "urchin.setup()" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import requests\n", "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load an STL file\n", "\n", "We'll just load a cube as an example. The cube is the size of the CCF for convenience." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# obj_url = 'https://drive.google.com/uc?id=11VIfFz7dO9TOPfkL9sPgihapjs1hNANe'\n", "stl_url = 'https://drive.google.com/uc?id=1TUsqumhZWZRL_VEjjlxs4gLeEuicDS34'\n", "\n", "# obj_response = requests.get(obj_url, stream=True)\n", "stl_response = requests.get(stl_url, stream=True)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "## Load STL/OBJ files\n", "from stl import mesh\n", "import tempfile\n", "\n", "def loadSTL(stl_bytes):\n", " # Convert bytes to string\n", " with tempfile.NamedTemporaryFile(delete=False) as temp_stl:\n", " temp_stl.write(stl_bytes)\n", " \n", " # Load STL file using numpy-stl\n", " stl_mesh = mesh.Mesh.from_file(temp_stl.name)\n", "\n", " #get unique vertices\n", " vertices = np.unique(np.reshape(stl_mesh.points,(-1,3)), axis=0)\n", "\n", " #triangles: go through each triangle and figure out which indexes it corresponds to\n", " triangles = []\n", " for vector in stl_mesh.vectors:\n", " for vi in np.arange(0,3):\n", " index = np.where((vertices == vector[vi]).all(axis=1))[0][0] \n", " triangles.append(index)\n", "\n", " return vertices, triangles" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "\n", "# Example usage:\n", "stl_vertices, stl_triangles = loadSTL(stl_response.content)\n", "\n", "vertices = urchin.utils.list_of_list2vector3(stl_vertices)\n", "triangles = [int(x) for x in stl_triangles]" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(Warning) Atlas was already loaded, the renderer can have issues if you try to load an atlas twice.\n" ] } ], "source": [ "# Note that an atlas must be loaded to create custom meshes, otherwise no reference coordinate information will be available\n", "urchin.ccf25.load()" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "mesh = urchin.custom.CustomMesh(vertices, triangles)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "mesh.set_position([3,1,-1], True)" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "mesh.set_scale([1, 1, 1])" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "packet queue is empty, aborting\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "packet queue is empty, aborting\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "packet queue is empty, aborting\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "packet queue is empty, aborting\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "packet queue is empty, aborting\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "packet queue is empty, aborting\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "packet queue is empty, aborting\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "packet queue is empty, aborting\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n", "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "packet queue is empty, aborting\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "packet queue is empty, aborting\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "packet queue is empty, aborting\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(URN) disconnected from server\n", "(URN) connected to server\n", "Login sent with ID: 3f54bbeb, copy this ID into the renderer to connect.\n" ] } ], "source": [ "urchin.custom.clear()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "iblenv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.13" } }, "nbformat": 4, "nbformat_minor": 2 }