LiveCon Printer

This is a proof of concept, to directly producting a Program book, out of the LiveCon CSV.


In [1]:
import pylatex.base_classes.command
def patched_commandbase_eq(self,other):
    if isinstance(other, CommandBase):
        return self._CommandBase__key() == other._CommandBase__key()
    return False
pylatex.base_classes.command.CommandBase.__eq__=patched_commandbase_eq

In [2]:
from sessions import *

In [3]:
from pylatex.base_classes import *
from pylatex.base_classes.command import Command,Arguments


class TcboxFit(Command):  
    def __init__(self,arguments=None,options=None):
        packages = [Package('tcolorbox', options='fitting')]
        Command.__init__(self, "tcboxfit", arguments=arguments, options=options, packages=packages)

class FixedTextbox(LatexObject): #Hack: THis should be a container
    def __init__(self,text, hpos,vpos, height,width, tcb_options=None):
        self.text=text
        self.hpos=hpos
        self.vpos=vpos
        self.height=height
        self.width=width
        
        self.tcboxfit = TcboxFit(options=tcb_options, arguments=text)
        self.tcboxfit.options._key_value_args["height"]=height
        
        self.packages = [Package('textpos', options='absolute'),Package('tcolorbox', options='fitting')]
        LatexObject.__init__(self)
    
    def dumps(self): 
        return """
\\begin{textblock*}{%(width)s}(%(hpos)s, %(vpos)s)
    %(tcbox)s
\\end{textblock*}
        """ % {'width':self.width, 'hpos':self.hpos, 'vpos':self.vpos, 'tcbox':self.tcboxfit.dumps()}
    
class TextcolorboxStyle(LatexObject):
    def __init__(self, *args, **kwargs):
        self.args = args
        self.kwargs= kwargs
        self.packages = [Package('tcolorbox', options='fitting')]
        LatexObject.__init__(self)

    def dumps(self): 
        def express_arguments(args,kwargs):
            args_strs = list(map(str,args))
            kwargs_strs = ["%s=%s" % (k,v) for (k,v) in kwargs.items()]
            return ",".join(args_strs + kwargs_strs)
        return "\\tcbset{%s}" % express_arguments(self.args, self.kwargs)

def textpos_origin(x,y):
    return Command('textblockorigin',arguments=[x,y])

In [19]:
def get_tag_colors(sessions):
        from collections import defaultdict
        tag_occurances = defaultdict(lambda: 0)
        for session in sessions:
            for tag in session.tags:
                tag_occurances[tag]+=1

        tags = list(tag_occurances)
        tags.sort(key=lambda tt: -tag_occurances[tt])

        colors=["blue","brown","cyan","green","lime","magenta","olive","orange","pink","purple","red","teal","violet", "yellow"]
        color_map = {tag:color for tag,color in zip(tags,colors)}
        return color_map

#Overwrite
def get_tag_colors(sessions):
    return {' Needs Moderator': 'green',
    ' Needs Panelists': 'red'}



#Overwrite
def get_tag_colors(sessions):
    return {}

#Overwrite
def get_tag_colors(sessions):
    return {
        "Anime" : "Maroon",
        "Art" : "Lime",
        "Comics" : "Pink",
        "Core" : "SlateGray",
        "Creative Works" : "PaleGreen",
        "discussion" : "SlateBlue",
        "Fandom/Conrunning" : "Teal",
        "Fantasy" : "Wheat",
        "Gaming" : "Green",
        "Horror" : "DarkGreen",
        "Science and Tech" : "Chocolate",
        "Scifi" : "Salmon",
        "TV/Movies" : "LightBlue",
        "Written Fiction" : "Coral",
        "a launch in five parts" : "DarkViolet",
        "Academic" : "Gold",
        "AdultsOnly" : "HotPink",
        "Family" : "Cornsilk",
        "Lightning (series of 3 minute)" : "Yellow",
        "Loud" : "SaddleBrown",
        "Music" : "Violet",
        "Video Games" : "SeaGreen",
        "Video Games (outside the gamesroom)" : "CadetBlue",
        "workshop " : "RoyalBlue"
    }

