# 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)