Everyday graphic

Not sure how practical it is, but will try and upload a new graphic everyday .. to start with will probably be quite basic ๐Ÿ™‚ Here is the first, some moving granual thingies.. Shoebot code:
import random
from math import sin, cos

size(800, 800)
colours=ximport("colors")


def draw():
    background(colors.aliceblue())
    scale(1, 1)
    nostroke()
    fill(0.1, 0.2, 0.3)

    random.seed(0)
    for y in xrange(0, HEIGHT, 80):
        wiggle = sin(FRAME * 0.1)
        xs = 2.0 + (cos(y * 0.1) + sin(y) * 8.1)

        distance = 1.0 / HEIGHT * y
        fill(1.0, 1.0-distance, 0, distance)
        for x in xrange(0, 60):
            xpos = ((xs * FRAME-x * 40) % (WIDTH + 40)) - 20
            circle(xpos, y + (wiggle * random.random() * 20.0), 20 + (wiggle * 2.0) * distance * 8.0)

        #xs = -sin(y) * 4.0
        #for x in xrange(0, 60):
        #    circle(WIDTH-xs * WIDTH - FRAME + x * 40, y+40, 20)
To run this, install shoebot and type: sbot -w granuals.sbot

Belated post on libregraphics meeting 2014

Here is my very late post on LGM 2014! Back in April I went to Leipzig for my first in-the-flesh meeting of Shoebot devs .. I met with Ricardo + to collaborate on a workshop on shoebot. To make it more fun we hadn't decided what to do it on ! In the anarchic OSP (open source publishing) house we came with a plan to get people making examples for shoebot. Luckily Ricardo had done a lot of this sort of thing before so did most of the talking, then I showed off some bots - evolution, spirals and also the livecoding work. Overall the workshop seemed to go over well; we got a bunch of examples, and there was even a plugin for sublime text !

Things that came out of the workshop:

People want an integrated editor - this is OK, since the IDE still exists. Differences between the Nodebox/Shoebot API and Cairo are not always intuitive. Livecoding is cool! Shoebot 2 ... or something else ? Going forward, it might be best to take the Nodebox approach and build something new based on these lessons, I'm not sure exactly what yet. What is the most intuitive API, how can we be close to standard APIs.

Non Shoebot Stuff

Outside of the workshops and talks there were plenty of time to drink and chat - apart from talking the head off of one of the mypaint guys I learned quite a lot about OSP off Sarah Magnan and Brendan Howell .. which made me regret missing many of their talks, including Brendans on the screenless office. Leipzig was a really great city to visit, the venue for LGM was particularly impressive being inside an old church that the East Germans repurposed to a university. Importantly for me I learned about the "kebab circle" - the ring of gentrification moving from the inside of the city outwards (beyond which you can still buy kebabs). With any luck LGM will be able to make it next year and meet everyone again.

Simple python spectrograph with shoebot

Seeing"Realtime FFT Graph of Audio WAV File or Microphone Input with Python..."ย  on python.reddit.com reminded me of one I'd built in python with shoebot. While it works OK, I feel like I'm missing a higher level audio library (especially having seen Minim, for C++ and Java). To run it in shoebot:
sbot -w audiobot.bot

audiobot.bot

# Major library imports
import atexit
import pyaudio
from numpy import zeros, short, fromstring, array
from numpy.fft import fft

NUM_SAMPLES = 512
SAMPLING_RATE = 11025

def setup():
    size(350, 260)
    speed(SAMPLING_RATE / NUM_SAMPLES)

_stream = None

def read_fft():
    global _stream
    pa = None

    def cleanup_audio():
        if _stream:
            _stream.stop_stream()
            _stream.close()
        pa.terminate()

    if _stream is None:
        pa = pyaudio.PyAudio()
        _stream = pa.open(format=pyaudio.paInt16, channels=1,
                           rate=SAMPLING_RATE,
                           input=True, frames_per_buffer=NUM_SAMPLES)
        atexit.register(cleanup_audio)

    audio_data  = fromstring(_stream.read(NUM_SAMPLES), dtype=short)
    normalized_data = audio_data / 32768.0

    return fft(normalized_data)[1:1+NUM_SAMPLES/2]

def flatten_fft(scale = 1.0):
    """
    Produces a nicer graph, I'm not sure if this is correct
    """
    for i, v in enumerate(read_fft()):
        yield scale * (i * v) / NUM_SAMPLES

def triple(audio):
    '''return bass/mid/treble'''
    c = audio.copy()
    c.resize(3, 255 / 3)
    return c

