Code: Select all
# *******************************************************************************************
#
# SharpCap script "Betelgeuse_2023-11-13.py"
# 2023/11/13 Jean-Francois
#
# Version: 1.0.0: First version
#
# The script works only with a SharpCap PRO version.
#
# *******************************************************************************************
import time
import datetime
import math
import clr
clr.AddReference("Oxyplot")
clr.AddReference("OxyPlot.WindowsForms ")
clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
import OxyPlot
import System.Drawing
import System.Drawing.Drawing2D
import System.Windows.Forms
from System import Array
from System.Drawing import *
from System.Drawing.Drawing2D import GraphicsPath, CustomLineCap, SmoothingMode, LineJoin
from System.Windows.Forms import *
from System.Threading import Thread, ThreadStart, ApartmentState, ParameterizedThreadStart
Mean = 0.0
t0 = 0.0
M00 = 1
M10 = 1
M01 = 1
threshold = 4000
Time_frame = []
Max_frame = []
Surf_spot = []
Surf_value = []
Surf_Ratio = []
dumpdata = False
whitePen = Pen(Color.White, 1)
Pen.DashPattern.SetValue(whitePen, (5, 5))
if SharpCap.SelectedCamera.Controls.ColourSpace.Value == "MONO8":
I_min = 50
I_max = 200
Max_line = 220
Focus_line = 150
if SharpCap.SelectedCamera.Controls.ColourSpace.Value == "MONO16":
I_min = 20000
I_max = 40000
Max_line = 60000
Focus_line = 25000
start_pos = SharpCap.Focusers.SelectedFocuser.Position
#best_focus = 73200
#max_focus = 74400
best_focus = 24500
max_focus = 25500
def beforeframehandler(sender, args):
global M00, M10, M01, whitePen
ROI_X = SharpCap.Transforms.SelectionRect.X
ROI_Y = SharpCap.Transforms.SelectionRect.Y
dbitmap = args.Frame.GetDrawableBitmap()
gbitmap = dbitmap.GetGraphics()
try:
radius = int(math.sqrt(Surf_spot[-1]/6.28))
centerX = ROI_X + M10/M00 - 1
centerY = ROI_Y + M01/M00 - 1
print("Radius : ",radius, " Center: ", centerX, " ", centerY)
gbitmap.DrawEllipse(whitePen, centerX - radius, centerY - radius, radius + radius, radius + radius)
except:
print("Error Bildmap")
gbitmap.Dispose()
dbitmap.Dispose()
return()
def framehandler(sender, args):
global Mean, t0, Time_frame, Max_frame, Surf_spot, Surf_value, Surf_ratio, dumpdata, start_pos, delta_focus, best_focus, max_focus
global M00, M10, M01, whitePen, threshold
form.labelRectangle.Text = "Rectangle: " + str(SharpCap.Transforms.SelectionRect.Width) + " x " \
+ str(SharpCap.Transforms.SelectionRect.Height)
if (dumpdata):
try:
cutout = args.Frame.CutROI(SharpCap.Transforms.SelectionRect)
dt = (datetime.datetime.now() - t0).total_seconds()
Time_frame.append(dt)
data = cutout.ToFloats(0)
info = cutout.Info
temp = Array[System.Single](info.Height,info.Width)
actual_max = 0
#sum_spalten = []
#sum_zeilen = []
for i in range(info.Height):
for j in range(info.Width):
value = data[i,j]
if value > actual_max:
actual_max = value
Max_frame.append(actual_max)
for i in range(1, info.Height - 1):
for j in range(1, info.Width - 1):
temp[i,j] = data[i,0] + ((j - 1)*(data[i,info.Width-1] - data[i,0])/(info.Width - 1)) + \
data[0,j] + ((i - 1)*(data[info.Height-1,j] - data[0,j])/(info.Height - 1))
temp[i,j] = data[i,j] - temp[i,j]/2.0
M00 = 1
M10 = 0
M01 = 0
surface = 0
value = 0
#threshold = 4000
threshold = int(form.textBoxThreshold.Text)
for i in range(info.Height):
for j in range(info.Width):
M00 += temp[i,j]
M01 += (i + 1) * temp[i,j]
M10 += (j + 1) * temp[i,j]
if temp[i,j] > threshold:
surface += 1
value += temp[i,j]
Surf_spot.append(surface)
Surf_value.append(value)
# Surf_ratio.append(value/surface)
print("Max: ", actual_max, ", Centroid: ", M10/M00, ", ", M01/M00, " surface: ", surface)
# print("Preceding surface: ", Surf_spot[-2])
print("Focuser moving :", SharpCap.Focusers.SelectedFocuser.IsMoving)
form.ShowOxyGraphic()
cutout.Release()
if (form.checkbox_focuser.Checked):
if not SharpCap.Focusers.SelectedFocuser.IsMoving:
factor = float(value/Surf_value[0])
neu_pos = int((max_focus - best_focus)*math.sqrt(factor) + best_focus)
print("Pos: ", neu_pos, " , surface: ", surface, " , value: ", value, " , factor: ", factor)
if (factor < 0.5):
#neu_pos = int((max_focus - best_focus)*math.sqrt(factor) + best_focus)
#Focus_Thread(neu_pos)
SharpCap.Focusers.SelectedFocuser.Move(neu_pos)
print()
print("<0.5 Pos: ", neu_pos, " factor: ", factor)
#Surf_value[0] = value
#max_focus = neu_pos
#time.sleep(0.1)
if (factor > 1.1):
#neu_pos = int((max_focus - best_focus)*math.sqrt(factor) + best_focus)
#Focus_Thread(neu_pos)
SharpCap.Focusers.SelectedFocuser.Move(neu_pos)
print()
print("> 1.1 Pos: ", neu_pos, " factor: ", factor)
except:
print("error")
cutout.Release()
return()
def Start_Surface(sender, args):
global Surf_spot, Surf_value, Surf_ratio
cutout = args.Frame.CutROI(SharpCap.Transforms.SelectionRect)
data = cutout.ToFloats(0)
info = cutout.Info
temp = Array[System.Single](info.Height,info.Width)
for i in range(1, info.Height - 1):
for j in range(1, info.Width - 1):
temp[i,j] = data[i,0] + ((j - 1)*(data[i,info.Width-1] - data[i,0])/(info.Width - 1)) + \
data[0,j] + ((i - 1)*(data[info.Height-1,j] - data[0,j])/(info.Height - 1))
temp[i,j] = data[i,j] - temp[i,j]/2.0
threshold = 5000
#threshold = 50
surface = 0
value = 0
for i in range(info.Height):
for j in range(info.Width):
if temp[i,j] > threshold:
surface += 1
value += temp[i,j]
Surf_spot.append(surface)
Surf_value.append(value)
Surf_ratio.append(value/surface)
print("Surface:", Surf_spot, " Value: ", Surf_value, " Ratio: ", Surf_ratio)
cutout.Release()
return()
def mean(xs):
return sum(xs) / len(xs)
def stddev(xs):
m = sum(xs) / len(xs)
var = sum(abs(x - m) for x in xs) / len(xs)
return math.sqrt(var)
# *****************************************************************************
def Frame_measurement(self):
global t0, Time_frame, Max_frame, Surf_spot, Surf_value, Surf_ratio, dumpdata, start_pos, delta_focus, best_focus, de_focus
self.Monitoring.Text = "Monitoring running"
self.Monitoring.BackColor = Color.Red
self.Monitoring.Enabled = False
Time_frame = []
Max_frame = []
Surf_spot = []
Surf_value = []
Surf_ratio = []
dumpdata = True
t0 = datetime.datetime.now()
print()
print("Frame Max Monitoring:")
print("******************")
start_pos = SharpCap.Focusers.SelectedFocuser.Position
best_focus = int(self.textBoxBestFocus.Text)
de_focus = int(self.textBoxDeFocus.Text) #SharpCap.Focusers.SelectedFocuser.Position
#SharpCap.SelectedCamera.FrameCaptured += Start_Surface
#time.sleep(0.004*float(SharpCap.SelectedCamera.Controls.Exposure.Value))
#print("Start Surface : ", Surf_spot)
#SharpCap.SelectedCamera.FrameCaptured -= Start_Surface
SharpCap.SelectedCamera.FrameCaptured += framehandler
if (form.checkbox_surface.Checked):
SharpCap.SelectedCamera.BeforeFrameDisplay += beforeframehandler
temp = 0.0
while temp < float(self.textBoxTime.Text):
time.sleep(1.0)
temp += 1.0
if dumpdata == False:
break
print()
print("Start Position : ", start_pos)
print("End Position : ", SharpCap.Focusers.SelectedFocuser.Position)
print()
print("Number: ", len(Time_frame))
print()
dumpdata = False
SharpCap.SelectedCamera.FrameCaptured -= framehandler
if (form.checkbox_surface.Checked):
SharpCap.SelectedCamera.BeforeFrameDisplay -= beforeframehandler
print("End Surface : ", Surf_spot)
print("End Value : ", Surf_value)
print("End Ratio : ", Surf_ratio)
print()
print("Measurement done")
self.Monitoring.Text = "Start Measurement"
self.Monitoring.BackColor = Color.Gainsboro
self.Monitoring.Enabled = True
#file_path = "C:\\Data\\"
#file_name = file_path + "Mean_monitoring_" + str(t0).split()[1].split(".")[0].replace(":","-") + ".txt"
#file = open(file_name, "w")
#for index in range(len(Time_frame)):
# file.write(str("%.4f" % Time_frame[index]) + " " + str("%.4f" % Mean_frame[index]) + "\n")
#file.close()
return()
# *****************************************************************************
class MonitoringMeanMenuForm(Form):
def __init__(self):
self.SuspendLayout()
self.InitializeComponent()
self.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi
self.AutoScaleDimensions = SizeF(96, 96)
self.ResumeLayout()
def InitializeComponent(self):
global t0, Time_frame, Max_frame, Surf_spot, Surf_value, Surf_ratio, dumpdata, start_pos, delta_focus, best_focus, de_focus
self.Text = "Frame Mean Monitoring"
self.ClientSize = System.Drawing.Size(700, 450)
self.TopMost = True
self.Monitoring = Button()
self.labelTime = Label()
self.textBoxTime = TextBox()
self.labelThreshold = Label()
self.textBoxThreshold = TextBox()
self.button_StartStop = Button()
self.button_Exit = Button()
self.labelBestFocus = Label()
self.textBoxBestFocus = TextBox()
self.labelDeFocus = Label()
self.textBoxDeFocus = TextBox()
self.labelRectangle = Label()
self.checkbox_surface = CheckBox()
self.checkbox_focuser = CheckBox()
self.Monitoring.Text = "Start Measurement"
self.Monitoring.Location = Point(20, 10)
self.Monitoring.Click += self.Frame_monitor
self.Monitoring.AutoSize = True
self.labelTime.Text = "Measurement time [s]:"
self.labelTime.Location = Point(150, 14)
self.labelTime.Name = "labelTime"
self.labelTime.AutoSize = True
self.textBoxTime.Text = "1"
self.textBoxTime.Location = Point(280, 12)
self.textBoxTime.Name = "textBoxTime"
self.textBoxTime.Size = Size(40, 20)
self.textBoxTime.AutoSize = True
self.labelThreshold.Text = "Threshold:"
self.labelThreshold.Location = Point(350, 14)
self.labelThreshold.Name = "labelThreshold"
self.labelThreshold.AutoSize = True
self.textBoxThreshold.Text = str(threshold)
self.textBoxThreshold.Location = Point(415, 12)
self.textBoxThreshold.Name = "textBoxTime"
self.textBoxThreshold.Size = Size(40, 20)
self.textBoxThreshold.AutoSize = True
self.button_StartStop.Text = "Start"
self.button_StartStop.Location = Point(500, 10)
self.button_StartStop.Click += self.StartStop
self.button_StartStop.AutoSize = True
self.button_Exit.Text = "Exit"
self.button_Exit.Location = Point(600, 10)
self.button_Exit.Click += self.Exit
self.button_Exit.AutoSize = True
self.labelBestFocus.Text = "Best Focus:"
self.labelBestFocus.Location = Point(20, 50)
self.labelBestFocus.Name = "labelBestFocus"
self.labelBestFocus.AutoSize = True
self.textBoxBestFocus.Text = str(best_focus)
self.textBoxBestFocus.Location = Point(90, 48)
self.textBoxBestFocus.Name = "textBoxBestFocus"
self.textBoxBestFocus.Size = Size(60, 20)
self.labelDeFocus.Text = "De-Focus:"
self.labelDeFocus.Location = Point(180, 50)
self.labelDeFocus.Name = "labelBestFocus"
self.labelDeFocus.AutoSize = True
self.textBoxDeFocus.Text = str(max_focus)
self.textBoxDeFocus.Location = Point(250, 48)
self.textBoxDeFocus.Name = "textBoxDeFocus"
self.textBoxDeFocus.Size = Size(60, 20)
self.labelRectangle.Text = "Rectangle:"
self.labelRectangle.Location = Point(350, 50)
self.labelRectangle.Name = "labelRectangle"
self.labelRectangle.AutoSize = True
self.checkbox_surface.Text = "View Spot Surface"
self.checkbox_surface.Location = Point(500, 50)
self.checkbox_surface.AutoSize = True
self.checkbox_focuser.Text = "Move Focuser"
self.checkbox_focuser.Location = Point(500, 75)
self.checkbox_focuser.AutoSize = True
self.plot = OxyPlot.WindowsForms.PlotView()
self.plot.Location = System.Drawing.Point(10, 100)
self.plot.Size = System.Drawing.Size(680, 340)
self.Controls.Add(self.Monitoring)
self.Controls.Add(self.labelTime)
self.Controls.Add(self.textBoxTime)
self.Controls.Add(self.labelThreshold)
self.Controls.Add(self.textBoxThreshold)
self.Controls.Add(self.button_StartStop)
self.Controls.Add(self.button_Exit)
self.Controls.Add(self.labelBestFocus)
self.Controls.Add(self.textBoxBestFocus)
self.Controls.Add(self.labelDeFocus)
self.Controls.Add(self.textBoxDeFocus)
self.Controls.Add(self.labelRectangle)
self.Controls.Add(self.checkbox_surface)
self.Controls.Add(self.checkbox_focuser)
self.Controls.Add(self.plot)
Time_frame = []
Max_frame = []
Surf_spot = []
Surf_value = []
Surf_ratio = []
t0 = datetime.datetime.now()
SharpCap.Transforms.SelectTransform("ROI Selection") # Show the red selection rectangle
def ShowOxyGraphic(self):
global Time_frame, Mean_frame
self.plotmodel = OxyPlot.PlotModel()
if SharpCap.SelectedCamera.Controls.ColourSpace.Value == "MONO8":
self.YAxis = OxyPlot.Axes.LinearAxis(Position = OxyPlot.Axes.AxisPosition.Right, Minimum = 0.0, Maximum = 260)
if SharpCap.SelectedCamera.Controls.ColourSpace.Value == "MONO16":
self.YAxis = OxyPlot.Axes.LinearAxis(Position = OxyPlot.Axes.AxisPosition.Right, Minimum = 0.0, Maximum = 66000)
self.points_Max = []
for i in range(0,len(Time_frame)):
self.points_Max.Add(OxyPlot.DataPoint(Time_frame[i],Max_frame[i]))
self.serie = OxyPlot.Series.LineSeries()
self.serie.Color = OxyPlot.OxyColors.Red
self.serie.MarkerSize = 1
self.serie.MarkerType = OxyPlot.MarkerType.Circle
self.serie.StrokeThickness = 1
self.serie.ItemsSource = self.points_Max
self.plotmodel.Axes.Add(self.YAxis)
self.plotmodel.Series.Add(self.serie)
self.plot.Model = self.plotmodel
def Frame_monitor(self, sender, event):
th = Thread(ParameterizedThreadStart(Frame_measurement))
th.SetApartmentState(ApartmentState.STA)
th.Start(self)
def Exit(self, sender, event):
print("Exit monitoring script")
SharpCap.Transforms.SelectTransform(None) # Hide the red selection rectangle
SharpCap.SelectedCamera.FrameCaptured -= framehandler
self.Close()
def StartStop(self, sender, event):
global dumpdata
if (self.button_StartStop.Text == "Start"):
self.button_StartStop.Text = "Stop"
print("Start")
self.checkbox_surface.Enabled = False
self.checkbox_focuser.Enabled = False
dumpdata = True
SharpCap.SelectedCamera.FrameCaptured += framehandler
if (form.checkbox_surface.Checked):
SharpCap.SelectedCamera.BeforeFrameDisplay += beforeframehandler
else: #self.button_StartStop.Text == "Stop"
self.button_StartStop.Text = "Start"
print("Stop")
self.checkbox_surface.Enabled = True
self.checkbox_focuser.Enabled = True
dumpdata = False
SharpCap.SelectedCamera.FrameCaptured -= framehandler
if (form.checkbox_surface.Checked):
SharpCap.SelectedCamera.BeforeFrameDisplay -= beforeframehandler
def Measurement_Stop(self, sender):
global dumpdata
dumpdata = False
SharpCap.SelectedCamera.FrameCaptured -= framehandler
SharpCap.SelectedCamera.BeforeFrameDisplay -= beforeframehandler
print("Stop")
#def launch_form():
form = MonitoringMeanMenuForm()
form.StartPosition = FormStartPosition.CenterScreen
form.TopMost = True
form.FormClosing += Measurement_Stop
form.Show()
#SharpCap.AddCustomButton(" Mean__Monitoring |", None, "Mean__Monitoring", launch_form)
It was a script that I started to write before the occultation of Betelgeuse last December.
The idea was to change the focus of the telescope during the occultation.
A fainter star than Betelgeuse was focused (for example: Best Focus at 24500) and then move to Betelgeuse
Defocus the telescope until no overexposure (in this case defocus at 25500).
During the occultation, the focuser should refocus (from 25500 to 24500 and back) during the dimming of the spot.
The script was not completely finish and during November and December *zero* night for testing !
So I did not use the script during the occultation of Betelgeuse.
In the script ... you can see (and learn) how to catch a frame and perform some processing.
The script activates the selection red rectangle. You can move and re-dimension it with the mouse.
The graphic shows the maximum value of the spot from the red rectangle.
You can modify it for showing the average value of the spectrum.
The focuser part can be deleted. If you have something ... I can do a "review" of your script