In [5]:
def fixed_venue_order(sessions):
    return [
        "South Ballroom (Large Panel Room)",
        "North Ballroom (Large Panel Room)",
        "Hamersley North (Small Panel Room)",
        "Hamersley South (Discussion Room)",
        "Boardroom (Family Room)",
        "Centre Ballroom (Traders and Art Show)",
        "Pilbara (Video Gaming Room)",
        "Goldsworthy (Gaming Room)"]

In [35]:
def with_units(func):
    def wrapper(*args, **kwargs):
        units = args[0].units #Assumes that this is decorating a method on a class with a units field
        result = func(*args, **kwargs)
        return str(round(result,3))+units
    return wrapper
    
class timetable_metric_solver():
    import venueordering
    #Hack Me to have specified order of venues
    def __init__(self,sessions, hour_len, venue_width, units, 
                 voffset=0,
                 venue_orderer = venueordering.get_order_from_sessions):
        
        
        self.voffset = voffset
        self.hour_len = hour_len
        self.venue_width = venue_width
        self.units = units
        
        self.venues_to_x = { name:ii*venue_width
                                for ii, name in enumerate(venue_orderer(sessions))}
        
        from itertools import groupby
        self.day_starts = {date:min(map(lambda ss: ss.start, sessions))
                                for date, sessions in groupby(sessions, lambda ss: ss.start.date())}
        self.tag_colors = get_tag_colors(sessions)
    
    def get_color(self,session):
        if session.tags:
            colored_tags = set.intersection( set(session.tags), set(self.tag_colors.keys()) )
            if len(colored_tags)>0:
                mix = round(70/len(colored_tags)) #paleness
                colors = [self.tag_colors[tag]+ "!%s!" % mix 
                              for tag in colored_tags]
                return ''.join(colors)+"white"
            else:
                return ""
        else:
            return ""
        
    
    @with_units
    def get_width(self,session):
        if session.venues:
            return len(session.venues)*self.venue_width    
        else:
            nVenues = len(self.venues_to_x.keys())
            return nVenues*self.venue_width    
    
    @with_units
    def get_venue_x(self,venue):
        return self.venues_to_x[venue]
    
    @with_units
    def get_x(self, session):
        #Get the left most venue position
        if session.venues:
            return min(map(lambda vv: self.venues_to_x[vv],session.venues))
        else:
            return 0 # fills all Venues, starting from left
            
    
    def duration_to_height(self,duration):
        return duration.seconds/(60*60)*self.hour_len
    
    @with_units
    def get_y(self, session):
        day_start = self.day_starts[session.start.date()]
        time_til_start = session.start - day_start
        return self.voffset + self.duration_to_height(time_til_start)
    
    @with_units
    def get_height(self,session):
        return self.duration_to_height(session.duration)
    
    @with_units
    def get_venue_width(self):
        return self.venue_width
    
    @property
    def venues(self):
        return list(self.venues_to_x.keys())

In [36]:
from pylatex.utils import escape_latex, NoEscape
from pylatex.utils import NoEscape
from pagelayout import Multicols
from itertools import groupby
from pylatex.base_classes import Environment

class Minipage(Environment):
    def __init__(self, width):
        Environment.__init__(self,arguments=[width])


def write_descriptions(sessions, doc):
    for day_name, day_session in groupby(sessions, lambda ss: ss.day):
        #with doc.create(Section(day_name,numbering=False)):
            with doc.create(Multicols(2)):
                doc.append(NoEscape("[\section*{%s}]" %day_name))
                for session in day_session:
                    if len(session.description)==0:
                        continue
                    title = session.title
                    if "AdultsOnly" in session.tags:
                        title+=NoEscape(" [ADULT]")
                    with doc.create(Subsection(title,numbering=False)):
                        with doc.create(Description()) as desc:
                            doc.append(Command("setlength",[NoEscape("\itemsep"),"0pt"]))
                            doc.append(Command("setlength",[NoEscape("\parsep"),"0pt"]))
                            doc.append(Command("setlength",[NoEscape("\parskip"),"0pt"]))
                            desc.add_item("When:", session.day+", "+session.start_time+" -- "+session.end_time)

                            if len(session.venues)>0:
                                desc.add_item("Where:", ", ".join(session.venues))
                            if len(session.people)>0:
                                desc.add_item("Who:", ", ".join(session.people))
                            #if len(session.tags)>0:
                            #    desc.add_item("Tags:", ", ".join(session.tags))
                        doc.append(session.description)
                #doc.append(Command("newpage"))

