import sys #Wird benötigt, um auf Argumente im Terminal-Befehl zugreifen zu können.
import math #Wird benötigt, um den Tangens von spectrum_angle berechnen zu können.
import time #Wird benötigt, um den Prozess einige Sekunden zu pausieren, damit die Kamera aufwärmen kann.
import picamera #Wird benötigt, um auf das Raspberry Pi Camera Module V2 zugreifen zu können.
import csv #Wird benötigt, um auf die .csv-Datei des Referenzspektrums Zugriff zu erhalten.
from fractions import Fraction #Wird benötigt, um mit rationalen Zahlen rechnen zu können.
from collections import OrderedDict #Eine Unterklasse von "dict", die sich an die Reihenfolge erinnert, in der Einträge hinzugefügt wurden.
from PIL import Image, ImageDraw, ImageFile, ImageFont #"Python Image Library" - Wird für die Zeichnung des Overlays benötigt.











#--------Einstellungen-----------------------------------------------------------------------------------------------------------------------------
Speicherpfad = "/home/pi/LambdaSpektrometer"
        # Der Speicherpfad, unter dem der Programmordner gespeichert ist.
        # Das Argument hinter dem letzten Schrägstrich ist der Name des Ordners.
        
resolution = 2 #Mit "1" hat Spektrum eine Auflösung von 630x310, mit "2" 1260x620.
#--------------------------------------------------------------------------------------------------------------------------------------------------




# Scanne die vertikale Achse durch den Spalt, um dessen obere und untere Grenze zu finden.
def get_spectrum_y_bound(pix, x, middle_y, spectrum_threshold, spectrum_threshold_duration):
    c = 0
    spectrum_top = middle_y
    for y in range(middle_y, 0, -1): #Analysiert die Helligkeit entlang der vertikalen Gerade durch das gegebene x. Gibt die obere Grenze des Spalts an. 
        r, g, b = pix[x, y] #pix gibt ein Dreitupel der Helligkeitswerte für rot, grün und blau aus (Maxiumum: 255, 255, 255)
        brightness = r + g + b
        if brightness < spectrum_threshold:
            c = c + 1
            if c > spectrum_threshold_duration:
                break
        else:
            spectrum_top = y
            c = 0
    c = 0
    spectrum_bottom = middle_y
    for y in range(middle_y, middle_y * 2, 1): #Analysiert die Helligkeit entlang der vertikalen Gerade durch das gegebene x. Gibt die untere Grenze des Spalts an.
        r, g, b = pix[x, y] #pix gibt ein Dreitupel der Helligkeitswerte für rot, grün und blau aus (Maxiumum: 255, 255, 255)
        brightness = r + g + b
        if brightness < spectrum_threshold:
            c = c + 1
            if c > spectrum_threshold_duration:
                break
        else:
            spectrum_bottom = y
            c = 0
    return spectrum_top, spectrum_bottom #Das Ergebnis ist ein Dublett der y-Koordinaten der Ober- und Untergrenze des Spalts.




