#!/usr/bin/python # Based on simple python example to create a pdf, draw a circle within page rectangle found in ~/Developer/Examples/Quartz/Python # This specific experiment produces a 5-6 generation pdf page # tree that looks as I desired. However, there are several # refinements requires: # 1. eventually, I need to parse the text files that define the trees # 2. combine 2 or more such files to get 6-10 generations # 3. automatize the cell/individual numbering # as it is now, there are 3 numbering schemes or mental models at work # a. square grid with generations columns & total individuals rows # b. generation start + remainder # c. sequence in tree wherein latest individual is #1 # (placed at center left), # parents are #2 (at 2nd col middle of upper half of rows) & # #3 (2nd col middle of lower half of rows), # grand-parents are #4-7 # d. sequence in tree from top to bottom disregarding generation # 2018-02-24T20:31: yah, this pass is ugly and wasteful of # cycles because it iterates through all n (vertical rows) # rectangles, then checks every generation, whereas # there is only 1 entry for each row, but each column # (generation) can have n entries (rows) # 2018-02-24T20:49: so, am trying simply to reverse nesting # outer loop is generation (column), inner is rectangle (row) # but this will wreak havoc with calculating vertical position # because have been doing that incrementally, insted of # using formula for vertical position of row within page... # 2018-02-24T20:56: yes, only the 1st/middle/latest/gen=1 entry # got drawn... and it still wastes all those cycles # 2018-02-25:T12:07-:22: after many changes... # now have text file with names # makes 1st pass through name files merely counting entries, # requires 1 entry for every possible name in generation # even if I do not know that name (requres e.g. f of phred; # m of phred; d of george+henrietta) as place-holders # through this, it counts lines and calculates number of generatons # from which it can calculate co-ordinates for each entry # so, then closes & re-opens file again to reset to beginning # to iterate through # 2018-02-25:T15:00: after many changes... # looking OK, but somehow my vertical co-ordinate seems # to have gotten reversed, so, e.g. 3rd indiv is being displayed # above 2nd indiv # beginning to think on how connecting lines should be drawn, # which seems to require holding onto previous LtR gen (later # gen/descendant chronologically) while also juggling # co-ordinates for later LtR gen (earlier gen/parents) # knocking off to read # 2018-02-25:T21:50: That was easy to flip. from CoreGraphics import * import math # for pi import sys, os, getopt, string def layout(maxindiv, generations, namesfile): sumrects = 0 rectwidth = 330 rectheight = 20 twixtspace = 4 margin = 20 print "generations: ", str(generations) + " maxindiv=" + str(maxindiv) vertneeded = maxindiv * (rectheight + twixtspace) print "vertical needed: ", str(vertneeded) pageheight = vertneeded + (margin*2) pagewidth = (generations * (rectwidth*3/4)) + margin*2 print " rectheight:", str(rectheight) + " page height: ", str(pageheight) + " page width: ", str(pagewidth) drawpage(namesfile, pagewidth, pageheight, maxindiv, rectwidth, rectheight, twixtspace, margin, generations) def drawpage(namesfile, pagewidth, pageheight, maxindiv, rectwidth, rectheight, twixtspace, margin, generations): tbr = 0 #page_rect = CGRectMake(0, 0, 612, 792) pageleft = 0 pagebottom = 0 indent = 40 pageRect = CGRectMake(pageleft, pagebottom, pagewidth, pageheight) # landscape c = CGPDFContextCreateWithFilename("rectangles.pdf", pageRect) c.beginPage(pageRect) totrows = maxindiv + 1 generation = 1 genbase = 0 odds = 1 for indiv in range (1, maxindiv+1): #row = totrows/2, totrows*seqingen/4, totrows*seqingen/8, totrows*seqingen/16 #totrows = maxindiv+1 # odds = 1,3,5,7,9,11,13,15,17,19,21,23... # odds = like arrayofallodds[seqingen] # gendiv = 2,4,8,16,32,64 # row = totrows*odds/2^gen # genbase = last indiv in prev gen seqingen = indiv - genbase print "totrows=" + str(totrows) + " odds=" + str(odds) + " 2**generation=" + str(2**generation) if indiv == 1: row = totrows/2 else: row = totrows*odds/(2**generation) rectleft = ((generation-1) * rectwidth*9/16) + margin rectbottom = pageheight - (margin + row*(twixtspace + rectheight)) top = rectbottom + rectheight rectright = rectleft + rectwidth horcent = rectleft + (rectwidth/2) vertcent = rectbottom - (rectheight/2) #recttc = horcent, top #rectbc = horcent, bottom #rectlc = left, vertcent splat = "g=" + str(generation) splat += " row=" + str(row) + " indiv=" + str(indiv) splat += " " + (namesfile.readline()).rstrip() print " rectleft=" + str(rectleft) + " rectbottom=" + str(rectbottom) #print splat drawrect(c, rectleft, rectbottom, rectwidth, rectheight, twixtspace, margin, indiv, row, generation, splat) # if indiv just finished is end of generation, start next # 1,2-3,4-7,8-15,16-31,32-63...=2^1-1, 2^2-1, 2^3-1...=2^g-1 if indiv == ((2**generation) - 1): genbase = indiv generation += 1 odds = 1 else: odds += 2 # 3,5,7,9,11,13,15,17... c.endPage() c.finish() def drawrect(c, rectleft, rectbottom, rectwidth, rectheight, twixtspace, margin, indiv, row, generation, label): green=0.0 opacity=0.125 # starter individual always odd regardless of sex if indiv == 1: #then purple red=1.0 blue=1.0 elif indiv % 2 == 1: red=1.0 blue=0.0 else: red=0.0 blue=1.0 c.setRGBFillColor(red, green, blue, opacity) # xorig, yorig, width, height ; so top is yorig+height=420 recttop = rectbottom + rectheight rectright = rectleft + rectwidth print " rectleft=" + str(rectleft) + " rectright=" + str(rectright) + " rectbottom=" + str(rectbottom) + " recttop=" + str(recttop) print label + "\n" c.addRect(CGRectMake(rectleft, rectbottom, rectwidth, rectheight)) c.fillPath() textcolor = (0.1, 0.1, 0.8) font_name = 'Monaco' fontsize=10.0 c.saveGState() c.setRGBFillColor(textcolor[0], textcolor[1], textcolor[2], 1) c.setTextDrawingMode(kCGTextFill) c.setTextMatrix(CGAffineTransformIdentity) c.selectFont(font_name, fontsize, kCGEncodingMacRoman) c.translateCTM(rectleft+5, rectbottom+5) c.showTextAtPoint(0, 0, label, len(label)) c.restoreGState() #restore state, transform, etc. indiv = 0 # automagical iterator does not work in my version of python namesfile = open("names.txt","r") while 1: name = namesfile.readline() if not name: break indiv += 1 namesfile.close() # if there are indiv individuals there are ?? generations #1=1 and 1 row #3=2 and 3 rows #7=3 and 7 rows each individual gets a row #15=4 #31=5 #64=6 #128=7 #256=8 #512=9 #1024=10 #2048=11 #4096=12 each power-of-2 individuals get a generation generations = int(math.log(indiv+1,2)) print " individuals=" + str(indiv) + " generations=" + str(generations) namesfile = open("names.txt","r") layout(indiv, generations, namesfile) namesfile.close() #Now, try to open pdf back up and check page count #print "%d image files" % len(args) #print "Wrote output: \'%s\', %d pages, %dK bytes" % (output_file, len(pages), os.path.getsize(output_file)/1024) pdf = CGPDFDocumentCreateWithProvider (CGDataProviderCreateWithFilename("rectangles.pdf")) #print "%s: %d pages" % "circle.pdf", pdf.getNumberOfPages() #print("%s: %d pages" % "circle.pdf", pdf.getNumberOfPages()) print "rectangles.pdf" + ": ", pdf.getNumberOfPages(), "pages\n"