colorlab
clone your own copy | download snapshot

Snapshots | iceberg

Inside this repository

poster_back.py
text/x-python

Download raw (12.5 KB)

# -*- coding: utf-8 -*-

from chiplotle import *
import random
import math
import re

from shapes.chlorella import chlorella_cell
from shapes.dunaliella_salina import duna_cell
from shapes.nannochloropsis import nanno_cell
from shapes.p_cruentum import p_cell
from shapes.spirulina import spirulina_cell
from shapes.haematococcus import haema_cell


#################################
## VIRTUAL OR HARDWARE PLOTTER ##
#################################

VIRTUAL = True

if VIRTUAL:
    from chiplotle.tools.plottertools import instantiate_virtual_plotter
    plotter =  instantiate_virtual_plotter(left_bottom = Coordinate(-17300,-11880), right_top = Coordinate(16340,11880), type="DPX-3300")
    plotter.margins.hard.draw_outline()
    plotter.select_pen(1)

else:
    plotter = instantiate_plotters( )[0]
    plotter.select_pen(1)


#################################
## WRAPPING THE CELL FUNCTIONS ##
#################################

def wrapped_chlorella():
    plotter.select_pen(2)
    return chlorella_cell(random.randint(int(4.5 * y_unit), int(7 * y_unit)), random.randint(3,4))

def wrapped_duna():
    plotter.select_pen(3)
    return duna_cell(random.randint(int(4.5 * y_unit), int(7 * y_unit)), random.randint(3,6))

def wrapped_haema():
    plotter.select_pen(4)
    return haema_cell(random.randint(int(4.5 * y_unit), int(7 * y_unit)))

def wrapped_nanno():
    plotter.select_pen(5)
    return nanno_cell(random.randint(int(4.5 * y_unit), int(7 * y_unit)), 5)

def wrapped_p():
    plotter.select_pen(6)
    return p_cell(int(4.5 * y_unit), int(7 * y_unit))

def wrapped_spirulina():
    plotter.select_pen(7)
    return spirulina_cell(random.randint(3,12), random.uniform(0.1,0.3), random.randint(int(4.5 * y_unit), int(7 * y_unit)))


#######################################
## VARIOUS FUNCTIONS TO PROCESS TEXT ##
#######################################

def mm(amount):
    return amount * 40

def cm(amount):
    return amount * 400

def units_to_cm(amount):
    return amount / 400.0

def title(input_text, char_widht, char_height):
    input_text = input_text.upper()
    if " " in input_text:
        formatted_text = input_text.replace(" ", "\r\n")
        input_text = formatted_text
    title = shapes.group([])
    movement = 0
    for i in range(8):
        title_text = shapes.label(input_text, units_to_cm(char_widht), units_to_cm(char_height),0,0)
        transforms.center_at(title_text, (movement,0))
        title.append(title_text)
        movement += (y_unit)/7
    return title

def title_splitter(text): # Makes the title have the same spacing as the pattern.
    gapped_title = shapes.group([])
    pos_y = 0 * y_unit
    change = 8 * y_unit 
    for letter in text:
        l = title(letter, 5 * y_unit, 6 * x_unit)
        transforms.rotate(l, math.radians(90))
        transforms.offset(l, (0, pos_y))
        gapped_title.append(l)
        pos_y += change

    return gapped_title

# Returns a tuple with the word, and a boolean whether it's bold
# if it's bold also return tokens before and after bold sign
# *word*, → ('word,', True)
def add_style_annotation (word):
    m = re.match(r'^(\W?)\*(.+)\*(\W?)$', word)

    if m:
        return ('{}{}{}'.format(m.group(1), m.group(2), m.group(3)), True)
    else:
        return (word, False)

# Changes boldness across multiple word to bold per word.
# *one two three* *one* *two* *three*
def bold_per_word (m):
    return re.sub(r'(\s+)', '*\\1*', m.group(0))

def tokenize_text (text):
    text = re.sub(r'\*[^\*]+\*', bold_per_word, text.replace('\r\n', '\n').replace('\n', ' __newline__ '))
    return [add_style_annotation(w) for w in re.split(r'\s+', text)]


def line_length(txt, char_width):
    return len(txt) * char_width * 1.3

def make_label (text, char_width, char_height, offset):
    line = shapes.label(text, units_to_cm(char_width), units_to_cm(char_height), -.1, 1)
    transforms.offset(line, (0, -offset))
    return line

