procgraph 1.1 documentation

The ProcGraph tutorial

Contents

The ProcGraph tutorial

Welcome to the ProcGraph tutorial! This tutorial will guide you through the first steps with ProcGraph, from the basic syntax, up to the recommended design patterns and how to document your creations.

Even though it is fine to read this on the web, cutting&paste the examples to your terminal or editor, it is advised that you download the ProcGraph source code. There, in the directory docs/tutorial, you will find all these scripts and resources in separate files ready to run.

Basic syntax

The basic ProcGraph metaphors are blocks and signals. A model is an interconnection of blocks, and it is specified using ProcGraph‘s model language. This language is very much inspired by ASCII art; the idea being that a graphical representation of blocks is useful to understand your models, yet, the fact that everything is plain text makes the source clear, and editing fast.

Enough words! The first model that we consider can be found in the file tutorial00_basics.pg:

# Read from a .mp4 file, write to a .avi file.
|mplayer file="coastguard.mp4"| --> |mencoder vbitrate=1000 file="coastguard00.avi"|

This model is composed by two blocks: Block mplayer and Block mencoder. An instantiation of a block is specified using the syntax |block-type param=value|, with multiple parameters allowed. A complete list of the blocks, with documentation on what parameters they accept, is available at ProcGraph core blocks; this tutorial will explain also how to create your own blocks.

The two blocks are connected by the arrow -->. This means that all signals from the first block flow into the second. In this case, Block mplayer has only one output, and Block mencoder has only one input, but we will see that blocks can be very flexible in how many signals they accept or produce.

It’s time to run this model. As you might have guessed, the model transcodes one video file to another format. Albeit ProcGraph is pretty much data-agnostic, most of the examples involve reading and manipulating a video, as it is fun to have an immediate visual feedback of what you are doing. All the scripts refer to the file coastguard.mp4, which should be in your current directory; you can, of course, use any video you want.

ProcGraph has both an API to run modules from inside your Python code (see Executing ProcGraph models), and a command-line program that runs the models for you, called pg. In this tutorial, we are going to use the latter. If ProcGraph is properly installed, you can run a model using the syntax pg <model name>. If you saved the above model to a file tutorial00_basics.pg, then you can run it using:

$ pg tutorial00_basics

The expected output is coastguard00.avi.

Naming signals

We will see that ProcGraph models can become quite complex. In particular, you are not limited to have only one series of blocks; you can process the same signal in a parallel pathway. So one necessary ability is being able to give names to signals so that you can refer to them later.

You can see an example of this in tutorial01_signals.pg:

# Model demonstrating the syntax for naming signals.
|mplayer file="coastguard.mp4"| --> rgb

   rgb --> |mencoder vbitrate=100 file="coastguard01.avi"|

Here, we give the name rgb to the output of the first block. Then, we can refer to this signal later, and use it as input to the second block.

In general, if a block has multiple outputs, you would use the syntax:

|block| --> signal1, signal2, signal3

to give the various outputs names.

An extended example

This section must still be written.

Passing configuration variables

This section must still be written.

# Show how to use configuration

config in   "Input file"
config out  "Output file"

|mplayer file=$in| --> rgb --> |mencoder file=$out|

Organizing code in multiple models

This section must still be written.

# Show how to put multiple models, and how to write 
--- model tutorial04_models
''' The master model '''
config in   "Input file"
config out  "Output file"

|mplayer file=$in| --> |tutorial04_filter| --> |mencoder file=$out|


--- model tutorial04_filter
''' The filtering model '''

input  rgb        "Input image"
output processed  "The processed image"

|input name=rgb| --> |posterize levels=3| --> |output name=processed|

Shortcuts for complex configuration

This section must still be written.

# Show how to put multiple models, and how to write 
--- model tutorial05_config_advanced
''' The master model '''
config in        "Input file"
config out       "Output file"
config levels = 3 "Number of channels for posterization."


|player:mplayer| --> |tut:tutorial05_filter| --> |encoder:mencoder file=$out|

player.file  = $in
tut.levels   = $levels
encoder.file = $out

--- model tutorial05_filter
''' The filtering model '''

input  rgb        "Input image"
output processed  "The processed image"
config levels = 3 "Number of channels for posterization."

|input name=rgb| --> |posterize| --> |output name=processed|

# We can use the block type if there is no confusion
posterize.levels = $levels

Explicit signal routing

This section must still be written.

# Given a block name, we can route the signal
# Useful for doing different things with the same model 
|player:mplayer file="coastguard.mp4"|  --> |mencoder file="coastguard.avi"|

    player.video --> |mencoder file="coastguard06.avi"|    
    # Also by signal number (0: first output)
    # player.0 --> |mencoder file="coastguard06.avi"|

Creating simple blocks from Python functions

This section must still be written.

from procgraph import simple_block

@simple_block
def green_channel(rgb):
    green = rgb[:,:,1]
    rgb[:,:,0] = green
    rgb[:,:,2] = green
    return rgb    

Adding configuration to simple blocks

This section must still be written.

import numpy
from procgraph import simple_block

@simple_block
def choose(rgb, channel=0):
    v = rgb[:,:,channel]
    result = numpy.dstack((v,v,v))
    return result
--- model tutorial08_simple_blocks
import tutorial08_blocks

|player:mplayer file="coastguard.mp4"|  --> rgb
    
    rgb --> |choose channel=0| --> processed
    
    processed --> |mencoder file="coastguard08.avi"|

Best practices for documenting simple blocks

This section must still be written.

--- model tutorial09_best_practices
''' Same as tutorial8. '''

import tutorial09_blocks

|player:mplayer file="coastguard.mp4"|  --> rgb

    rgb --> |choose channel=0| --> red
    rgb --> |choose channel=1| --> green
    rgb --> |choose channel=2| --> blue
    
    rgb, red, green, blue --> |sync| --> |grid cols=2| --> processed
    
    processed --> |mencoder file="coastguard09.avi"|
    
import numpy
from procgraph import simple_block, BadConfig

@simple_block
def choose(rgb, channel=0):
    ''' Chooses a channel from an rgb image and replicates it 
        over the other two.

        Raises an error if ``channel`` is invalid.
    
        :param rgb: Input image.
        :param channel: Which channel to choose.        
        :return: processed: The processed image.
    '''
    if not channel in [0,1,2]:
        raise BadConfig('Invalid channel specified.', config='channel')
    
    v = rgb[:,:,channel]
    return numpy.dstack((v,v,v))

Creating stateful blocks from Python classes

This section must still be written.

from procgraph import Block

class Psychedelic(Block):
    Block.alias('psychedelic')
    Block.input('rgb', 'An RGB image.')
    Block.output('processed', 'The processed image.')
    
    def init(self):
        self.channel = 0
        
    def update(self):
        self.channel = (self.channel + 1) % 3

        rgb = self.input.rgb.copy()
        for i in [0, 1, 2]:
            if i != self.channel:
                rgb[:,:,i] = 0 
        
        self.output.processed = rgb
--- model tutorial10_stateful_blocks
import tutorial10_blocks

|mplayer file="coastguard.mp4"|-->|psychedelic|-->|mencoder file="coastguard10.avi"|

Contents