Python Library Installation

Discussions on extending SharpCap using the built in Python scripting functionality
User avatar
admin
Site Admin
Posts: 13177
Joined: Sat Feb 11, 2017 3:52 pm
Location: Vale of the White Horse, UK
Contact:

Re: Python Library Installation

#11

Post by admin »

Hi,

You can access the controls to turn the LED on and off and adjust the calibration values by searching for them in the controls collection of the camera. The simplest way to do this is probably

Code: Select all

SharpCap.SelectedCamera.Controls.FindByName(<control name>)
You can also connect to the FrameCaptued event as discussed in this thread :

viewtopic.php?t=1141

Finally, in the event handler you can call GetStats() on the frame object - this will return a tuple containing the mean and standard deviation of the frame value, which should be enough to spot the light/dark transition.

Hope this helps, Robin
Jean-Francois
Posts: 360
Joined: Sun Oct 13, 2019 10:52 am
Location: Germany

Re: Python Library Installation

#12

Post by Jean-Francois »

Hello Robin,

I try first the control list ... It found a "GPS" ... but what can I do after ?

Control_GPS.png
Control_GPS.png (167.04 KiB) Viewed 2144 times
In the "QHY174M-GPS On-Line Technology Document - Manual" from the QHY website, few explanation is in the section "Programming with QHYCCD API".
Here the function related to the GPS:
set_GPS_VCOX_Freq, set_GPS_LEDCAL_Mode, set_GPS_POSA, set_GPS_POSB, set_GPS_MasterSlave, set_GPS_SlaveMode_Parameter
Note that I have the QHY-174-GPS camera connected and running with SharpCap.


I try the other code ... and it crashed SharpCap.

It is really not simple to program/use the script language.
For my mathematics calculation, I search in 100 (or more) websites ... I found now 3 candidates of mathematical (free) libraries:
- ALGLIB
- MetNumerics
- MathNet_Numerics

Does somebody somewhere with some experience with these libraries ?


Regards,
Jean-Francois
User avatar
admin
Site Admin
Posts: 13177
Joined: Sat Feb 11, 2017 3:52 pm
Location: Vale of the White Horse, UK
Contact:

Re: Python Library Installation

#13

Post by admin »

Hi,

the names of the controls will match the labels in the right hand control panel, not the QHY documentation names for them.

This code will print a list of all the controls (sadly all on one line)

Code: Select all

print SharpCap.SelectedCamera.Controls
This code worked for me on the frame statistics

Code: Select all

>>> def handler(sender,args):
... 	print args.Frame.GetStats()
... 
>>> SharpCap.SelectedCamera.FrameCaptured += handler;
>>> (25.7640062251824, 14.6842555920002)
(25.8690748919384, 14.7005426853545)
(25.7855811127688, 14.6700787691339)
(25.6712577967102, 14.6455822968702)
(25.8495202292315, 14.6804978311238)
(25.8033314126255, 14.6569116310604)
(25.6668117352348, 14.6389484833819)
(25.7985868000369, 14.6629440409719)
(25.8939107758673, 14.6953733917686)
(25.7741269338365, 14.6537962265353)
(25.8728781545885, 14.6268604813459)
(8.58095174265068, 8.38441516433171)
(8.5923354182588, 8.37453244853936)
(8.72210810161531, 8.41017660880494)
(8.52925974991339, 8.35370851855314)
(8.69169723261397, 8.41719021922858)
(8.70935526886138, 8.42276359908516)
(8.71688606836907, 8.39944870417961)
(8.58763606706346, 8.37444949022656)
You can see where I turned the calibration LED off part way through and the mean dropped from 25 to 8.

Robin
Jean-Francois
Posts: 360
Joined: Sun Oct 13, 2019 10:52 am
Location: Germany

Re: Python Library Installation

#14

Post by Jean-Francois »

Hello Robin,

Thank you for the help.

For the controls ... it is important to use the correct "listing" function ...
I look in the "dir()" function or in the IronPython console with the automatic list after typing the "." : "SharpCap.SelectedCamera.Controls." ... and there is no GPS name. But with the "print" ... it is possible to see the "other" function.
Control_list.png
Control_list.png (66.54 KiB) Viewed 2129 times

