This commit is contained in:
2018-04-17 12:05:48 +02:00
parent 14edc0e745
commit 58a1260003
428 changed files with 41350 additions and 477 deletions

14
script/tutorial/10_LineScan.js Executable file
View File

@@ -0,0 +1,14 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Demonstrate the use of Line Scan: one or multiple positioners move together linearly.
///////////////////////////////////////////////////////////////////////////////////////////////////
//Execute the scan: 100 steps, a1 from 0 to 40
r1 = lscan(ao1, [ai1,ai2,wf1], 0, 40, 100, 0.01)
//Steps of size 1.0, a1 from 0 to 40
r2 = lscan(ao1, [ai1,ai2,wf1], 0, 40, 1.0, 0.01)
//2 positioners moving together in 10 steps. Also sampling an image:
r3 = lscan([ao1,ao2], [ai1,ai2,wf1,im1], [0, 0], [40, 100], 4, 0.01)

8
script/tutorial/11_TimeScan.js Executable file
View File

@@ -0,0 +1,8 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Demonstrate the use of Time Scan: time-based sensor sampling
///////////////////////////////////////////////////////////////////////////////////////////////////
//Execute the scan: 100 samples, 10ms sampling interval
r1 = tscan((ai1,ai2,wf1), 100, 0.01)

10
script/tutorial/12_AreaScan.js Executable file
View File

@@ -0,0 +1,10 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Area Scan: Multiple positioners, each one is one dimension.
///////////////////////////////////////////////////////////////////////////////////////////////////
//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.
r1 = ascan([m1,m2], [ai1,wf1], [0.0,0.0], [2.0,1.0], [10,10])

View File