# Finde den Spalt auf der rechten Seite des Bildes entlang der mittleren horizontalen Gerade.
def find_aperture(pic_pixels, pic_width: int, pic_height: int) -> object:
    middle_x = int(pic_width / 2) #x-Koordinate der Mitte des Bildes.
    middle_y = int(pic_height / 2) #y-Koordinate der Mitte des Bildes.
    aperture_brightest = 0
    aperture_x = 0
    for x in range(middle_x, pic_width, 1): #Scannt nach der hellsten x-Koordinate auf der rechten Seite des Bildes entlang der mittleren horizontalen Gerade.
        r, g, b = pic_pixels[x, middle_y]
        brightness = r + g + b
        if brightness > aperture_brightest:
            aperture_brightest = brightness
            aperture_x = x
    aperture_threshold = aperture_brightest * 0.9
    aperture_x1 = aperture_x
    for x in range(aperture_x, middle_x, -1): #Ermittelt die x-Koordinate mit 90% der Helligkeit links von der hellsten x-Koordinate.
        r, g, b = pic_pixels[x, middle_y]
        brightness = r + g + b
        if brightness < aperture_threshold:
            aperture_x1 = x
            break
    aperture_x2 = aperture_x
    for x in range(aperture_x, pic_width, 1): #Ermittelt die x-Koordinate mit 90% der Helligkeit rechts von der hellsten x-Koordinate.
        r, g, b = pic_pixels[x, middle_y]
        brightness = r + g + b
        if brightness < aperture_threshold:
            aperture_x2 = x
            break
    aperture_x = (aperture_x1 + aperture_x2) / 2 #Berechnet die x-Koordinate der Mitte des Spalts auf der mittleren horizontalen Gerade.
    spectrum_threshold_duration = 64
    aperture_y_bounds = get_spectrum_y_bound(pic_pixels, aperture_x, middle_y, aperture_threshold, spectrum_threshold_duration)
    aperture_y = (aperture_y_bounds[0] + aperture_y_bounds[1]) / 2 #Berechnet die y-Koordinate der Mitte des Spalts.
    aperture_height = (aperture_y_bounds[1] - aperture_y_bounds[0]) * 1.0 #Berechnet die Höhe des Spalts in Pixeln.
    return {'x': aperture_x, 'y': aperture_y, 'h': aperture_height, 'b': aperture_brightest}




# Zeichne den detektierten Spalt auf das Bild.
def draw_aperture(aperture, draw):
    fill_color = "#000" #"#000" ist schwarz.
    draw.line((aperture['x'], aperture['y'] - aperture['h'] / 2, aperture['x'], aperture['y'] + aperture['h'] / 2),
              fill=fill_color)




# Zeichne die Scanlinien.
def draw_scan_line(aperture, draw, spectrum_angle):
    fill_color = "#888" #"#888" ist grau.
    xd = aperture['x'] #x-Koordinate des Spalts.
    h = aperture['h'] / 2 #Hälfte der Höhe des Spalts.
    y0 = math.tan(spectrum_angle) * xd + aperture['y'] #math.tan(x) gibt den Tangens von x (Bogenmaß!) an.
    draw.line((0, y0 - h, aperture['x'], aperture['y'] - h), fill=fill_color) #Zeichnet die obere Scanlinie.
    draw.line((0, y0 + h, aperture['x'], aperture['y'] + h), fill=fill_color) #Zeichnet die untere Scanlinie.




# Erstelle eine visuelle RGB-Repräsentation der Wellenlängen für das Spektrum.
# Grenzen = [ 380,     400,  440,    460,      490,    580,  780]
#             violett  blau  türkis  hellgrün  orange  rot  
def wavelength_to_color(lambda2):
    factor = 0.0
    color = [0, 0, 0]
    thresholds = [380, 400, 440, 460, 490, 580, 780]
    for i in range(0, len(thresholds) - 1, 1): #len() gibt die Anzahl der Einträge in einem Objekt an.
        t1 = thresholds[i]
        t2 = thresholds[i + 1]
        if lambda2 < t1 or lambda2 >= t2: #Stellt sicher, dass nur Wellenlängen im gesuchten Bereich untersucht werden.
            continue
        if i % 2 != 0: #"Wenn i ungerade ist..."
            tmp = t1
            t1 = t2
            t2 = tmp
        if i < 5:
            color[i % 3] = (lambda2 - t2) / (t1 - t2)
        color[2 - int(i / 2)] = 1.0
        factor = 1.0
        break

    # Lasse die Intensität nahe der Grenzen der Sichtbarkeit des Lichts abfallen.
    if 380 <= lambda2 < 420:
        factor = 0.2 + 0.8 * (lambda2 - 380) / (420 - 380)
    elif 600 <= lambda2 < 780:
        factor = 0.2 + 0.8 * (780 - lambda2) / (780 - 600)
    return int(255 * color[0] * factor), int(255 * color[1] * factor), int(255 * color[2] * factor)




