Browse Source

Bootstraping repo, and setting up the RPDE notebook.

master
hadware 6 years ago
parent
commit
40c4eb1477
  1. BIN
      numba_examples/pho_a.wav
  2. 464
      numba_examples/rpde.ipynb
  3. 8
      requirements.txt
  4. 107
      sly_examples/json_parser.py
  5. 478
      sly_examples/star.stl
  6. 115
      sly_examples/stl_parser.py

BIN
numba_examples/pho_a.wav

Binary file not shown.

464
numba_examples/rpde.ipynb

@ -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
}

8
requirements.txt

@ -0,0 +1,8 @@
sly
numba
scipy
numpy
tqdm
librosa
jupyter
dataclasses >= 0.7; python_version <'3.7'

107
sly_examples/json_parser.py

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

478
sly_examples/star.stl

@ -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

115
sly_examples/stl_parser.py

@ -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)
Loading…
Cancel
Save