In [37]:
from pylatex.utils import escape_latex, NoEscape
from itertools import groupby
from pylatex.base_classes.command import Options
from pylatex.utils import escape_latex

def write_venues(doc, tt_solver):
    doc.append(textpos_origin('2cm','2cm'))
    doc.append(TextcolorboxStyle('sharp corners','fit algorithm=hybrid*','center upper', valign='center',
                                 colframe='blue!50!black',colback='blue!10!white',
                                 boxsep='0pt',top='0mm',bottom='0mm',left='0mm',right='0mm'))
            
    for venue in tt_solver.venues:
        doc.append(FixedTextbox(venue,
                                tt_solver.get_venue_x(venue),
                                '0cm', 
                                '1.5cm',
                                tt_solver.get_venue_width())
                               )

def make_pretty_timetable(doc,sessions):
    tt_solver = timetable_metric_solver(sessions,1.7,2.15,'cm', 1.7, venue_orderer=fixed_venue_order)

    
    for date, day_sessions in groupby(sessions, lambda ss: ss.start.date()):   
        day_str = str(DAYS[date.weekday()])
        with doc.create(Subsection(NoEscape(day_str+" \hfill "+day_str+" \hfill "+day_str), numbering=False)):
           
            write_venues(doc,tt_solver)
            doc.append(TextcolorboxStyle('fit algorithm=hybrid*','rounded corners', 'center upper', valign='center',
                                 colframe='blue!50!black',colback='white!10!white',
                                 boxsep='1pt',top='0mm',bottom='0mm',left='0mm',right='0mm'))
            
            day_sessions = sorted(day_sessions, key = lambda ss: -len(ss.venues) or -len(tt_solver.venues)-1)
            for session in day_sessions:
                #print("*", session.title)
                colback = tt_solver.get_color(session)
                tcb_options = Options(colback=colback) if colback else None
                doc.append(FixedTextbox(NoEscape('%s \\\\ \\tcbfontsize{0.75} %s -- %s ' % 
                                                     tuple(map(escape_latex, (session.title, session.start_time, session.end_time)))),
                                        tt_solver.get_x(session),
                                        tt_solver.get_y(session), 
                                        tt_solver.get_height(session),
                                        tt_solver.get_width(session),
                                        tcb_options=tcb_options))

            doc.append(Command('newpage'))

In [ ]:


In [71]:
from sessions import load_sessions_csv
sessions = []
sessions = load_sessions_csv('con_data/sc2016.csv')
sessions = list(filter(lambda ss: not "NotInPrintProgram" in ss.tags, sessions))
sessions.sort(key=lambda ss: ss.start)


#sessions = list(filter(lambda ss: ss.day == "Monday", sessions))
#sessions = list(filter(lambda ss: 'Jane Espenson' in ss.people, sessions))
#sessions = list(filter(lambda ss: 'Gillian Rubinstein' in ss.people, sessions))
#sessions = list(filter(lambda ss: 'Fe Waters' in ss.people, sessions))
#sessions = list(filter(lambda ss: "Michael O'Brien" in ss.people, sessions))
#sessions = list(filter(lambda ss: " Gaming" in ss.tags or "Gaming" in ss.tags, sessions))
#sessions = list(filter(lambda ss: "Family" in ss.tags or " Family" in ss.tags, sessions))
len(sessions)


Out[71]:
214

In [39]:
import pylatex
from pylatex import Document, Section, Subsection, Subsubsection, Table, Package, lists
from pylatex.lists import Description

from tabulartimetable import write_timetable