Hier after using the correct way:
Control_GPS_names.png
Control_GPS_names.png (115.94 KiB) Viewed 2129 times
It was possible after a lot of search, try and errors (a lot of errors ;) ) to find the GPS functions ... so I write a small script for testing some GPS features:

Code: Select all

LED_status = SharpCap.SelectedCamera.Controls[21].Value
print("GPS Calibration LED         : %s") % (LED_status)

if LED_status == "Off" :
	print("LED illumination of the Camera was Off.")
	print("LED is now switch on.")
	SharpCap.SelectedCamera.Controls[21].Value = "On"
	print("GPS Calibration LED         : %s") % (SharpCap.SelectedCamera.Controls[21].Value)

print
Cal_End_Pos = SharpCap.SelectedCamera.Controls[19].Value
Cal_Start_Pos = SharpCap.SelectedCamera.Controls[20].Value

print SharpCap.SelectedCamera.Controls[18]
print("Calibration Start Pos Adjust: %i") % (Cal_Start_Pos)
print("Calibration End Pos Adjust  : %i") % (Cal_End_Pos)
print("GPS Freq Stabilizazion      : %s") % (SharpCap.SelectedCamera.Controls[22].Value)
print("GPS                         : %s") % (SharpCap.SelectedCamera.Controls[23].Value)
print

SharpCap.SelectedCamera.Controls[20].Value = Cal_Start_Pos + 100
print("New Start Pos : %i") % (SharpCap.SelectedCamera.Controls[20].Value)

SharpCap.SelectedCamera.Controls[19].Value = Cal_End_Pos + 100
print("New End Pos   : %i") % (SharpCap.SelectedCamera.Controls[19].Value)


I have still not found how to use the "GPS Frame Control" controls (slave/master choice and the time transfer for the imaging start)

Concerning the other small script with the "handler" function ... it works, but how to stop it ?
It was not sufficient to stop the IronPython console or to close the camera ... it was necessary to quit SharpCap and restart it.

What I want is to have the statistic in the "Selection Rectangle" like shown in the software manual in the script section.
The idea is that the user select a small region where the LED illuminates at the maximum.

Regards,
Jean-Francois
User avatar
admin
Site Admin
Posts: 13177
Joined: Sat Feb 11, 2017 3:52 pm
Location: Vale of the White Horse, UK
Contact:

Re: Python Library Installation

#15

Post by admin »

Hi,

if you close the camera (or set a long exposure like 60s) then you should be able to run this code to detach the handler function

Code: Select all

SharpCap.SelectedCamera.FrameCaptured -= handler;
A better approach obviously would be to leave the handler attached all the time but to have a variable set somewhere else that would enable or disable its functionality.

As to getting the statistics for a particular area, you can recover the selection area using

Code: Select all

print SharpCap.Transforms.SelectionRect
Although you have to make sure that you are using something like the histogram that triggers the selection to become available.

You can also cut out the area you want from the frame that you receive in the event handler -

Code: Select all

cutout = args.Frame.CutROI(SharpCap.Transforms.SelectionRect)
... do stuff with cutout
cutout.Release()
It's important to release the ROI frame data otherwise SharpCap will quickly run out of memory.

Hope this helps, Robin
Jean-Francois
Posts: 360
Joined: Sun Oct 13, 2019 10:52 am
Location: Germany

Re: Python Library Installation

#16

Post by Jean-Francois »

Hello,

Thank you for the small peace of code ... but, each time the peaces are too short ... I cannot use it directly and the expertise to write the missing code is not present in me ... I try the last 2 hours but without good results.

I can use the print SharpCap.Transforms.SelectionRect ... or with ".Width" or ".Size" ...
at the end I have all the time only {X=1343,Y=593,Width=271,Height=210}, means the position and the size of the selected rectangle, not the sub image itself.
I wish (today) only some statistics of the selected rectangle (it could be for me sufficient to have the average of all pixels in the rectangle).

With the other code:
def handler(sender,args):
... print args.Frame.GetStats()
...
Sometimes I can stop the process with "SharpCap.SelectedCamera.FrameCaptured -= handler", but not each time.
(Thank you for the tip of setting a longer exposure)
I try to write a menu button for stopping the handler ... it was without success (and my other menu button was not more working).

