Startup
This commit is contained in:
25
script/tutorial/01_LineScan.py
Normal file
25
script/tutorial/01_LineScan.py
Normal file
@@ -0,0 +1,25 @@
|
||||
"""
|
||||
Demonstrate the use of Line Scan: one or multiple positioners move together linearly.
|
||||
"""
|
||||
|
||||
#This optional preference limits the displayed plots
|
||||
#set_preference(Preference.ENABLED_PLOTS, [ai1, ai2,])
|
||||
|
||||
#This optional preference displays wf1 as a 1d plot at each scan point, instead of a matrix plot
|
||||
#set_preference(Preference.PLOT_TYPES, {wf1:1})
|
||||
|
||||
#Execute the scan: 200 steps, a1 from 0 to 40
|
||||
a= lscan(ao1, (ai1,ai2,wf1,im1), 0, 40, 200, 0.01)
|
||||
|
||||
#Alternative: Steps of size 0.1, a1 from 0 to 40
|
||||
#a= lscan(ao1, (ai1,ai2,wf1,im1), 0, 40, 0.5, 0.01)
|
||||
|
||||
#2 positioners moving together in 200 steps, a1 from 0 to 40 and a2 from 0 to 100
|
||||
#a= lscan((ao1,ao2), (ai1,ai2,wf1,im1), (0, 0), (40, 100), 200, 0.01)
|
||||
|
||||
#Setting attributes to the scan group
|
||||
path = get_current_group()
|
||||
set_attribute(path, "AttrString", "Value")
|
||||
set_attribute(path, "AttrInteger", 1)
|
||||
set_attribute(path, "AttrDouble", 2.0)
|
||||
set_attribute(path, "AttrBoolean", True)
|
||||
20
script/tutorial/02_ScanCallbacks.py
Normal file
20
script/tutorial/02_ScanCallbacks.py
Normal file
@@ -0,0 +1,20 @@
|
||||
"""
|
||||
Demonstrate use of scan callbacks to trigger a detector at falling edge.
|
||||
"""
|
||||
|
||||
def BeforeReadout():
|
||||
ao1.write(1)
|
||||
ao1.write(0)
|
||||
|
||||
#Example with an epics direct channel access
|
||||
#caput("CHANNEL_NAME", 1)
|
||||
#caput("CHANNEL_NAME", 0)
|
||||
|
||||
index=0
|
||||
|
||||
def AfterReadout():
|
||||
global index
|
||||
print "Aquired frame: " + str(index)
|
||||
index=index+1
|
||||
|
||||
a= lscan((m1,m2), (ai1, ai2), (0,0), (4,8), steps=20, latency = 0.01, before_read=BeforeReadout, after_read=AfterReadout)
|
||||
21
script/tutorial/03_ManipulatingScanData.py
Normal file
21
script/tutorial/03_ManipulatingScanData.py
Normal file
@@ -0,0 +1,21 @@
|
||||
"""
|
||||
Processing and plotting scan data.
|
||||
"""
|
||||
|
||||
ao1.write(0.0)
|
||||
scan1= lscan(ao1, (ai1,ai2,wf1), 0, 40, 40, 0.01, False, "Scan 1")
|
||||
scan2= lscan(ao1, (ai1,ai2,wf1), 0, 40, 40, 0.01, False, "Scan 2")
|
||||
|
||||
|
||||
from operator import add
|
||||
result = map(add, scan1.getReadable(0), scan2.getReadable(0))
|
||||
|
||||
#Alternative:
|
||||
#result=[]
|
||||
#for i in range(len(scan1.records)):
|
||||
# result.append(scan1.records[i].values[0]+scan2.records[i].values[0])
|
||||
|
||||
|
||||
plot(result)
|
||||
print result
|
||||
|
||||
12
script/tutorial/04_AreaScan.py
Normal file
12
script/tutorial/04_AreaScan.py
Normal file
@@ -0,0 +1,12 @@
|
||||
"""
|
||||
Area Scan: Multiple positioners, each one is one dimension.
|
||||
"""
|
||||
|
||||
#This optional preference displays wf1 as a 1d plot at each scan point, instead of a matrix plot
|
||||
#set_preference(Preference.PLOT_TYPES, {wf1:1})
|
||||
|
||||
#The second sensor is an array. In the plot window it is overwritten in every same x position.
|
||||
#The data window never displays 3d data, but the 3d data can be accesses during the scan in the Data tab.
|
||||
ascan((m1,m2), (ai1,wf1), (0.0,0.0), (2.0,1.0), (20,20))
|
||||
|
||||
|
||||
12
script/tutorial/05_RelativeScan.py
Normal file
12
script/tutorial/05_RelativeScan.py
Normal file
@@ -0,0 +1,12 @@
|
||||
"""
|
||||
Demonstrate use of Relative Line Scan.
|
||||
The arguments start and end are relative to the current position.
|
||||
After the scan the positioner(s) move back to the initial position.
|
||||
"""
|
||||
|
||||
print "Initial position = " + str(m1.position)
|
||||
|
||||
a= lscan(m1, (ai1,ai2,wf1,im1), start = -2, end =2, steps = 20, relative = True)
|
||||
|
||||
|
||||
print "Final position = " + str(m1.position)
|
||||
22
script/tutorial/06_VectorScan.py
Normal file
22
script/tutorial/06_VectorScan.py
Normal file
@@ -0,0 +1,22 @@
|
||||
"""
|
||||
Demonstrate use of Vector Scan: one or multiple positioners set according to a position vector.
|
||||
"""
|
||||
|
||||
#1D vector scan, plot to 1D Vector tab
|
||||
vector = [ 1, 3, 5, 10, 25, 40, 45, 47, 49]
|
||||
a= vscan(ao1,(ai1,ai2),vector,False, 0.5, context = "1D Vector")
|
||||
|
||||
|
||||
|
||||
|
||||
#2D vector scan, plot to 2D Vector tab
|
||||
vector = [ [1,1] , [1,2] , [1,3] , [1,4] ,
|
||||
[1.5,2.5] ,
|
||||
[2,1] , [2,2] , [2,3] , [2,4] ,
|
||||
[2.5,2.5] ,
|
||||
[3,1] , [3,2] , [3,3] , [3,4] ]
|
||||
|
||||
a= vscan((m1,m2),(ai1,ai2),vector,False, 0.1, context = "2D Vector")
|
||||
|
||||
|
||||
|
||||
58
script/tutorial/07_MathFit.py
Normal file
58
script/tutorial/07_MathFit.py
Normal file
@@ -0,0 +1,58 @@
|
||||
"""
|
||||
Function fitting and peak search with mathutils.py
|
||||
"""
|
||||
|
||||
from mathutils import fit_polynomial,fit_gaussian, fit_harmonic, calculate_peaks
|
||||
from mathutils import PolynomialFunction, Gaussian, HarmonicOscillator
|
||||
import math
|
||||
|
||||
|
||||
start = 0
|
||||
end = 10
|
||||
step_size = 0.1
|
||||
|
||||
result= lscan(ao1,ai1,start,end,[step_size,],0.01)
|
||||
|
||||
readable = result.getReadable(0)
|
||||
positions = result.getPositions(0)
|
||||
|
||||
def get_function_data(function, start, end, resolution):
|
||||
ret = []
|
||||
for x in frange(start, end, resolution, True):
|
||||
fit_polinomial.append(function.value(x))
|
||||
|
||||
|
||||
pars_polynomial = (a0, a1, a2, a3, a4, a5, a6) = fit_polynomial(readable, positions, 6)
|
||||
fitted_polynomial_function = PolynomialFunction(pars_polynomial)
|
||||
print pars_polynomial
|
||||
|
||||
(normalization, mean, sigma) = fit_gaussian(readable, positions, True)
|
||||
fitted_gaussian_function = Gaussian(normalization, mean, sigma)
|
||||
print (normalization, mean, sigma)
|
||||
|
||||
(amplitude, angular_frequency, phase) = fit_harmonic(readable, positions)
|
||||
fitted_harmonic_function = HarmonicOscillator(amplitude, angular_frequency, phase)
|
||||
print (amplitude, angular_frequency, phase)
|
||||
|
||||
|
||||
resolution = step_size/100
|
||||
fit_polinomial = []
|
||||
fit_gaussian = []
|
||||
fit_harmonic = []
|
||||
for x in frange(start,end,resolution, True):
|
||||
fit_polinomial.append(fitted_polynomial_function.value(x))
|
||||
fit_gaussian.append(fitted_gaussian_function.value(x))
|
||||
fit_harmonic.append(fitted_harmonic_function.value(x))
|
||||
x = frange(start, end+resolution, resolution)
|
||||
|
||||
|
||||
peaks = calculate_peaks(fitted_polynomial_function)
|
||||
|
||||
plots = plot([readable, fit_polinomial, fit_gaussian, fit_harmonic] ,
|
||||
["data", "polinomial", "gaussian", "harmonic"], xdata = [positions,x,x,x], context="Data")
|
||||
|
||||
for p in peaks:
|
||||
print "Max: " + str(p)
|
||||
plots[0].addMarker(p, None, "Max=" + str(round(p,2)), None)
|
||||
import java.awt.Color
|
||||
plots[0].addMarker(mean, None, "Mean=" + str(round(mean,2)), java.awt.Color.LIGHT_GRAY)
|
||||
37
script/tutorial/08_MathMultipleGaussians.py
Normal file
37
script/tutorial/08_MathMultipleGaussians.py
Normal file
@@ -0,0 +1,37 @@
|
||||
"""
|
||||
Multiple Gaussians peak search
|
||||
"""
|
||||
|
||||
from mathutils import estimate_peak_indexes, fit_gaussians, create_fit_point_list
|
||||
|
||||
start = 0
|
||||
end = 50
|
||||
step_size = 0.2
|
||||
|
||||
result= lscan(ao1,ai1,start,end,[step_size,])
|
||||
|
||||
readable = result.getReadable(0)
|
||||
positions = result.getPositions(0)
|
||||
|
||||
threshold = (min(readable) + max(readable))/2
|
||||
min_peak_distance = 5.0
|
||||
|
||||
peaks = estimate_peak_indexes(readable, positions, threshold, min_peak_distance)
|
||||
print "Peak indexes: " + str(peaks)
|
||||
print "Peak x: " + str(map(lambda x:positions[x], peaks))
|
||||
print "Peak y: " + str(map(lambda x:readable[x], peaks))
|
||||
|
||||
|
||||
|
||||
gaussians = fit_gaussians(readable, positions, peaks)
|
||||
|
||||
|
||||
plots = plot([readable],["sin"],[positions], context="Data" )
|
||||
for i in range(len(peaks)):
|
||||
peak = peaks[i]
|
||||
(norm, mean, sigma) = gaussians[i]
|
||||
if abs(mean - positions[peak]) < min_peak_distance:
|
||||
print "Peak -> " + str(mean)
|
||||
plots[0].addMarker(mean, None, "N="+str(round(norm,2)), None)
|
||||
else:
|
||||
print "Invalid gaussian fit: " + str(mean)
|
||||
26
script/tutorial/09_PseudoDevices.py
Normal file
26
script/tutorial/09_PseudoDevices.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""
|
||||
Using pseudo-device to :
|
||||
- Add calculations to scan data.
|
||||
- Execute logic during scan
|
||||
"""
|
||||
|
||||
class Clock(Readable):
|
||||
def read(self):
|
||||
return time.clock()
|
||||
|
||||
class Averager(Readable):
|
||||
def read(self):
|
||||
arr = wf1.take() #Gets the CACHED waveform
|
||||
return reduce(lambda x, y: x + y, arr) / len(arr)
|
||||
|
||||
class Positioner(Writable):
|
||||
def write(self,pos):
|
||||
print "Step = " + str(pos)
|
||||
|
||||
averager=Averager()
|
||||
clock=Clock()
|
||||
positioner=Positioner()
|
||||
|
||||
a= lscan((ao1,positioner),(ai2,wf1,averager,clock),(0,0),(40,20),20,0.1)
|
||||
|
||||
|
||||
25
script/tutorial/10_DeviceListener.py
Normal file
25
script/tutorial/10_DeviceListener.py
Normal file
@@ -0,0 +1,25 @@
|
||||
"""
|
||||
Create a device listener to interrupt the scan
|
||||
"""
|
||||
import java.lang.InterruptedException
|
||||
|
||||
class Listener (DeviceListener):
|
||||
def onStateChanged(self, device, state, former):
|
||||
pass
|
||||
def onValueChanged(self, device, value, former):
|
||||
if value > 1.01:
|
||||
print "Value over limit-> aborting"
|
||||
abort()
|
||||
|
||||
listener = Listener()
|
||||
|
||||
ai1.addListener(listener)
|
||||
try:
|
||||
lscan(ao1, (ai1), 0, 40, 200, 0.01)
|
||||
except java.lang.InterruptedException:
|
||||
print "Aborted"
|
||||
finally:
|
||||
ai1.removeListener(listener)
|
||||
|
||||
|
||||
|
||||
22
script/tutorial/11_ParametersAndReturn.py
Normal file
22
script/tutorial/11_ParametersAndReturn.py
Normal file
@@ -0,0 +1,22 @@
|
||||
"""
|
||||
Settign script parameters and return value
|
||||
"""
|
||||
|
||||
|
||||
#Providing an array of global variables
|
||||
#run ("tutorial/11_ParametersAndReturn", {"start":10.0, "end":50.0, "step":40})
|
||||
|
||||
#Providing the locals dictionary
|
||||
# The parameters are not set as globals, and nor script definitions
|
||||
#run ("tutorial/11_ParametersAndReturn", locals={"start":10.0, "end":50.0, "step":40})
|
||||
|
||||
#Setting sys.argv:
|
||||
#run ("tutorial/11_ParametersAndReturn", [10.0, 50.0, 40])
|
||||
#start = sys.argv[0]
|
||||
#end = sys.argv[1]
|
||||
#step = sys.argv[2]
|
||||
|
||||
|
||||
a= lscan(ao1, ai1, start, end, step, 0.1)
|
||||
a.getReadable(0)
|
||||
set_return(a.getReadable(0))
|
||||
33
script/tutorial/12_ManualScan.py
Normal file
33
script/tutorial/12_ManualScan.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""
|
||||
Manual scan: Manually setting positioners and reading back sensors, but still using
|
||||
the standard data handling and plotting of built-in scans.
|
||||
"""
|
||||
|
||||
MOTOR_RANGE = (0.0, 8.0)
|
||||
OUTPUT_SETPOINTS = (1.0, 2.0, 3.0)
|
||||
FIXED_X = True
|
||||
|
||||
|
||||
writables_names = [m1.getName(), ao1.getName()]
|
||||
readable_names = [ai1.getName(), ai2.getName()]
|
||||
start = [ MOTOR_RANGE[0] if FIXED_X else -1, OUTPUT_SETPOINTS[0]]
|
||||
stop = [ MOTOR_RANGE[1] if FIXED_X else -1, OUTPUT_SETPOINTS[-1]]
|
||||
steps = [int(MOTOR_RANGE[1]-MOTOR_RANGE[0]), len(OUTPUT_SETPOINTS)-1 if FIXED_X else -1]
|
||||
|
||||
scan = ManualScan(writables_names, readable_names ,start, stop, steps)
|
||||
|
||||
|
||||
#This option is to plot the foe each output value one 1D series, intead of all in a matrix plot
|
||||
set_preference(Preference.PLOT_TYPES, {ai1:1,ai2:1})
|
||||
|
||||
|
||||
scan.start()
|
||||
m1.setSpeed(10.0)
|
||||
for setpoint1 in frange(MOTOR_RANGE[0], MOTOR_RANGE[1], 1.0, True):
|
||||
m1.move(setpoint1)
|
||||
for setpoint2 in OUTPUT_SETPOINTS:
|
||||
ao1.write(setpoint2)
|
||||
scan.append ([setpoint1, setpoint2], [m1.read(), ao1.read()], [ai1.read(), ai2.read()])
|
||||
|
||||
|
||||
scan.end()
|
||||
19
script/tutorial/13_CustomPlot.py
Normal file
19
script/tutorial/13_CustomPlot.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""
|
||||
Custom plot: Example of creating a 1D plot for a 2D scan where each scanned row is a series
|
||||
|
||||
"""
|
||||
|
||||
#Setting the 1d preference would create in the place of the matrix plot, a 1d plot where
|
||||
#each scanned column is a series
|
||||
#set_preference(Preference.PLOT_TYPES, {'ai1':1})
|
||||
|
||||
|
||||
|
||||
p = plot(None, context="1d Plot")[0]
|
||||
def AfterReadout(record, scan):
|
||||
if record.setpoints[1] == scan.getStart()[1]:
|
||||
p.addSeries(LinePlotSeries(str(record.positions[0])))
|
||||
p.getSeries(p.numberOfSeries-1).appendData(record.positions[1], record.values[0])
|
||||
|
||||
|
||||
ascan((ao1,ao2), (ai1), (0,10), (20,30), (20,20), 0.1, after_read=AfterReadout)
|
||||
68
script/tutorial/14_DataManipulation.py
Normal file
68
script/tutorial/14_DataManipulation.py
Normal file
@@ -0,0 +1,68 @@
|
||||
"""
|
||||
Data Manipulation: Using the data access API to generate and retrieve data
|
||||
|
||||
"""
|
||||
|
||||
#Creating a 1D dataset from an array
|
||||
path="group/data1"
|
||||
data1d = [1.0, 2.0, 3.0, 4.0, 5.0]
|
||||
save_dataset(path, data1d)
|
||||
#Reading ii back
|
||||
read =load_data(path)
|
||||
print read.tolist()
|
||||
assert data1d==read.tolist()
|
||||
plot(read)
|
||||
|
||||
#Creating a 2D dataset from an array with some attributes
|
||||
data2d = [ [1.0, 2.0, 3.0, 4.0, 5.0], [2.0, 3.0, 4.0, 5.0, 6.0, ], [3.0, 4.0, 5.0, 6.0, 7.0]]
|
||||
path="group/data2"
|
||||
save_dataset(path, data2d)
|
||||
set_attribute(path, "AttrString", "Value")
|
||||
set_attribute(path, "AttrInteger", 1)
|
||||
set_attribute(path, "AttrDouble", 2.0)
|
||||
set_attribute(path, "AttrBoolean", True)
|
||||
#Reading it back
|
||||
read =load_data(path)
|
||||
print read.tolist()
|
||||
plot(read)
|
||||
|
||||
#Creating a 3D dataset from an array
|
||||
data3d = [ [ [1,2,3,4,5], [2,3,4,5,6], [3,4,5,6,7]], [ [3,2,3,4,5], [4,3,4,5,6], [5,4,5,6,7]]]
|
||||
path="group/data3"
|
||||
save_dataset(path, data3d)
|
||||
#Reading it back
|
||||
read =load_data(path,0)
|
||||
print read.tolist()
|
||||
read =load_data(path,1)
|
||||
print read.tolist()
|
||||
|
||||
#Creating a INT dataset adding elements one by one
|
||||
path = "group/data4"
|
||||
create_dataset(path, 'i')
|
||||
for i in range(10):
|
||||
append_dataset(path,i)
|
||||
|
||||
|
||||
#Creating a 2D data FLOAT dataset adding lines one by one
|
||||
path = "group/data5"
|
||||
create_dataset(path, 'd', False, (0,0))
|
||||
for row in data2d:
|
||||
append_dataset(path, row)
|
||||
|
||||
|
||||
#Creating a Table (compund type)
|
||||
path = "group/data6"
|
||||
names = ["a", "b", "c", "d"]
|
||||
types = ["d", "d", "d", "[d"]
|
||||
lenghts = [0,0,0,5]
|
||||
table = [ [1,2,3,[0,1,2,3,4]],
|
||||
[2,3,4,[3,4,5,6,7]],
|
||||
[3,4,5,[6,7,8,9,4]] ]
|
||||
create_table(path, names, types, lenghts)
|
||||
for row in table:
|
||||
append_table(path, row)
|
||||
flush_data()
|
||||
#Read it back
|
||||
read =load_data(path)
|
||||
print read
|
||||
|
||||
51
script/tutorial/15_Pararellization.py
Normal file
51
script/tutorial/15_Pararellization.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
Using Pararellization API to execute tasks concurrently
|
||||
|
||||
"""
|
||||
import traceback
|
||||
|
||||
#Simple parallization
|
||||
def task1():
|
||||
m1.moveRel(1.0)
|
||||
return m1.getPosition()
|
||||
|
||||
def task2():
|
||||
m2.moveRel(1.0)
|
||||
return m1.getPosition()
|
||||
|
||||
def task3():
|
||||
return ai1.read()
|
||||
|
||||
ret = parallelize(task1, task2, task3)
|
||||
print ret
|
||||
|
||||
|
||||
#Fork amd join
|
||||
ret = fork(task1, task2, task3)
|
||||
print ai1.read()
|
||||
ret = join(ret)
|
||||
print ret
|
||||
|
||||
|
||||
|
||||
#Functions with parameters
|
||||
def moveRelative(motor, step):
|
||||
print "Moving " + motor.getName() + " step = " + str(step)
|
||||
motor.moveRel(step)
|
||||
return motor.getPosition()
|
||||
|
||||
ret = parallelize((moveRelative,(m1,-2)), (moveRelative,(m2,-2)))
|
||||
print ret
|
||||
|
||||
|
||||
#Exception in parallel task is thrown back to script
|
||||
try:
|
||||
parallelize((moveRelative,(ai1,1)), (moveRelative,(ai2,1)))
|
||||
except:
|
||||
print "Ok, caught exception:"
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
15
script/tutorial/16_SimultaneousScans.py
Normal file
15
script/tutorial/16_SimultaneousScans.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""
|
||||
Example on running simultaneous scans. They should not manipulate same writables
|
||||
"""
|
||||
|
||||
|
||||
def scan1():
|
||||
print "scan1"
|
||||
return lscan(ao1, ai1, 0, 40, 20, 0.1, context = "scan1")
|
||||
|
||||
def scan2():
|
||||
print "scan2"
|
||||
return lscan(ao2, wf1, 0, 40, 20, 0.1, context = "scan2")
|
||||
|
||||
|
||||
parallelize(scan1, scan2)
|
||||
31
script/tutorial/17_DirectEpicsAccess.py
Normal file
31
script/tutorial/17_DirectEpicsAccess.py
Normal file
@@ -0,0 +1,31 @@
|
||||
"""
|
||||
EPICS direct channel access.
|
||||
EPICS devices implemented are included in PShell, package ch.psi.pshell.epics.
|
||||
However direct channel access builtin functions are available.
|
||||
"""
|
||||
|
||||
channel_name = "TESTIOC:TESTCALCOUT:Output"
|
||||
|
||||
#reading/writing to a channel
|
||||
print (caget(channel_name))
|
||||
caput(channel_name, 0.0)
|
||||
#Put with no wait
|
||||
caput(channel_name, 0.0)
|
||||
print (caget(channel_name))
|
||||
|
||||
#waiting for a channel valur
|
||||
cawait(channel_name, 0.0, timeout = 10.0)
|
||||
|
||||
#If many IO it is better to keep the same CA connection
|
||||
channel = Channel(channel_name, 'd')
|
||||
for i in range(100):
|
||||
print channel.get()
|
||||
lscan(channel, (ai2,channel), 0, 10, 0.1)
|
||||
|
||||
#The channel class implements Readable and Writable and therefore can be used in scans
|
||||
lscan(channel, ai2, 0, 10, 0.1)
|
||||
|
||||
#Or else we can use a Device
|
||||
import ch.psi.pshell.epics.ChannelDouble as ChannelDouble
|
||||
channel = ChannelDouble("My Channel", channel_name)
|
||||
channel.initialize()
|
||||
27
script/tutorial/18_Imaging.py
Normal file
27
script/tutorial/18_Imaging.py
Normal file
@@ -0,0 +1,27 @@
|
||||
"""
|
||||
Demonstrate creation of an image filter, applying it to a source and creating a new source
|
||||
based on the filter.
|
||||
"""
|
||||
|
||||
|
||||
import ch.psi.pshell.imaging.Filter as Filter
|
||||
from ch.psi.pshell.imaging.Utils import *
|
||||
|
||||
|
||||
class MyFilter(Filter):
|
||||
def process(self, image, data):
|
||||
image = grayscale(image)
|
||||
image = blur(image)
|
||||
image = sobel(image)
|
||||
return image
|
||||
|
||||
#Setting the filter to a source
|
||||
src1.setFilter(MyFilter())
|
||||
|
||||
#Creating a new source with the filter
|
||||
src2.setFilter(None)
|
||||
add_device(MyFilter("f1"), True)
|
||||
#f1.passive = True
|
||||
src2.addListener(f1)
|
||||
|
||||
|
||||
15
script/tutorial/19_ContinuousScan.py
Normal file
15
script/tutorial/19_ContinuousScan.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""
|
||||
Demonstrate the use of Continuous Scan Scan: a Linear Scan with continuous motor move and
|
||||
sampling on the fly.
|
||||
"""
|
||||
|
||||
#A single motor at current speed
|
||||
a= cscan(m1, (ai1,ai2), -2, 3 , steps=100, relative=True)
|
||||
|
||||
|
||||
#A single motor in a given time
|
||||
a= cscan(m1, (ai1,ai2), -2.0, 3.0, steps=100 ,time = 4.0, relative=True)
|
||||
|
||||
#Multiple motors in a given time
|
||||
a= cscan((m1, m2), (ai1,ai2), (-2.0, -3), (3.0, 5.0), steps=100,time = 4.0, relative=True)
|
||||
|
||||
46
script/tutorial/20_Interlocks.py
Normal file
46
script/tutorial/20_Interlocks.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""
|
||||
Interlocks: example on creating and installing device interlock rules.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class MyInterlock1 (Interlock):
|
||||
#Motor and Positioners
|
||||
def __init__(self):
|
||||
Interlock.__init__(self, (m1, p1))
|
||||
|
||||
def check(self, (m, p)):
|
||||
if p<500 and (m<5 and m>4):
|
||||
return False
|
||||
return True
|
||||
|
||||
interlock1 = MyInterlock1()
|
||||
|
||||
"""
|
||||
#Motor group
|
||||
class MyInterlock2(Interlock):
|
||||
def __init__(self):
|
||||
Interlock.__init__(self, (mg1, p1))
|
||||
|
||||
def check(self, ((m1,m2), p)):
|
||||
if p<500 and (m1>4 and m2>4):
|
||||
return False
|
||||
return True
|
||||
|
||||
interlock2 = MyInterlock2()
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
#Discrete Positioner
|
||||
class MyInterlock3(Interlock):
|
||||
def __init__(self):
|
||||
Interlock.__init__(self, (dp1, p1))
|
||||
|
||||
def check(self, (dp, p)):
|
||||
if p<500 and dp=="Out":
|
||||
return False
|
||||
return True
|
||||
|
||||
#interlock3 = MyInterlock3()
|
||||
"""
|
||||
195
script/tutorial/devices.py
Normal file
195
script/tutorial/devices.py
Normal file
@@ -0,0 +1,195 @@
|
||||
import random
|
||||
import ch.psi.pshell.device.DummyMotor as DummyMotor
|
||||
import ch.psi.pshell.device.DummyRegister as DummyRegister
|
||||
import ch.psi.pshell.device.DummyPositionable as DummyPositionable
|
||||
import ch.psi.pshell.device.RegisterBase as RegisterBase
|
||||
import ch.psi.pshell.device.MotorGroupBase as MotorGroupBase
|
||||
import ch.psi.pshell.device.MotorGroupDiscretePositioner as MotorGroupDiscretePositioner
|
||||
import ch.psi.pshell.device.ReadonlyRegisterBase as ReadonlyRegisterBase
|
||||
import ch.psi.pshell.device.ReadonlyRegister.ReadonlyRegisterArray as ReadonlyRegisterArray
|
||||
import ch.psi.pshell.device.ReadonlyRegister.ReadonlyRegisterMatrix as ReadonlyRegisterMatrix
|
||||
import ch.psi.pshell.imaging.RegisterMatrixSource as RegisterMatrixSource
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Simulated Devices
|
||||
####################################################################################################
|
||||
|
||||
class AnalogOutput(RegisterBase):
|
||||
def doRead(self):
|
||||
return self.val if hasattr(self, 'val') else 0.0
|
||||
|
||||
def doWrite(self, val):
|
||||
self.val = val
|
||||
|
||||
class AnalogInput(ReadonlyRegisterBase):
|
||||
def doRead(self):
|
||||
time.sleep(0.01)
|
||||
self.val = to_array(self.calc(), 'd')
|
||||
return self.val
|
||||
|
||||
class Waveform(ReadonlyRegisterBase, ReadonlyRegisterArray):
|
||||
def doRead(self):
|
||||
time.sleep(0.01)
|
||||
self.val = to_array(self.calc(), 'd')
|
||||
return self.val
|
||||
|
||||
def getSize(self):
|
||||
return len(self.take(-1)) #only reads if cache is None
|
||||
|
||||
class Image(ReadonlyRegisterBase, ReadonlyRegisterMatrix):
|
||||
def doRead(self):
|
||||
time.sleep(0.01)
|
||||
self.val = to_array(self.calc(), 'd')
|
||||
return self.val
|
||||
|
||||
def getWidth(self):
|
||||
return len(self.take(-1)[0])
|
||||
|
||||
def getHeight(self):
|
||||
return len(self.take(-1))
|
||||
|
||||
|
||||
|
||||
class Random(AnalogInput):
|
||||
def calc(self):
|
||||
return random.random()
|
||||
|
||||
|
||||
class SinusoidSample(AnalogInput):
|
||||
def calc(self):
|
||||
self.x = self.x + 0.1 if hasattr(self, 'x') else 0.0
|
||||
noise = (random.random() - 0.5) / 10.0
|
||||
return math.sin(self.x) + noise
|
||||
|
||||
class SinusoidTime(AnalogInput):
|
||||
def calc(self):
|
||||
noise = (random.random() - 0.5) / 10.0
|
||||
return math.sin(time.time()) + noise
|
||||
|
||||
|
||||
class SinusoidWaveform(Waveform):
|
||||
def calc(self):
|
||||
ret = []
|
||||
x = random.random()
|
||||
for i in range (20):
|
||||
ret.append(math.sin(x))
|
||||
x = x + 0.1
|
||||
return ret
|
||||
|
||||
class SinusoidImage(Image):
|
||||
def calc(self):
|
||||
(width, height) = (200, 100)
|
||||
ret = []
|
||||
x = random.random();
|
||||
base = []
|
||||
for i in range (width):
|
||||
base.append( math.sin(x))
|
||||
x = x + 0.05
|
||||
for i in range (height):
|
||||
noise = (random.random() - 0.5)/5.0
|
||||
ret.append([x+noise for x in base])
|
||||
return ret
|
||||
|
||||
|
||||
#Defintion
|
||||
add_device(DummyMotor("m1"), True)
|
||||
add_device(DummyMotor("m2"), True)
|
||||
add_device(DummyRegister("reg1",3), True)
|
||||
add_device(AnalogOutput("ao1"), True)
|
||||
add_device(AnalogOutput("ao2"), True)
|
||||
add_device(SinusoidSample("ai1"), True)
|
||||
add_device(SinusoidTime("ai2"), True)
|
||||
add_device(Random("ai3"), True)
|
||||
add_device(SinusoidWaveform("wf1"), True)
|
||||
add_device(SinusoidImage("im1"), True)
|
||||
add_device(DummyPositionable("p1"),True)
|
||||
add_device(MotorGroupBase("mg1", m1, m2), True)
|
||||
add_device(MotorGroupDiscretePositioner("dp1", mg1), True)
|
||||
|
||||
|
||||
|
||||
#Initial Configuration
|
||||
p1.config.minValue = 0.0 #Not persisted
|
||||
p1.config.maxValue = 1000.0
|
||||
|
||||
if dp1.config.positions is None:
|
||||
dp1.config.positions = ["Park","Ready","Out","Clear"]
|
||||
dp1.config.motor1 = ["0.0","4.0","8.0" ,"0.0"]
|
||||
dp1.config.motor2 = ["0.0","5.0","3.0" ,"NaN"]
|
||||
dp1.config.save()
|
||||
dp1.initialize()
|
||||
|
||||
|
||||
|
||||
#Update
|
||||
m1.setMonitored(True)
|
||||
m2.setMonitored(True)
|
||||
|
||||
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Simple Readable / Writable objects can be created and used in scans
|
||||
####################################################################################################
|
||||
class WritableScalar(Writable):
|
||||
def write(self, value):
|
||||
pass
|
||||
|
||||
class ReadableScalar(Readable):
|
||||
def read(self):
|
||||
return random.random()
|
||||
|
||||
|
||||
class ReadableWaveform(ReadableArray):
|
||||
def getSize(self):
|
||||
return 20
|
||||
|
||||
def read(self):
|
||||
ret = []
|
||||
for i in range (self.getSize()):
|
||||
ret.append(random.random())
|
||||
return ret
|
||||
|
||||
class ReadableImage(ReadableMatrix):
|
||||
def read(self):
|
||||
ret = []
|
||||
for i in range (self.getHeight()):
|
||||
ret.append([random.random()] * self.getWidth())
|
||||
return to_array(ret, 'd')
|
||||
|
||||
def getWidth(self):
|
||||
return 80
|
||||
|
||||
def getHeight(self):
|
||||
return 40
|
||||
|
||||
|
||||
|
||||
ws1 = WritableScalar()
|
||||
rs1 = ReadableScalar()
|
||||
rw1 = ReadableWaveform()
|
||||
ri1 = ReadableImage()
|
||||
|
||||
|
||||
####################################################################################################
|
||||
# Imaging
|
||||
####################################################################################################
|
||||
|
||||
configured = os.path.exists(Device.getConfigFileName("src1"))
|
||||
|
||||
add_device(RegisterMatrixSource("src1", im1), True)
|
||||
add_device(RegisterMatrixSource("src2", ri1), True)
|
||||
|
||||
#Some configuration for so the imaging will work out of the box
|
||||
if not configured:
|
||||
import ch.psi.pshell.imaging.Colormap
|
||||
src1.config.dataPolling = 100
|
||||
src1.config.colormapAutomatic = True
|
||||
src1.config.colormap = ch.psi.pshell.imaging.Colormap.Temperature
|
||||
src1.config.save()
|
||||
src2.config.dataPolling = 100
|
||||
src2.config.colormapAutomatic = True
|
||||
src2.config.save()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user