#Einstellungen der Kamera
def take_picture(name, shutter):
    camera = picamera.PiCamera()
    try:
        camera.vflip = True
        camera.rotation = 90
        camera.framerate = Fraction(1, 2)
        camera.shutter_speed = shutter
        camera.iso = 100
        camera.exposure_mode = 'off'
        camera.awb_mode = 'off'
        camera.awb_gains = (1, 1)
        time.sleep(3)
        camera.capture(name, resize=(1296, 972))
    finally:
        camera.close()
    return name




# Zeichne das Overlay auf das Bild. 
def draw_graph(draw, pic_pixels, aperture: object, spectrum_angle, wavelength_factor):
    aperture_height = aperture['h'] / 2 #Hälfte der Höhe des Spalts in Pixeln.
    step = 1
    last_graph_y = 0
    max_result = 0
    results = OrderedDict() #Spezielle Form von "dictionary", die sich an die Reihenfolge erinnert, in der die Einträge hinzugefügt wurden. 
    for x in range(0, int(aperture['x'] * 7 / 8), step):
        wavelength = (aperture['x'] - x) * wavelength_factor #Für alle x zwischen 0 und 7/8 mal dem x-Wert des Spalts wird wavelength definiert.
        if 1000 < wavelength or wavelength < 380:
            continue #Stellt sicher, dass nur Werte zwischen 380 und 1000 analysiert werden.

        # Allgemeine Effizienz von 1000 Linien/mm Diffraktionsgitter
        eff = (800 - (wavelength - 250)) / 800
        if eff < 0.3:
            eff = 0.3

        y0 = math.tan(spectrum_angle) * (aperture['x'] - x) + aperture['y'] #math.tan(x) gibt den Tangens von x (Bogenmaß!) an.
        amplitude = 0
        ac = 0.0
        for y in range(int(y0 - aperture_height), int(y0 + aperture_height), 1): 
            r, g, b = pic_pixels[x, y]
            q = r + b + g * 2
            if y < (y0 - aperture_height + 2) or y > (y0 + aperture_height - 3):
                q = q * 0.5
            amplitude = amplitude + q
            ac = ac + 1.0
        amplitude = amplitude / ac / eff
        results[str(wavelength)] = amplitude #Jedem wavelength-Wert wird ein amplitude-Wert zugeordnet.
        if amplitude > max_result:
            max_result = amplitude #Gibt nach vollem Durchlauf der for-Schleife den höchsten Wert der amplitude-Folge an.
        graph_y = amplitude / 50 * aperture_height
        draw.line((x - step, y0 + aperture_height - last_graph_y, x, y0 + aperture_height - graph_y), fill="#fff") #Zeichnet eine weiße Strecke vom y-Wert von x bis zum y-Wert von x+1.
        last_graph_y = graph_y
    draw_ticks_and_frequencies(draw, aperture, spectrum_angle, wavelength_factor)
    return results, max_result #Das Ergebnis ist ein Dublett




#Zeichne Skalenmarkierungen und Beschriftungen auf das Bild mit Overlay.
def draw_ticks_and_frequencies(draw, aperture, spectrum_angle, wavelength_factor):
    aperture_height = aperture['h'] / 2
    for wl in range(400, 1001, 50):
        x = aperture['x'] - (wl / wavelength_factor)
        y0 = math.tan(spectrum_angle) * (aperture['x'] - x) + aperture['y'] #math.tan(x) gibt den Tangens von x (Bogenmaß!) an.
        draw.line((x, y0 + aperture_height + 5, x, y0 + aperture_height - 5), fill="#fff") #"#fff" ist weiß.
        font = ImageFont.truetype('/usr/share/fonts/truetype/lato/Lato-Regular.ttf', 12)
        draw.text((x, y0 + aperture_height + 15), str(wl), font=font, fill="#fff") #"#fff" ist weiß.




# Speichere das Bild mit Overlay.
def save_image_with_overlay(im, name):
    output_filename = name + "_Overlay.jpg"
    ImageFile.MAXBLOCK = 2 ** 20
    im.save(output_filename, "JPEG", quality=80, optimize=True, progressive=True)