@@ -0,0 +1,20 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// 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]
r1 = vscan(ao1, [ai1,ai2], vector, false, 0.5, false, undefined, undefined, undefined, undefined, title = "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] ]
r2 = vscan([m1,m2], [ai1,ai2], vector, false, 0.1, false, undefined, undefined, undefined, undefined, title = "2D Vector")

View File

@@ -0,0 +1,11 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Demonstrate the use of Region Scan: one positioner move linearly in multiple regions.
///////////////////////////////////////////////////////////////////////////////////////////////////
//Execute the scan: 3 regions with different number of steps
r1 = rscan(ao1, [ai1,ai2], [[0,5,5], [10,15,20], [20,25,5]] , 0.01)
//Execute the scan: 3 regions with different step size
r2 = rscan(ao1, [ai1,ai2], [[0,5,1.0], [10,15,0.2], [20,25,1.0]] , 0.01)

View File

@@ -0,0 +1,17 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Demonstrate the use of Continuous Scan Scan: a Linear Scan with continuous motor move and
// sampling on the fly.
///////////////////////////////////////////////////////////////////////////////////////////////////
m1.move(0.0)
//A single motor at current speed
r1 = cscan(m1, (ai1,ai2), -2, 3 , steps=10, undefined, undefined ,true)
//A single motor in a given time
r2 = cscan(m1, (ai1,ai2), -2.0, 3.0, 100 , undefined , 4.0, true)
//Multiple motors in a given time
r3 = cscan((m1, m2), (ai1,ai2), (-2.0, -3), (3.0, 5.0), steps=100, undefined, time = 4.0, relative=true)

View File

@@ -0,0 +1,46 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Use of HardwareScan
///////////////////////////////////////////////////////////////////////////////////////////////////
CrlogicPositioner = Java.type('ch.psi.pshell.crlogic.CrlogicPositioner')
CrlogicSensor = Java.type('ch.psi.pshell.crlogic.CrlogicSensor')
//sc1.stop()
//sc1.setOneShot()
//sc1.channels[0].setPreset(false)
//sc1.channels[0].setPresetValue(0)
//sc1.start()
config = {}
config["class"] = "ch.psi.pshell.crlogic.CrlogicScan"
config["prefix"] = "MTEST-HW3-CRL"
config["ioc"] = "MTEST-VME-HW3.psi.ch"
config["integrationTime"] = 0.01
config["additionalBacklash"] = 0.0
pos = new CrlogicPositioner("CrlogicPositioner", "MTEST-HW3:MOT1", null)
sensors = [
new CrlogicSensor("Trigger0", "TRIGGER0"),
new CrlogicSensor("Trigger1", "TRIGGER1"),
new CrlogicSensor("Scaler0", "SCALER0", true),
new CrlogicSensor("Scaler1", "SCALER1", true),
new CrlogicSensor("Timestamp", "TIMESTAMP"),
]
//pos.initialize()
//pos.move(0.0)
try {
r1 = hscan(config, pos, sensors,0.0, 10.0, 0.1,1, false)
}
catch(err) {
}
finally {
pos.close()
}

13
script/tutorial/20_Relative.js Executable file
View File

@@ -0,0 +1,13 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// 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 = " + m1.position)
r1 = lscan(m1, [ai1,ai2,wf1], start = -2, end =2, steps = 20, latency = undefined, relative = true)
print ("Final position = " + m1.position)

View File

@@ -0,0 +1,13 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Multi-pass and zigzag scans
///////////////////////////////////////////////////////////////////////////////////////////////////
//Linear with 2 passes
a= lscan(m1, [ai1,wf1], -0.2, 0.2, 20, latency = 0.0, relative = true, passes = 4)
//Linear with 4 passes and zigzag
a= lscan(m1, [ai1,wf1], -0.2, 0.2, 20, latency = 0.0, relative = true, passes = 4, zigzag = true)
//Multi-dimentional zigzag
x = ascan ([m1,m2], ai1, [0,0], [1, 1], [0.25,0.25], latency=0.01, relative = undefined, passes = undefined, zigzag=true)

View File

@@ -0,0 +1,23 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Demonstrate use of scan callbacks to trigger a detector at falling edge.
///////////////////////////////////////////////////////////////////////////////////////////////////
function BeforeReadout(position){
ao1.write(1)
ao1.write(0)
//Example with an epics direct channel access
//caput("CHANNEL_NAME", 1)
//caput("CHANNEL_NAME", 0)
print ("In position: " + position[0] + ", " + position[1])
}
function AfterReadout(record, scan){
print ("Aquired frame: " + record.index)
}
a= lscan([m1,m2], [ai1, ai2], [0,0], [4,8], steps=20, latency = 0.01, relative = undefined,
passes = undefined, zigzag = undefined,before_read=BeforeReadout, after_read=AfterReadout)

21
script/tutorial/23_Metadata.js Executable file
View File

@@ -0,0 +1,21 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Demonstrate adding attributs to scan groups and datasets.
///////////////////////////////////////////////////////////////////////////////////////////////////
//Execute the scan: 200 steps, a1 from 0 to 40
a= lscan(ao1, [ai1,ai2], 0, 40, 10, 0.01)
//Setting attributes to the scan group
path = get_exec_pars().group
set_attribute(path, "AttrString", "Value")
set_attribute(path, "AttrInteger", 1)
set_attribute(path, "AttrDouble", 2.0)
set_attribute(path, "AttrBoolean", true)
//Setting attributes to the scan datasets
set_attribute(path + ao1.name, "AttrInteger", 2)
set_attribute(path + ai1.name, "AttrInteger", 3)
set_attribute(path + ai2.name, "AttrInteger", 4)

View File

@@ -0,0 +1,19 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Processing and plotting scan data.
///////////////////////////////////////////////////////////////////////////////////////////////////
ao1.write(0.0)
scan1= lscan(ao1, [ai1,ai2,wf1], 0, 40, 40, 0.01, false)
scan2= lscan(ao1, [ai1,ai2,wf1], 0, 40, 40, 0.01, false)
result=[]
for (var i=0; i<scan1.records.length; i++){
result.push(scan1.records[i].values[0]+scan2.records[i].values[0])
}
plot(result)
print (result
)

View File

@@ -0,0 +1,36 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Using pseudo-device to :
// - Add calculations to scan data.
// - Execute logic during scan
///////////////////////////////////////////////////////////////////////////////////////////////////
var Clock = Java.extend(Readable)
var clock = new Clock() {
read: function (value) {
return Date.now()
},
}
set_device_alias(clock, "Clock")
var PseudoSensor = Java.extend(Readable)
var averager = new PseudoSensor() {
read: function (value) {
arr = wf1.take() //Gets the CACHED waveform
arr = to_array(arr) //Converts to a javascript array
return arr.reduce(function(a, b) { return a + b; }) / arr.length
},
}
set_device_alias(averager, "Averager")
var PseudoPositioner = Java.extend(Writable)
var positioner = new PseudoPositioner() {
write: function (value) {
print ("Step = " + value)
},
}
set_device_alias(positioner, "Positioner")
a= lscan([ao1,positioner],[ai2,wf1,averager,clock],[0,0],[40,20],20,0.1)

View File

@@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Create a device listener to interrupt the scan
///////////////////////////////////////////////////////////////////////////////////////////////////
InterruptedException = Java.type('java.lang.InterruptedException')
//Create a listener to the sensor, verifying the readback values.
var ListenerAI = Java.extend(DeviceListener)
var listenerAI = new ListenerAI() {
onValueChanged: function (device, value, former) {
if (value > 1.02) {
print ("Value over limit-> aborting")
abort()
}
},
}
ai1.addListener(listenerAI)
var ListenerAO = Java.extend(DeviceListener)
var listenerAO = new ListenerAO() {
onStateChanged: function (device, state, former) {
},
onValueChanged: function (device, value, former) {
print ("Moved to: " + value)
},
onValueChanginf: function (device, value, former) {
if (value > 20) {
throw "Forbidden move to " + value
}
print( "Moving to: " + value + " ... ")
},
}
ao1.addListener(listenerAO)
try{
lscan(ao1, (ai1), 0, 40, 200, 0.01)
} catch (ex){
print ("Aborted"
)
}
finally{
ai1.removeListener(listenerAI)
ao1.removeListener(listenerAO)

View File

@@ -0,0 +1,19 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//Resampling a scan record if a fail condition is met.
///////////////////////////////////////////////////////////////////////////////////////////////////
index=0
function AfterReadout(rec){
print (rec.getIndex() + " - " + to_array(rec.values))
//Only accept records if ai2 is positive
if (ai2.take() < 0){
sleep(1.0)
print("Invalidating")
rec.invalidate()
}
}
a= lscan(m1, [ai1,ai2], [0,], [0.4,], 20, 0.1, relative = undefined, passes = undefined, zigzag = undefined, before_read = undefined, after_read=AfterReadout)

View File

@@ -0,0 +1,9 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Scan averaging
///////////////////////////////////////////////////////////////////////////////////////////////////
av = create_averager(ai2, 50, 0.05)
//set_preference(Preference.PLOT_TYPES, {av.name:'minmax'}) //This is to display min/max instead of sigma.
res= lscan(ao1, [av, av.samples], 0, 40, 20, 0.1)

View File

@@ -0,0 +1,55 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Calibrating array and matrix pseudo-devices
///////////////////////////////////////////////////////////////////////////////////////////////////
var ArrayCalibrated = Java.extend(ReadableArray, ReadableCalibratedArray)
var ac1 = new ArrayCalibrated() {
read: function () {
return wf1.read()
},
getSize: function (value) {
return wf1.size
},
getCalibration: function (value) {
return new ArrayCalibration(5,1000)
},
}
var ac2 = new ArrayCalibrated() {
read: function () {
return wf1.read()
},
getSize: function (value) {
return wf1.size
},
getCalibration: function (value) {
return new ArrayCalibration(5,1000)
},
}
var MatrixCalibrated = Java.extend(ReadableMatrix, ReadableCalibratedMatrix)
var mc1 = new MatrixCalibrated() {
read: function () {
return im1.read()
},
getWidth: function (value) {
return im1.width
},
getHeight: function (value) {
return im1.height
},
getCalibration: function (value) {
return new MatrixCalibration(2,4,100,200)
},
}
set_device_alias(ac1, "wf1_calib")
set_device_alias(ac2, "wf1_calib_1d")
set_device_alias(mc1, "im1_calib")
set_preference(Preference.PLOT_TYPES, {"wf1_calib_1d":1})

View File

@@ -0,0 +1,30 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Demonstrate configuring scan plot options
///////////////////////////////////////////////////////////////////////////////////////////////////
//This optional preference limits the displayed plots
set_preference(Preference.ENABLED_PLOTS, [ai1, wf1])
//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})
//This optional preference disables printing the scan table
//set_preference(Preference.PLOT_DISABLED, true)
//This optional preference disable all scan plotting
//set_preference( Preference.TABLE_DISABLED, true)
//Execute the scan: 200 steps, a1 from 0 to 40
a= lscan(ao1, [ai1,ai2,wf1], 0, 40, 100, 0.01)
//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})
ascan([m1,m2], [ai1,wf1], [0.0,0.0], [2.0,1.0], [4,4])

View File

@@ -0,0 +1,24 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Direct creation of plots
///////////////////////////////////////////////////////////////////////////////////////////////////
data_1d = [10.0, 20.0, 30.0, 40.0, 50.0]
data_2d = [ data_1d, data_1d, data_1d, data_1d, data_1d]
data_3d = [ data_2d, data_2d , data_2d, data_2d, data_2d]
data_x = [1.0, 2.0, 3.0, 4.0, 5.0]
data_y = [2.0, 4.0, 6.0, 8.0, 10.0]
//1d-plot with optional xdata
plot(data_1d, name = undefined, xdata = data_x, ydata = undefined, title = "1d")
//2d-plot with optional xdata and ydata
plot(data_2d, name = undefined, xdata = data_x, ydata = data_y, title = "2d")
//3d-plot
plot(data_3d, name = undefined, xdata = undefined, ydata = undefined, title = "3d")
//3 plots in the save panel
plot([data_1d, data_2d, data_3d], ["1d", "2d", "3d"])

View File

@@ -0,0 +1,29 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Advanced plotting examples
///////////////////////////////////////////////////////////////////////////////////////////////////
//2 series in the same plot
var xdata = [10,20,30,40,50,60]
var p = plot(null, name="Data 1")[0]
p.addSeries(new LinePlotSeries("Data2"))
p.getSeries(0).setData(xdata, [1,2,3,4,5,6])
p.getSeries(1).setData(xdata, [6,5,4,3,2,1])
p.addMarker(35.0, null, "This is the answer", Color.BLACK)
//2 series in the same plot, setting range & appending point by point
var p = plot(null,name="Data 1", title = "Plot 2")[0]
p.getAxis(AxisId.X).setRange(0.0,80.0)
p.getAxis(AxisId.Y).setRange(0.0,7.0)
p.addSeries(new LinePlotSeries("Data2"))
for (var i = 0; i< xdata.length; i++){
p.getSeries(0).appendData(xdata[i], i)
p.getSeries(1).appendData(xdata[i], 1.0/(i+1))
}

View File

@@ -0,0 +1,18 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// 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
//setup_plotting(line_plots = (ai1,))
p = plot(null, name=undefined, xdata=undefined, ydata=undefined, title="1D Plot")[0]
function AfterReadout(record, scan){
if (record.setpoints[1] == scan.getStart()[1]){
p.addSeries(new LinePlotSeries(record.positions[0].toString()))
}
p.getSeries(p.numberOfSeries-1).appendData(record.positions[1], record.values[0])
}
ascan([ao1,ao2], [ai1], [0,10], [20,30], [20,20], 0.1, relative = undefined, passes = undefined, zigzag = undefined, before_read = undefined, after_read=AfterReadout)

57
script/tutorial/34_ErrorPlot.js Executable file
View File

@@ -0,0 +1,57 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Example creating error plots
///////////////////////////////////////////////////////////////////////////////////////////////////
plots=plot([null,null,null],["y","x", "xy"])
py = plots[0]
px = plots[1]
pxy = plots[2]
//Y error plot
py.setStyle(LinePlotStyle.ErrorY)
py.setLegendVisible(true)
sy1 = new LinePlotErrorSeries("F1")
py.addSeries(sy1)
sy1.appendData(1.0, 10.0, 9.0, 11.0)
sy1.appendData(10.0, 6.1, 4.34, 7.54)
sy1.appendData(17.8, 4.5, 3.1, 5.8)
//One can define error instead of min/max (appendData(x, y, error))
sy2 = new LinePlotErrorSeries("F2")
py.addSeries(sy2)
sy2.setLinesVisible(false)
sy2.appendData(3.0, 7.0, 2.0);
sy2.appendData(13.0, 13.0, 2.0);
sy2.appendData(24.0, 16.1, 1.0);
//X error plot
px.setStyle(LinePlotStyle.ErrorX)
px.setLegendVisible(true)
sx = new LinePlotErrorSeries("F3")
px.addSeries(sx)
sx.appendData(1.0, 10.0, 0.5, 1.5)
sx.appendData(10.0, 6.1, 9.0, 10.3)
sx.appendData(17.8, 4.5, 17.0, 18.0)
//One can define error instead of min/max (appendData(x, y, error))
sx2 = new LinePlotErrorSeries("F4")
px.addSeries(sx2)
sx2.setLinesVisible(false)
sx2.appendData(1.0, 3.0, 1.0)
sx2.appendData(10.0, 5.1, 1.0)
sx2.appendData(17.8, 7.5, 0.5)
//XY error plot
pxy.setStyle(LinePlotStyle.ErrorXY)
pxy.setLegendVisible(true)
sxy = new LinePlotErrorSeries("F5")
pxy.addSeries(sxy)
sxy.appendData(1.0,0.5,1.5, 10.0, 9.0, 11.0)
sxy.appendData(10.0,9.0, 11.0, 6.1, 4.34, 7.54)
sxy.appendData(17.8, 17.0, 18.0, 4.5, 3.1, 5.8)
//One can define error instead of min/max (appendData(x, y, errorX, errorY))
sxy2 = new LinePlotErrorSeries("F6")
pxy.addSeries(sxy2)
sxy2.appendData(3.0, 7.0, 0.5, 4.0);
sxy2.appendData(13.0, 13.0, 0.5, 3.0);
sxy2.appendData(24.0, 16.1, 0.2, 2.0);

View File

@@ -0,0 +1,12 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Example changing plot styles
///////////////////////////////////////////////////////////////////////////////////////////////////
data = [0,3,5,1,3,5,3,4,3,2,1,0]
plots = plot([data, data, data], ["normal", "step", "spline"])
p1 = plots[0]
p2 = plots[1]
p3 = plots[2]
p2.setStyle(LinePlotStyle.Step)
p3.setStyle(LinePlotStyle.Spline)

View File

@@ -0,0 +1,12 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Displaying logarithmic scales
///////////////////////////////////////////////////////////////////////////////////////////////////
p = plot([10,500,1000,5000,1000], name = undefined, xdata = [0.1,1,10,100,1000, 10000])[0]
p.getAxis(AxisId.X).logarithmic = true
p.getAxis(AxisId.Y).setRange(1, 100000)
p.getAxis(AxisId.Y).logarithmic = true

View File

@@ -0,0 +1,27 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Creating a secondary X axis, using the underlying JFreeChart libraey API
///////////////////////////////////////////////////////////////////////////////////////////////////
importClass(org.jfree.chart.axis.NumberAxis)
importClass(org.jfree.chart.axis.LogarithmicAxis)
p = plot([1,2,3,4,5])[0]
x2 = new NumberAxis("Secondary X Axis") //Linear scale
//x2 = new LogarithmicAxis("Secondary X Axis") //Logarithmic scale
x2.setRange(0.1, 100)
p.getAxis(AxisId.X).setRange(-2, 5) // So the relation between X1 and X2 is enforced
jf = p.chart.plot
jf.setDomainAxis(1, x2 )
//This is just for formatting te new axis fonts and colors, equals to the first axis
jf.getDomainAxis(1).labelPaint = jf.getDomainAxis(0).labelPaint
jf.getDomainAxis(1).labelFont = jf.getDomainAxis(0).labelFont
jf.getDomainAxis(1).tickLabelPaint = jf.getDomainAxis(0).tickLabelPaint
jf.getDomainAxis(1).tickLabelFont = jf.getDomainAxis(0).tickLabelFont

View File

@@ -0,0 +1,16 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Example on running simultaneous scans. They should not manipulate same writables
///////////////////////////////////////////////////////////////////////////////////////////////////
function scan1(){
print ("scan1")
return lscan(ao1, ai1, 0, 40, 20, 0.1)
}
function scan2(){
print ("scan2")
return lscan(ao2, wf1, 0, 40, 20, 0.1, undefined, undefined, undefined, undefined, undefined, title = "scan2")
}
parallelize(scan1, scan2)

View File

@@ -0,0 +1,41 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Manual scan: Manually setting positioners and reading back sensors, but still using
// the standard data handling and plotting of built-in scans.
///////////////////////////////////////////////////////////////////////////////////////////////////
var MOTOR_RANGE = [0.0, 8.0]
var OUTPUT_SETPOINTS = [1.0, 2.0, 3.0]
var FIXED_X = true
writables_names = to_array([m1.getName(), ao1.getName()], 's')
readable_names = to_array([ai1.getName(), ai2.getName()], 's')
start = to_array( [ FIXED_X ? MOTOR_RANGE[0] : -1, OUTPUT_SETPOINTS[0]] , 'd')
stop =to_array([ FIXED_X ? MOTOR_RANGE[1] : -1, OUTPUT_SETPOINTS[OUTPUT_SETPOINTS.length-1]] , 'd')
steps = to_array([Math.round(MOTOR_RANGE[1]-MOTOR_RANGE[0]), OUTPUT_SETPOINTS.length-1] , 'i')
print (to_array(writables_names))
print (to_array(readable_names))
print (to_array(start))
print (to_array(stop))
print (to_array(steps))
scan = new ManualScan(writables_names, readable_names, start, stop, steps, false)
//This option is to plot the foe each output value one 1D series, instead of all in a matrix plot
set_preference(Preference.PLOT_TYPES, {"ai1":1, "ai2":1})
scan.start()
m1.setSpeed(10.0)
for (var setpoint1 = MOTOR_RANGE[0]; setpoint1 <=MOTOR_RANGE[1]; setpoint1+=1.0){
m1.move(setpoint1)
for (var setpoint2 in OUTPUT_SETPOINTS){
ao1.write(setpoint2)
scan.append (to_array([setpoint1, setpoint2], 'd'), to_array([m1.read(), ao1.read()], 'd'), to_array([ai1.read(), ai2.read()], 'd'))
}
}
scan.end()

View File

@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Using bsearch(Binary Search) and hsearch(Hill Climbing Search) to find optimum
///////////////////////////////////////////////////////////////////////////////////////////////////
var FitnessFunction = Java.extend(ReadonlyRegisterBase)
add_device(new FitnessFunction("fitness") {
doRead: function () {
return 1000.0 - (Math.pow(ao1.take()-18, 2) + Math.pow(ao2.take()-6, 2))
},
}, true)
//Plot Fitness Function
r = ascan([ao1, ao2], fitness, [0.0,0.0], [21.0,26.0], [1.0, 1.0], title = "Fitness")
//Binary Search
strategy = "Normal" // or "Boundary" or "FullNeighborhood"
r = bsearch([ao1, ao2], fitness, [0.0,0.0], [21.0,26.0], [0.1, 0.1], maximum=true, strategy = strategy, latency = 0.01, relative=false, before_read=undefined, after_read=undefined, title = "Binary Search")
//Relative search:
//ao1.write(10.5); ao2.write(13.0)
//r = bsearch([ao1, ao2], fitness, [-10.5,-13.0], [10.5,13.0], [0.1, 0.1],maximum=true, strategy = strategy, latency = 0.01, relative = true, before_read=undefined, after_read=undefined, title = "Binary Search")
print ("--------------- Binary Search -----------------")
print (r)
print (r.print())
print (r.getRecords().length)
//Hill Climbing Search
ao1.write(10.5)
ao2.write(13.0)
r = hsearch([ao1, ao2], fitness,[0.0,0.0], [21.0,26.0], [1.0, 1.0], [0.1, 0.1], 1, maximum=true, latency = 0.01, relative=false, before_read=undefined, after_read=undefined, title = "Hill Climbing")
print ("--------------- Hill Climbing Search -----------------")
print (r)
print (r.print())
print (r.getRecords().length)

View File

@@ -0,0 +1,37 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Scans with beam synchronous streams
///////////////////////////////////////////////////////////////////////////////////////////////////
//Creating a stream, assuming a provided named "dispatcher".
st1 = new Stream("st1", dispatcher)
//Adding channels to that stream
s1=st1.addScalar("Int8Scalar", "Int8Scalar", 10, 0)
s2=st1.addScalar("Float64Scalar", "Float64Scalar", 10, 0)
w1=st1.addWaveform("Int32Waveform", "Int32Waveform", 10, 0)
mt1=st1.addMatrix("Int16Waveform", "Int16Waveform", 10, 0, 64, 32)
st1.initialize()
try{
//The stream can be used on any conventional scan. The next stream value is sampled.
//Readable values belong to same pulse id.
tscan (st1.getReadables(), 10 , 0.2)
//The bscan command performs samples every stream element
//Readable values belong to same pulse id.
bscan (st1, 10) //Sampling 10 elements
//An individual stream channel can be used in a conventional scan, but in this case the stream
//must be explicitly started, and there is no guarantee the values belong to the same PulseID
//(likely they are since as only cached values are taken).
st1.start(true)
tscan ([s1,s2], 10 , 0.2)
//If waveform individual stream channel is used, and no size is provided in constructor/config,
//then it must be read previously to the scan to update the size value.
st1.start(true)
w1.update()
tscan ([s1,w1,mt1], 10 , 0.2)
} finally{
st1.close()
}

View File

@@ -0,0 +1,86 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//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(to_array(read)
)
assert (data1d.toString() == to_array(read).toString() )
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(to_array(read)
)
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(to_array(read))
read =load_data(path,1)
print(to_array(read))
//Creating a INT dataset adding elements one by one
path = "group/data4"
create_dataset(path, 'i')
for (var i=0; i<10; i++){
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 (var row in data2d){
append_dataset(path, data2d[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 (var row in table){
append_table(path, table[row])
}
flush_data()
//Read it back
read =load_data(path)
print(read
)
//Writing scalars (datasets with rank 0)
save_dataset("group/val1", 1)
save_dataset("group/val2", 3.14)
save_dataset("group/val3", "test")
print (load_data("group/val1")
)
print (load_data("group/val2")
)
print (load_data("group/val3")
)

View File

@@ -0,0 +1,54 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//// Using Parallelization API to execute tasks concurrently
///////////////////////////////////////////////////////////////////////////////////////////////////
//Simple parallization
function task1(){
m1.moveRel(1.0)
return m1.getPosition()
}
function task2(){
m2.moveRel(1.0)
return m1.getPosition()
}
function 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
function moveRelative(motor, 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]])
}catch (ex){
print ("Ok, caught exception:"
)
print(ex)
}

View File

@@ -0,0 +1,21 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Setting script parameters and return value
///////////////////////////////////////////////////////////////////////////////////////////////////
//Providing a map of global variables
//run ("52_ParametersAndReturn", {"start":10.0, "end":50.0, "step":40})
//Setting sys.argv:
//run ("52_ParametersAndReturn", [10.0, 50.0, 2.0])
//In this case the parameters would be parsed as:
//start = argv[0]
//end = argv[1]
//step = argv[2]
a= lscan(ao1, ai1, start, end, step, 0.1)
a.getReadable(0)
set_return(a.getReadable(0))

View File

@@ -0,0 +1,68 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// 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 value
cawait(channel_name, 0.0, timeout = 10.0)
//If many IO it is better to keep the same CA connection
channel = create_channel(channel_name, 'd')
for (var i=0; i<10; i++){
print (channel.get()
)
}
channel.close()
//The create_channel_device method return a device implements Readable and Writable and therefore can be used in scans
channel = create_channel_device(channel_name, 'd', null, "My Channel")
lscan(channel, ai2, 0, 10, 0.1)
channel.close()
//Or else we can use a Device
ChannelDouble= Java.type('ch.psi.pshell.epics.ChannelDouble')
channel = new ChannelDouble("My Channel", channel_name)
channel.initialize()
lscan(channel, ai2, 0, 10, 0.1)
channel.close()
//Creating a table reading set of channels for each scan step.
attrs_dataset = null
attrs_names = ["TESTIOC:TESTCALCOUT:Input",
"TESTIOC:TESTCALCOUT:Output",
"TESTIOC:TESTSINUS:SinCalc",
"TESTIOC:TESTWF2:MyWF"]
attrs_types = ["d", "d", "d", "[d"]
attrs_lenghts = [0,0,0,10]
function AfterReadout(rec){
if (attrs_dataset == null){
attrs_dataset = get_exec_pars().group + "attributes"
create_table(attrs_dataset, attrs_names, attrs_types, attrs_lenghts)
}
record = []
for (var i=0; i<attrs_names.length; i++){
val = caget(attrs_names[i], attrs_types[i])
record.push(val)
}
//print record
append_table(attrs_dataset, record)
}
a = lscan(m1, [ai1, ai2], 0, 0.1, 20, 0.01, undefined, undefined, undefined, undefined, after_read=AfterReadout)

View File

@@ -0,0 +1,29 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Creation of EPICS CA servers over register devices
///////////////////////////////////////////////////////////////////////////////////////////////////
CAS = Java.type('ch.psi.pshell.epics.CAS')
cas = []
//CAS.setServerPort(5062)
cas1 = new CAS("TESTCAS:c1", ai1, 'double')
cas2 = new CAS("TESTCAS:c2", ai1, 'int')
cas3 = new CAS("TESTCAS:c3", ai1, 'string')
cas4 = new CAS("TESTCAS:c4", ao1, 'double')
cas5 = new CAS("TESTCAS:c5", dp1, 'string')
cas6 = new CAS("TESTCAS:c6", wf1, 'double')
cas7 = new CAS("TESTCAS:c7", wf1, 'int')
cas8 = new CAS("TESTCAS:c8", wf1, 'string')
print (caget("TESTCAS:c1")
)
print (caget("TESTCAS:c2")
)
print (caget("TESTCAS:c3")
)
print (caget("TESTCAS:c4")
)
print (caget("TESTCAS:c5")
)

View File

@@ -0,0 +1,51 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Interlocks: example on creating and installing device interlock rules.
///////////////////////////////////////////////////////////////////////////////////////////////////
//Motor and Positioners
var MyInterlock1 = Java.extend(Interlock)
var interlock1 = new MyInterlock1( [m1, p1]) {
check: function (pos) {
m=pos[0]
p=pos[1]
if ((p<500) && (m<5) && (m>4)){
return false
}
return true
},
}
/*
//Motor group
var MyInterlock2 = Java.extend(Interlock)
var interlock2 = new MyInterlock2( [mg1, p1]) {
check: function (pos) {
print(pos)
mg=pos[0]
p=pos[1]
print(to_array(mg))
if ((p<500) && (mg[0]<5) && (mg[1]>4)){
return false
}
return true
},
}
*/
/*
//Discrete Positioner
var MyInterlock3 = Java.extend(Interlock)
interlock3 = new MyInterlock3( [dp1, p1]) {
check: function (pos) {
dp=pos[0]
p=pos[1]
print ("DP " + dp)
print ("P " + p)
if ((p<500) && (dp=="Out")){
return false
}
return true
},
}
*/

View File

@@ -0,0 +1,9 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Executing CPython in external process.
// Requires cpython.py to be put in the scripts folder, or else in the python path.
///////////////////////////////////////////////////////////////////////////////////////////////////
//Executing a module
ret = exec_cpython("cpython", [])
print (ret

View File

@@ -0,0 +1,98 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Embedding CPython with JEP: USe of numpy, pandas and matpplotlib in the same process.
// Requires cpython.py to be put in the scripts folder, or else in the python path.
///////////////////////////////////////////////////////////////////////////////////////////////////
//Requirements to the use of JEP:
// 1- PYTHONHOME is set to the python interpreter home folder.
// 2- jep*.so is in LD_LIBRARY_PATH (e.g. in extensions folder )
// 3- jep*.jar is in the CLASS_PATH (e.g. in extensions folder )
//JEP works with python 2 and 3.
run("jeputils")
//In order to use matplotlib we must set Tk backend before importing plt
eval_jep("import matplotlib")
eval_jep("matplotlib.use('TkAgg')")
//Evaluating statements
eval_jep("import sys")
eval_jep("import numpy as np")
eval_jep("a = np.array((100, 100), )")
eval_jep("print (a)")
eval_jep("\
def stderr(str): \n\
if sys.version_info < (3,0) :\n\
exec(\"print >> sys.stderr, '\" + str + \"'\") \n\
else: \n\
exec(\"print ('\" + str + \"', file=sys.stderr)\") \n\
")
eval_jep("stderr('Testing stderr')")
//Accessing a numpy array
a=get_jep("a")
print (a.getData()
)
print (a.getDimensions()
)
//Setting numpy array with scan data
steps = [3,4]
dims = [steps[0]+1 , steps[1]+1 ]
r = ascan([m1,m2], [ai1], [0.0,0.0], [0.2,0.2], steps)
data = r.getReadable(0)
a = new_numpy_array(data, dims,'d')
print (to_array(a.getDimensions()))
print (to_array(a.getData()))
plot( Convert.reshape(a.getData(),a.getDimensions()),null, null, null, "Scan Data")
//Calling a module function
b = call_jep("numpy", "transpose", [a,])
print (to_array(b.getDimensions()))
print (to_array(b.getData()))
plot( Convert.reshape(b.getData(),b.getDimensions()),null, null, null, title="Transposed")
//More calculations calling numpy
a = call_jep("numpy", "ones", [[400,200],'d'])
for (var i=0; i<100; i++){
b = call_jep("numpy", "ones", [[400,200],'d'])
a = call_jep("numpy", "add", [a,b])
s = call_jep("numpy", "sum", [a,])
print (a.getData()[0] + " " + s
)
sleep(0.001)
}
//Calling a local function
data = [1,2,3,4,5,6,7,8,9,0]
dims = [2,5]
array = new_numpy_array(data, dims,'d') //Auxiliary function to create numpy arrays from lists or java arrays.
ret = call_jep("cpython", "calc", [array,])
print (ret.getDimensions() + " - " + ret.getData()
)
//Testing pandas
ret = call_jep("cpython", "test_pandas")
//Testing tkinter
ret = call_jep("cpython", "test_tkinter")
//Testing matplotlib
ret = call_jep("cpython", "test_matplotlib", [0.1, 4, 0.4])
//Running a modole
run_jep("cpython")

68
script/tutorial/60_Fitting.js Executable file
View File

@@ -0,0 +1,68 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Function fitting and peak search with mathutils.py
///////////////////////////////////////////////////////////////////////////////////////////////////
run("mathutils")
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)
function get_function_data(func, start, end, resolution){
ret = []
for (var x=start; x<=end; x+=resolution){
fit_polinomial.push(func.value(x))
}
}
pars_polynomial = fit_polynomial(readable, positions, 6)
//(a0, a1, a2, a3, a4, a5, a6)
fitted_polynomial_function = new PolynomialFunction(pars_polynomial)
print (pars_polynomial)
pars_gaussian = fit_gaussian(readable, positions)
normalization = pars_gaussian[0]
mean_val = pars_gaussian[1]
sigma = pars_gaussian [2]
fitted_gaussian_function = new Gaussian(normalization, mean_val, sigma)
print (normalization + " " + mean_val + " " + sigma)
pars_harmonic= fit_harmonic(readable, positions)
amplitude = pars_harmonic[0]
angular_frequency = pars_harmonic[1]
phase = pars_harmonic[2]
fitted_harmonic_function = new HarmonicOscillator(amplitude, angular_frequency, phase)
print (amplitude+ " " + angular_frequency+ " " + phase)
resolution = step_size/100
fit_polinomial = []
fit_gaussian = []
fit_harmonic = []
for (var x=start; x<=end; x+=resolution){
fit_polinomial.push(fitted_polynomial_function.value(x))
fit_gaussian.push(fitted_gaussian_function.value(x))
fit_harmonic.push(fitted_harmonic_function.value(x))
}
x = range(start, end+resolution, resolution)
peaks = calculate_peaks(fitted_polynomial_function, start, end)
plots = plot([readable, fit_polinomial, fit_gaussian, fit_harmonic] ,
["data", "polinomial", "gaussian", "harmonic"], xdata = [positions,x,x,x], ydata=undefined, title="Data")
for (var p in peaks){
print ("Max: " + p)
plots[0].addMarker(p, null, "Max=" + Math.round(p,2), Color.LIGHT_GRAY)
}
plots[0].addMarker(mean_val, null, "Mean=" + Math.round(mean_val,2), Color.LIGHT_GRAY)

View File

@@ -0,0 +1,43 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Multiple Gaussians peak search with mathutils.py
///////////////////////////////////////////////////////////////////////////////////////////////////
run("mathutils")
start = 0
end = 50
step_size = 0.2
result= lscan(ao1,ai1,start,end,[step_size,])
readable = result.getReadable(0)
positions = result.getPositions(0)
min = Math.min.apply(null, readable)
max = Math.max.apply(null, readable)
threshold = (min + max)/2
min_peak_distance = 5.0
peaks = estimate_peak_indexes(readable, positions, threshold, min_peak_distance)
print ("Peak indexes: " + peaks)
print ("Peak x: " + peaks.map(function(x) {return positions[x]}))
print ("Peak y: " + peaks.map(function(x) {return readable[x]}))
gaussians = fit_gaussians(readable, positions, peaks)
plots = plot([readable],["sin"],[positions], undefined, title="Data" )
for (var i=0; i< peaks.length; i++){
peak = peaks[i]
pars_gaussian = gaussians[i]
normalization = pars_gaussian[0]
mean_val = pars_gaussian[1]
sigma = pars_gaussian [2]
if (Math.abs(mean_val - positions[peak]) < min_peak_distance){
print ("Peak -> " + mean_val)
plots[0].addMarker(mean_val, null, "N="+ Math.round(normalization,2), new Color(210,0,0))
}else {
print ("Invalid gaussian fit: " + mean_val)
}
}

30
script/tutorial/62_FFT.js Executable file
View File

@@ -0,0 +1,30 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Demonstrate the use of fft function in mathutils.py
///////////////////////////////////////////////////////////////////////////////////////////////////
run("mathutils")
//The signal is composed by 3 sinusoids (100Hz, 200Hz, 400Hz) and a background noise (a sin waveform is A.sin(2.pi.f.t))
function signal_generator(t){
return Math.sin(100*2*Math.PI*t) + 0.5 * Math.sin(200*2*Math.PI*t) + 0.25 * Math.sin(400*2*Math.PI*t) + 0.5* Math.random()
}
sampling_frequency = 1024.0
number_of_samples = 1024
time_vector = range(0, number_of_samples, 1).map(function(x) {return x / sampling_frequency})
signal = time_vector.map(function(x) {return signal_generator(x)})
tranform = fft(signal)
two_side_spectrum = get_modulus(tranform).map(function(x) {return x / number_of_samples})
spectrum = two_side_spectrum.slice(1,two_side_spectrum.length/2 + 1).map(function(x) {return (x * x)})
spectrum.splice(0,0,two_side_spectrum[0])
number_of_samples = tranform.length // Signal may have been padded to next power of two
freq_vector = range(0, spectrum.length , 1).map(function(x) {return x * sampling_frequency / parseFloat(number_of_samples)})
plot([signal,spectrum], ["signal", "spectrum"],[time_vector, freq_vector])

View File

@@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Create an online spectrum analyser uysing mathutils.py
///////////////////////////////////////////////////////////////////////////////////////////////////
run("mathutils")
function plot_spectrum(signal, sampling_freq){
if (!is_defined(plots)) plots = null
signal = to_array(signal)
number_of_samples = signal.length
time_vector = range(0, number_of_samples, 1).map(function(x) {return x / sampling_freq})
tranform = fft(signal)
two_side_spectrum = get_modulus(tranform).map(function(x) {return x / number_of_samples})
spectrum = two_side_spectrum.slice(1,two_side_spectrum.length/2 + 1).map(function(x) {return x * x})
spectrum.splice(0,0,two_side_spectrum[0])
number_of_samples = tranform.length // Signal may have been padded to next power of two
freq_vector = range(0, spectrum.length , 1).map(function(x) {return x * sampling_freq / parseFloat(number_of_samples)})
if (plots == null){
plots = plot([signal,spectrum], ["signal", "spectrum"],[time_vector, freq_vector], undefined, title = "Spectrum")
plots[0].getAxis(AxisId.Y).setRange(-1.5,2.5)
plots[1].getAxis(AxisId.Y).setRange(0.0,1.1)
} else {
plots[0].getSeries(0).setData(time_vector,signal)
plots[1].getSeries(0).setData(freq_vector,spectrum)
}
return plots
}
function get_sample(samples, sampling_freq){
return range(0,samples,1).map(function(t) {return Math.sin(200*2*Math.PI*t/sampling_freq) + Math.random()})
//Simple example sampling a device:
//set_exec_pars(undefined, undefined, undefined, undefined, persist=false)
//set_preference(Preference.PLOT_DISABLED, true)
//set_preference(Preference.TABLE_DISABLED, true)
//return tscan(ai1, samples, 1/sampling_freq).getReadable(0)
}
plots = null
samples = 1024
sampling_freq = 1024.0
while(true){
signal = get_sample(samples, sampling_freq)
plots = plot_spectrum(signal, sampling_freq, plots)
sleep(0.1)
if (plots[0].displayable == false){
break
}
}

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Use of numerical analysis functions in mathutils
///////////////////////////////////////////////////////////////////////////////////////////////////
run("mathutils")
//interpolation
var fy = [0, 1, 4,10,50,25,12, 5, 3, 0]
var fx = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
types = ["linear", "cubic", "akima", "loess", "neville", "newton"]
functions = types.map(function(t) {return interpolate(fy,fx,t)})
plot_x = range (0,9,0.01)
values = functions.map(function(f) {return get_values(f,plot_x)})
plots=plot(values,types,plot_x)
//derivative
for (var i=0; i<types.length; i++){
try{
d = deriv(functions[i])
plots[i].addSeries(new LinePlotSeries("derivative"))
plots[i].getSeries(1).setData(plot_x, get_values(d,plot_x))
} catch(ex){
//not differentiable
}
}
//integration
for (var i=0; i<types.length; i++){
s = integrate(functions[i],fx)
plots[i].addMarker(fx[fx.length-1]+0.1, null, "Integral=" + Math.round(s,4), plots[i].background).setLabelPaint(Color.BLACK)
}
//Direct calculation on arrays:
print ("Deriv (linear interpolation): ", deriv(fy,fx))
print ("Deriv (cubic interpolation): ", deriv(fy, fx, "cubic"))
print ("Integral (linear interpolation): ", integrate(fy, null, fx, "cubic"))
print ("Integral (cubic interpolation): ", integrate(fy, null, fx, "cubic"))
print ("Integral (linear interpolation in range [1,5]): ", integrate(fy, [1,5], fx))

View File

@@ -0,0 +1,70 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Example of convex hull plot
//
//////////////////////////////////////////////////////////////////////////////////////////////////
function add_convex_hull_plot(title, x,y, name, clear){
if (!is_defined(name)) name = null
if (!is_defined(clear)) clear = false
plots = get_plots(title = title)
p = null
if (plots.length==0){
p = plot(null,name=name, undefined, undefined, title = title)[0]
p.getAxis(AxisId.X).setRange(-50,150)
p.getAxis(AxisId.Y).setRange(-50,150)
p.setLegendVisible(true)
} else {
p = plots[0]
if (clear){
p.clear()
}
p.addSeries(new LinePlotSeries(name))
}
s = p.getSeries(name)
s.setLinesVisible(false)
s.setPointSize(3)
s.setData(x, y)
//In the first time the plot shows, it takes some time for the color to be assigned
while (s.color == null){
sleep(0.001)
}
hull = new LinePlotSeries(name + " Hull", s.color)
//Bounding box
//x1 = Math.min.apply(null, x)
//x2 = Math.max.apply(null, x)
//y1 = Math.min.apply(null, y)
//y2 = Math.max.apply(null, y)
//(hx,hy) = ([x1,x2, x2, x1, x1], [y1, y1, y2, y2, y1])
//Convex Hull
ret = convex_hull(point_list=undefined, x=x, y=y)
hx=ret[0]
hy=ret[1]
hx.push(hx[0])
hy.push(hy[0])
p.addSeries(hull)
hull.setLineWidth(2)
hull.setData(hx,hy)
hull.setColor(s.color)
}
title = "Convex Hull"
if (get_plots(title).length>0){
get_plots(title)[0].clear()
}
for (var step=1; step<=5; step++){
x=[]
y=[]
for (var i=0; i<=50 ; i++){
x.push(Math.random() * 100 / step)
y.push(Math.random() * 100/ step)
}
add_convex_hull_plot (title, x,y,"Scan " + step)
}

View File

@@ -0,0 +1,41 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Example if fitting with weights
///////////////////////////////////////////////////////////////////////////////////////////////////
run("mathutils")
run("plotutils")
fx = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
fy = [36.0, 66.0, 121.0, 183.0, 263.0, 365.0, 473.0, 603.0, 753.0, 917.0]
num_samples = fx.length
p=plot(fy, "Observed Data", xdata=fx)[0]
p.setLegendVisible(true)
pars_polynomial= fit_polynomial(fy, fx, 1, null)
func = new PolynomialFunction(pars_polynomial)
plot_function(p, func, "1st order", fx)
var w = []; size=num_samples; while(size--) w.push(1.0);
w[5]=20.0
pars_polynomial= fit_polynomial(fy, fx, 1, null, w)
func = new PolynomialFunction(pars_polynomial)
plot_function(p, func, "1st order Weighted: " + w , fx)
pars_polynomial= fit_polynomial(fy, fx, 2, null, w)
func = new PolynomialFunction(pars_polynomial)
plot_function(p, func, "2nd order" + w , fx)
for (var xp in fx){
print (fx[xp] + " " + poly(fx[xp], pars_polynomial))
}
print ("")
w = [ 10.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 10.0]
pars_polynomial= fit_polynomial(fy, fx, 2, null, w)
func = new PolynomialFunction(pars_polynomial)
plot_function(p, func, "2n order Weighted: " + w , fx)
for (var xp in fx){
print (fx[xp] + " " + poly(fx[xp], pars_polynomial))
}

View File

@@ -0,0 +1,122 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Example of least squares optimization
// http://commons.apache.org/proper/commons-math/userguide/leastsquares.html
///////////////////////////////////////////////////////////////////////////////////////////////////
run("mathutils")
run("plotutils")
plots = plot([null, null], [null, null])
p1=plots[0]
p2=plots[1]
///////////////////////////////////////////////////////////////////////////////////////////////////
//Fitting the quadratic function f(x) = a x2 + b x + c
///////////////////////////////////////////////////////////////////////////////////////////////////
var fx = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
var fy = [36.0, 66.0, 121.0, 183.0, 263.0, 365.0, 473.0, 603.0, 753.0, 917.0]
num_samples = fx.length
weigths = []; size=num_samples; while(size--) weigths.push(1.0)
p1.getSeries(0).setData(fx, fy)
p1.getSeries(0)
var Model = Java.extend(MultivariateJacobianFunction)
var model = new Model() {
value: function (variables) {
value = new ArrayRealVector(num_samples)
jacobian = new Array2DRowRealMatrix(num_samples, 3)
for (var i=0; i< num_samples; i++){
a=variables.getEntry(0)
b=variables.getEntry(1)
c=variables.getEntry(2)
model = a*fx[i]*fx[i] + b*fx[i] + c
value.setEntry(i, model)
jacobian.setEntry(i, 0, fx[i]*fx[i]) // derivative with respect to p0 = a
jacobian.setEntry(i, 1, fx[i]) // derivative with respect to p1 = b
jacobian.setEntry(i, 2, 1.0) // derivative with respect to p2 = c
}
return new Pair(value, jacobian)
},
}
initial = [1.0, 1.0, 1.0] //parameters = a, b, c
target = fy.slice(0) //the target is to have all points at the positios
ret = optimize_least_squares(model, target, initial, weigths)
parameters = ret[0]
residuals = ret[1]
rms = ret[2]
evals = ret[3]
iters = ret[4]
a = parameters[0]
b = parameters[1]
c = parameters[2]
print ("A: " + a + " B: "+ b, " C: "+ c
)
print ("RMS: " + rms+ " evals: " + evals+ " iters: " + iters
)
for (var i=0; i<num_samples; i++){
print (fx[i] + " " + fy[i] + " " + poly(fx[i] + " " + [c,b,a])
)
}
plot_function(p1, new PolynomialFunction([c,b,a]), "Fit", fx)
print ("----------------------------------------------------------------------------\n"
)
///////////////////////////////////////////////////////////////////////////////////////////////////
//Fitting center of circle of known radius to observed points
///////////////////////////////////////////////////////////////////////////////////////////////////
radius = 70.0
fx = [30.0, 50.0, 110.0, 35.0, 45.0]
fy = [68.0, -6.0, -20.0, 15.0, 97.0]
num_samples = fx.length
weigths = [0.1, 0.1, 1.0, 0.1, 1.0]
p2.getSeries(0).setData(fx, fy)
p2.getSeries(0).setLinesVisible(false)
p2.getSeries(0).setPointSize(4)
// the model function components are the distances to current estimated center,
// they should be as close as possible to the specified radius
var Model = Java.extend(MultivariateJacobianFunction)
var model = new Model() {
value: function (variables) {
cx=variables.getEntry(0)
cy=variables.getEntry(1)
value = new ArrayRealVector(num_samples)
jacobian = new Array2DRowRealMatrix(num_samples, 2)
for (var i=0; i< num_samples; i++){
var mod = hypot(cx-fx[i], cy-fy[i])
value.setEntry(i, mod)
jacobian.setEntry(i, 0, (cx - fx[i]) / mod) // derivative with respect to p0 = x center
jacobian.setEntry(i, 1, (cy - fy[i]) / mod) // derivative with respect to p1 = y center
}
return new Pair(value, jacobian)
},
}
initial = [mean(fx), mean(fy)] //parameters = cx, cy
target = []; size=num_samples; while(size--) target.push(radius); //the target is to have all points at the specified radius from the center
ret = optimize_least_squares(model, target, initial, weigths)
parameters = ret[0]
residuals = ret[1]
rms = ret[2]
evals = ret[3]
iters = ret[4]
cx = parameters[0]
cy = parameters[1]
print ("CX: " + cx + " CY: "+ cy)
print ("RMS: " + rms+ " evals: " + evals, " iters: " + iters)
plot_point(p2, cx, cy, size = 5, color = null, name = "Fit Center")
plot_circle(p2, cx, cy, radius, width = 1, color = null, name = "Fit")

View File

@@ -0,0 +1,95 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Demonstrate creation of an image filters and new source based on filter.
// Also demonstrate creation of image histogram and use of overlays.
///////////////////////////////////////////////////////////////////////////////////////////////////
importClass(java.awt.Point)
importClass(java.awt.Dimension)
importClass(java.awt.Font)
Filter = Java.type('ch.psi.pshell.imaging.Filter')
Pen = Java.type('ch.psi.pshell.imaging.Pen')
Line = Java.type('ch.psi.pshell.imaging.Overlays.Line')
Rect = Java.type('ch.psi.pshell.imaging.Overlays.Rect')
Crosshairs = Java.type('ch.psi.pshell.imaging.Overlays.Crosshairs')
Text = Java.type('ch.psi.pshell.imaging.Overlays.Text')
Utils = Java.type('ch.psi.pshell.imaging.Utils')
var MyFilter = Java.extend(Filter)
var filter = new MyFilter() {
process: function (image, data) {
image = Utils.grayscale(image)
image = Utils.blur(image)
image = Utils.sobel(image)
return image
},
}
//Setting the filter to a source
src2.setFilter(filter)
//Creating a new source with the filter
src1.setFilter(null)
add_device(new MyFilter("f1") {
process: function (image, data) {
image = Utils.grayscale(image)
image = Utils.blur(image)
image = Utils.sobel(image)
return image
},
}, true)
//f1.passive = true
src1.addListener(f1)
//Open renderers
renderer_filter = show_panel(f1)
renderer = show_panel(src1)
//Overlays
plots = null
size = renderer.getImageSize()
ov_text = new Text(new Pen(Color.GREEN.darker()), "Ploting Histogram", new Font("Verdana", Font.PLAIN, 12), new Point(20,20))
ov_line = new Line(new Pen(Color.DARK_GRAY), new Point(0,size.height/2), new Point( size.width ,size.height/2))
ov_rect = new Rect(new Pen(Color.DARK_GRAY), new Point(size.width/2 -15,size.height/2+10), new Dimension(30,30))
ov_cross = new Crosshairs(new Pen(Color.DARK_GRAY), new Point(size.width/2 ,size.height/3), new Dimension(15,15))
ov_rect.setSolid(true)
ov_rect.setMovable(true)
//Histogram
try{
renderer.addOverlays([ov_text,ov_line, ov_rect, ov_cross])
while(true){
h = histogram(im1.read(), undefined, undefined, bin=0.1)
hd=h[0]; xd = h[1]
image = Utils.grayscale(src1.getOutput())
data = Convert.toUnsigned(image.getData().getDataBuffer().getData())
h = histogram(data, range_min=0, range_max=255)
hi=h[0]; xi = h[1]
if (plots == null){
plots = plot([hd,hi], ["Data", "Image"],[xd, xi], title = "Histo")
} else{
plots[0].getSeries(0).setData(xd,hd)
plots[1].getSeries(0).setData(xi,hi)
}
if (plots[0].displayable == false){
break
}
ov_cross.update(new Point((ov_cross.position.x+1) % size.width ,(ov_cross.position.y+1) % size.height))
sleep(0.1)
}
} finally {
renderer.removeOverlays([ov_text,ov_line, ov_rect, ov_cross])
}

154
script/tutorial/71_ImageJ.js Executable file
View File

@@ -0,0 +1,154 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Example of using ImageJ functionalities through ijutils.
///////////////////////////////////////////////////////////////////////////////////////////////////
run("ijutils")
//Image Loading
ip = load_image("images/img.png", title="Image")
//Basic image manipulation: creation, copying, padding, saving
resized = resize(ip, 300,300)
save_image(resized, get_context().setup.expandPath("{images}/resized.tiff") ,"tiff")
crop=sub_image(ip,10,20,50,30)
bin_im = binning(ip,2)
new_im = new_image(256, 256, "color")
copy_image_to(bin_im, new_im, 20, 20)
pad_im = pad_image(ip, 1, 2, 3, 4, Color.RED)
stack=create_stack([ip,resized,crop, bin_im, new_im, pad_im], undefined, title = "Basic Functions")
save_image(stack, get_context().setup.expandPath("{images}/stack.tiff") ,"tiff")
stack.show()
//Decomposing color channels
create_stack([ get_channel(ip, "red"),
get_channel(ip, "green"),
get_channel(ip, "blue"),
get_channel(ip, "alpha"),
grayscale(get_channel(ip, "brightness"), false)], undefined, title = "Color Decomposition").show()
//Basic functions (in_place)
aux = ip.duplicate()
aux.show()
grayscale(aux)
gaussian_blur(aux); aux.repaintWindow()
invert(aux); aux.repaintWindow()
smooth(aux); aux.repaintWindow()
sharpen(aux); aux.repaintWindow()
noise(aux, 100); aux.repaintWindow()
//Changing LUT
aux = ip.duplicate()
aux = grayscale(aux, in_place=false)
r=[]; g=[]; b=[]
for (var i=0; i<256; i++){
r.push(0)
g.push(0)
b.push(i)
}
set_lut(aux, r, g, b)
aux.show()
//Histogram
plot(get_histogram(ip))
aux = grayscale(ip, in_place = false)
bin = ip.duplicate()
ip_bin = auto_threshold(aux, undefined, undefined, in_place=false)
create_stack([ ip_bin,
binary_fill_holes(ip_bin, dark_background = false, in_place=false),
binary_outline(ip_bin, dark_background = false, in_place=false),
binary_outline(binary_fill_holes(ip_bin, dark_background = false, in_place=false), dark_background = false),
binary_dilate(ip_bin, undefined, undefined, undefined, in_place=false),
binary_erode(ip_bin, undefined, undefined, undefined, in_place=false),
binary_open(ip_bin, undefined, undefined, undefined, in_place=false),
binary_close(ip_bin, undefined, undefined, undefined, in_place=false),
binary_skeletonize(ip_bin, in_place=false)], undefined, title = "Binarization").show()
//EDM, const & image operations
aux = grayscale(ip, in_place = false)
ip_bin = auto_threshold(aux, undefined, undefined, in_place=false)
binary_fill_holes(ip_bin)
edm = edm(ip_bin, dark_background=false, in_place=false)
ws = watershed(ip_bin, dark_background=false, in_place=false)
up = ultimate_points(ip_bin, dark_background=false, in_place=false)
vr = veronoi(ip_bin, dark_background=false, in_place=false)
edm_disp = remap(edm, min=null, max=null, in_place=false)
ws_disp = grayscale(ws, in_place=false)
up_disp = enhance_contrast(up, undefined, undefined, undefined, undefined, in_place=false)
vr_disp = enhance_contrast(vr, undefined, undefined, undefined, undefined, in_place=false)
create_stack([edm_disp, aux, ip_bin, ws_disp, up_disp, vr_disp], undefined, title = "EDM Operations").show()
final_img = grayscale(ip_bin, in_place = false)
op_const(final_img,"add", -200)
op_image(final_img, vr_disp, 'or')
op_image(final_img, up_disp, 'or')
final_img.show()
aux = grayscale(ip, in_place = false)
create_stack([ aux,
subtract_background(aux, undefined, undefined, undefined, undefined, undefined, undefined, undefined, in_place=false),
smooth(aux, false),
sharpen(aux, false),
edges(aux, false),
bandpass_filter(aux,0, 5, undefined, undefined, undefined, undefined, undefined, in_place=false),
bandpass_filter(aux,5, 100, undefined, undefined, undefined, undefined, undefined, in_place=false),
op_const(aux,"and", 127, false),
convolve(aux, KERNEL_BLUR, false),
convolve(aux, KERNEL_SHARPEN, false),
convolve(aux, KERNEL_SHARPEN_2, false),
convolve(aux, KERNEL_LIGHT, false),
convolve(aux, KERNEL_DARK, false),
convolve(aux, KERNEL_EDGE_DETECT, false),
convolve(aux, KERNEL_EDGE_DETECT_2, false),
convolve(aux, KERNEL_DIFFERENTIAL_EDGE_DETECT, false),
convolve(aux, KERNEL_PREWITT, false),
convolve(aux, KERNEL_SOBEL, false)
], undefined, title = "General Operations").show()
//Rank operators
rank_opers = []
oplist = ["mean", "min", "max", "variance", "median", "close_maxima", "open_maxima", "remove_outliers", "remove_nan", "despeckle"]
for (var op in oplist){
rank_opers.push(op_rank(aux,oplist[op],kernel_radius=1, undefined, undefined, in_place=false))
}
create_stack(rank_opers, undefined, title = "Rank Operations").show()
//Reslicing
//orig = load_image("{data}/img/img2.png")
orig = resize(ip, 300,200)
grayscale(orig)
images=[]
for (var i=0; i<20; i++){
images.push(orig.duplicate())
op_const(orig, "multiply", 0.9)
}
stack=create_stack(images, undefined, title = "Original Stack")
//stack.show()
r1 = reslice(stack, start_at="Left", undefined, undefined, undefined, undefined, title="Reslice Horizontally")
r2 = reslice(stack, start_at="Top", undefined, undefined, undefined, undefined, title="Reslice Vertically")
r1.show()
r2.show()
//Particle Analysis
aux = grayscale(ip, in_place = false)
auto_threshold(aux)
//binary_fill_holes(aux)
//aux.show()
var ret=analyse_particles(aux, 100,1000, true, true, 0, print_table=true)
var results=ret[0]
var output_img=ret[1]
output_img.show()