"""
File:     Zweistrahlinterferometrie von Doppelsternen.py
Author:   Olaf Fischer, HdA
  
Beschreibung:
Das wesentliche Ziel des Programms ist die grafische Ausgabe der relativen
Intensitätsverteilungen nach Beugung und Interferenz des Lichts von 
Doppelsternen am Doppelspalt für einen anzugebenden Winkelbereich 
in Abhängigkeit von der Spaltbreite (diese Abhängigkeit wird zum Teil 
vernachlässigt), vom Spaltabstand, von der Wellenlänge des als monochromatisch 
angenommenen Lichts der als Punktquellen angenommenen Doppelsternen bei 
gegebenem Winkelabstand und mit gegebenem Intensitätsverhätnis des Lichts von 
Komponente B zu Komponente A.
"""
#==============================================================================
"""
IMPORTE aller für das Programm notwendiger Programmbibliotheken:
 - mathematische Funktonen (math)
 - einfache Behandlung von Arrays (munpy)
 - grafische Ausgabe (matplotlib)
"""   
import math
import numpy as np
import matplotlib.pyplot as plt


#==============================================================================
# Eingaben zur Doppelsterninterferometrie
# EINGABEN (z.B. b_mm = 4, d_mm = 27, lambd_micro = 0,525, rho_sek = 2, w = 1)
print()
print("Doppelsterninterferometrie - Eingaben".upper())
# ------------------------->  EINGABE: Spaltbreite in mm
b_mm = 4
# Spaltbreite in m: b
b = b_mm / 1000
# ------------------------->  EINGABE: Spaltabstand in mm
d_mm = 27
# Spaltabstand in m: d
d = d_mm / 1000
# ------------------------->  EINGABE: Wellenlänge in Mikrometer 
lambd_micro = 0.525
# Wellenlänge in Meter: lambd
lambd = lambd_micro / 1000000
# ------------------------->  EINGABE: Winkelabstand zwischen den Doppelstern-
#                                      komponenten A und B in Bogensekunden 
rho_sek = 2 
# Winkelabstand in Grad: rho
rho = rho_sek / 3600 * np.pi / 180
# ------------------------->  EINGABE: Intensitätsverhältnis I_B / I_A) der 
#                                      Doppelsternkomponenten (w, 0 ...1)
w = 1.0
# ------------------------->  EINGABE: Winkelbereich der ausgegebenen 
#                                      Intensitätsverteilung in Bogensekunden  
a_limit = 30
#Erzeugung der Ausgabewinkelliste
a_list = np.linspace(-a_limit, a_limit, 20000) 
a_list_deg = a_list / 3600 * np.pi / 180

#==============================================================================
# Übersicht zu den Eingabewerten
print("\x1B[31m   Spaltbreite in mm = \x1B[0m",b_mm)
print("\x1B[31m   Spaltabstand in mm = \x1B[0m",d_mm)
print("\x1B[31m   Wellenlänge in Mikrometer  = \x1B[0m",lambd_micro)
print("\x1B[31m   Winkelabstand zwischen den Doppelsternkomponenten A und B \x1B[0m")
print("\x1B[31m      in Bogensekunden  = \x1B[0m",rho_sek)
print("\x1B[31m   Intensitätsverhältnis I_B / I_A) der  \x1B[0m")
print("\x1B[31m      Doppelsternkomponenten (w, 0 ...1)  = \x1B[0m",w)
print("\x1B[31m   Winkelbereich der ausgegebenen Intensitätsverteilung \x1B[0m")
print("\x1B[31m      in Bogensekunden (-a_limit ... a_limit) = \x1B[0m",a_limit)

#==============================================================================
# Definition von Funktionen zur Berechnung der Intensitätsverteilungen und
# zur Grafikausgabe