def draw():
    '''Draw 3 different colour graphs'''
    global NUM_SAMPLES
    audio = array(list(flatten_fft(scale = 80)))
    freqs = len(audio)
    bass, mid, treble = triple(audio)

    colours = (0.5, 1.0, 0.5), (1, 1, 0), (1, 0.2, 0.5)

    fill(0, 0, 1)
    rect(0, 0, WIDTH, 400)
    translate(50, 200)

    for spectrum, col in zip((bass, mid, treble), colours):
        fill(col)
        for i, s in enumerate(spectrum):
            rect(i, 0, 1, -abs(s))
        else:
            translate(i, 0)

    audio = array(list(flatten_fft(scale = 80)))

Processing with Jython and Nodebox/Shoebot libraries

Update: 26/April/2010 Problems I was having with incomplete images have been fixed in the current version of the web library, available in shoebots mecurial repository.
Using Processing from Jython is a promising idea, so I took the base from this post on backspaces.net where they explained how to use Jython and built on it a little. This is great as Shoebot/Nodebox have great libraries for data manipulation, while processing is more focused on graphics. The result is the attached Netbeans project which demonstrates using the nodebox web library andย  drawing with processing.

Slowcessing

The glue code is in slowcessing.py Theres a special version of PApplet (PJApplet), and 'pj_frame' which can put this in a JFrame. The other method is 'shoebot_imports' adds the shoebot imports to the library path In case anybody doesn't want to download the whole project, heres the code: imagestrip.py
from slowcessing import PJApplet, pj_frame, shoebot_imports
from processing.opengl import *

shoebot_imports()
import web
import thread

class ImageQueue(list):
    """
    Download images in the background and add them to a list
    """
    def __init__(self, search, size):
        list.__init__(self)
        self._search = search
        self._image_size = size
        thread.start_new_thread(self._get_images, ())

    def _image_downloaded(self, path):
        p = PJApplet()
        self.append(p.loadImage(path))

    def _get_images(self):
        for image in self._search:
            image.download(self._image_size, asynchronous=False)
            self._image_downloaded(image.path)

class WebTest (PJApplet):
  def setup(self):
    self.size(400, 400, self.P3D)
    self.images = ImageQueue(web.morguefile.search("sweets", max=1), size='small')

  def draw(self):
    self.background(0);
    y = (self.height * 0.2) - self.mouseY * (len(self.images) * 0.58)
    for image in self.images:
        self.image(image, 20, y)
        y += image.height

if __name__ == '__main__':
    pj_frame(WebTest)
slowcessing.py
from javax.swing import JFrame

from processing.core import PApplet

class PJApplet(PApplet):
  # rqd due to PApplet's using frameRate and frameRate(n) etc.
  def getField(self, name):
      return PApplet.getDeclaredField(name).get(self)

def pj_frame(pj_applet, **kwargs):
    from time import sleep

    frame = JFrame(kwargs.get('title', 'Slowcessing'))
    frame.defaultCloseOperation = kwargs.get('defaultCloseOperation', JFrame.EXIT_ON_CLOSE)
    frame.resizable = kwargs.get('resizable', False)

    panel = pj_applet()
    frame.add(panel)
    panel.init()

    while panel.defaultSize and not panel.finished:
        sleep(0.5)

    frame.pack()
    frame.visible = 1

    return frame

def shoebot_imports():
    """
    Allow import of the shoebot libraries
    """
    ##APP = 'shoebot'
    import sys
    DIR = sys.prefix + '/share/shoebot/locale'
    ##locale.setlocale(locale.LC_ALL, '')
    ##gettext.bindtextdomain(APP, DIR)
    ###gettext.bindtextdomain(APP)
    ##gettext.textdomain(APP)
    ##_ = gettext.gettext

    LIB_DIR = sys.prefix + '/share/shoebot/lib'
    sys.path.append(LIB_DIR)

Problems

There are some things I couldn't work : The callback to say that images have been downloaded happens before the whole file is available, for this reason there are grey parts on the images on the first run.

Nodebox web...

While I did manage to fix things to get this working in Jython and get Morguefile working, I had a lot of trouble understanding what was going on here. Cheers to Tom De Smedt for fixing these the areas of nodebox-web that I couldn't ๐Ÿ™‚

Processing...

Some parts of PApplet to do with image loading seem to be static, which may also explain problems I was getting with reentrancy.

Download

If you want to have a go, you'll need to: Install Netbeans 6.8 Install Jython (2.5 or higher) by installing the Netbeans python module Add python to the path (if using Netbeans it's copy is where Netbeans is installed). Get nodebox-web by downloading shoebot and install it with:
jython setup.py install
In Netbeans, add all the jars in the processing\lib folder to the Jython classpath, and opengl\library\opengl.jar Download the PythonOnProcessing (tested on Netbeans 6.8)