Bootstraping repo, and setting up the RPDE notebook.
This commit is contained in:
Executable
BIN
Binary file not shown.
@@ -0,0 +1,464 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
" <script type=\"text/javascript\">\n",
|
||||
" window.PlotlyConfig = {MathJaxConfig: 'local'};\n",
|
||||
" if (window.MathJax) {MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}\n",
|
||||
" if (typeof require !== 'undefined') {\n",
|
||||
" require.undef(\"plotly\");\n",
|
||||
" requirejs.config({\n",
|
||||
" paths: {\n",
|
||||
" 'plotly': ['https://cdn.plot.ly/plotly-latest.min']\n",
|
||||
" }\n",
|
||||
" });\n",
|
||||
" require(['plotly'], function(Plotly) {\n",
|
||||
" window._Plotly = Plotly;\n",
|
||||
" });\n",
|
||||
" }\n",
|
||||
" </script>\n",
|
||||
" "
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import librosa\n",
|
||||
"import numpy as np\n",
|
||||
"import plotly.express as px\n",
|
||||
"import plotly.graph_objs as go\n",
|
||||
"from plotly.offline import init_notebook_mode, iplot\n",
|
||||
"init_notebook_mode(connected=True)\n",
|
||||
"from numpy.linalg import norm\n",
|
||||
"\n",
|
||||
"from tqdm import tqdm\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### First things first\n",
|
||||
"\n",
|
||||
"_Loading the audio data, and embedding the audio time series_\n",
|
||||
" Our algorithm operates on time series\n",
|
||||
"(here, it's audio, what a coincidence!).\n"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"pycharm": {
|
||||
"name": "#%% md\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# loads the sound data into a float32\n",
|
||||
"data, rate = librosa.core.load(\"pho_a.wav\")\n",
|
||||
"\n",
|
||||
"px.line(data, x=range(len(data)), y=data)\n"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"pycharm": {
|
||||
"name": "#%%\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def embed_time_series(data: np.ndarray, dim: int, tau: int):\n",
|
||||
" \"\"\"This creates an special embedding for the input data. The\n",
|
||||
" output shape of this function is (N, D) with\n",
|
||||
" N = len(data) - (dim - 1) * tau\n",
|
||||
" D = dim\"\"\"\n",
|
||||
" embed_points_nb = data.shape[0] - (dim - 1) * tau\n",
|
||||
" embed_mask = np.arange(embed_points_nb)[:, np.newaxis] + np.arange(dim)\n",
|
||||
" tau_offsets = np.arange(dim) * (tau - 1)\n",
|
||||
" embed_mask = embed_mask + tau_offsets\n",
|
||||
" return data[embed_mask]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 51,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# this creates an embedding of a slice of the time series\n",
|
||||
"ts = embed_time_series(data[:2000], dim=4, tau=22)\n",
|
||||
"print(ts.shape)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"trace = go.Scatter3d(\n",
|
||||
" x=ts[:,0],\n",
|
||||
" y=ts[:,1],\n",
|
||||
" z=ts[:,2],\n",
|
||||
" name=\"Pho_a\",\n",
|
||||
" mode='markers',\n",
|
||||
" marker=dict(\n",
|
||||
" color=\"blue\",\n",
|
||||
" size=2,\n",
|
||||
" symbol='circle',\n",
|
||||
" line=dict(\n",
|
||||
" color='rgb(204, 204, 204)',\n",
|
||||
" width=1\n",
|
||||
" ),\n",
|
||||
" opacity=0.7\n",
|
||||
" )\n",
|
||||
" )\n",
|
||||
"layout = go.Layout(margin=dict(l=0,r=0,b=0,t=0),\n",
|
||||
" scene = dict(\n",
|
||||
" xaxis={\"title\":\"f1\"},\n",
|
||||
" yaxis={\"title\":\"f2\"},\n",
|
||||
" zaxis={\"title\":\"f3\"})\n",
|
||||
" )\n",
|
||||
"fig = go.Figure(data=[trace], layout=layout)\n",
|
||||
"iplot(fig, filename=\"/tmp/pho_a_trajectory.png\")"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"pycharm": {
|
||||
"name": "#%%\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### This is where the fun begins\n",
|
||||
"\n",
|
||||
"Now, let's implement the RPDE algorithm.\n",
|
||||
"I've provided 4 different implementations:\n",
|
||||
"\n",
|
||||
"1. The first one is a plain python implem of the recurrence diagram\n",
|
||||
"2. The second one is numba implem without any parallelization\n",
|
||||
"2. The third one is a naïve parallelized numba implem. It's \"almost\" working,\n",
|
||||
"as it outputs a value close to the actual value, but some race conditions make it\n",
|
||||
"undeterministic.\n",
|
||||
"3. The third one is a fixed parallelized version of the previous numba implementation,\n",
|
||||
"fully adapted to work in parallel"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"pycharm": {
|
||||
"name": "#%% md\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def plain_python_recurrence_histogram(ts: np.ndarray, epsilon: float, t_max: int):\n",
|
||||
" distances_histogram = np.zeros(len(ts))\n",
|
||||
" epsilon = 0.25\n",
|
||||
" for i in tqdm(np.arange(len(ts))):\n",
|
||||
" # finding the first \"out of ball\" index\n",
|
||||
" first_out = len(ts) # security\n",
|
||||
" for j in np.arange(i + 1, len(ts)):\n",
|
||||
" d = norm(ts[i] - ts[j])\n",
|
||||
" if d > epsilon:\n",
|
||||
" first_out = j\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
" # finding the first \"back to the ball\" index\n",
|
||||
" for j in np.arange(first_out + 1, len(ts)):\n",
|
||||
" d = norm(ts[i] - ts[j])\n",
|
||||
" if d < epsilon:\n",
|
||||
" distances_histogram[j - i] += 1\n",
|
||||
" break\n",
|
||||
" return distances_histogram"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"pycharm": {
|
||||
"name": "#%%\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 44,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from numba import jit, float32, prange, int32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 42,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"@jit(int32[:](float32[:,:], float32, int32), nopython=True)\n",
|
||||
"def recurrence_histogram(ts: np.ndarray, epsilon: float, t_max: int):\n",
|
||||
" distances_histogram = np.zeros(len(ts), dtype=np.int32)\n",
|
||||
" for i in np.arange(len(ts)):\n",
|
||||
" # finding the first \"out of ball\" index\n",
|
||||
" first_out = len(ts) # security\n",
|
||||
" for j in np.arange(i + 1, len(ts)):\n",
|
||||
" if t_max > 0 and j - i > t_max:\n",
|
||||
" break\n",
|
||||
" d = norm(ts[i] - ts[j])\n",
|
||||
" if d > epsilon:\n",
|
||||
" first_out = j\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
" # finding the first \"back to the ball\" index\n",
|
||||
" for j in np.arange(first_out + 1, len(ts)):\n",
|
||||
" if 0 < t_max < j - i:\n",
|
||||
" break\n",
|
||||
" d = norm(ts[i] - ts[j])\n",
|
||||
" if d < epsilon:\n",
|
||||
" distances_histogram[j - i] += 1\n",
|
||||
" break\n",
|
||||
" return distances_histogram"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Here, we naively just switched out all \"np.arange\" occurences to numba.prange.\n",
|
||||
"@jit(int32[:](float32[:,:], float32, int32), nopython=True)\n",
|
||||
"def wrong_parallel_recurrence_histogram(ts: np.ndarray, epsilon: float, t_max: int):\n",
|
||||
" distances_histogram = np.zeros(len(ts), dtype=np.int32)\n",
|
||||
" for i in prange(len(ts)):\n",
|
||||
" # finding the first \"out of ball\" index\n",
|
||||
" first_out = len(ts) # security\n",
|
||||
" for j in prange(i + 1, len(ts)):\n",
|
||||
" if t_max > 0 and j - i > t_max:\n",
|
||||
" break\n",
|
||||
" d = norm(ts[i] - ts[j])\n",
|
||||
" if d > epsilon:\n",
|
||||
" first_out = j\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
" # finding the first \"back to the ball\" index\n",
|
||||
" for j in prange(first_out + 1, len(ts)):\n",
|
||||
" if 0 < t_max < j - i:\n",
|
||||
" break\n",
|
||||
" d = norm(ts[i] - ts[j])\n",
|
||||
" if d < epsilon:\n",
|
||||
" distances_histogram[j - i] += 1\n",
|
||||
" break\n",
|
||||
" return distances_histogram"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"pycharm": {
|
||||
"name": "#%%\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 46,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"@jit(int32[:](float32[:,:], float32, int32), parallel=True, nopython=True)\n",
|
||||
"def parallel_recurrence_histogram(ts: np.ndarray, epsilon: float, t_max: int):\n",
|
||||
" return_distances = np.zeros(len(ts), dtype=np.int32)\n",
|
||||
" for i in prange(len(ts)):\n",
|
||||
" # finding the first \"out of ball\" index\n",
|
||||
" first_out = len(ts) # security\n",
|
||||
" for j in np.arange(i + 1, len(ts)):\n",
|
||||
" if t_max > 0 and j - i > t_max:\n",
|
||||
" break\n",
|
||||
" d = norm(ts[i] - ts[j])\n",
|
||||
" if d > epsilon:\n",
|
||||
" first_out = j\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
" # finding the first \"back to the ball\" index\n",
|
||||
" for j in np.arange(first_out + 1, len(ts)):\n",
|
||||
" if t_max > 0 and j - i > t_max:\n",
|
||||
" break\n",
|
||||
" d = norm(ts[i] - ts[j])\n",
|
||||
" if d < epsilon:\n",
|
||||
" return_distances[i] = j - i\n",
|
||||
" break\n",
|
||||
" \n",
|
||||
" # building histogram, can't be parallel\n",
|
||||
" distance_histogram = np.zeros(len(ts), dtype=np.int32)\n",
|
||||
" for i in np.arange(len(ts)):\n",
|
||||
" if return_distances[i] != 0:\n",
|
||||
" distance_histogram[return_distances[i]] += 1\n",
|
||||
" return distance_histogram"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### Running stuff\n",
|
||||
"\n",
|
||||
"Let's run the good ol' python implementation, just to take a look at what does\n",
|
||||
"the algorithm's output look like.\n",
|
||||
"\n",
|
||||
"Also, let's check that the various numba implementations's outputs match the plain\n",
|
||||
"python \"ground truth\"."
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"pycharm": {
|
||||
"name": "#%% md\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"CPU times: user 1min 30s, sys: 67.9 ms, total: 1min 30s\n",
|
||||
"Wall time: 55.6 s\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([0, 0, 0, ..., 0, 0, 0], dtype=int32)"
|
||||
]
|
||||
},
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"distances_histogram = plain_python_recurrence_histogram(ts, 0.12, 10000)\n",
|
||||
"px.line(distances_histogram, x=range(len(distances_histogram)), y=distances_histogram)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"### The ~~hour~~ seconds of truth"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%time plain_python_recurrence_histogram(ts, 0.12, 10000)"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"pycharm": {
|
||||
"name": "#%%\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%time numba_recurrence_histogram(ts, 0.12, 10000)"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"pycharm": {
|
||||
"name": "#%%\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%time parallel_recurrence_histogram(ts, 0.12, 10000)"
|
||||
],
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"pycharm": {
|
||||
"name": "#%%\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 52,
|
||||
"metadata": {
|
||||
"pycharm": {
|
||||
"name": "#%%\n"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"CPU times: user 16min 10s, sys: 3.01 s, total: 16min 13s\n",
|
||||
"Wall time: 6min 59s\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([0, 0, 0, ..., 0, 0, 0], dtype=int32)"
|
||||
]
|
||||
},
|
||||
"execution_count": 52,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"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.7.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
sly
|
||||
numba
|
||||
scipy
|
||||
numpy
|
||||
tqdm
|
||||
librosa
|
||||
jupyter
|
||||
dataclasses >= 0.7; python_version <'3.7'
|
||||
@@ -0,0 +1,107 @@
|
||||
from sly import Lexer, Parser
|
||||
import pprint
|
||||
|
||||
"""
|
||||
Implementation with SLY of a very simple JSON parser.
|
||||
Little reminder: here's the grammar
|
||||
|
||||
json := object | array
|
||||
object := '{' members '}'
|
||||
members := pair | pair ',' members
|
||||
array := '[' elements ']'
|
||||
elements := value | value "," elements
|
||||
pair := STRING ':' value
|
||||
value := STRING | INTEGER | FLOAT | object | array
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class JSONLexer(Lexer):
|
||||
tokens = {"FLOAT", "INTEGER", "STRING"}
|
||||
|
||||
literals = {'{', '}', '[', ']', ',', ':'}
|
||||
ignore = " \t\n"
|
||||
|
||||
@_(r"\".*?\"")
|
||||
def STRING(self, t):
|
||||
t.value = t.value.strip("\"")
|
||||
return t
|
||||
|
||||
@_(r"\d+\.\d*")
|
||||
def FLOAT(self, t):
|
||||
t.value = float(t.value)
|
||||
return t
|
||||
|
||||
@_(r"\d+")
|
||||
def INTEGER(self, t):
|
||||
t.value = int(t.value)
|
||||
return t
|
||||
|
||||
|
||||
class JSONParser(Parser):
|
||||
tokens = JSONLexer.tokens
|
||||
start = "json"
|
||||
|
||||
@_('object',
|
||||
'array')
|
||||
def json(self, p):
|
||||
return p[0]
|
||||
|
||||
@_('"{" members "}"')
|
||||
def object(self, p):
|
||||
return {key: value for key, value in p.members}
|
||||
|
||||
@_('pair')
|
||||
def members(self, p):
|
||||
return [p.pair]
|
||||
|
||||
@_('pair "," members')
|
||||
def members(self, p):
|
||||
return [p.pair] + p.members
|
||||
|
||||
@_('STRING ":" value')
|
||||
def pair(self, p):
|
||||
return p.STRING, p.value
|
||||
|
||||
@_('"[" elements "]"')
|
||||
def array(self, p):
|
||||
return p.elements
|
||||
|
||||
@_('value')
|
||||
def elements(self, p):
|
||||
return [p.value]
|
||||
|
||||
@_('value "," elements')
|
||||
def elements(self, p):
|
||||
return [p.value] + p.elements
|
||||
|
||||
@_('STRING',
|
||||
'INTEGER',
|
||||
'FLOAT',
|
||||
'object',
|
||||
'array')
|
||||
def value(self, p):
|
||||
return p[0]
|
||||
|
||||
def error(self, p):
|
||||
raise ValueError("Parsing error at token %s" % str(p))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
lexer = JSONLexer()
|
||||
parser = JSONParser()
|
||||
json_text = """{"menu": {
|
||||
"id": "file",
|
||||
"value": "File",
|
||||
"popup": {
|
||||
"menuitem": [
|
||||
{"value": "New", "onclick": "CreateNewDoc()"},
|
||||
{"value": "Open", "onclick": "OpenDoc()"},
|
||||
{"value": "Close", "onclick": "CloseDoc()"}
|
||||
],
|
||||
"delay" : 1.5
|
||||
}
|
||||
}}
|
||||
"""
|
||||
result = parser.parse(lexer.tokenize(json_text))
|
||||
pprint.pprint(result)
|
||||
@@ -0,0 +1,478 @@
|
||||
solid Star
|
||||
facet normal 0 -1 0
|
||||
outer loop
|
||||
vertex 0.83404 0 0.694596
|
||||
vertex 0.36904 0 1.5
|
||||
vertex 1.78814e-006 0 0.75
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 -1 0
|
||||
outer loop
|
||||
vertex 0.36904 0 1.5
|
||||
vertex 0.83404 0 2.3054
|
||||
vertex 1.78814e-006 0 2.25
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 -1 0
|
||||
outer loop
|
||||
vertex 1.29904 0 0
|
||||
vertex 1.76404 0 0.694596
|
||||
vertex 0.83404 0 0.694596
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 -1 0
|
||||
outer loop
|
||||
vertex 0.83404 0 2.3054
|
||||
vertex 1.76404 0 2.3054
|
||||
vertex 1.29904 0 3
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 -1 0
|
||||
outer loop
|
||||
vertex 1.76404 0 0.694596
|
||||
vertex 2.59808 0 0.75
|
||||
vertex 2.22904 0 1.5
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 -1 0
|
||||
outer loop
|
||||
vertex 2.22904 0 1.5
|
||||
vertex 2.59808 0 2.25
|
||||
vertex 1.76404 0 2.3054
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 -1 0
|
||||
outer loop
|
||||
vertex 0.83404 0 0.694596
|
||||
vertex 0.83404 0 2.3054
|
||||
vertex 0.36904 0 1.5
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 -1 0
|
||||
outer loop
|
||||
vertex 0.83404 0 0.694596
|
||||
vertex 1.76404 0 0.694596
|
||||
vertex 0.83404 0 2.3054
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 -1 0
|
||||
outer loop
|
||||
vertex 1.76404 0 0.694596
|
||||
vertex 2.22904 0 1.5
|
||||
vertex 0.83404 0 2.3054
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 -1 0
|
||||
outer loop
|
||||
vertex 2.22904 0 1.5
|
||||
vertex 1.76404 0 2.3054
|
||||
vertex 0.83404 0 2.3054
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.897262 0 -0.441498
|
||||
outer loop
|
||||
vertex 0.36904 0 1.5
|
||||
vertex 1.78814e-006 0 2.25
|
||||
vertex 0.36904 0.25 1.5
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.897262 0 -0.441498
|
||||
outer loop
|
||||
vertex 1.78814e-006 0 2.25
|
||||
vertex 1.78814e-006 0.25 2.25
|
||||
vertex 0.36904 0.25 1.5
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0662822 0 0.997801
|
||||
outer loop
|
||||
vertex 1.78814e-006 0 2.25
|
||||
vertex 0.83404 0 2.3054
|
||||
vertex 1.78814e-006 0.25 2.25
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0662822 0 0.997801
|
||||
outer loop
|
||||
vertex 0.83404 0 2.3054
|
||||
vertex 0.83404 0.25 2.3054
|
||||
vertex 1.78814e-006 0.25 2.25
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.83098 0 0.556302
|
||||
outer loop
|
||||
vertex 0.83404 0 2.3054
|
||||
vertex 1.29904 0 3
|
||||
vertex 0.83404 0.25 2.3054
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.83098 0 0.556302
|
||||
outer loop
|
||||
vertex 1.29904 0 3
|
||||
vertex 1.29904 0.25 3
|
||||
vertex 0.83404 0.25 2.3054
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.83098 0 0.556303
|
||||
outer loop
|
||||
vertex 1.76404 0 2.3054
|
||||
vertex 1.76404 0.25 2.3054
|
||||
vertex 1.29904 0 3
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.83098 0 0.556303
|
||||
outer loop
|
||||
vertex 1.29904 0 3
|
||||
vertex 1.76404 0.25 2.3054
|
||||
vertex 1.29904 0.25 3
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0662822 0 0.997801
|
||||
outer loop
|
||||
vertex 2.59808 0 2.25
|
||||
vertex 2.59808 0.25 2.25
|
||||
vertex 1.76404 0 2.3054
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0662822 0 0.997801
|
||||
outer loop
|
||||
vertex 1.76404 0 2.3054
|
||||
vertex 2.59808 0.25 2.25
|
||||
vertex 1.76404 0.25 2.3054
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.897262 0 -0.441498
|
||||
outer loop
|
||||
vertex 2.22904 0 1.5
|
||||
vertex 2.22904 0.25 1.5
|
||||
vertex 2.59808 0 2.25
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.897262 0 -0.441498
|
||||
outer loop
|
||||
vertex 2.59808 0 2.25
|
||||
vertex 2.22904 0.25 1.5
|
||||
vertex 2.59808 0.25 2.25
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.897262 0 0.441498
|
||||
outer loop
|
||||
vertex 2.59808 0 0.75
|
||||
vertex 2.59808 0.25 0.75
|
||||
vertex 2.22904 0 1.5
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.897262 0 0.441498
|
||||
outer loop
|
||||
vertex 2.22904 0 1.5
|
||||
vertex 2.59808 0.25 0.75
|
||||
vertex 2.22904 0.25 1.5
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0662821 0 -0.997801
|
||||
outer loop
|
||||
vertex 1.76404 0 0.694596
|
||||
vertex 1.76404 0.25 0.694596
|
||||
vertex 2.59808 0 0.75
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0662821 0 -0.997801
|
||||
outer loop
|
||||
vertex 2.59808 0 0.75
|
||||
vertex 1.76404 0.25 0.694596
|
||||
vertex 2.59808 0.25 0.75
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.83098 0 -0.556302
|
||||
outer loop
|
||||
vertex 1.29904 0 0
|
||||
vertex 1.29904 0.25 0
|
||||
vertex 1.76404 0 0.694596
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.83098 0 -0.556302
|
||||
outer loop
|
||||
vertex 1.76404 0 0.694596
|
||||
vertex 1.29904 0.25 0
|
||||
vertex 1.76404 0.25 0.694596
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.83098 0 -0.556302
|
||||
outer loop
|
||||
vertex 1.29904 0 0
|
||||
vertex 0.83404 0 0.694596
|
||||
vertex 1.29904 0.25 0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.83098 0 -0.556302
|
||||
outer loop
|
||||
vertex 0.83404 0 0.694596
|
||||
vertex 0.83404 0.25 0.694596
|
||||
vertex 1.29904 0.25 0
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.066282 0 -0.997801
|
||||
outer loop
|
||||
vertex 0.83404 0 0.694596
|
||||
vertex 1.78814e-006 0 0.75
|
||||
vertex 0.83404 0.25 0.694596
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.066282 0 -0.997801
|
||||
outer loop
|
||||
vertex 1.78814e-006 0 0.75
|
||||
vertex 1.78814e-006 0.25 0.75
|
||||
vertex 0.83404 0.25 0.694596
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.897262 0 0.441498
|
||||
outer loop
|
||||
vertex 1.78814e-006 0 0.75
|
||||
vertex 0.36904 0 1.5
|
||||
vertex 1.78814e-006 0.25 0.75
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.897262 0 0.441498
|
||||
outer loop
|
||||
vertex 0.36904 0 1.5
|
||||
vertex 0.36904 0.25 1.5
|
||||
vertex 1.78814e-006 0.25 0.75
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 1 0
|
||||
outer loop
|
||||
vertex 0.48049 0.35 1.5
|
||||
vertex 0.155677 0.35 2.16012
|
||||
vertex 0.889765 0.35 2.20888
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 1 0
|
||||
outer loop
|
||||
vertex 0.889765 0.35 0.791115
|
||||
vertex 0.155677 0.35 0.839879
|
||||
vertex 0.48049 0.35 1.5
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 1 0
|
||||
outer loop
|
||||
vertex 0.889765 0.35 2.20888
|
||||
vertex 1.29904 0.35 2.82024
|
||||
vertex 1.70831 0.35 2.20888
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 1 0
|
||||
outer loop
|
||||
vertex 1.29904 0.35 0.179758
|
||||
vertex 0.889765 0.35 0.791115
|
||||
vertex 1.70831 0.35 0.791115
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 1 0
|
||||
outer loop
|
||||
vertex 2.11759 0.35 1.5
|
||||
vertex 1.70831 0.35 2.20888
|
||||
vertex 2.4424 0.35 2.16012
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 1 0
|
||||
outer loop
|
||||
vertex 1.70831 0.35 0.791115
|
||||
vertex 2.11759 0.35 1.5
|
||||
vertex 2.4424 0.35 0.839879
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 1 0
|
||||
outer loop
|
||||
vertex 0.889765 0.35 0.791115
|
||||
vertex 0.48049 0.35 1.5
|
||||
vertex 0.889765 0.35 2.20888
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 1 0
|
||||
outer loop
|
||||
vertex 0.889765 0.35 0.791115
|
||||
vertex 0.889765 0.35 2.20888
|
||||
vertex 1.70831 0.35 2.20888
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 1 0
|
||||
outer loop
|
||||
vertex 0.889765 0.35 0.791115
|
||||
vertex 1.70831 0.35 2.20888
|
||||
vertex 2.11759 0.35 1.5
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0 1 0
|
||||
outer loop
|
||||
vertex 0.889765 0.35 0.791115
|
||||
vertex 2.11759 0.35 1.5
|
||||
vertex 1.70831 0.35 0.791115
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.63446 0.707107 0.312186
|
||||
outer loop
|
||||
vertex 1.78814e-006 0.25 0.75
|
||||
vertex 0.36904 0.25 1.5
|
||||
vertex 0.155677 0.35 0.839879
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.63446 0.707107 0.312186
|
||||
outer loop
|
||||
vertex 0.36904 0.25 1.5
|
||||
vertex 0.48049 0.35 1.5
|
||||
vertex 0.155677 0.35 0.839879
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.63446 0.707107 -0.312186
|
||||
outer loop
|
||||
vertex 0.36904 0.25 1.5
|
||||
vertex 0.155677 0.35 2.16012
|
||||
vertex 0.48049 0.35 1.5
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.634459 0.707107 -0.312186
|
||||
outer loop
|
||||
vertex 0.36904 0.25 1.5
|
||||
vertex 1.78814e-006 0.25 2.25
|
||||
vertex 0.155677 0.35 2.16012
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0468686 0.707106 0.705552
|
||||
outer loop
|
||||
vertex 1.78814e-006 0.25 2.25
|
||||
vertex 0.83404 0.25 2.3054
|
||||
vertex 0.155677 0.35 2.16012
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0468684 0.707107 0.705552
|
||||
outer loop
|
||||
vertex 0.83404 0.25 2.3054
|
||||
vertex 0.889765 0.35 2.20888
|
||||
vertex 0.155677 0.35 2.16012
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.587592 0.707107 0.393365
|
||||
outer loop
|
||||
vertex 0.83404 0.25 2.3054
|
||||
vertex 1.29904 0.25 3
|
||||
vertex 1.29904 0.35 2.82024
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.587591 0.707107 0.393365
|
||||
outer loop
|
||||
vertex 0.83404 0.25 2.3054
|
||||
vertex 1.29904 0.35 2.82024
|
||||
vertex 0.889765 0.35 2.20888
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.587591 0.707107 0.393365
|
||||
outer loop
|
||||
vertex 1.76404 0.25 2.3054
|
||||
vertex 1.29904 0.35 2.82024
|
||||
vertex 1.29904 0.25 3
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.587591 0.707107 0.393365
|
||||
outer loop
|
||||
vertex 1.76404 0.25 2.3054
|
||||
vertex 1.70831 0.35 2.20888
|
||||
vertex 1.29904 0.35 2.82024
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0468686 0.707106 0.705552
|
||||
outer loop
|
||||
vertex 2.59808 0.25 2.25
|
||||
vertex 2.4424 0.35 2.16012
|
||||
vertex 1.76404 0.25 2.3054
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0468684 0.707107 0.705552
|
||||
outer loop
|
||||
vertex 1.76404 0.25 2.3054
|
||||
vertex 2.4424 0.35 2.16012
|
||||
vertex 1.70831 0.35 2.20888
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.63446 0.707107 -0.312187
|
||||
outer loop
|
||||
vertex 2.22904 0.25 1.5
|
||||
vertex 2.4424 0.35 2.16012
|
||||
vertex 2.59808 0.25 2.25
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.63446 0.707107 -0.312187
|
||||
outer loop
|
||||
vertex 2.22904 0.25 1.5
|
||||
vertex 2.11759 0.35 1.5
|
||||
vertex 2.4424 0.35 2.16012
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.63446 0.707106 0.312187
|
||||
outer loop
|
||||
vertex 2.59808 0.25 0.75
|
||||
vertex 2.4424 0.35 0.839879
|
||||
vertex 2.22904 0.25 1.5
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.63446 0.707107 0.312187
|
||||
outer loop
|
||||
vertex 2.22904 0.25 1.5
|
||||
vertex 2.4424 0.35 0.839879
|
||||
vertex 2.11759 0.35 1.5
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0468685 0.707107 -0.705552
|
||||
outer loop
|
||||
vertex 1.76404 0.25 0.694596
|
||||
vertex 2.4424 0.35 0.839879
|
||||
vertex 2.59808 0.25 0.75
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.0468684 0.707107 -0.705552
|
||||
outer loop
|
||||
vertex 1.76404 0.25 0.694596
|
||||
vertex 1.70831 0.35 0.791115
|
||||
vertex 2.4424 0.35 0.839879
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.587591 0.707107 -0.393365
|
||||
outer loop
|
||||
vertex 1.76404 0.25 0.694596
|
||||
vertex 1.29904 0.35 0.179758
|
||||
vertex 1.70831 0.35 0.791115
|
||||
endloop
|
||||
endfacet
|
||||
facet normal 0.587592 0.707107 -0.393365
|
||||
outer loop
|
||||
vertex 1.29904 0.25 0
|
||||
vertex 1.29904 0.35 0.179758
|
||||
vertex 1.76404 0.25 0.694596
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.587592 0.707107 -0.393365
|
||||
outer loop
|
||||
vertex 0.83404 0.25 0.694596
|
||||
vertex 0.889765 0.35 0.791115
|
||||
vertex 1.29904 0.35 0.179758
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.587592 0.707107 -0.393365
|
||||
outer loop
|
||||
vertex 1.29904 0.25 0
|
||||
vertex 0.83404 0.25 0.694596
|
||||
vertex 1.29904 0.35 0.179758
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0468684 0.707107 -0.705552
|
||||
outer loop
|
||||
vertex 0.83404 0.25 0.694596
|
||||
vertex 0.155677 0.35 0.839879
|
||||
vertex 0.889765 0.35 0.791115
|
||||
endloop
|
||||
endfacet
|
||||
facet normal -0.0468685 0.707107 -0.705552
|
||||
outer loop
|
||||
vertex 0.83404 0.25 0.694596
|
||||
vertex 1.78814e-006 0.25 0.75
|
||||
vertex 0.155677 0.35 0.839879
|
||||
endloop
|
||||
endfacet
|
||||
endsolid Star
|
||||
@@ -0,0 +1,115 @@
|
||||
import pprint
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Tuple
|
||||
|
||||
from sly import Lexer, Parser
|
||||
|
||||
|
||||
@dataclass
|
||||
class Vertex:
|
||||
coords: Tuple[float, float, float]
|
||||
|
||||
def __repr__(self):
|
||||
return "VERTEX(%f,%f,%f)" % self.coords
|
||||
|
||||
|
||||
@dataclass
|
||||
class Facet:
|
||||
vertices: Tuple[Vertex, Vertex, Vertex]
|
||||
normal: Vertex
|
||||
|
||||
def __repr__(self):
|
||||
return "\t FACET({normal})\n\t\t{vertices}".format(
|
||||
normal=repr(self.normal),
|
||||
vertices="\n\t\t".join(repr(vertex) for vertex in self.vertices)
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Solid:
|
||||
name: str
|
||||
facets: List[Facet]
|
||||
|
||||
def __repr__(self):
|
||||
return "SOLID({name})\n{facets}\n".format(
|
||||
name=self.name,
|
||||
facets="\n".join(repr(facet) for facet in self.facets)
|
||||
)
|
||||
|
||||
|
||||
class STLLexer(Lexer):
|
||||
tokens = {"SOLID_START", "SOLID_END",
|
||||
"FACET_START", "FACET_END", "NAME_LITERAL",
|
||||
"LOOP_START", "LOOP_END",
|
||||
"NAME_LITERAL", "VERTEX_TAG", "FLOAT"}
|
||||
|
||||
@_(r"[ \t\n]+")
|
||||
def ignore_whitespace(self, t):
|
||||
self.lineno += t.value.count("\n")
|
||||
|
||||
SOLID_START = r"solid"
|
||||
SOLID_END = r"endsolid"
|
||||
FACET_START = r"facet normal"
|
||||
FACET_END = r"endfacet"
|
||||
LOOP_START = r"outer loop"
|
||||
LOOP_END = r"endloop"
|
||||
VERTEX_TAG = r"vertex"
|
||||
|
||||
@_("[+-]?\d+(\.\d*(e[+-]?\d+)?)?")
|
||||
def FLOAT(self, t):
|
||||
t.value = float(t.value)
|
||||
return t
|
||||
|
||||
NAME_LITERAL = r"\w+"
|
||||
|
||||
|
||||
class STLParser(Parser):
|
||||
tokens = STLLexer.tokens
|
||||
start = "stl"
|
||||
|
||||
@_("solid")
|
||||
def stl(self, p):
|
||||
return p.solid
|
||||
|
||||
@_("SOLID_START NAME_LITERAL facets_list SOLID_END")
|
||||
@_("SOLID_START NAME_LITERAL facets_list SOLID_END NAME_LITERAL")
|
||||
def solid(self, p):
|
||||
return Solid(name=p[1], facets=p.facets_list)
|
||||
|
||||
@_("facet")
|
||||
def facets_list(self, p):
|
||||
return [p.facet]
|
||||
|
||||
@_("facet facets_list")
|
||||
def facets_list(self, p):
|
||||
return [p.facet] + p.facets_list
|
||||
|
||||
@_("FACET_START triplet loop FACET_END")
|
||||
def facet(self, p):
|
||||
return Facet(vertices=p.loop, normal=Vertex(p.triplet))
|
||||
|
||||
@_("LOOP_START vertex vertex vertex LOOP_END")
|
||||
def loop(self, p):
|
||||
return p[1], p[2], p[3]
|
||||
|
||||
@_("VERTEX_TAG triplet")
|
||||
def vertex(self, p):
|
||||
return Vertex(p.triplet)
|
||||
|
||||
@_("FLOAT FLOAT FLOAT")
|
||||
def triplet(self, p):
|
||||
return p[0], p[1], p[2]
|
||||
|
||||
def error(self, token):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
lexer = STLLexer()
|
||||
parser = STLParser()
|
||||
|
||||
with open("star.stl") as stl_file:
|
||||
# pprint.pprint(list(lexer.tokenize(stl_file.read())))
|
||||
solid = parser.parse(lexer.tokenize(stl_file.read()))
|
||||
|
||||
print(solid)
|
||||
Reference in New Issue
Block a user