# Transform text lines into plotter labels
def make_labels (lines, charwidth, charheight, charspace=None, linespace=None, offset=None):
    text = '{}{}'.format(chr(10), chr(13)).join(lines)
    label = shapes.label(text, charwidth=units_to_cm(charwidth), charheight=units_to_cm(charheight), charspace=charspace, linespace=linespace)
    if offset:
        transforms.offset(label, offset)
    return label

def bufferLength (annotated_words, separator=" ", prefix="", char_width=1):
    if annotated_words:
        separator_length = line_length(separator, char_width)
        length = line_length(prefix, char_width)

        # Loop through words, if they're bold count an extra char
        for word, bold in annotated_words:
            length += line_length(word, char_width)
            if bold:
                length += line_length(word[-1], char_width)

        # add spaces
        length += (len(annotated_words) - 1) * separator_length

        return length
    else:
        return 0

def makeLines (text, width, char_width, prefix = ""):
    lines = []
    buff = []
    separator = " "
    # print(text, tokenize_text(text))
    for token in tokenize_text(text):
        # print(token)
        length = bufferLength(buff, separator, prefix, char_width)
        word_length = bufferLength([token], separator, separator, char_width)

        if (width and length + word_length > width) or token[0] == '__newline__':
            lines.append(buff)
            buff = [token] if token[0] <> '__newline__' else []
        else:
            if '°' in token[0]:
                buff.append((token[0].replace("°", chr(14) + chr(122) + chr(15)), token[1]))
            else:
                buff.append(token)

    if buff:
        lines.append(buff)

    normal = [prefix + separator.join([word for word, _ in line]) for line in lines]
    bold = [prefix + separator.join([word if bold else len(word) * ' ' for word, bold in line]) for line in lines]

    return (normal, bold)

def body(input_text, width, char_width, char_height, line_height, charspace=-.1, linespace=None):
    linesRegular, _ = makeLines(input_text, width, char_width)

    return make_labels(linesRegular, charwidth=char_width, charheight=char_height, charspace=charspace, linespace=linespace)

#######################
## VARIOUS FUNCTIONS ##
#######################

def kask(): #Draws the KASK logo
    logo = shapes.group([])
    half = shapes.group([])
    lower_half = shapes.group([])

    height = 1 * x_unit
    width = 0.8 * y_unit

    vertical_indent = height / 2.0

    k_1 = shapes.label("K", units_to_cm(width), units_to_cm(height),0,0)
    a = shapes.label("A", units_to_cm(width), units_to_cm(height),0,0)
    transforms.offset(a, (1 * y_unit, vertical_indent))
    s = shapes.label("S", units_to_cm(width), units_to_cm(height),0,0)
    transforms.offset(s, (2 * y_unit, vertical_indent))
    k_2 = shapes.label("K", units_to_cm(width), units_to_cm(height),0,0)
    transforms.offset(k_2, (3 * y_unit, 0))

    half.append(k_1)
    half.append(a)
    half.append(s)
    half.append(k_2)
    
    k_3 = shapes.label("K", units_to_cm(width), units_to_cm(height),0,0)
    a_1 = shapes.label("A", units_to_cm(width), units_to_cm(height),0,0)
    transforms.offset(a_1, (1 * y_unit, vertical_indent))
    s_1 = shapes.label("S", units_to_cm(width), units_to_cm(height),0,0)
    transforms.offset(s_1, (2 * y_unit, vertical_indent))
    k_4 = shapes.label("K", units_to_cm(width), units_to_cm(height),0,0)
    transforms.offset(k_4, (3 * y_unit, 0))

    lower_half.append(k_3)
    lower_half.append(a_1)
    lower_half.append(s_1)
    lower_half.append(k_4)
    
    logo.append(half)
    transforms.rotate(lower_half, math.radians(180))
    transforms.offset(lower_half, (3.8 * y_unit,- 0.2 * y_unit))
    logo.append(lower_half)

    border = shapes.ellipse(5.5 * y_unit, 4 * x_unit)
    transforms.offset(border, ((3.8 * y_unit)/2, (-0.2 * y_unit)/2))
    logo.append(border)

    transforms.rotate(logo, math.radians(90))
    transforms.center_at(logo, (0,0))
    return logo

