{ "cells": [ { "cell_type": "markdown", "id": "15d5dc47", "metadata": {}, "source": [ "Print the version to check that Pandas is available.\n", "If the module is not found, install pandas with `pip install pandas`." ] }, { "cell_type": "code", "execution_count": 1, "id": "18226a2f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.4.0\n" ] } ], "source": [ "import pandas as pd\n", "print(pd.__version__)" ] }, { "cell_type": "markdown", "id": "d014d5f3", "metadata": {}, "source": [ "Import the Json file with read_json. This will make a Pandas [*DataFrame*](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html) (a table)." ] }, { "cell_type": "code", "execution_count": 2, "id": "1dd112b3", "metadata": {}, "outputs": [], "source": [ "df = pd.read_json(\"Debug_Log.json\")\n" ] }, { "cell_type": "markdown", "id": "5be4622f", "metadata": {}, "source": [ "Print the first five rows to see what the table looks like." ] }, { "cell_type": "code", "execution_count": 3, "id": "5c70ce3e", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
tickspeertypeeventarg1arg2arg3objectidcomponentid
06377993137414760332990c448-6701d991Ubiq.Messaging.NetworkSceneAwakeDESKTOP-F1J0MRRSystem Product Name (ASUS)f73fe01b1e21031d49274a1491d1d6b5714c92e9NaNNaN
16377993138909156972990c448-6701d991Ubiq.Voip.VoipPeerConnectionManagerCreatePeerConnectionForPeer0b6034cb-5c98087221119b9e-9028aafaNaN2990c448-6701d99150.0
26377993138909757132990c448-6701d991Ubiq.Voip.VoipPeerConnectionManagerRequestPeerConnection0b6034cb-5c98087221119b9e-9028aafaNaN2990c448-6701d99150.0
36377993138910157012990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject2b0edec0e-fcf7792aTrue7725a971-a369264349018.0
46377993138910556952990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject243b53edd-7c900c8fFalse7725a971-a369264349018.0
\n", "
" ], "text/plain": [ " ticks peer type \\\n", "0 637799313741476033 2990c448-6701d991 Ubiq.Messaging.NetworkScene \n", "1 637799313890915697 2990c448-6701d991 Ubiq.Voip.VoipPeerConnectionManager \n", "2 637799313890975713 2990c448-6701d991 Ubiq.Voip.VoipPeerConnectionManager \n", "3 637799313891015701 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "4 637799313891055695 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "\n", " event arg1 arg2 \\\n", "0 Awake DESKTOP-F1J0MRR System Product Name (ASUS) \n", "1 CreatePeerConnectionForPeer 0b6034cb-5c980872 21119b9e-9028aafa \n", "2 RequestPeerConnection 0b6034cb-5c980872 21119b9e-9028aafa \n", "3 SpawnObject 2 b0edec0e-fcf7792a \n", "4 SpawnObject 2 43b53edd-7c900c8f \n", "\n", " arg3 objectid componentid \n", "0 f73fe01b1e21031d49274a1491d1d6b5714c92e9 NaN NaN \n", "1 NaN 2990c448-6701d991 50.0 \n", "2 NaN 2990c448-6701d991 50.0 \n", "3 True 7725a971-a3692643 49018.0 \n", "4 False 7725a971-a3692643 49018.0 " ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head(5)" ] }, { "cell_type": "markdown", "id": "4bc3369d", "metadata": {}, "source": [ "We can use Pandas to filter and process the structured logs. Use Unique to find all the event types seen during the session." ] }, { "cell_type": "code", "execution_count": 11, "id": "2b55c17c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array(['Ubiq.Messaging.NetworkScene',\n", " 'Ubiq.Voip.VoipPeerConnectionManager',\n", " 'Ubiq.Samples.NetworkSpawner'], dtype=object)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.type.unique()" ] }, { "cell_type": "markdown", "id": "c03241ae", "metadata": {}, "source": [ "Pandas can perform vector comparisons, and filter DataFrames by row indices. Select all the SpawnObject events." ] }, { "cell_type": "code", "execution_count": 5, "id": "05170ba7", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
tickspeertypeeventarg1arg2arg3objectidcomponentid
36377993138910157012990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject2b0edec0e-fcf7792aTrue7725a971-a369264349018.0
46377993138910556952990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject243b53edd-7c900c8fFalse7725a971-a369264349018.0
56377993139354757362990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject1bf000355-ece0ea90False7725a971-a369264349018.0
66377993139517757222990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject1ba22e255-c3d84eb4False7725a971-a369264349018.0
76377993139673257092990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject11ad3fc82-d41c3b8fFalse7725a971-a369264349018.0
\n", "
" ], "text/plain": [ " ticks peer type \\\n", "3 637799313891015701 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "4 637799313891055695 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "5 637799313935475736 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "6 637799313951775722 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "7 637799313967325709 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "\n", " event arg1 arg2 arg3 objectid componentid \n", "3 SpawnObject 2 b0edec0e-fcf7792a True 7725a971-a3692643 49018.0 \n", "4 SpawnObject 2 43b53edd-7c900c8f False 7725a971-a3692643 49018.0 \n", "5 SpawnObject 1 bf000355-ece0ea90 False 7725a971-a3692643 49018.0 \n", "6 SpawnObject 1 ba22e255-c3d84eb4 False 7725a971-a3692643 49018.0 \n", "7 SpawnObject 1 1ad3fc82-d41c3b8f False 7725a971-a3692643 49018.0 " ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[df.event == \"SpawnObject\"].head(5)" ] }, { "cell_type": "markdown", "id": "059a464c", "metadata": {}, "source": [ "The Shape member shows the size of the result" ] }, { "cell_type": "code", "execution_count": 13, "id": "1dfceb39", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(22, 9)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df[df.event == \"SpawnObject\"].shape" ] }, { "cell_type": "markdown", "id": "9b48fbdc", "metadata": {}, "source": [ "The Pandas [*merge*](https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html) method is used to perform inner and outer joins to relate different log events. We merge the `Awake` events with the local `SpawnObject` events based on the `NetworkScene` Ids (`peer`)." ] }, { "cell_type": "code", "execution_count": 20, "id": "eef34af9", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ticks_xpeertype_xevent_xarg1_xarg2_xarg3_xobjectid_xcomponentid_xticks_ytype_yevent_yarg1_yarg2_yarg3_yobjectid_ycomponentid_y
06377993138910157012990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject2b0edec0e-fcf7792aTrue7725a971-a369264349018.0637799313741476033Ubiq.Messaging.NetworkSceneAwakeDESKTOP-F1J0MRRSystem Product Name (ASUS)f73fe01b1e21031d49274a1491d1d6b5714c92e9NaNNaN
16377993138910556952990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject243b53edd-7c900c8fFalse7725a971-a369264349018.0637799313741476033Ubiq.Messaging.NetworkSceneAwakeDESKTOP-F1J0MRRSystem Product Name (ASUS)f73fe01b1e21031d49274a1491d1d6b5714c92e9NaNNaN
26377993139354757362990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject1bf000355-ece0ea90False7725a971-a369264349018.0637799313741476033Ubiq.Messaging.NetworkSceneAwakeDESKTOP-F1J0MRRSystem Product Name (ASUS)f73fe01b1e21031d49274a1491d1d6b5714c92e9NaNNaN
36377993139517757222990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject1ba22e255-c3d84eb4False7725a971-a369264349018.0637799313741476033Ubiq.Messaging.NetworkSceneAwakeDESKTOP-F1J0MRRSystem Product Name (ASUS)f73fe01b1e21031d49274a1491d1d6b5714c92e9NaNNaN
46377993139673257092990c448-6701d991Ubiq.Samples.NetworkSpawnerSpawnObject11ad3fc82-d41c3b8fFalse7725a971-a369264349018.0637799313741476033Ubiq.Messaging.NetworkSceneAwakeDESKTOP-F1J0MRRSystem Product Name (ASUS)f73fe01b1e21031d49274a1491d1d6b5714c92e9NaNNaN
\n", "
" ], "text/plain": [ " ticks_x peer type_x \\\n", "0 637799313891015701 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "1 637799313891055695 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "2 637799313935475736 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "3 637799313951775722 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "4 637799313967325709 2990c448-6701d991 Ubiq.Samples.NetworkSpawner \n", "\n", " event_x arg1_x arg2_x arg3_x objectid_x \\\n", "0 SpawnObject 2 b0edec0e-fcf7792a True 7725a971-a3692643 \n", "1 SpawnObject 2 43b53edd-7c900c8f False 7725a971-a3692643 \n", "2 SpawnObject 1 bf000355-ece0ea90 False 7725a971-a3692643 \n", "3 SpawnObject 1 ba22e255-c3d84eb4 False 7725a971-a3692643 \n", "4 SpawnObject 1 1ad3fc82-d41c3b8f False 7725a971-a3692643 \n", "\n", " componentid_x ticks_y type_y event_y \\\n", "0 49018.0 637799313741476033 Ubiq.Messaging.NetworkScene Awake \n", "1 49018.0 637799313741476033 Ubiq.Messaging.NetworkScene Awake \n", "2 49018.0 637799313741476033 Ubiq.Messaging.NetworkScene Awake \n", "3 49018.0 637799313741476033 Ubiq.Messaging.NetworkScene Awake \n", "4 49018.0 637799313741476033 Ubiq.Messaging.NetworkScene Awake \n", "\n", " arg1_y arg2_y \\\n", "0 DESKTOP-F1J0MRR System Product Name (ASUS) \n", "1 DESKTOP-F1J0MRR System Product Name (ASUS) \n", "2 DESKTOP-F1J0MRR System Product Name (ASUS) \n", "3 DESKTOP-F1J0MRR System Product Name (ASUS) \n", "4 DESKTOP-F1J0MRR System Product Name (ASUS) \n", "\n", " arg3_y objectid_y componentid_y \n", "0 f73fe01b1e21031d49274a1491d1d6b5714c92e9 NaN NaN \n", "1 f73fe01b1e21031d49274a1491d1d6b5714c92e9 NaN NaN \n", "2 f73fe01b1e21031d49274a1491d1d6b5714c92e9 NaN NaN \n", "3 f73fe01b1e21031d49274a1491d1d6b5714c92e9 NaN NaN \n", "4 f73fe01b1e21031d49274a1491d1d6b5714c92e9 NaN NaN " ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spawn = df[df.event == \"SpawnObject\"]\n", "awake = df[df.event == \"Awake\"]\n", "f = pd.merge(spawn,awake,how=\"left\",left_on=\"peer\",right_on=\"peer\")\n", "f.head(5)" ] }, { "cell_type": "markdown", "id": "e6da9562", "metadata": {}, "source": [ "We can perform arithmetic operations too. We use [string](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.contains.html) operations, boolean arrays and [size](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.size.html) to find the number of distinct objects spawned by the Oculus Quest." ] }, { "cell_type": "code", "execution_count": 22, "id": "712540f1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "is_quest = f.arg2_y.astype(str).str.contains(\"Quest\")\n", "is_owner = f.arg3_x.astype(bool)\n", "spawned_ids = f[is_quest & is_owner].arg2_x\n", "spawned_ids.unique().size\n" ] }, { "cell_type": "code", "execution_count": null, "id": "98f8ffe4", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.9.4" } }, "nbformat": 4, "nbformat_minor": 5 }