I try to combine the "GetStats()" function with the "SharpCap.Transforms.SelectionRect", but errors after errors ...

Is it possible to retrieve the value of the pixels average in the selected rectangle ?
If yes ... how ?

Best regards,
Jean-Francois
User avatar
admin
Site Admin
Posts: 13177
Joined: Sat Feb 11, 2017 3:52 pm
Location: Vale of the White Horse, UK
Contact:

Re: Python Library Installation

#17

Post by admin »

Hi,

try this code

Code: Select all


dumpdata = True

def framehandler(sender, args):
	if (dumpdata):
		cutout = args.Frame.CutROI(SharpCap.Transforms.SelectionRect)
		print cutout.GetStats()
		cutout.Release()
		
def evthandler(sender, args):
	if (SharpCap.SelectedCamera != None):
		SharpCap.SelectedCamera.FrameCaptured -= framehandler

def monitorFrames():
	SharpCap.SelectedCamera.FrameCaptured += framehandler

SharpCap.CaptureEvent += evthandler
Put it in the lower box in the scripting window and press the green run button. Then when you've opened the camera just into the single line

Code: Select all

monitorFrames()
In the top box and press return. You should then see the statistics appearing line by line. If you show the histogram and then the selection rectangle and move the selection area around you will see that the values reflect the selection area.

The code is set up so that when you close the camera (or change the camera bit depth/binning/resolution) it will stop monitoring the frames. At that point you may find that the '>>>' is missing in the scripting window. The way to fix that is to clear all the text out of the bottom box and then press the run button again which should make the '>>>' reappear.

Hope this helps, Robin
Jean-Francois
Posts: 360
Joined: Sun Oct 13, 2019 10:52 am
Location: Germany

Re: Python Library Installation

#18

Post by Jean-Francois »

Hello Robin,

The code you send me has not the wanted effect ... except I want to quit SharpCap with an error :
monitorFrame_error.png
monitorFrame_error.png (172.51 KiB) Viewed 2098 times
I try to generate a log file with the error, but the start of SharpCap from the command line with /dump does nothing.
The starting image of SharpCap was visible some seconds, but nothing else happen.


The use of IronPython (I mean today the not use) is 2 steps forward and 3 steps backwards.
After 2000 website visits ... I found by chance that somebody program a numpy (= NumpyDotNet) and a similar Matplotlib for .NET,
in addition I found IronLab 1.1.2 using IronPython 2.7.0.
I test this NumpyDotNet on the IronLab (IronPython) ... it works !
IronPython_numpy_plot.png
IronPython_numpy_plot.png (92.11 KiB) Viewed 2098 times
So I try to import these libraries in IronPython from SharpCap ... and it does not work. May be it could works, but I do not find my error(s).

I try the opposite ... to command SharpCap from the IronLab ... and it does not work too.
Is it possible to start a script from another IronPython console (also not started from SharpCap itself) ?
Is it possible to "import" the SharpCap libraries in a different IronPython ?

Regards,
Jean-Francois
User avatar
admin
Site Admin
Posts: 13177
Joined: Sat Feb 11, 2017 3:52 pm
Location: Vale of the White Horse, UK
Contact:

Re: Python Library Installation

#19

Post by admin »

Hi,

sorry, I took a line out of the script just before I popped it into the forums thinking that that line wasn't needed and it was. I have now corrected the script by editing the previous post.

I'm afraid that you can only access the SharpCap scripting functionality inside the ironpython that runs in SharpCap – there's no way to load the functionality into another IronPython program. What errors you get when you try to use the numpy/ironplot in SharpCap?

Thanks, Robin
Jean-Francois
Posts: 360
Joined: Sun Oct 13, 2019 10:52 am
Location: Germany

Re: Python Library Installation

#20

Post by Jean-Francois »

Hello Robin,

Thank you for the last message.
A question first ... Is it possible to have a longer time before the forum logoff me automatically ?
The reason is ... I write a long message ... and it take a long time ... when I was fast finished I try "Preview" ... but it was necessary to log me again, and then when I come back ... the message box was empty !

