Meta input using Python
Python syntax can be used in FRED input files to generate very powerful, compact and versatile meta input. It is possible to define constants, variables, and functions. You can also use for-loops to generate complex input structures. The input file is preparsed by the Python interpreter that generates the actual input file before invoking FRED executable.
Important
The Python interpreter is invoked with the following environment:
from math import *
from random import *
import numpy as np
from numpy import dot, cross, prod
# some utility functions
def norm(v): # modulus of a vector
return sqrt(dot(v,v))
def distance(P,Q): # distance between two points
return norm(P-Q)
def mod(m,n): # remainder of integer division
return m%n
All the numpy features are available for the creation of meta-input.
Hereafter, the implemented directives and control structures.
def:
constant parameter definition. Syntax:
def: name = value
Example:
def: N = 5 # number of turns def: nspots = 100 # total number of spots def: Rmax = 3 # major radius def: Rmin =0 # minor radius def: Rmean = (Rmax+Rmin)/2
func:
function definition. Syntax:
func: name(args...) = expression
Example:
func: Sdisc(r) = pi*r**2 # disc area func: Vsphere(r) = 4./3.*pi*r**3 # sphere volume func: Vbox(a,b,c) = a*b*c # box volume func: r(theta) = Rmax-(Rmax-Rmin)*theta/(N*2*pi) # spiraling radius
substitution of scalar parameters in normal FRED input
scalar parameters defined using def: directive can be inserted in normal input by the Python preparser. Syntax:
$parname
Example:
this meta-input
# how to define the number of voxels for a given spacing def: Lx = 8 # cm def: Ly = 6 # cm def: Lz = 13 # cm def: spacing = 0.3 # 3 mm voxels def: nx = int(Lx/spacing) def: ny = int(Ly/spacing) def: nz = int(Lz/spacing) region: phantom ; L=[$Lx,$Ly,$Lz] ; voxels = [$nx,$ny,$nz]
will generate to following input to FRED
region: phantom ; L=[8,6,13] ; voxels = [26,20,43]
substitution of vector parameters in normal FRED input
vector parameters defined using def: directive and numpy arrays can be inserted in normal input by the python preparser. Syntax:
${parname}
For instance, the previous example can be obtained in a more compact way using numpy arrays
def: L = np.array([8,6,13]) def: spacing = 0.3 def: nn = (L/spacing).astype(int) region: phantom ; L=${L} ; voxels = ${nn}
substitution of expressions in normal FRED input
expressions are evaluated by the python preparser and placed in FRED input using the following syntax:
${expression}
Example:
this meta-input
# how to define a beam with tranverse area equal to half of phantom entry surface def: Lx = 8 # cm def: Ly = 8 # cm def: Lz = 20 # cm func: myDiameter(S) = sqrt(4*S/pi) # diameter of a disc with area S region: phantom ; L=[$Lx,$Ly,$Lz] ; voxels = [200,200,100] pb: 1 0 ; Xsec = disc ; FWHM = ${myDiameter((Lx*Ly)/2)}
will generate to following input to FRED
region: phantom ; L=[8,8,20] ; voxels = [200,200,100] pb: 1 0 ; Xsec = disc ; FWHM = 6.38308
for()<…>
definition of a multiline loop to be executed by the preparser. Syntax:
for (condition) < ... ... ... for>
For constructs can be nested: indentation level must be preseved as in normal python code.
Example:
for(th in np.linspace(0,N*2*pi,nspots))< def: x = r(th)*cos(th) def: y = r(th)*sin(th) transform: phantom move_to $x $y 0 deliver: all for>
(see the complete example Spiralling Spots irradiation pattern)
if()<…>
conditional execution of a block of code by the preparser. Syntax:
if (condition) < ... ... ... for>
Example: using for and if to produce a chessboard irradiation pattern
for(ix in range(nspot+1))< # control points in x for(iy in range(nspot+1))< # control points in y if(mod(ix,2)==mod(iy,2))< # choose alternate squares def: x = -side/2 + ix*spotSpacing def: y = -side/2 + iy*spotSpacing transform: field_0 move_to $x $y -50 deliver: all if> for> for>
(see the complete example Chessboard irradiation pattern)