#!/usr/bin/env python ### graph_iterate_log5.py -- Xtreme version of graph_iterate_log4.py. output_file = "graph_iterate_log5.pdf" # Steve Witham ess doubleyou at tiac remove-this dot net. # http://www.tiac.net/~sw from reportlab.pdfgen import canvas from reportlab.lib.pagesizes import letter, A4 from reportlab.lib.units import inch from reportlab.lib.colors import pink, black, red, blue, green from arrowline import arrowLine from math import sqrt, pow, pi, e from cmath import log, exp, sinh, asinh from os import system # From iterate_log.py: e0 = ( 0.31813150520476413 + 1.3372357014306895j ) BIGGEST = pow(2.0,1023) * (2.0-pow(2.0,-52)) SMALLEST = pow(2,-1074) def graph_iterate_log(c): # choose some colors c.setStrokeColorRGB(0,0,0) c.setFillColorRGB(0,0,0) c.setFont("Helvetica", 14 ) c.drawString( 1 * inch, 10 * inch, "Iterated Complex Natural Log" ) # initial set of points: nPoints = 101 # points = [ 0j + (i+.5)/nPoints for i in range( nPoints ) ] original_points = [ (pi * 1j) + sinh( i/3.0 ) for i in range( -(nPoints-1)/2, nPoints-(nPoints-1)/2 ) ] pmin, pmax = original_points[0].real, original_points[-1].real c.setFont("Helvetica", 11 ) c.drawString( 1 * inch, 9.5 * inch, "Original points at y = pi range from x = %f to %+f ." % ( pmin, pmax ) ) c.drawString( 1 * inch, 9.25 * inch, "(Only those from about -5 to +5 are visible.)" ) # Set the origin in the middle of the page: c.translate( 8.5 * inch / 2, 11 * inch / 2 ) # Scale so that range of the graph is about +/- 5: # NOTE: THIS MEANS LINE WIDTHS AND FONTS AREN'T IN POINTS ANY MORE. c.scale( .7*inch, .7*inch ) point = 1/( .7*inch ) # Draw the axes: c.setLineWidth( .25 * point ) # c.line( -4,0, 4,0 ) # No x axis, it obscures the little arrows. c.line( 0,-4, 0,4 ) points = original_points m = len( points ) / 2 arrows = [ ( points[i], points[i+1], red ) for i in range( 0, m ) ] arrows += [ ( points[i], points[i+1], black ) for i in range( m, len( points ) - 1 ) ] for i in range(4): arrows += [ expsafereal( arrow ) for arrow in arrows ] color = None for i in range(11): print len(arrows), "arrows" newarrows = [ [], [], [], [], [] ] for arrow in arrows: z0, z1, acolor = arrow if z0 == None or z1 == None: continue size = abs( z1 - z0 ) # keep arrows that cross between + and - real: if size < point * .1 and ( z1.real * z0.real ) > 1: continue if z0.imag >= 0 and size < 10 and ( abs( z0 )<10 or abs( z1 )<10 ): if color != acolor: c.setStrokeColor( acolor ) color = acolor c.setLineWidth( size / 10 ) arrowLine( c, z0.real, z0.imag, z1.real, z1.imag ) if z0.imag != 0: # only positive (imaginary) offsets? for k in range( 3 ): newarrows[k].append( logsafe( arrow, k*2j*pi, 1 ) ) for k in range( 1, 3 ): newarrows[ 2 + k ].append( logsafe( arrow, k*2j*pi, -1 ) ) arrows = [] print [ len( a ) for a in newarrows ] for k in range( len( newarrows ) ): arrows += newarrows[k] ticks = [ -1, e**-1, 1, e**(e**-1), e, e**(e**(e**-1)) ] names = [ "-1", "e^-1", "1", "e^e^-1", "e", "e^e^e^-1" ] c.setFont("Helvetica", 10 * point ) c.setLineWidth( .25 * point ) for i in range( len( ticks ) ): x, name = ticks[i], names[i] c.line( x, -.3, x, -.1 ) printexp( c, x, -.55, name, "Helvetica", 10 * point ) def expsafe( z ): if type(z) == tuple: z0, z1, color = z return ( expsafe(z0), expsafe(z1), color ) if z != None and abs(z) < 706: z1 = exp(z) if abs(z1.imag) > 9: print "e^", z, "=", z1 return z1 else: return None def expsafereal( z ): if type(z) == tuple: z0, z1, color = z return ( expsafereal(z0), expsafereal(z1), color ) if z != None and abs(z) < 5: z1 = exp(z) return z1.real+0j else: return None def logsafe( z, more=0, conj=1 ): if type(z) == tuple: z0, z1, color = z return ( logsafe(z0,more,conj), logsafe(z1,more,conj), color ) if z != None: return log( (z.real + conj * z.imag * 1j ) + more ) else: return None def logsafesafe( z, more=0 ): global logsafe if type(z) == tuple: z0, z1, color = z z2, z3 = logsafe(z0+more), logsafe(z1+more) if z2.imag * z3.imag < 0: print (z0,z1), "==>", (z2,z3) logsafe = logsafe0 return ( z2, z3, color ) if z != None: z1 = log( z + more ) if abs(z1.imag) > 9: print "log(", z, "+", more, ") =", z1 return z1 else: return None def printexp( c, x, y, name, fontname, fontsize ): width = c.stringWidth( name.replace('^',''), fontname, fontsize ) pieces = name.split( '^' ) jump = fontsize * .5 y -= ( len(pieces) - 1 ) * jump * .5 x -= width / 2 for piece in pieces: c.drawString( x, y, piece ) x += c.stringWidth( piece, fontname, fontsize ) y += jump # pageCompression = 0 if I can look at the text in the output. # set to 1 in rl_config.py. c = canvas.Canvas( output_file, pagesize=letter ) width, height = letter #keep for later graph_iterate_log(c) c.showPage() c.save() system( "open " + output_file )