So I need now to rewrite all my message :(

Here the test script for setting the Start and End Position of the LED illumination (also only for the use with the QHY-174-GPS camera!).

The test user shall follow the following steps:
- Start SharpCap
- Select the QHY-174-GPS camera
- Set the camera parameters (bit, binning, exposure, ...)
- Switch-on the LED Illumination (the GPS receiver is not necessary for this test sequence)
- Click the "Auto Stretch" button
- Show "The Image Histogram"
- Click for the "FX Selection", move/modify the rectangle above the LED illumination area
- Start the Scripting console
- Copy the following code in the (lower part of the) console
- Start the script

The script does the assumption that a directory "C:\Temp\" exists. One image LED_test.png is saved in this directory.
On my desktop for the test today, I have large PCI 4.0 SSD M.2 ... also fast no delay for saving the image on the "disc".
In future, the image rectangle selection will "stay" in memory.

The script search for the transition between the "no-light" and "full-light" coming from the LED.
In future, I plane to solve a Fermi function for finding the middle intensity position and to show the curve in a nice graphic.
I will upload the future script in a separate message in the section of the QHY camera.

Please, note that part with the "dumpdata" and the "framehandler" is working.
I insert "dumpdata=False" after some delay time.
The problem is ... it is nice to have the value on the screen ... but I prefer to have it in a variable.
I try to copy the value ... but nothing happen. Haw can I have access to the data ?
In addition, please can you explain the meaning of both numbers ?

Code: Select all

# IronPython Pad. Write code snippets here and F5 to run. If code is selected, only selection is run.

import clr
clr.AddReference("System.Drawing")
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')
import sys
import time
import System.Drawing
import math

dumpdata = True

def framehandler(sender, args):
	if (dumpdata):
		cutout = args.Frame.CutROI(SharpCap.Transforms.SelectionRect)
		print cutout.GetStats()
		cutout.Release()
		
def evthandler(sender, args):
	if (SharpCap.SelectedCamera != None):
		SharpCap.SelectedCamera.FrameCaptured -= framehandler

def monitorFrames():
	SharpCap.SelectedCamera.FrameCaptured += framehandler

SharpCap.CaptureEvent += evthandler
monitorFrames()
time.sleep(1)
dumpdata = False


print("GPS Calibration LED on/off  : %s") % (SharpCap.SelectedCamera.Controls[21].Value)
print
Cal_End_Pos = SharpCap.SelectedCamera.Controls[19].Value
Cal_Start_Pos = SharpCap.SelectedCamera.Controls[20].Value

print SharpCap.SelectedCamera.Controls[18]
print("Calibration Start Pos Adjust: %i") % (Cal_Start_Pos)
print("Calibration End Pos Adjust  : %i") % (Cal_End_Pos)
print("GPS Calibration LED on/off  : %s") % (SharpCap.SelectedCamera.Controls[21].Value)
print("GPS Freq Stabilizazion      : %s") % (SharpCap.SelectedCamera.Controls[22].Value)
print("GPS                         : %s") % (SharpCap.SelectedCamera.Controls[23].Value)
print

cloneRect = SharpCap.Transforms.SelectionRect
print("Rectangle Selection : "),
print cloneRect
print

#SharpCap.SelectedCamera.Controls.OutputFormat.Value = 'FITS files (*.fits)'
SharpCap.SelectedCamera.Controls.OutputFormat.Value = 'PNG files (*.png)'

def rect_average():
   SharpCap.SelectedCamera.CaptureSingleFrameTo("c:\Temp\LED_test.png")
   time.sleep(2)
   bm = System.Drawing.Bitmap("c:\Temp\LED_test.png")
   cloneBitmap = bm.Clone(cloneRect, bm.PixelFormat)
   sum = 0.0
   nb_pixel = cloneRect.Height * cloneRect.Width
   for i in range(cloneRect.Height):
      for j in range(cloneRect.Width):
         pixel = cloneBitmap.GetPixel(5,5)
         sum += float(pixel.R)
#   print("Pixel sum  : %f") % (sum)
#   print("Box average: %f") % (sum/nb_pixel)
   bm.Dispose()
   cloneBitmap.Dispose()
#   return sum/nb_pixel
   return math.floor(sum/1000)

def LED_cal_start_pos():
   X.append(SharpCap.SelectedCamera.Controls[20].Value)
   time.sleep(1)
   box.append(rect_average())
   temp.append((X[-1],box[-1]))
   return
   
def LED_cal_start_pos_set(calvalue):
   SharpCap.SelectedCamera.Controls[20].Value = int(calvalue)
   X.append(SharpCap.SelectedCamera.Controls[20].Value)
   time.sleep(1)
   box.append(rect_average())
   temp.append((X[-1],box[-1]))
   return

def LED_cal_end_pos():
   X.append(SharpCap.SelectedCamera.Controls[19].Value)
   time.sleep(1)
   box.append(rect_average())
   temp.append((X[-1],box[-1]))
   return
   
def LED_cal_end_pos_set(calvalue):
   SharpCap.SelectedCamera.Controls[19].Value = int(calvalue)
   X.append(SharpCap.SelectedCamera.Controls[19].Value)
   time.sleep(1)
   box.append(rect_average())
   temp.append((X[-1],box[-1]))
   return

'''
def Show_vector(V):
   for i in range(len(V)):
      print V[i]
   return
'''

def Show_matrix(M):
   for i in range(len(M)):
      for j in range(len(M[0])):
         print str(M[i][j]) + "      ",
      print
   return


# *****************************************************************************
# LED Calibration Start Position Adjustment
box = []
X = []
temp = []
SharpCap.SelectedCamera.Controls[20].Value = Cal_Start_Pos


LED_cal_start_pos()  	# Initialise with the SharpCap start position
print("Cal Start Pos: %i") % Cal_Start_Pos
LED_cal_start_pos_set(Cal_Start_Pos * 1.1)
LED_cal_start_pos_set(Cal_Start_Pos * 0.9)

average_start = (min(box) + max(box)) / 2.0
print("Average"), average_start

cal_start = math.floor(math.log10(Cal_Start_Pos)) - 1
cal_start = 10**cal_start

LED_cal_start_pos_set(Cal_Start_Pos)

while (cal_start >= 1.0):
   print cal_start
   while True:
      Cal_Start_Pos -= cal_start
      LED_cal_start_pos_set(Cal_Start_Pos)
      if (box[-1] < average_start):
         Cal_Start_Pos = X[-1] + cal_start
         break
   cal_start = cal_start / 10

print
print("Measurement:")
print("StartPos:  Intensity:")
Show_matrix(temp)

# END    LED Calibration Start Position Adjustment
# *****************************************************************************

# *****************************************************************************
# LED Calibration End Position Adjustment
box = []
X = []
temp = []
SharpCap.SelectedCamera.Controls[19].Value = Cal_End_Pos
SharpCap.SelectedCamera.Controls[19].Value = Cal_End_Pos
LED_cal_end_pos()                # Initialise with the SharpCap end position
print
print("Cal End Pos: %i") % Cal_End_Pos
LED_cal_end_pos_set(Cal_End_Pos * 0.9)
LED_cal_end_pos_set(Cal_End_Pos * 1.1)

average_end = (min(box) + max(box)) / 2.0
print("Average"), average_end

cal_end = math.floor(math.log10(Cal_End_Pos)) - 1
cal_end = 10**cal_end

LED_cal_end_pos_set(Cal_End_Pos)

while (cal_end >= 1.0):
   print cal_end
   while True:
      Cal_End_Pos += cal_end
      LED_cal_end_pos_set(Cal_End_Pos)
      if (box[-1] < average_end):
         Cal_End_Pos = X[-1] - cal_end
         break
   cal_end = cal_end / 10

print
print("Measurement:")
print("EndPos:  Intensity:")
Show_matrix(temp)

# END    LED Calibration End Position Adjustment
# *****************************************************************************

Concerning the IronPython inside SharpCap ... Is it possible to "exchange" the IronPython (2.7.9) with the IronLab (2.7.0.40) ?

In IronPython from SharpCap, it is not possible to load the dlls (ImportError: No module named NumpyDotNet).
Maybe it is possible to link some parts from IronLab in the IronPython (SC).
On the other side, I achieve to load the ALGLIB, MetNumerics and Math.Net libraries.
Each library has different way to represent the vector/matrices and different functions, but no library has a plot capability.
I begin to have a look in the .NET graphic function ... the problem is ... it exists maybe several 100 functions, but very few examples.


Regards,
Jean-Francois
Post Reply