Changeset - f29e26811206
[Not reviewed]
default
0 16 0
Drew Perttula - 6 years ago 2019-06-02 21:19:57
drewp@bigasterisk.com
pmfstats now update at 1hz. some ui improvements to stats lines.
Ignore-this: be2b416f56b6f6604a0af86f5cd69fef
16 files changed with 44 insertions and 40 deletions:
0 comments (0 inline, 0 general)
bin/captureDevice
Show inline comments
 
@@ -22,13 +22,14 @@ from light9.paint.capture import writeCa
 
from greplin.scales.cyclonehandler import StatsHandler
 
from light9.effect.settings import DeviceSettings
 
from light9.collector.collector_client import sendToCollector
 
from rdfdb.patch import Patch
 
from light9.zmqtransport import parseJsonMessage
 

	
 
stats = scales.collection('/webServer', scales.PmfStat('setAttr'))
 
stats = scales.collection('/webServer', scales.PmfStat('setAttr',
 
                                                       recalcPeriod=1))
 

	
 

	
 
class Camera(object):
 

	
 
    def __init__(self, imageUrl):
 
        self.imageUrl = imageUrl
bin/collector
Show inline comments
 
@@ -41,13 +41,13 @@ class Updates(cyclone.websocket.WebSocke
 
    def messageReceived(self, message):
 
        json.loads(message)
 

	
 

	
 
stats = scales.collection(
 
    '/webServer',
 
    scales.PmfStat('setAttr'),
 
    scales.PmfStat('setAttr', recalcPeriod=1),
 
    scales.RecentFpsStat('setAttrFps'),
 
)
 

	
 

	
 
class Attrs(PrettyErrorHandler, cyclone.web.RequestHandler):
 

	
bin/effecteval
Show inline comments
 
@@ -111,13 +111,12 @@ class SongEffectsUpdates(cyclone.websock
 
                    out[-1]['effects'].append({
 
                        'uri': uri,
 
                        'label': self.graph.label(uri)
 
                    })
 
            out[-1]['effects'].sort(key=lambda e: e['uri'])
 
                    
 
                    
 
        self.sendMessage({'songs': out})
 

	
 

	
 
class EffectUpdates(cyclone.websocket.WebSocketHandler):
 
    """
 
    stays alive for the life of the effect page
 
@@ -223,16 +222,16 @@ class App(object):
 
        self.graph = SyncedGraph(networking.rdfdb.url, "effectEval")
 
        self.graph.initiallySynced.addCallback(self.launch).addErrback(
 
            log.error)
 

	
 
        self.stats = scales.collection(
 
            '/',
 
            scales.PmfStat('sendLevels'),
 
            scales.PmfStat('getMusic'),
 
            scales.PmfStat('evals'),
 
            scales.PmfStat('sendOutput'),
 
            scales.PmfStat('sendLevels', recalcPeriod=1),
 
            scales.PmfStat('getMusic', recalcPeriod=1),
 
            scales.PmfStat('evals', recalcPeriod=1),
 
            scales.PmfStat('sendOutput', recalcPeriod=1),
 
            scales.IntStat('errors'),
 
        )
 

	
 
    def launch(self, *args):
 
        log.info('launch')
 
        if self.outputWhere:
bin/effectsequencer
Show inline comments
 
@@ -26,16 +26,16 @@ class App(object):
 

	
 
        self.graph = SyncedGraph(networking.rdfdb.url, "effectSequencer")
 
        self.graph.initiallySynced.addCallback(self.launch)
 

	
 
        self.stats = scales.collection(
 
            '/',
 
            scales.PmfStat('sendLevels'),
 
            scales.PmfStat('getMusic'),
 
            scales.PmfStat('evals'),
 
            scales.PmfStat('sendOutput'),
 
            scales.PmfStat('sendLevels', recalcPeriod=1),
 
            scales.PmfStat('getMusic', recalcPeriod=1),
 
            scales.PmfStat('evals', recalcPeriod=1),
 
            scales.PmfStat('sendOutput', recalcPeriod=1),
 
            scales.IntStat('errors'),
 
        )
 

	
 
    def launch(self, *args):
 
        self.seq = Sequencer(
 
            self.graph,
bin/paintserver
Show inline comments
 
@@ -68,13 +68,13 @@ class App(object):
 
        self.graph = SyncedGraph(networking.rdfdb.url, "paintServer")
 
        self.graph.initiallySynced.addCallback(self.launch).addErrback(
 
            log.error)
 

	
 
        self.stats = scales.collection(
 
            '/',
 
            scales.PmfStat('solve'),
 
            scales.PmfStat('solve', recalcPeriod=1),
 
        )
 

	
 
    def launch(self, *args):
 

	
 
        self.solver = light9.paint.solve.Solver(
 
            self.graph,
light9/ascoltami/player.py
Show inline comments
 
@@ -7,16 +7,18 @@ import time, logging, traceback
 
from gi.repository import Gst
 
from twisted.internet import task
 
from greplin import scales
 

	
 
log = logging.getLogger()
 

	
 
stats = scales.collection('/player',
 
stats = scales.collection(
 
    '/player',
 
                          scales.RecentFpsStat('currentTimeFps'),
 
)
 

	
 

	
 
class Player(object):
 

	
 
    def __init__(self, autoStopOffset=4, onEOS=None):
 
        """autoStopOffset is the number of seconds before the end of
 
        song before automatically stopping (which is really pausing).
 
        onEOS is an optional function to be called when we reach the
light9/ascoltami/webapp.py
Show inline comments
 
@@ -164,9 +164,11 @@ def makeWebApp(app):
 
        (r"/time", timeResource),
 
        (r"/song", songResource),
 
        (r"/songs", songs),
 
        (r"/seekPlayOrPause", seekPlayOrPause),
 
        (r"/output", output),
 
        (r"/go", goButton),
 
        (r'/stats/(.*)', StatsHandler, {'serverName': 'ascoltami'}),
 
        (r'/stats/(.*)', StatsHandler, {
 
            'serverName': 'ascoltami'
 
        }),
 
    ],
 
                                   app=app)