doc = Document(documentclass="scrreprt")
margins=['tmargin=1.5cm','bmargin=2.5cm','lmargin=2.5cm','rmargin=2.5cm',]
doc.packages.append(Package('geometry', options=margins))
doc.packages.append(Package('xcolor', options=["svgnames","dvipsnames"]))

#doc.packages.append(Package("draftwatermark"))
#doc.append(Command("newgeometry",arguments=",".join(margins)))
#doc.append(Command("SetWatermarkText", "Draft 8"))
#doc.append(Command("SetWatermarkScale", "0.5"))
#doc.append(Command("SetWatermarkColor", "0.9,0.59,0.5", "rgb"))

make_pretty_timetable(doc,sessions)
write_descriptions(sessions,doc)

from IPython.display import FileLink, FileLinks
with open("out/exported.tex", 'w') as fh:
    doc.dump(fh)

!lualatex --output-directory=out --interaction=nonstopmode out/exported.tex
FileLinks("./out")
FileLinks("./out")


This is LuaTeX, Version beta-0.79.1 (TeX Live 2015/dev/Debian) (rev 4971) 
 restricted \write18 enabled.
(./out/exported.tex
LaTeX2e <2014/05/01>
Babel <3.9l> and hyphenation patterns for 79 languages loaded.
(/usr/share/texlive/texmf-dist/tex/latex/koma-script/scrreprt.cls
Document Class: scrreprt 2013/12/19 v3.12 KOMA-Script document class (report)
(/usr/share/texlive/texmf-dist/tex/latex/koma-script/scrkbase.sty
(/usr/share/texlive/texmf-dist/tex/latex/koma-script/scrbase.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty)
(/usr/share/texlive/texmf-dist/tex/latex/koma-script/scrlfile.sty
Package scrlfile, 2013/12/19 v3.12 KOMA-Script package (loading files)
                  Copyright (C) Markus Kohm

))) (/usr/share/texlive/texmf-dist/tex/latex/koma-script/tocbasic.sty)
(/usr/share/texlive/texmf-dist/tex/latex/koma-script/scrsize11pt.clo)
(/usr/share/texlive/texmf-dist/tex/latex/koma-script/typearea.sty
Package typearea, 2013/12/19 v3.12 KOMA-Script package (type area)
                  Copyright (C) Frank Neukam, 1992-1994
                  Copyright (C) Markus Kohm, 1994-

)) (/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty
(/usr/share/texlive/texmf-dist/tex/latex/base/t1enc.def))
(/usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty

Package inputenc Warning: inputenc package ignored with utf8 based engines.

) (/usr/share/texmf/tex/latex/lm/lmodern.sty)
(/usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty
(/usr/share/texlive/texmf-dist/tex/latex/base/ts1enc.def))
(/usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/ifpdf.sty)
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/ifvtex.sty)
(/usr/share/texlive/texmf-dist/tex/generic/ifxetex/ifxetex.sty))
(/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty
(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/color.cfg)
(/usr/share/texlive/texmf-dist/tex/latex/pdftex-def/pdftex.def
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/infwarerr.sty)
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/ltxcmds.sty)
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/pdftexcmds.sty
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/ifluatex.sty)
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/luatex-loader.sty
(/usr/share/texlive/texmf-dist/scripts/oberdiek/oberdiek.luatex.lua))))
(/usr/share/texlive/texmf-dist/tex/latex/graphics/dvipsnam.def)
(/usr/share/texlive/texmf-dist/tex/latex/xcolor/svgnam.def))
(/usr/share/texlive/texmf-dist/tex/latex/tcolorbox/tcolorbox.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def
(/usr/share/texlive/texmf-dist/tex/latex/ms/everyshi.sty))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty
(/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty)
(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/graphics.cfg)))
(/usr/share/texlive/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.t
ex)) (/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.de
f)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.
tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonomet
ric.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.cod
e.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.
tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerari
thmetics.code.tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.
code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code
.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformation
s.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.t
ex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing
.code.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex
)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex

(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.
tex))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.te
x)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.c
ode.tex)
(/usr/share/texlive/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.
tex)))
(/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex
) (/usr/share/texlive/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex
)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65
.sty)
(/usr/share/texlive/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18
.sty)) (/usr/share/texlive/texmf-dist/tex/latex/tools/verbatim.sty)
(/usr/share/texlive/texmf-dist/tex/latex/environ/environ.sty
(/usr/share/texlive/texmf-dist/tex/latex/trimspaces/trimspaces.sty))
(/usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty
(/usr/share/texlive/texmf-dist/tex/latex/etex-pkg/etex.sty))
(/usr/share/texlive/texmf-dist/tex/latex/tcolorbox/tcbfitting.code.tex
Library (tcolorbox): 'tcbfitting.code.tex' version '3.21'
)) (/usr/share/texlive/texmf-dist/tex/latex/textpos/textpos.sty
Package: textpos 2014/01/03 1.7j, absolute positioning of text on the page
Grid set 16 x 16 = 37.34424pt x 52.81543pt
TextBlockOrigin set to 0pt x 0pt
) (/usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty)
(./out/exported.aux) (/usr/share/texlive/texmf-dist/tex/latex/base/ts1cmr.fd)
(/usr/share/texmf/tex/latex/lm/t1lmr.fd)
*geometry* driver: auto-detecting
*geometry* detected driver: pdftex
(/usr/share/texlive/texmf-dist/tex/context/base/supp-pdf.mkii
[Loading MPS to PDF converter (version 2006.09.02).]
) ABD: EveryShipout initializing macros
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/epstopdf-base.sty
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/grfext.sty
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/kvdefinekeys.sty))
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/kvoptions.sty
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/kvsetkeys.sty
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/etexcmds.sty)))
(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg))
(/usr/share/texmf/tex/latex/lm/t1lmss.fd)
TextBlockOrigin set to 2cm x 2cm

! Package pgfkeys Error: Choice 'hybrid*' unknown in choice key '/tcb/fit algor
ithm'. I am going to ignore this key.

See the pgfkeys package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.16 ...tom=0mm,colback=blue!10!white,valign=center}
                                                  
(/usr/share/texmf/tex/latex/lm/ot1lmr.fd)
(/usr/share/texmf/tex/latex/lm/omllmm.fd)
(/usr/share/texmf/tex/latex/lm/omslmsy.fd)
(/usr/share/texmf/tex/latex/lm/omxlmex.fd)

! Package pgfkeys Error: Choice 'hybrid*' unknown in choice key '/tcb/fit algor
ithm'. I am going to ignore this key.

See the pgfkeys package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.57 ...om=0mm,colback=white!10!white,valign=center}
                                                  
[1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}]
TextBlockOrigin set to 2cm x 2cm

! Package pgfkeys Error: Choice 'hybrid*' unknown in choice key '/tcb/fit algor
ithm'. I am going to ignore this key.

See the pgfkeys package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.173 ...om=0mm,colback=blue!10!white,valign=center}
                                                  

! Package pgfkeys Error: Choice 'hybrid*' unknown in choice key '/tcb/fit algor
ithm'. I am going to ignore this key.

See the pgfkeys package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.214 ...m=0mm,colback=white!10!white,valign=center}
                                                  
[2]
TextBlockOrigin set to 2cm x 2cm

! Package pgfkeys Error: Choice 'hybrid*' unknown in choice key '/tcb/fit algor
ithm'. I am going to ignore this key.

See the pgfkeys package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.500 ...om=0mm,colback=blue!10!white,valign=center}
                                                  

! Package pgfkeys Error: Choice 'hybrid*' unknown in choice key '/tcb/fit algor
ithm'. I am going to ignore this key.

See the pgfkeys package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.541 ...m=0mm,colback=white!10!white,valign=center}
                                                  
[3]
TextBlockOrigin set to 2cm x 2cm

! Package pgfkeys Error: Choice 'hybrid*' unknown in choice key '/tcb/fit algor
ithm'. I am going to ignore this key.

See the pgfkeys package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.807 ...om=0mm,colback=blue!10!white,valign=center}
                                                  