# Speichere die Ergebnisse der Einzelmessung als .csv-Datei.
def export_csv(name, results):
    Settings = Speicherpfad + "/Settings.txt"
    with open(Settings, "r") as sf:
        csv_mode = sf.readlines()[10].lstrip("csv_mode = ").rstrip("\n")
    print("csv_mode=", csv_mode)
    csv_filename = name + ".csv"
    csv_new = open(csv_filename, 'w')
    if csv_mode == "English":
        csv_new.write("Wellenlänge [nm],Intensität (Referenzmessung),Intensität,Extinktion\n")
    else:
        csv_new.write("Wellenlänge [nm];Intensität (Referenzmessung);Intensität;Extinktion\n")
    with open(Speicherpfad + "/Reference_files/reference.csv") as reference_csv_file:
        if csv_mode == "English":
            reference_csv = csv.reader(reference_csv_file, delimiter=",")
        else:
            reference_csv = csv.reader(reference_csv_file, delimiter=";")
        rr = []
        rw = []
        line_count = 0
        for row in reference_csv:
            if line_count == 0:
                line_count += 1
            else:
                if csv_mode == "English":
                    reference_intensity = row[1]
                    reference_wavelength = row[0]
                else:
                    reference_intensity = row[1].replace(",", ".")
                    reference_wavelength = row[0].replace(",", ".")
                if float(reference_intensity) == 0:
                    reference_intensity = 0.00001
                line = line_count
                line_count += 1
                rr.append(float(reference_intensity))
                rw.append(float(reference_wavelength)) 
    i = 0
    diff = len(results) - len(rr) + 1
    for wavelength in results:
        diff = diff - 1
        if diff > 0: #Wenn mehr Wellenlängen als in der Referenzmessung untersucht wurden werden diese Werte übersprungen
            continue
        if i == 0 and len(rr) - len(results) > 0: #Wenn weniger Wellenlängen als in der Referenzmessung untersucht wurden werden leere Einträge hinzugefügt.
            for j in range(0, len(rr) - len(results), 1):
                if csv_mode == "English":
                    csv_new.write(str(rw[i]))
                    csv_new.write(",")
                    csv_new.write(str(rr[i]))
                    csv_new.write(",")
                    csv_new.write(" ")
                    csv_new.write(",")
                    csv_new.write(" ")
                    csv_new.write("\n")
                    i += 1
                else:
                    csv_new.write(str(rw[i]).replace(".", ","))
                    csv_new.write(";")
                    csv_new.write(str(rr[i]).replace(".", ","))
                    csv_new.write(";")
                    csv_new.write(" ")
                    csv_new.write(";")
                    csv_new.write(" ")
                    csv_new.write("\n")
                    i += 1
        if csv_mode == "English":
            csv_new.write(str(rw[i]))
            csv_new.write(",")
            csv_new.write(str(rr[i]))
            csv_new.write(",")
            csv_new.write("{:0.3f}".format(results[wavelength]))
            csv_new.write(",")
            csv_new.write("{:0.3f}".format((-1) * math.log10(results[wavelength] / rr[i])))
            csv_new.write("\n")
            i += 1
        else:
            csv_new.write(str(rw[i]).replace(".", ","))
            csv_new.write(";")
            csv_new.write(str(rr[i]).replace(".", ","))
            csv_new.write(";")
            csv_new.write(str("{:0.3f}".format(results[wavelength])).replace(".", ","))
            csv_new.write(";") 
            csv_new.write(str("{:0.3f}".format((-1) * math.log10(results[wavelength] / rr[i]))).replace(".", ","))
            csv_new.write("\n")
            i += 1

    csv_new.close()

    
    

