Math.sin() is giving me Math Domain Error

Question:

I am making a program to create an image of the mandelbrot set as a .ppm file.
I tried implementing a rudimentary version of "normalized iteration count", when math.sin() started giving me a math domain error.
Math.sin() shouldn’t have a domain, right? I’m stumped…

import math
def ask(question):
    return float(input(question))
maxIts=ask("max iterations? ")
size=int(ask("image side length? "))
sideTuple=(round(-size/2),round(size/2))
ppmFile=["P3",str(size),str(size),"255"]
def getV(z,n):
    return n-math.log2(math.log10(z))
def addValue(v):
        for i in range(0,3):
            ppmFile.append(str(math.sin(v)))
def iterate(x,y):
    coord=complex(x,y)
    i=0
    z=coord
    while i<maxIts and z.real<10:
        z=(z*z)+coord
        i+=1
    if z.real>10:
        addValue(getV(z.real,i))
    else:
        ppmFile.append("0 0 0")
def render(x,y,scale):
    for j in range(*sideTuple):
        for i in range(*sideTuple):
            iterate(4*i/(scale*size)+x,4*j/(scale*size)-y)
render(ask("x position? "),ask("y position? "),ask("zoom? "))
newFile=open("brotPPM.ppm","w")
newFile.write(" ".join(ppmFile))
newFile.close

Putting in 256, 1000, 0, 0, and 1 as inputs gave me this:

Traceback (most recent call last):
  File "C:UsersMeDownloadsPythonbrotPPM_v4.py", line 34, in <module>
    render(ask("x position? "),ask("y position? "),ask("zoom? "))
  File "C:UsersMeDownloadsPythonbrotPPM_v4.py", line 32, in render
    iterate(4*i/(scale*size)+x,4*j/(scale*size)-y)
  File "C:UsersMeDownloadsPythonbrotPPM_v4.py", line 24, in iterate
    addValue(getV(z.real,i))
  File "C:UsersMeDownloadsPythonbrotPPM_v4.py", line 13, in addValue
    ppm.append(str(math.sin(v)))
                   ^^^^^^^^^^^
ValueError: math domain error
Asked By: TheGuy888

||

Answers:

If you wrap addValue in a try-catch statement, you can show what value of v or what value of z is the problem.

It turns out to be infinities. Sometimes, the real part of z escapes to infinity, and then you’ll end up with an infinite value being passed to math.sin. Consider mapping infinity to its own colour.

def getV(z, n):
    v = n - math.log2(math.log10(z))
    try:
        return math.sin(v)
    except ValueError:
        return 42 # ??

def addValue(v):
        for i in range(3):
            ppmFile.append(str(v))

By the way, you don’t close the file at the end (unless you forgot to include the parentheses when pasting your code here), which may or may not end up being a problem. By using a context manager, you can be sure the file is closed at the end:

with open("brotPPM.ppm","w") as newFile:
   newFile.write(" ".join(ppmFile))
Answered By: Jasmijn
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.