! Package pgfkeys Error: Choice 'hybrid*' unknown in choice key '/tcb/fit algor
ithm'. I am going to ignore this key.

See the pgfkeys package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.848 ...m=0mm,colback=white!10!white,valign=center}
                                                  
[4]
TextBlockOrigin set to 2cm x 2cm

! Package pgfkeys Error: Choice 'hybrid*' unknown in choice key '/tcb/fit algor
ithm'. I am going to ignore this key.

See the pgfkeys package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.1114 ...m=0mm,colback=blue!10!white,valign=center}
                                                  

! Package pgfkeys Error: Choice 'hybrid*' unknown in choice key '/tcb/fit algor
ithm'. I am going to ignore this key.

See the pgfkeys package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.1155 ...=0mm,colback=white!10!white,valign=center}
                                                  
[5]
Underfull \hbox (badness 10000) in paragraph at lines 1333--1334


Underfull \hbox (badness 10000) in paragraph at lines 1378--1379

[6]
Underfull \hbox (badness 10000) in paragraph at lines 1438--1439


Underfull \hbox (badness 10000) in paragraph at lines 1496--1497
[][]\T1/lmr/m/n/10.95 Eesh-war, Michael Co-gan, Michael

Underfull \hbox (badness 10000) in paragraph at lines 1498--1499


Underfull \hbox (badness 10000) in paragraph at lines 1528--1529

[7] [8]
Underfull \hbox (badness 10000) in paragraph at lines 1666--1667


Underfull \hbox (badness 10000) in paragraph at lines 1739--1740


Underfull \hbox (badness 10000) in paragraph at lines 1769--1770

[9]
Underfull \hbox (badness 10000) in paragraph at lines 1799--1800


Underfull \hbox (badness 10000) in paragraph at lines 1829--1830


Underfull \hbox (badness 10000) in paragraph at lines 1919--1920

[10] [11]
Underfull \hbox (badness 10000) in paragraph at lines 2084--2085

[12]
Underfull \hbox (badness 10000) in paragraph at lines 2232--2233


Underfull \hbox (badness 10000) in paragraph at lines 2277--2278

[13]
Underfull \hbox (badness 10000) in paragraph at lines 2395--2396
[][]\T1/lmr/m/n/10.95 Stephen Ded-man, Daniel Drhoz,
[14]
Underfull \hbox (badness 10000) in paragraph at lines 2460--2461

[15]
Underfull \hbox (badness 10000) in paragraph at lines 2655--2656

[16]
Underfull \hbox (badness 10000) in paragraph at lines 2700--2701


Underfull \hbox (badness 10000) in paragraph at lines 2700--2701

[17]
Underfull \hbox (badness 10000) in paragraph at lines 2865--2866


Underfull \hbox (badness 10000) in paragraph at lines 2953--2954
[][]\T1/lmr/m/n/10.95 Sue Ack-er-mann, Satima Flavell,

Underfull \hbox (badness 10000) in paragraph at lines 2955--2956

[18]
Underfull \hbox (badness 5862) in paragraph at lines 2968--2969
[][]\T1/lmr/m/n/10.95 Kitty Byrne, Regina Chow, John

Underfull \hbox (badness 10000) in paragraph at lines 2970--2971


Underfull \hbox (badness 10000) in paragraph at lines 3030--3031


Underfull \hbox (badness 10000) in paragraph at lines 3030--3031

[19] [20]
Underfull \hbox (badness 10000) in paragraph at lines 3228--3229


Underfull \hbox (badness 5374) in paragraph at lines 3258--3259
\T1/lmr/m/n/10.95 This is the main trailer park. Note

Underfull \hbox (badness 10000) in paragraph at lines 3348--3349

[21]
Underfull \hbox (badness 10000) in paragraph at lines 3419--3420
[][]\T1/lmr/m/n/10.95 Daniel Drhoz, Re-becca Hand-cock,

Underfull \hbox (badness 10000) in paragraph at lines 3421--3422


Underfull \hbox (badness 10000) in paragraph at lines 3496--3497

[22]
Underfull \hbox (badness 10000) in paragraph at lines 3616--3617