# Speichere die Ergebnisse der Messreihe als .csv-Datei.
def append_to_csv(name, name2, results, mode, iteration): #results zu bereits bestehender .csv-Datei hinzufügen.
    if mode == "Erweitert" and iteration > 2:
        last_csv_filename = name2 + "_" + str(iteration - 1) + ".csv"
    else:
        last_csv_filename = name2 + ".csv"
    previous_intensities = [0]
    previous_absorptions = [0]
    line_count = 0
    pi = []
    pa = []
    Settings = Speicherpfad + "/Settings.txt"
    with open(Settings, "r") as sf:
        csv_mode = sf.readlines()[10].lstrip("csv_mode = ").rstrip("\n")
    print("csv_mode=", csv_mode)    
    for x in range(1, iteration, 1):
        with open(last_csv_filename) as last_csv_file:
            if csv_mode == "English":
                last_csv = csv.reader(last_csv_file, delimiter=",")
            else:
                last_csv = csv.reader(last_csv_file, delimiter=";")
            for row in last_csv:
                if line_count == 0:
                    line_count += 1
                else:
                    intensity = row[2 * x]
                    absorption = row[2 * x + 1]
                    pi.append(intensity)
                    pa.append(absorption)
            previous_intensities.append(pi)
            previous_absorptions.append(pa)
            pi = []
            pa = []
            line_count = 0
        last_csv_file.close()
    csv_filename = name + ".csv"
    csv_new = open(csv_filename, 'w')
    if csv_mode == "English":
        headings = "Wellenlänge [nm],Intensität (Referenzmessung)"
        for i in range(1, iteration + 1, 1):
            headings = headings + ",Intensität (" + str(i) + "),Extinktion (" + str(i) + ")"
    else:
        headings = "Wellenlänge [nm];Intensität (Referenzmessung)"
        for i in range(1, iteration + 1, 1):
            headings = headings + ";Intensität (" + str(i) + ");Extinktion (" + str(i) + ")"
    headings = headings + "\n"        
    csv_new.write(headings)
    with open(Speicherpfad + "/Reference_files/reference.csv") as reference_csv_file:
        if csv_mode == "English":
            reference_csv = csv.reader(reference_csv_file, delimiter=",")
        else:
            reference_csv = csv.reader(reference_csv_file, delimiter=";")
        rr = []
        rw = []
        line_count = 0
        for row in reference_csv:
            if line_count == 0:
                line_count += 1
            else:
                if csv_mode == "English":
                    reference_intensity = row[1]
                    reference_wavelength = row[0]
                else:
                    reference_intensity = row[1].replace(",", ".")
                    reference_wavelength = row[0].replace(",", ".")
                if float(reference_intensity) == 0:
                    reference_intensity = 0.00001
                line = line_count
                line_count += 1
                rr.append(float(reference_intensity))
                rw.append(float(reference_wavelength))    
    i = 0
    diff = len(results) - len(rr) + 1
    for wavelength in results:
        diff = diff - 1
        if diff > 0: #Wenn mehr Wellenlängen als in der Referenzmessung untersucht wurden werden diese Werte übersprungen
            continue
        if i == 0 and len(rr) - len(results) > 0: #Wenn weniger Wellenlängen als in der Referenzmessung untersucht wurden werden leere Einträge hinzugefügt.
            for j in range(0, len(rr) - len(results), 1):
                if csv_mode == "English":
                    csv_new.write(str(rw[i]))
                    csv_new.write(",")
                    csv_new.write(str(rr[i]))
                    csv_new.write(",")
                    for x in range(1, iteration, 1):
                        csv_new.write(str(previous_intensities[x][i]))
                        csv_new.write(",")
                        csv_new.write(str(previous_absorptions[x][i]))
                        csv_new.write(",")            
                    csv_new.write(" ")
                    csv_new.write(",")
                    csv_new.write(" ")
                    csv_new.write("\n")
                    i += 1
                else:
                    csv_new.write(str(rw[i]).replace(".", ","))
                    csv_new.write(";")
                    csv_new.write(str(rr[i]).replace(".", ","))
                    csv_new.write(";")
                    for x in range(1, iteration, 1):
                        csv_new.write(str(previous_intensities[x][i]))
                        csv_new.write(";")
                        csv_new.write(str(previous_absorptions[x][i]))
                        csv_new.write(";")            
                    csv_new.write(" ")
                    csv_new.write(";")
                    csv_new.write(" ")
                    csv_new.write("\n")
                    i += 1
        if csv_mode == "English":
            csv_new.write(str(rw[i]))
            csv_new.write(",")
            csv_new.write(str(rr[i]))
            csv_new.write(",")
            for x in range(1, iteration, 1):
                csv_new.write(str(previous_intensities[x][i]))
                csv_new.write(",")
                csv_new.write(str(previous_absorptions[x][i]))
                csv_new.write(",") 
            csv_new.write("{:0.3f}".format(results[wavelength]))
            csv_new.write(",")
            csv_new.write("{:0.3f}".format((-1) * math.log10(results[wavelength] / rr[i])))
            csv_new.write("\n")
            i += 1
        else:
            csv_new.write(str(rw[i]).replace(".", ","))
            csv_new.write(";")
            csv_new.write(str(rr[i]).replace(".", ","))
            csv_new.write(";")
            for x in range(1, iteration, 1):
                csv_new.write(str(previous_intensities[x][i]))
                csv_new.write(";")
                csv_new.write(str(previous_absorptions[x][i]))
                csv_new.write(";") 
            csv_new.write(str("{:0.3f}".format(results[wavelength])).replace(".", ","))
            csv_new.write(";")
            csv_new.write(str("{:0.3f}".format((-1) * math.log10(results[wavelength] / rr[i]))).replace(".", ","))
            csv_new.write("\n")
            i += 1
    csv_new.close()




# Zeichne Spektrum.
def export_diagram(name, results):
    antialias = 4
    w = resolution * 630 * antialias #Breite des gesamten Bildes
    h2 = resolution * 310 * antialias #Höhe des gesamten Bildes

    h = h2 - resolution* 25 * antialias #y-Koordinate der x-Achse
    l = resolution * 25 * antialias #x-Koordinate des linken Randes
    r = resolution * 5 * antialias #x-Koordinate des rechten Randes
    o = resolution * 5 * antialias #y-Koordinate des oberen Randes
    sd = Image.new('RGB', (w, h2), (255, 255, 255))
    draw = ImageDraw.Draw(sd)

    w1 = 380.0
    w2 = 780.0
    f1 = 1.0 / w1
    f2 = 1.0 / w2
    # Zeichne die bunten vertikalen Linien
    for x in range(l, w - r, 1):
        # Ordne Pixeln Wellenlängen zu.
        lambda2 = 1.0 / (f1 - (float(x - l) / float(w - l - r) * (f1 - f2)))
        c = wavelength_to_color(lambda2)
        draw.line((x, o, x, h), fill=c)

    # Zeichne weißes Polygon und lege Skala der y-Achse fest
    pl = [(w - r, 0), (w - r, h)]
    Settings = Speicherpfad + "/Settings.txt"
    with open(Settings, "r") as sf:
        csv_mode = sf.readlines()[10].lstrip("csv_mode = ").rstrip("\n")
    print("csv_mode=", csv_mode)
    with open(Speicherpfad + "/Reference_files/reference.csv") as reference_csv_file: #ReadingWritingCSV
        if csv_mode == "English":
            reference_csv = csv.reader(reference_csv_file, delimiter=",")
        else:
            reference_csv = csv.reader(reference_csv_file, delimiter=";")
        rr = []
        line_count = 0
        for row in reference_csv:
            if line_count == 0:
                line_count += 1
            else:
                if csv_mode == "English":
                    reference_intensity = row[1]
                else:
                    reference_intensity = row[1].replace(",", ".")
                if float(reference_intensity) == 0:
                    reference_intensity = 0.00001
                line = line_count
                line_count += 1
                rr.append(float(reference_intensity))
        diff = len(results) - len(rr) + 1
        if diff - 1 < 0: #Wenn mehr Referenzwerte als Messwerte zur Verfügung stehen
            diff = len(rr)-len(results)
            for x in range(0, len(results) + 1, 1):
                if x + diff >= len(rr):
                    continue
                rr[x] = rr[x + diff]
        i = 0
        max_ext = 0
        diff = len(results) - len(rr) + 1
        for wavelength in results:
            diff = diff - 1
            if diff > 0:
                continue
            ext = (-1) * math.log10(results[wavelength] / rr[i]) #Extinkion
            if ext > max_ext:
                max_ext = ext
            if i < len(rr) - 1:
                i += 1
        if max_ext <= 0.1:
            f = 10
            ii = ("   0", "0,025", " 0,05", "0,075", "  0,1")
        if 0.1 < max_ext <= 0.2:
            f = 5
            ii = ("  0", "0,05", " 0,1", "0,15", " 0,2")
        if 0.2 < max_ext <= 0.4:
            f = 2.5
            ii = ("  0", " 0,1", " 0,2", " 0,3", " 0,4")
        if 0.4 < max_ext <= 0.8:
            f = 1.25
            ii = ("  0", " 0,2", " 0,4", " 0,6", " 0,8")
        if 0.8 < max_ext <= 1:
            f = 1
            ii = ("  0", "0,25", " 0,5", "0,75", "  1")
        if 1 < max_ext <= 2:
            f = 0.5
            ii = ("  0", " 0,5", "  1", " 1,5", "  2")
        if 2 < max_ext <= 4:
            f = 0.25
            ii = ("  0", "  1", "  2", "  3", "  4")
        if 4 < max_ext <= 8:
            f = 0.125
            ii = ("  0", "  2", "  4", "  6", "  8")
        i = 0
        diff = len(results) - len(rr) + 1
        for wavelength in results:
            diff = diff - 1
            if diff > 0:
                continue
            wl = float(wavelength)
            x = l + int((wl - w1) / (w2 - w1) * (w - l - r))                    
            pl.append((int(x), int(o + (1 - (-1) * f * math.log10(results[wavelength] / rr[i])) * (h - o))))
            if i < len(rr) - 1:
                i += 1
        pl.append((l, h))
        pl.append((l, 0))
        draw.polygon(pl, fill="#FFF")
        draw.polygon(pl)

    font = ImageFont.truetype('/usr/share/fonts/truetype/lato/Lato-Regular.ttf', 12 * antialias  * int(resolution / 2))
    font2 = ImageFont.truetype('/usr/share/fonts/truetype/lato/Lato-Regular.ttf', 16 * antialias * int(resolution / 2))
    draw.line((l, h, w - r, h), fill="#000", width=antialias * resolution) #untere x-Achse
    draw.line((l, o, w - r, o), fill="#000", width=antialias * resolution) #obere x-Achse
    draw.line((l, o, l, h), fill="#000", width=antialias * resolution) #linke y-Achse
    draw.line((w - r, o, w - r, h), fill="#000", width=antialias * resolution) #rechte y-Achse

    for wl in range(380, 1001, 10):
        x = l + int((float(wl) - w1) / (w2 - w1) * (w - l - r))
        draw.line((x, h, x, h + 3 * antialias * resolution), fill="#000", width=antialias * resolution) #kleine Markierungen auf unterer x-Achse
        draw.line((x, o, x, o - 3 * antialias * resolution), fill="#000", width=antialias * resolution) #kleine Markierungen auf oberer x-Achse

    for wl in range(400, 1001, 50):
        x = l + int((float(wl) - w1) / (w2 - w1) * (w - l - r))
        draw.line((x, h, x, h + 5 * antialias * resolution), fill="#000", width=antialias * resolution) #große Markierungen auf unterer x-Achse
        draw.line((x, o, x, o - 5 * antialias * resolution), fill="#000", width=antialias * resolution) #große Markierungen auf oberer x-Achse
        wls = str(wl)
        tx = draw.textsize(wls, font=font)
        draw.text((x - tx[0] / 2, h + 5 * antialias * resolution), wls, font=font, fill="#000")
        
    for i in range(0, 101, 5):
        y = o + (100 - i) / 100 * (h - o)
        draw.line((l - 3 * antialias * resolution, y, l, y), fill="#000", width=antialias * resolution) #kleine Markierungen auf linker y-Achse
        draw.line((w - r + 3 * antialias * resolution, y, w - r, y), fill="#000", width=antialias * resolution) #kleine Markierungen auf rechter y-Achse

    for i in range(0, 101, 25):
        y = o + (100 - i) / 100 * (h - o)
        draw.line((l - 5 * antialias * resolution, y, l, y), fill="#000", width=antialias * resolution) #große Markierungen auf linker y-Achse
        draw.line((w - r + 5 * antialias * resolution, y, w - r, y), fill="#000", width=antialias * resolution) #große Markierungen auf rechter y-Achse        
        i2 = int(i / 25)
        tx = draw.textsize(ii[i2], font=font)
        draw.text((l - 15 * antialias * resolution, y - tx[1] / 2), ii[i2], font=font, fill="#000")

    # Beschrifte x-Achse
    x_axis_label = "Wellenlänge [nm]"
    xal = draw.textsize(x_axis_label, font=font)
    draw.text((l + (int((580 - w1) / (w2 - w1) * (w - l - r))) - xal[0] / 2, h + 30 *antialias), text=x_axis_label, font=font2, fill="#000")
    
    # Beschrifte y-Achse
    y_img = Image.open(Speicherpfad + "/Images/yaxis.png")
    y_img = y_img.convert("RGBA")
    
    # Speichere Spektrum.
    sd = sd.resize((int(w / antialias), int(h2 / antialias)), Image.ANTIALIAS)
    sd = sd.convert("RGBA")
    sd2 = Image.alpha_composite(sd, y_img) #PythonPILDrawing
    output_filename = name + "_Spektrum.png"
    sd2.save(output_filename, "PNG", quality=95, optimize=True, progressive=True)