def Doppelsterninterferogramm(b,d,rho,lambd,w,a_list_deg):
    #--------------------------------------------------------------------------
    # Berechnung der Intensität für Doppelsternkomponente A (die hellere Komponent)
    argb_A = math.pi * b * np.sin(a_list_deg) / lambd
    argd_A = math.pi * d * np.sin(a_list_deg) / lambd
    I_list_A = np.cos(argd_A)**2 * (np.sin(argb_A) / argb_A)**2
    # Berechnung der Intensität für Doppelsternkomponente B 
    # (die i.d.R. um den Winkel roho verschobene schwächere Komponente)
    argb_B = math.pi * b * np.sin(a_list_deg + rho) / lambd
    argd_B = math.pi * d * np.sin(a_list_deg + rho) / lambd
    I_list_B = np.cos(argd_B)**2 * (np.sin(argb_B) / argb_B)**2
    # Inkohärente Summe der Intensitäten der Doppelsternkomponenten A+B 
    I_list = I_list_A + I_list_B
    return(I_list_A, I_list_B, I_list)
    #--------------------------------------------------------------------------
    
def Interferogrammgrafik(winkelliste, intensitätsliste, w, label_y, titel):
    maxwinkel = max(winkelliste)
    #--------------------------------------------------------------------------
    # Die Intensitäten (Die Werte aus 'intensitätsliste' werden im Diagramm 
    # in Abhängigkeit vom Ablenkwinkel aus der 'winkelliste' im Sehfeld ausgegeben
    ax.scatter(winkelliste, intensitätsliste, s = 0.2, marker = 'o', color='gray')
    ax.set_title("Interferogramm nach Doppelspalt: Komponente A")
    ax.title.set_fontsize(12)
    # Bereich der x-Achse
    ax.set_xlim([-maxwinkel, maxwinkel])
    # Bezeichnunmg der x-Achse, Zeichengröße
    ax.set_xlabel(r'$\alpha $ ["]')
    ax.xaxis.label.set_fontsize(16)
    # Bereich, Bezeichnung und Zeichengröße für y-Achse
    ax.set_ylim([0, 1+w])
    ax.set_ylabel(label_y)
    ax.yaxis.label.set_fontsize(16)
    ax.grid()
    return()
    #-------------------------------------------------------------------------
    
#==============================================================================
# Hauptprogramm - Interferogramme
    
# Berechnung der Intensitätsverläufe der Interferogramme    
I_list_A, I_list_B, I_list = Doppelsterninterferogramm(b,d,rho,lambd,w,a_list_deg)  
 
# Festlegung der Größe der Zeichenfläche in inch (=2,54 cm)
fig = plt.figure(figsize = (18, 4))
# Die Zeichenebene wird in 6 gleich große Bereiche (3 Spalten, 2 Zeilen) unterteilt
# Hier wird in den linken oberen Bereich gedruckt

# Grafikausgabe der Intensitätsverteilung des Interferogramms für Komponente A
ax=fig.add_subplot(131)   
titel = "Summe der Interferogramme (Komp. A + Komp. B)" 
y_label = '$I_\mathrm{A}$ = 1'
Interferogrammgrafik(a_list, I_list_A, w, y_label, titel)   
# Grafikausgabe der Intensitätsverteilung des Interferogramms für Komponente B 
ax=fig.add_subplot(132) 
y_label = '$I_\mathrm{A} \cdot w$'
titel = "Summe der Interferogramme (Komp. A + Komp. B)" 
Interferogrammgrafik(a_list, I_list_B, w, y_label, titel)  
# Grafikausgabe der Intensitätsverteilung der sich inkohärent überlagernden
# Interferogramme von Komponente A und Komponente B
ax=fig.add_subplot(133) 
y_label = '$I_\mathrm{A} + I_\mathrm{B}$'
titel = "Summe der Interferogramme (Komp. A + Komp. B)" 
Interferogrammgrafik(a_list, I_list, w, y_label, titel)       

# Ausgabe der Eingabewerte in Grafik
ax=fig.add_subplot(131) 
plt.text(-a_limit-10, -0.55, 'Spaltbreite = {:.1f} mm'.format(b_mm),\
         fontsize=12, color='black')