def conservatorium ():
    charwidth = .2 * x_unit
    charheight = 0.3 * y_unit
    shift = 0.5 * charheight

    parts = ['CON', 'SER', 'VA', 'TO', 'RIUM']

    logo = Group()
    lines = Group()

    outline = shapes.rectangle(16 * 1.5 * charwidth, 6.5 * 2 * charheight)
    transforms.offset(outline, (7 * 1.5 * charwidth, -2.1 * 2 * charheight))
    logo.append(outline)

    for r in range(6):
        omit = len(parts) - r
        line = Group()
        x = 0
        for p, text in enumerate(parts):
            if p <> omit:
                label = shapes.label(text, charwidth=units_to_cm(charwidth), charheight=units_to_cm(charheight), charspace=0, linespace=0)
                if p % 2 == 1:
                    transforms.offset(label, (x, shift))
                else:
                    transforms.offset(label, (x, 0))
                line.append(label)

            x += len(text) * charwidth * 1.55

        transforms.offset(line, (0, -charheight * 2 * r))

        lines.append(line)
    
    # transforms.center_at(lines, (0,0))

    logo.append(lines)

    transforms.rotate(logo, math.radians(90))

    return logo

def hogent():
    charwidth = .5 * x_unit
    charheight = .6 * y_unit

    hogent = shapes.label('HO\r\nGENT', charwidth=units_to_cm(charwidth), charheight=units_to_cm(charheight), charspace=0, linespace=0)
    howest = shapes.label('howest', charwidth=units_to_cm(charwidth) * .75, charheight=units_to_cm(charheight), charspace=-.1, linespace=0)
    
    transforms.offset(hogent, (0, charheight * -1))
    transforms.offset(howest, (0, charheight * -6))

    logo = Group([hogent, howest])

    transforms.rotate(logo, math.radians(90))
    transforms.center_at(logo, (0,0))

    return logo

def make_combinations(options=[], length=1): #Makes every possible combination of patterns
    if length > 1:
        combinations = []
        
        for i in range(len(options) - 1):
            for combination in make_combinations(options[i+1:], length - 1):
                combinations.append([options[i]] + combination)

        return combinations
    else:
        return [[option] for option in options]

def x(input):
    return input * x_unit

def y(input):
    return input * y_unit


#######################
## DEFINING THE GRID ##
#######################

plotter.set_origin_bottom_left()
width = plotter.margins.hard.width
height = plotter.margins.hard.height

x_unit = width / 80.0 
y_unit = height / 64.0 


#############################
### DRAWING THE PATTERNS  ###
#############################


posx = x(4)
posy = y(4)
counter = 0

wraps = [wrapped_chlorella, wrapped_duna, wrapped_haema, wrapped_nanno, wrapped_p, wrapped_spirulina]
random.shuffle(wraps)

combinations = make_combinations(wraps, 1) + make_combinations(wraps, 2) + make_combinations(wraps, 3) + make_combinations(wraps, 4) + make_combinations(wraps, 5) + make_combinations(wraps, 6)
# random.shuffle(combinations) ### Uncomment this if you want the patterns to be drawn randomly and not from 1 - 6 combinations.

for pattern in combinations[:-2]:
    for p in pattern:
        shape = p()
        transforms.center_at(shape,(posx,posy))
        plotter.write(shape)
    counter += 1

    if counter%8 != 0:
        posy += y(8)
    
    else:
        posy = y(4)
        posx += x(8)


######################
## DRAWING THE TEXT ##
######################

plotter.select_pen(1)

header_title_text = "Colorlab research,"
header_text = "Colorlab research, initiated by Laboratorium with\nOSP (Einar Andersen, Gijs de Heij & Sarah Magnan)."
body_text = "This publication is published under the Free Art License and has been generated with a python script.\nAll files are available on osp.kitchen/work/colorlab.\n\nPlotted with living colors produced by Maria Boto Ordonez within Kask Laboratorium.\n\nwww.laboratorium.bio."

poster_title = shapes.group([])

living = title_splitter("Living")
transforms.offset(living, (x(71), y(1)))
colors = title_splitter("Colors")
transforms.offset(colors, (x(79), y(1)))

header_t = body(header_text, y(14), y(0.2), x(0.4), x(1))
transforms.rotate(header_t, math.radians(90))
transforms.offset(header_t, (x(70), y(48)))

body_t = body(body_text, y(14), y(0.2), x(0.4), x(1))
transforms.rotate(body_t, math.radians(90))
transforms.offset(body_t, (x(73), y(48)))

kask_logo = kask()
transforms.center_at(kask_logo, (x(60), y(44)))

conservatorium_logo = conservatorium()
transforms.center_at(conservatorium_logo, (x(60), y(50.5)))

hogent_logo = hogent()
transforms.center_at(hogent_logo, (x(60), y(54.5)))
transforms.offset(hogent_logo, (x(.25), 0))

poster_title.extend([living, colors, header_t, body_t, kask_logo, conservatorium_logo, hogent_logo])
plotter.write(poster_title)


############
## FINISH ##
############

plotter.select_pen(0)

if VIRTUAL:
    io.view(plotter)