# Hauptfunktion
def main():
    # 1. Schieße Bild
    name2 = sys.argv[1] #Speicherpfad
    shutter = int(sys.argv[2]) #Verschlusszeit
    mode = sys.argv[3] #"Standard" oder "Erweitert"
    iteration = int(sys.argv[4]) #Wievielte Messung in Messreihe
    if mode == "Erweitert" and iteration > 1:
        name = name2 + "_" + str(iteration)
    else:
        name = name2
    raw_filename = name + "_Bild.jpg"
    take_picture(raw_filename,shutter)

    # 2. Finde den Spalt im Bild
    im = Image.open(raw_filename) #Öffnet das Bild.
    pic_pixels = im.load() #Lädt die Informationen über die Pixel des Bildes.
    aperture = find_aperture(pic_pixels, im.size[0], im.size[1]) #im.size[0] ist die Breite, im.size[1] die Höhe des Bildes.

    # 3. Zeichne Spalt und Scanlinie auf das Bild
    Settings = Speicherpfad + "/Settings.txt"
    with open(Settings, "r") as sf:
        sa = sf.readlines()[8].lstrip("spectrum_angle = ").rstrip("\n")
    print("sa=", sa)
    spectrum_angle = float(sa) * -3.14159265359 / 180 #Wandelt die Information in eine Dezimalzahl um, wandelt vom Grad- ins negative Bogenmaß um.
    draw = ImageDraw.Draw(im) #Erstellt ein Objekt, das benutzt werden kann um im Bild zu zeichnen.
    draw_aperture(aperture, draw)
    draw_scan_line(aperture, draw, spectrum_angle)

    # 4. Zeichne Intensitätskurve auf das Bild
    with open(Settings, "r") as sf:
        ss = sf.readlines()[9].lstrip("spectrum_scale = ").rstrip("\n")
    print("ss=", ss)
    wavelength_factor = float(ss) #Wandelt die Information in eine Dezimalzahl um.
    results, max_result = draw_graph(draw, pic_pixels, aperture, spectrum_angle, wavelength_factor)

    # 5. Speichere Bild mit Overlay
    save_image_with_overlay(im, name)

    # 6. Speichere .csv-Datei der Ergebnisse
    if iteration == 1:
        export_csv(name, results)
    else:
        append_to_csv(name, name2, results, mode, iteration)

    # 7. Erstelle Spektrum
    export_diagram(name, results)




main() #Hauptfunktion wird ausgeführt und enthält alle zuvor definierten Vorgänge.
