from deFIBrillator import FIBG2, plot_stream_file

# Initialize the FIB G2
fib = FIBG2()

# Default Ion Beam is 48pA at 30kV, but you can change it with the set_beam() method. Beams are found under fib.Beams.
fib.set_beam(fib.Beams.Acceleration30kV.pA48)

# Default magnification is 1000x. Change directly with set_magnification(), or indirectly with set_fov().
fib.set_magnification(5000)
fib.set_fov(20, "um")  # Adjust magnification so the field of view is 20x20 microns

# You can print the fib to get it's parameters, including the beam parameters.
print(fib)

# Create a new pattern
pat = fib.new_pattern()

# Default substrate is Silicon with inf thickness. Change with set_material() method.
# Materials are found under pat.Materials. If no depth is provided when calling the material, it's infinite.
# Layers are top to bottom. Here the sample is 115 nm Au on top, 10 nm Ti beneath, and inf SiO2 at the bottom.
pat.set_material(pat.Materials.Au(115, "nm"), pat.Materials.Ti(10, "nm"), pat.Materials.SiO2)

# Default dwell time for a pattern is 1 μs, but you can change it with the set_dwell_time() method.
pat.set_dwell_time(1, "us")

# Default milling depth for a pattern is 0.5 μm. You can change it with set_depth(). Some examples:
pat.set_depth(100, "nm")  # Mill 100 nm deep.
pat.set_depth(pat.substrate[0])  # Mill first layer. Units don't need to be specified when only materials are provided.
pat.set_depth([pat.substrate[0], 10], "nm")  # Through first layer + 10 nm.
pat.set_depth(pat.substrate[:2] + [10], "nm")  # Through first two layers + 10 nm.
pat.set_depth(pat.substrate[:2])  # Through first two layers.

# Default scan style is shrinking contours (contour inwards). Change with set_scan_style().
# Scan styles are found under pat.ScanStyles
pat.set_scan_style(pat.ScanStyles.contour_outward)

# Create a shape. Shapes are found under pat.add.
# All areas covered by only shapes with millable=True will be milled. If you overlay the shape with another shape with
# millable=False, the area covered by that shape won't be milled. This way you can create exclusion zones.
circle = pat.add.circle(radius=100, millable=True)

# Add a lattice. Aplha is the lattice vector in x, beta in y, and gamma the angle
# between them (90 for rectangular lattice).
PERIODICITY = 300
lat = pat.add.lattice(rows=10, cols=10, alpha=PERIODICITY, beta=PERIODICITY, gamma=90, shape=circle)

pat.set_position(5, 5, "um")

# You can draw the pattern with pat.plot_pattern(). The coordinates are relative to the pattern itself
pat.plot_pattern()

# Alternatively you can use the fib.plot_patterns(). This plots all patterns inside the actual field of view.
# Here you can easily see if any of your millable area is outside the fov.
fib.plot_patterns()

# You can plot the beam path with plot_beam_path(). NB! The dots on the plot does not correspond to the beam radius.
pat.plot_beam_path()

# You can get an animation of the beam path with animate_beam_path(). The circle radius corresponds to the beam radius.
pat.animate_beam_path()

# Create a stream file with write_stream_file(). The filename does not need to contain the .str suffix.
# It is recomended to include the FIB magnification, beam voltage and beam current in the filename, as you must use
# these parameters when milling the stream file on the FIB. If not, the results will not be what you want.
pat.write_stream("test")

# You can plot the stream file you just made. As the magnification has an effect on how positions are translated into
# pixel space, you should double check that the beam path turned out like you intended.
# Lower magnifications generally produce more inaccurate beam paths.
plot_stream_file("test.str")