light9/collector/collector_client.py
Show inline comments
 
@@ -9,13 +9,13 @@ from greplin import scales
 
log = logging.getLogger('coll_client')
 

	
 
_zmqClient = None
 

	
 
stats = scales.collection(
 
    '/collectorClient/',
 
    scales.PmfStat('send'),
 
    scales.PmfStat('send', recalcPeriod=1),
 
)
 

	
 

	
 
class TwistedZmqClient(object):
 

	
 
    def __init__(self, service):
light9/collector/output.py
Show inline comments
 
@@ -42,13 +42,13 @@ class Output(object):
 
        if msg != self._lastLoggedMsg:
 
            log.debug(msg)
 
            self._lastLoggedMsg = msg
 

	
 
    _writeSucceed = scales.IntStat('write/succeed')
 
    _writeFail = scales.IntStat('write/fail')
 
    _writeCall = scales.PmfStat('write/call')
 
    _writeCall = scales.PmfStat('write/call', recalcPeriod=1)
 
    _writeFps = scales.RecentFpsStat('write/fps')
 

	
 
    def _write(self, buf: bytes) -> None:
 
        """
 
        write buffer to output hardware (may be throttled if updates are
 
        too fast, or repeated if they are too slow)
 
@@ -166,14 +166,14 @@ class UdmxOld(BackgroundLoopOutput):
 
                log.warn(msg)
 
            raise
 
          
 
                                
 
# out of date
 
class EnttecDmx(BackgroundLoopOutput):
 
    stats = scales.collection('/output/enttecDmx', scales.PmfStat('write'),
 
                              scales.PmfStat('update'))
 
    stats = scales.collection('/output/enttecDmx', scales.PmfStat('write', recalcPeriod=1),
 
                              scales.PmfStat('update', recalcPeriod=1))
 

	
 
    def __init__(self, uri, devicePath='/dev/dmx0', numChannels=80):
 
        sys.path.append("dmx_usb_module")
 
        from dmx import Dmx
 
        self.dev = Dmx(devicePath)
 
        super().__init__(uri)
light9/effect/sequencer.py
Show inline comments
 
@@ -22,29 +22,29 @@ from light9.effect.simple_outputs import
 
from rdfdb.syncedgraph import SyncedGraph
 

	
 
from greplin import scales
 
import imp
 

	
 
log = logging.getLogger('sequencer')
 
stats = scales.collection('/sequencer/',)
 

	
 
updateStats = scales.collection(
 
    '/update/',
 
    scales.PmfStat('s0_getMusic'),
 
    scales.PmfStat('s1_eval'),
 
    scales.PmfStat('s2_sendToWeb'),
 
    scales.PmfStat('s3_send'),
 
    scales.PmfStat('sendPhase'),
 
    scales.PmfStat('updateLoopLatency'),
 
    scales.PmfStat('s0_getMusic', recalcPeriod=1),
 
    scales.PmfStat('s1_eval', recalcPeriod=1),
 
    scales.PmfStat('s2_sendToWeb', recalcPeriod=1),
 
    scales.PmfStat('s3_send', recalcPeriod=1),
 
    scales.PmfStat('sendPhase', recalcPeriod=1),
 
    scales.PmfStat('updateLoopLatency', recalcPeriod=1),
 
    scales.DoubleStat('updateLoopLatencyGoal'),
 
    scales.RecentFpsStat('updateFps'),
 
    scales.DoubleStat('goalFps'),
 
)
 
compileStats = scales.collection(
 
    '/compile/',
 
    scales.PmfStat('graph'),
 
    scales.PmfStat('song'),
 
    scales.PmfStat('graph', recalcPeriod=1),
 
    scales.PmfStat('song', recalcPeriod=1),
 
)
 

	
 

	
 
class Note(object):
 

	
 
    def __init__(self, graph: SyncedGraph, uri: NoteUri, effectevalModule,
 
@@ -153,14 +153,13 @@ class CodeWatcher(object):
 
        # in case we got an event at the start of the write
 
        reactor.callLater(.1, go)
 

	
 

	
 
class Sequencer(object):
 

	
 
    def __init__(
 
            self,
 
    def __init__(self,
 
            graph: SyncedGraph,
 
            sendToCollector: Callable[[DeviceSettings], defer.Deferred],
 
            fps=40):
 
        self.graph = graph
 
        self.fps = fps
 
        updateStats.goalFps = self.fps
light9/web/index.html
Show inline comments
 
@@ -21,15 +21,12 @@
 
         }
 
         div {
 
             display: flex;
 
             justify-content: space-between;
 
             padding: 2px 3px;
 
         }
 
         div:hover {
 
             background: gray;
 
         }
 
         .left {
 
             display: inline-block;
 
             margin-right: 3px;
 
             flex-grow: 1;
 
         }
 
         .window {
light9/web/stats-line.js
Show inline comments
 
@@ -34,12 +34,13 @@ class StatsLine extends LitElement {
 
    }
 
    
 
    static get styles() {
 
        return css`
 
        :host {
 
            border: 2px solid #46a79f;
 
            display: inline-block;
 
        }
 
        table { 
 
            border-collapse: collapse;
 
            background: #000;
 
            color: #ccc;
 
            font-family: sans-serif;
 
@@ -104,23 +105,22 @@ class StatsLine extends LitElement {
 
        const recents = (d, path) => {
 
            const hi = Math.max.apply(null, d.recents);
 
            const scl = 30 / hi;
 
            
 
            const bar = (y) => {
 
                let color;
 
                if (y < hi * .85) {
 
                if (y < d.average) {
 
                    color="#6a6aff";
 
                } else {
 
                    color="#d09e4c";
 
                }
 
                return html`<div class="bar" style="height: ${y * scl}px; background: ${color};"></div>`;
 
            };
 
            return tdWrap(table({
 
                average: rounding(d.average, 3),
 
                recents: html`<div class="recents">${d.recents.map(bar)}</div>`
 
            }, path));
 
            return html`<td>
 
               <div class="recents">${d.recents.map(bar)}</div>
 
               <div>avg=${rounding(d.average ,3)}</div>`;
 

	
 
        };
 
        const pmf = (d, path) => {
 
            return tdWrap(table({
 
                count: d.count,
 
                'values [ms]': html`
light9/web/style.css
Show inline comments
 
@@ -194,6 +194,10 @@ table {
 
}
 

	
 
table.borders td, table.borders th {
 
    border: 1px solid #4a4a4a;
 
    padding: 2px 8px;
 
}
 
hr {
 
    width: 100%;
 
    border-color: #1d3e1d;
 
}
light9/zmqtransport.py
Show inline comments
 
@@ -19,13 +19,13 @@ def parseJsonMessage(msg):
 
    return body['client'], body['clientSession'], settings, body['sendTime']
 

	
 

	
 
def startZmq(port, collector):
 
    stats = scales.collection(
 
        '/zmqServer',
 
        scales.PmfStat('setAttr'),
 
        scales.PmfStat('setAttr', recalcPeriod=1),
 
        scales.RecentFpsStat('setAttrFps'),
 
    )
 

	
 
    zf = ZmqFactory()
 
    addr = 'tcp://*:%s' % port
 
    log.info('creating zmq endpoint at %r', addr)
requirements.txt
Show inline comments
 
@@ -33,13 +33,13 @@ flake8
 
hunter
 
ipdb==0.10.2
 
ipython==5.3.0
 
mypy==0.701
 
typing_extensions
 

	
 
git+http://github.com/drewp/scales.git@3f2609c#egg=scales
 
git+http://github.com/drewp/scales.git@4b011434f7469a442c3fc1d7e81685c0bfa56eeb#egg=scales
 
git+http://github.com/11craft/louie.git@f18bb71010c114eca9c6b88c96453340e3b39454#egg=louie
 
git+http://github.com/webpy/webpy@ace0f8954c28311004b33c7a513c6e40a3c02470#egg=web
 
https://github.com/drewp/cyclone/archive/python3.zip#egg=cyclone
 

	
 
cycloneerr==0.3.0
 
rdfdb==0.19.0
stubs/greplin/scales/__init__.pyi
Show inline comments
 
@@ -113,13 +113,13 @@ class PmfStatDict(UserDict):
 
    def __init__(self, sample: Optional[Any] = ...) -> None: ...
 
    def __getitem__(self, item: Any): ...
 
    def addValue(self, value: Any) -> None: ...
 
    def time(self): ...
 

	
 
class PmfStat(Stat):
 
    def __init__(self, name: Any, _: Optional[Any] = ...) -> None: ...
 
    def __init__(self, name: Any, _: Optional[Any] = ..., recalcPeriod: Optional[float]=20) -> None: ...
 
    def __set__(self, instance: Any, value: Any) -> None: ...
 

	
 
class NamedPmfDict(UserDict):
 
    def __init__(self) -> None: ...
 
    def __getitem__(self, item: Any): ...
 
    def __setitem__(self, key: Any, value: Any) -> None: ...
0 comments (0 inline, 0 general)