Underfull \hbox (badness 10000) in paragraph at lines 3616--3617


Underfull \hbox (badness 10000) in paragraph at lines 3646--3647

[23]
Underfull \hbox (badness 10000) in paragraph at lines 3706--3707

[24]
Underfull \hbox (badness 5231) in paragraph at lines 3794--3795
[][]\T1/lmr/m/n/10.95 Stephen Ded-man, Leonard Goulds,
[25]
Underfull \hbox (badness 10000) in paragraph at lines 3994--3995


Underfull \hbox (badness 10000) in paragraph at lines 4009--4010

[26]
Underfull \hbox (badness 6510) in paragraph at lines 4037--4038
[][]\T1/lmr/m/n/10.95 Jack Bridges, Christo-pher Cour-tis,

Underfull \hbox (badness 10000) in paragraph at lines 4114--4115

[27]
Underfull \hbox (badness 10000) in paragraph at lines 4172--4173
[][]\T1/lmr/m/n/10.95 Dave Cake, Daniel Drhoz, Keira

Underfull \hbox (badness 10000) in paragraph at lines 4204--4205

[28] (./out/exported.aux))
(see the transcript file for additional information)
 486 words of node memory still in use:
   3 hlist, 1 vlist, 1 rule, 2 glue, 45 glue_spec, 1 write nodes
   avail lists: 1:1,2:25,3:3279,4:3423,5:589,6:7631,7:192,9:1269,10:460
{/usr/share/texmf/fonts/enc/dvips/lm/lm-ec.enc}<</usr/share/texmf/fonts/type1/pu
blic/lm/lmr10.pfb><</usr/share/texmf/fonts/type1/public/lm/lmr5.pfb><</usr/share
/texmf/fonts/type1/public/lm/lmr6.pfb><</usr/share/texmf/fonts/type1/public/lm/l
mr7.pfb><</usr/share/texmf/fonts/type1/public/lm/lmr8.pfb><</usr/share/texmf/fon
ts/type1/public/lm/lmr9.pfb><</usr/share/texmf/fonts/type1/public/lm/lmssbx10.pf
b>
Output written on exported.pdf (28 pages, 331299 bytes).
Transcript written on exported.log.
Out[39]:

In [ ]:


In [78]:
#ROOMs/DAYS

import pylatex
from pylatex import Document, Section, Subsection, Subsubsection, Table, Package,lists
from pylatex.lists import Description
from pylatex.base_classes import Command


from itertools import groupby

from collections import defaultdict
vds = defaultdict(lambda : defaultdict(list))
for date, day_sessions in groupby(sessions, lambda ss: ss.start.date()):
    for sess in day_sessions:
        for venue in sess.venues:
            vds[venue][date].append(sess)

#################################
doc = Document(documentclass="standalone")
#doc.packages.add("enumitem")
#doc.append(r"\setlist[description]{leftmargin=10em,labelindent=0em")
for venue in vds.keys():
    sessions_on_page=0
    doc.append(Command("newpage"))
    for date in sorted(vds[venue]):
        day = DAYS[date.weekday()]
        with doc.create(Section(NoEscape("%s\\\\ %s" % (day,venue.replace("(","\\\\("))), numbering=False)):
            doc.append(Command("vfill"))
            with doc.create(Description()) as sched:
                sesses = sorted(vds[venue][date], key=lambda ss: ss.start)
                sessions_on_page+=len(sesses)
                for sess in sesses:
                    sched.add_item(NoEscape("%s -- %s" % (sess.start_time, sess.end_time)), sess.title)
            doc.append(Command("vfill"))
            if sessions_on_page>=6:
                doc.append(Command("newpage"))
                sessions_on_page=0
            else:
                doc.append(Command("vfill"))

In [79]:
from IPython.display import FileLink, FileLinks
with open("out/exported_days.tex", 'w') as temp_out:
    doc.dump(temp_out)

#!lualatex --output-directory=out --interaction=nonstopmode exported_days.tex
FileLinks("./out")





In [ ]:


In [ ]:


In [ ]: