MaxMacros	40
Macro	0
MacroName mapgrids

# Dock a cassette, setup full montage, change cooldown delay time and start this script
# Whenreloading a previously mapped grid, see SerialEM help in Navigator menu, Align with Rotation.

Delay 5 min # change cooldown wait time to match your local autoloader cooldown time

CallFunction dosemonitor # measuring empty beam dose rate for monitoring purposes

# Autoloader inventory
LongOperation In

# Loop over slots
Loop 12 index
   echo $index
   ReportSlotStatus $index
   if $RepVal1 == 1
      LoadCartridge $index	
      MoveStageTo 0 0 0
      SetColumnOrGunValve 1
      M
      NewMap	
   endif
endloop

CloseFile
SetColumnOrGunValve 0

# Mail user
MailSubject Krios 2 gridmaps ready
SendEmail Krios 2 gridmaps ready
EndMacro
Macro	1
macroname ZwithV
Loop 2
   G -1 2
   ReportAutofocus 
   t  = -1 * $reportedValue1
   if $t >= 0
      changeZ = $t + 3
      MoveStage 0 0 $changeZ
      MoveStage 0 0 -3
   elseif $t <= 0
      MoveStage 0 0 $t
   endif
   echo --> Z moved $t micron 
EndLoop

UpdateItemZ
SaveNavigator 
EndMacro
Macro	2
MacroName ZwithG

Echo ===> Running focus with stage ...
   Loop 2
      G -1
      ReportAutofocus 
      t  =  -1 * $RepVal1
      if $t >= 0
         changeZ = $t + 3
         MoveStage 0 0 $changeZ
         MoveStage 0 0 -3
      elseif $t <= 0
         MoveStage 0 0 $t
      endif
      echo --> Z moved $t micron 
   EndLoop

UpdateItemZ 
SaveNavigator 
EndMacro
Macro	4
MacroName SPAK3aligntohole
# SPA macro for Krios/Quantum/K3
# Wim Hagen, EMBL Heidelberg 20191030

####### SETTINGS ####### 

# Buffer P is expected to have refference hole image from Low Dose View!

driftcrit                 = 28            # A/sec
driftinterval        = 3               # seconds
drifttimes 	        = 3	       # max no of drift measurements

TD_low              =  -0.5            # low defocus microns
TD_high             = -1.6       # high defocus microns
delta                    = 0.10     # defocus step microns
focusdistance    = 0            # micrometers

maxholeshift      = 2         # maximum hole shift in microns
MultiShot            = 1            # 0 for single shot, 1 for multi shots

vpp                             = 0
conditiong                 = 45       # seconds 
tonextphaseplate     = 75        # switch phase plate every x images

####### END SETTINGS ####### 

If $vpp == 1
   SetUserSetting  AutofocusBeamTilt 10
   ReportUserSetting AutofocusBeamTilt
ElseIf $vpp == 0 
   SetUserSetting  AutofocusBeamTilt 4
   ReportUserSetting AutofocusBeamTilt
Endif 

SuppressReports
MoveStage -0.025 -0.025
ReportNavItem

MailSubject Krios 2
ErrorBoxSendEmail Krios 2 has a problem!
SetColumnOrGunValve 1

ReportClock 
ticks = $RepVal1

####### Align to hole #######

CallFunction AutoFillDarkRef
CallFunction HoleCentering

ReportClock
holecenteringticks = ($repVal1 - $ticks)

####### Focus #######

CallFunction AutoFillDarkRef
CallFunction AutoFocusSPA

ReportClock
focusticks = ($repVal1 - $ticks)

####### Drift #######

CallFunction AutoFillDarkRef
CallFunction DriftSPA

ReportClock
driftticks = ($repVal1 - $ticks)

####### Acquire images #######

ReportTargetDefocus targetedfocus
echo target defocus = $targetedfocus
ReportDefocus actualdefocus
echo actual defocus = $actualdefocus

GoToLowDoseArea R
delay 1 sec
CallFunction AutoFillDarkRef
If $MultiShot == 1
   MultipleRecords 
ElseIf  $MultiShot == 0
   EarlyReturnNextShot 0
   R
Endif 

####### Next phase plate #######

If $vpp == 1
   remainder = modulo $navAcqIndex $tonextphaseplate
   echo Acquiring Item is $navAcqIndex , remain is $remainder
   if $remainder == 0
      echo Moving to next phase plate!
      ShowMessageOnScope NextPhasePlate
      Delay 30 sec
      ScreenDown
      Delay $conditiong sec
      ScreenUp
   endif
Endif 

RefineZLP 60
UpdateHWDarkRef 0.5

GoToLowDoseArea V

# timing
ReportClock
recordticks = ($repVal1 - $ticks)
holetime = $holecenteringticks
focustime = $focusticks - $holecenteringticks
drifttime = $driftticks - $focusticks
recordtime = $recordticks - $driftticks
echo timing $holetime $focustime $drifttime $recordtime $recordticks seconds

Echo ===> Done ...
Echo ====================================================
EndMacro
Macro	5
MacroName SPAK2aligntomap
# SPA macro for Krios/Quantum/K2
# Buffer P is expected to have refference hole image from Low Dose View
# Wim Hagen, EMBL Heidelberg 20170309
# Credits to Chen Xu & Henning Stahlberg group

####### SETTINGS ####### 

driftcrit                 = 3	# A/sec
driftinterval        = 5        # seconds
drifttimes 	        = 5	# max no of drift measurements

TD_low              = -0.8       # low defocus microns
TD_high             = -2      # high defocus microns
delta                    = 0.1    # defocus step microns
focusdistance   = 0      # micrometers

####### END SETTINGS ####### 

SuppressReports
ReportClock 
ticks = $RepVal1

MoveStage -0.025 -0.025

MailSubject Krios 2
ErrorBoxSendEmail Krios 2 has a problem!
SetColumnOrGunValve 1
SetUserSetting  AutofocusBeamTilt 4
ReportUserSetting AutofocusBeamTilt

####### Align to map #######

CallFunction AutoFillDarkRef
CallFunction MapCentering
CallFunction BlackStripeCheck

ReportClock
holecenteringticks = ($repVal1 - $ticks)

####### Focus #######

CallFunction AutoFillDarkRef
CallFunction AutoFocusSPA
CallFunction BlackStripeCheck

ReportClock
focusticks = ($repVal1 - $ticks)

####### Drift #######

ChangeFocus -3
CallFunction AutoFillDarkRef
CallFunction DriftSPA
CallFunction BlackStripeCheck
ChangeFocus 3

ReportClock
driftticks = ($repVal1 - $ticks)

####### Acquire images #######

ReportDefocus actualdefocus
echo actual defocus = $actualdefocus

GoToLowDoseArea R
delay 3 sec
CallFunction AutoFillDarkRef
EarlyReturnNextShot 0
MultipleRecords 

RefineZLP 60
GoToLowDoseArea V

# timing
ReportClock
recordticks = ($repVal1 - $ticks)
holetime = $holecenteringticks
focustime = $focusticks - $holecenteringticks
drifttime = $driftticks - $focusticks
recordtime = $recordticks - $driftticks
echo timing $holetime $focustime $drifttime $recordtime $recordticks seconds

Echo ===> Done ...
Echo ====================================================
EndMacro
Macro	6
MacroName SPAK3PP
# SPA macro for Krios/Quantum/K3
# Wim Hagen, EMBL Heidelberg 20170309
# Credits to Chen Xu & Henning Stahlberg group

####### SETTINGS ####### 

# Buffer P is expected to have refference hole image from Low Dose View

maxholeshift = 200     # max beam/image shift after hole centering in nanometers

TD_low                     = -0.3     # low defocus microns
TD_high                   = -0.8      # high defocus microns
delta                          = 0.1       # defocus step microns
focusdistance           = 0            # micrometers

tonextphaseplate   = 100000        # switch phase plate every x holes

####### END SETTINGS ####### 

MailSubject Krios 2
ErrorBoxSendEmail Krios 2 has a problem!

SetColumnOrGunValve 1

SetUserSetting  AutofocusBeamTilt 4
ReportUserSetting AutofocusBeamTilt

SuppressReports

####### Align to hole #######

MoveToNavItem

CallFunction 15::AutoFill

Echo ===> Running align to hole ...

V
AlignTo P
ReportAlignShift
Echo hole shift 1 $RepVal5 $RepVal6
holeshift = sqrt $RepVal5 * $RepVal5 + $RepVal6 * $RepVal6

if $holeshift > $maxholeshift
   ResetImageShift
   delay 3 sec
   V
   AlignTo P
   ReportAlignShift
   Echo hole shift 2 $RepVal5 $RepVal6
endif

MoveStage -0.025 -0.025

#CallFunction thicknesmap

####### Focus #######

CallFunction 15::AutoFill

CallFunction AutoFocusSPA

####### Acquire images #######

GoToLowDoseArea R
delay 10 sec
CallFunction 15::AutoFill
EarlyReturnNextShot 0
MultipleRecords

####### Next phase plate #######


   ReportNavItem
   remainder = modulo $navAcqIndex $tonextphaseplate
   echo Acquiring Item is $navAcqIndex , remain is $remainder
   if $remainder == 0
      echo Moving to next phase plate!
      Call PrepareVPPspa
   endif


#RefineZLP 30
UpdateHWDarkRef  0.5
GoToLowDoseArea V
ResetImageShift 

Echo ===> Done ...
Echo ====================================================
EndMacro
Macro	8
MacroName TuneScope

# Settings, use higher defocus for lower mags when doing lamellae!
defocusoffset = -2.5  # defocus target to be used for tuning, -2.5 for high mag, -6 for lower mags

###################################################

# remove objective aperture
Pause  retract objective aperture.

SetLowDoseMode 0

SetUserSetting CtfBinning 2 1
SetUserSetting CtfExposure 2 1
SetUserSetting CtfUseFullField 1 1
SetUserSetting CtfDoFullArray 0 1
SetUserSetting SideBySideFFT 1 1

# set microcope focus to zero
SetDefocus 0

echo ###################################################
ReportImageShift 

# focus with stage Z
Loop 2
   G -1
   ReportAutofocus 
   t  =  -1 * $RepVal1 + $defocusoffset
   if $t >= 0
      changeZ = $t + 3
      MoveStage 0 0 $changeZ
      MoveStage 0 0 -3
   elseif $t <= 0
      MoveStage 0 0 $t
   endif
   echo --> Z moved $t micron 
EndLoop

# auto-stigmate
FixAstigmatismByCTF 0 1


# Zemlin tableau
FixComaByCTF 0 1 0

# Switch to diffraction
ScreenDown 
ReportMagIndex
currentmag = $RepVal1
SetCamLenIndex 20

# insert and center objective aperture
Pause  Insert and center objective aperture.

# Switch to imaging
SetMagIndex $currentmag
ScreenUp 
delay 3 sec

# auto-stigmate
FixAstigmatismByCTF 0 1

SetUserSetting SideBySideFFT 0

# Acuire and save an image and its FFT for monitoring purposes
SetSlitIn 
SetExposure R 5
SetBinning R 1
SetCameraArea R F
SetProcessing R 2
SetK2ReadMode R 1
SetFrameTime R 0.25
SetDoseFracParams R 1 0 1 1

SetDirectory X:\Data\Wim\monitoring
ReportDateTime
OpenNewFile tune_$RepVal1_$RepVal2_img.mrc
R
RestoreCameraSet 
S
CloseFile 
FFT A
SaveToOtherFile A JPG NONE tune_$RepVal1_$RepVal2_fft.jpg

# Write settings to text file
ReportDateTime date time
ReportMag mag
ReportSpotSize spot
ReportProbeMode probe
If $probe == 0
   probemode = nano
ElseIf  $probe == 1
Endif 
probemode = micro
ReportBeamTilt BTx BTy
ReportObjectiveStigmator OSx OSy
ReportEnergyFilter slit
ReportIlluminatedArea beamsize
beamsize = 100 * $beamsize
ReportEnergyFilter width loss inout
If $inout == 1
   slit = in
ElseIf $inout == 0
   slit = out
Endif 

SetDirectory X:\Data\Wim\monitoring
OpenTextFile alignmentmonitor A 0 alignment.txt
WriteLineToFile alignmentmonitor $date $time $mag $spot $probemode $beamsize $BTx $BTy $OSx $OSy $width $loss $slit
EndMacro
Macro	10
MacroName PreTomo

echo ################# PreTomo 

TD_low               = -1   # low defocus microns
TD_high             = -3    # high defocus microns
delta                    = 1     # defocus step microns

ReportTargetDefocus TD 
if $TD > $TD_low
   SetTargetDefocus $TD_low
   ReportTargetDefocus
elseif $TD <= $TD_low AND $TD > $TD_high
   IncTargetDefocus -$delta
elseif $TD <= $TD_high
   SetTargetDefocus $TD_low
   ReportTargetDefocus
endif
ReportTargetDefocus  
TomoTargetDefocus := $RepVal1
echo TomoTargetDefocus = $TomoTargetDefocus

echo ################# PreTomo END
EndMacro
Macro	11
MacroName DuringTomo

echo ################# DuringTomo 

SetTargetDefocus $TomoTargetDefocus 
delay 3 sec

CallFunction AutoFill
CallFunction BlackStripeCheck

echo ################# DuringTomo END
EndMacro
Macro	12
MacroName PostTomo

echo ################# PostTomo 

ResetImageShift
SetDefocus -5
RefineZLP
UpdateHWDarkRef  0

echo ################# PostTomo END
EndMacro
Macro	14
MacroName Functions

############################

Function MapCentering

Echo ===> Running align to map ...

LoadNavMap 

V
ImageProperties A xsize ysize bin expos pixel
if $xsize < $ysize
   halfsize = 0.95 * $pixel * $ysize / 2 / 1000
elseif $xsize > $ysize
   halfsize = 0.95 * $pixel * $xsize / 2 / 1000
endif

ReportProperty realignitemminmarginneeded minmarginneeded
SetProperty realignitemminmarginneeded $halfsize

AlignTo K 0 1

SetProperty realignitemminmarginneeded $minmarginneeded

ReportAlignShift
TotalShift = SQRT ( ( POWER $RepVal5 2 ) + ( POWER $RepVal6 2 ) ) / 1000
Echo Total map shift = $TotalShift micrometer

EndFunction 

############################

Function HoleCentering
Echo ===> Running align to hole ...

ReportProperty AlignFilterSigma2 sigma2
ReportProperty AlignFilterRadius2 radius2

SetProperty AlignFilterSigma2 0.005
SetProperty AlignFilterRadius2 0.17

V
ImageProperties A xsize ysize bin expos pixel
if $xsize < $ysize
   halfsize = 0.95 * $pixel * $ysize / 2 / 1000
elseif $xsize > $ysize
   halfsize = 0.95 * $pixel * $xsize / 2 / 1000
endif

ReportProperty realignitemminmarginneeded minmarginneeded
SetProperty realignitemminmarginneeded $halfsize

AlignTo P 0 1
ReportAlignShift
holeshift = sqrt $RepVal5 * $RepVal5 + $RepVal6 * $RepVal6
Echo hole shift  1 $RepVal5 $RepVal6 $holeshift

ResetShiftIfAbove $maxholeshift

V
AlignTo P 0 1
ReportAlignShift
holeshift = sqrt $RepVal5 * $RepVal5 + $RepVal6 * $RepVal6
Echo hole shift  2 $RepVal5 $RepVal6 $holeshift

SetProperty AlignFilterSigma2 $sigma2
SetProperty AlignFilterRadius2 $radius2
SetProperty realignitemminmarginneeded $minmarginneeded

EndFunction 

############################

Function TestHoleCentering
Echo ===> Running align to hole ...

ReportProperty AlignFilterSigma2 sigma2
ReportProperty AlignFilterRadius2 radius2

SetProperty AlignFilterSigma2 0.005
SetProperty AlignFilterRadius2 0.17

V
ImageProperties A xsize ysize bin expos pixel
if $xsize < $ysize
   halfsize = 0.95 * $pixel * $ysize / 2 / 1000
elseif $xsize > $ysize
   halfsize = 0.95 * $pixel * $xsize / 2 / 1000
endif

ReportProperty realignitemminmarginneeded minmarginneeded
SetProperty realignitemminmarginneeded $halfsize

AlignTo P 0 1
ReportAlignShift
holeshift = sqrt $RepVal5 * $RepVal5 + $RepVal6 * $RepVal6
Echo hole shift  1 $RepVal5 $RepVal6 $holeshift

V
AlignTo P 0 1
ReportAlignShift
holeshift = sqrt $RepVal5 * $RepVal5 + $RepVal6 * $RepVal6
Echo hole shift  2 $RepVal5 $RepVal6 $holeshift

SetProperty AlignFilterSigma2 $sigma2
SetProperty AlignFilterRadius2 $radius2
SetProperty realignitemminmarginneeded $minmarginneeded

EndFunction 

############################

Function DriftSPA
Echo ===> Running Drift ...
GoToLowDoseArea T
Delay 2 sec

ReportClock
time1 = $RepVal1

T
Delay $driftinterval
Loop $drifttimes index
    ReportClock time2
	T
	AlignTo B
	ReportAlignShift
	dx = $reportedValue3 # in nm
	dy = $reportedValue4 # in nm
	dist = sqrt $dx * $dx + $dy * $dy
	elapsedtime = $time2 - $time1
                      time1 = $time2 
	rate = 10 * ( $dist / $elapsedtime  )
	echo Rate = $rate A/sec
	echo ----------------
	
	If $rate < $driftcrit
	    echo Drift is $Rate A/s after shot $index      
	    break
	Elseif  $index < $drifttimes
	    Delay $driftinterval
	Else
	    echo Drift never got below $driftcrit : Skipping ...
	    break   
	Endif
EndLoop
EndFunction 

############################

Function AutoFocusSPA
SuppressReports
ReportNavItem 

Echo ===> focus ... 

ReportTargetDefocus TD 
if $TD > $TD_low
   SetTargetDefocus $TD_low
   diff = $TD_low - $TD
   ChangeFocus $diff
   ReportTargetDefocus
   echo Target defocus = $RepVal1 , focus changed by $diff
elseif $TD <= $TD_low AND $TD > $TD_high
   IncTargetDefocus -$delta
   ChangeFocus -$delta
   ReportTargetDefocus
   echo Target defocus = $RepVal1 , focus changed by -$delta
elseif $TD <= $TD_high
   SetTargetDefocus $TD_low
   diff = $TD_low - $TD
   ChangeFocus $diff
   ReportTargetDefocus
endif

GoToLowDoseArea F

echo navigator acquisition index is $navAcqIndex
if $navAcqIndex == 1
   ReportStageXYZ
   stagerefx := $RepVal1
   stagerefy := $RepVal2
   stagerefz := $RepVal3
endif

### work out stage xyz distance since last autofocus
ReportStageXYZ
stagecurrentx = $RepVal1
stagecurrenty = $RepVal2
stagecurrentz = $RepVal3
stagex = $stagerefx - $stagecurrentx
stagey = $stagerefy - $stagecurrenty
stagemovementxy = sqrt $stagex * $stagex + $stagey * $stagey
stagez = $stagerefz - $stagecurrentz
echo delta stage xyz: $stagex $stagey $stagez

# condition to autofocus, distance, z-change, or first item 
if $stagemovementxy > $focusdistance OR abs ( $stagez ) > 0.5 OR $navAcqIndex == 1
   G
   ReportStageXYZ
   stagerefx := $RepVal1
   stagerefy := $RepVal2
   stagerefz := $RepVal3
endif

EndFunction 

############################

Function AutoFill
SuppressReports

loop 10
   AreDewarsFilling
   if $reportedvalue1 == 0
      break
   elseif $reportedvalue1 == 1
      echo dewars are filling
      delay 60 sec
   endif
endloop

endfunction

############################

Function BlackStripeCheck
#SuppressReports
BlackStripeTreshold = 0.5

   ImageProperties A xsize ysize binning
   Height = 512 / $binning
   Width = 512 / $binning

   # 90 degree rotation so horizontal stripes
   If $xsize < $ysize
      Loop 7 index
         x0 = 0
         x1 = $xsize - 1
         y0 = ($index - 1) * $Height + 10
         y1 = $index * $Height  - 10
         #echo $x0 $x1 $y0 $y1 
         SubareaMean $x0 $x1 $y0 $y1 mean
         If $mean < $BlackStripeTreshold 
            echo  mean =  $mean : black stripe!
            MailSubject Krios 2
            SendEmail Black stripe problem, acquisition paused, valves closed.
            SetColumnOrGunValve 0
            Pause Restart camera (see EM-help) then continue 
         endif
      endloop

      yend = $ysize - 1
      SubareaMean $x0 $x1 $y1 $yend mean
      if $mean < $BlackStripeTreshold 
         echo  mean =  $mean : black stripe!
         MailSubject Krios 2
         SendEmail Black stripe problem, acquisition paused, valves closed.
         SetColumnOrGunValve 0
         Pause Restart camera (see EM-help) then continue 
      endif
   Endif 

   # 0 degree rotation so vertical stripes
   If $xsize > $ysize
      Loop 7 index
         echo $index
         x0 = ($index - 1) * $Width + 10
         x1 = $index * $Width  - 10
         y0 = 0
         y1 = $ysize - 1 
         SubareaMean $x0 $x1 $y0 $y1 mean
         echo $x0 $x1 $y0 $y1 $mean
         If $mean < $BlackStripeTreshold 
            echo  mean =  $mean : black stripe!
            MailSubject Krios 2
            SendEmail Black stripe problem, acquisition paused, valves closed.
            SetColumnOrGunValve 0
            Pause Restart camera (see EM-help) then continue 
         endif
      endloop

      xend = $xsize - 1
      SubareaMean $x1 $xend $y0 $y1 mean
      If $mean < $BlackStripeTreshold 
         echo  mean =  $mean : black stripe!
         MailSubject Krios 2
         SendEmail Black stripe problem, acquisition paused, valves closed.
         SetColumnOrGunValve 0
         Pause Restart camera (see EM-help) then continue 
      endif
   Endif 

endfunction

############################

Function thicknesmap
SetCameraArea V Q
SetSlitIn 0
UpdateLowDoseParams V 1
V
ReportMeanCounts
I = $RepVal1

SetSlitIn 1
UpdateLowDoseParams V 1
V
ReportMeanCounts
I0 = $RepVal1
Ratio = $I0 / $I
echo Thickness I Io Ratio $i $i0 $Ratio

SetCameraArea V F
EndFunction 

############################

Function dosemonitor   # Measure dose and write to text file
   SuppressReports 
   SetColumnOrGunValve 0
   R
   SetColumnOrGunValve 1
   R
   SetColumnOrGunValve 0
   
   ReportDateTime date time
   ReportMag mag
   ReportSpotSize spot
   ReportProbeMode probe
   If $probe == 0
      probemode = nano
   ElseIf  $probe == 1
   Endif 
   probemode = micro
   ReportIlluminatedArea beamsize
   beamsize = 100 * $beamsize
   beamsize = ROUND $beamsize 0
   ReportEnergyFilter width loss inout
   If $inout == 1
      slit = in
   ElseIf $inout == 0
      slit = out
   Endif 
   
   ElectronStats 
   doserate = ROUND $RepVal5 0
   
   SetDirectory X:\Data\Wim\monitoring
   OpenTextFile dosemonitor A 0 dose.txt
   WriteLineToFile dosemonitor $date $time $mag $spot $probemode $beamsize $slit $doserate
EndFunction 
EndMacro
Macro	16

EndMacro
Macro	19
MacroName preparegridsquaremaps

SaveNavigator 

SetColumnOrGunValve 1

#RefineZLP 15

ReportGroupStatus
GS = $reportedValue1

if $GS == 1
   SetDefocus -100

   Eucentricity 1
   G -1
   ReportAutofocus

   If $RepVal2 == 0
      defocusoffset := $RepVal1
      echo offset is $defocusoffset 
   ElseIf
    Pause "Defocus measurement failed"
   Endif
Elseif $GS != 1
   Loop 2
      G -1
      ReportAutofocus 
      t  =  -1 * $RepVal1 + $defocusoffset
      if $t >= 0
         changeZ = $t + 3
         MoveStage 0 0 $changeZ
         MoveStage 0 0 -3
      elseif $t <= 0
         MoveStage 0 0 $t
      endif
      echo --> Z moved $t micron 
   EndLoop
Endif

UpdateItemZ
EndMacro
Macro	30

EndMacro
Macro	40
ReportStageXYZ stx sty stz
EndMacro
Macro	41
Eucentricity 2
EndMacro
Macro	42
movestageto 0 0 0
EndMacro
Macro	44
RealignToNavItem 0
EndMacro