plt.text(-a_limit+26, -0.55, 'Spaltabstand = {:.1f} mm'.format(d_mm),\
         fontsize=12, color='black')
plt.text(-a_limit+66, -0.55, 'Wellenlänge = {:.3f} \u03bcm'.format(lambd_micro),\
         fontsize=12, color='black')    
plt.text(-a_limit-10, -0.75, 'Doppelsternabstand = {:.1f}"'.format(rho_sek),\
         fontsize=12, color='black')
plt.text(-a_limit+26, -0.75, 'Intensitätsverhältnis IB/IA = {:.1f}'.format(w), \
         fontsize=12, color='black')

# Dateiausgabe der Grafik
plt.savefig("Interferogramme.png", dpi=100, bbox_inches='tight', pad_inches = 0)
plt.show()
    


#==============================================================================
# Berechnung und Anzeige der Minima und Maxima im Kontrast der Überlagerung
# der Interferogrammme von Komponente A und Komponente B

# Je 3 Minima und 3 Maxima werden ausgegeben
lst_min = [1,3,5]
lst_max = [0,2,4]
n_list_min = np.array(lst_min)
n_list_max = np.array(lst_max)

# Mmaximal möglicher Doppelspaltabstand im mm (Durchmesser Fernrohröffnung)
dmax=100

# Grafik: Druckbereich in inch und Strukturierung in Teilbereiche (hier nur
# ein Bereich)
fig = plt.figure(figsize = (4, 4))
ax=fig.add_subplot(111) 
 
# Berechnung der Doppelspaltabstände dmin, die zu Minima führen (in mm)
d_list_min = n_list_min/2.0 * 206265 * lambd / rho_sek * 1000
d_list_max = n_list_max/2.0 * 206265 * lambd / rho_sek * 1000

# Druckausgabe in Diagramm (d_list_min in Abhängigkeit von n_list_min 
# und d_list_max von n_list_max)
ax.scatter(n_list_min, d_list_min, s = 30, marker = 'o', color='lightgray')
ax.scatter(n_list_max, d_list_max, s = 30, marker = 'o', color='black')

# Diagrammtitel
ax.set_title('Maxima und Minima bei Doppelspaltabständen d$_\mathrm{min}$')
ax.title.set_fontsize(12)
# x-Achse: Bereich und Beschriftung
lstmax=max(lst_min)
ax.set_xlim([0, lstmax])
ax.set_xlabel('n')
ax.xaxis.label.set_fontsize(16)
# y-Achse: Bereich und Beschriftung
ax.set_ylim([0, dmax])
ax.set_ylabel('d$_\mathrm{Extremwert}$ [mm]')
ax.yaxis.label.set_fontsize(16)
# Ausgabe der Zahlenwerte für die Doppelspaötabstände für Maxima und Minima
# im Kontrast
plt.text(5.3, dmax-27, 'Maximum 0 bei = {:.1f} mm'.format(d_list_max[0]), \
         fontsize=12, color='black')
plt.text(5.3, dmax-34, 'Minimum 1 bei = {:.1f} mm'.format(d_list_min[0]), \
         fontsize=12, color='lightgray')
plt.text(5.3, dmax-41, 'Maximum 1 bei = {:.1f} mm'.format(d_list_max[1]), \
         fontsize=12, color='black')
plt.text(5.3, dmax-48, 'Minimum 2 bei = {:.1f} mm'.format(d_list_min[1]), \
         fontsize=12, color='lightgray')
plt.text(5.3, dmax-55, 'Maximum 2 bei = {:.1f} mm'.format(d_list_max[2]), \
         fontsize=12, color='black')
plt.text(5.3, dmax-62, 'Minimum 3 bei = {:.1f} mm'.format(d_list_min[2]), \
         fontsize=12, color='lightgray')

# Dateiausgabe der Grafik
plt.savefig("Minima und Maxima im Kontrast.png", dpi=100, bbox_inches='tight', pad_inches = 0)
plt.show()
    
    
    
    
    





