# **************************************************************************
# *
# * Authors: Federico P. de Isidro Gomez (fp.deisidro@cnb.csic.es) [1]
# *
# * [1] Centro Nacional de Biotecnologia, CSIC, Spain
# *
# * This program is free software; you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation; either version 2 of the License, or
# * (at your option) any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with this program; if not, write to the Free Software
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# * 02111-1307 USA
# *
# * All comments concerning this program package may be sent to the
# * e-mail address 'scipion@cnb.csic.es'
# *
# **************************************************************************
"""
This module contains utils functions for IMOD protocols
"""
import csv
import math
import numpy as np
import pyworkflow.object as pwobj
[docs]def generateIMODFiducialTextFile(landmarkModel, outputFilePath):
""" This method takes a Scipion LandmarkModel object and generates a text file in the sepecified location in IMOD
convention that contains the information of the position of each fiducial through the tilt-series.
:param landmarkModel: landmarkModel Scipion object.
:param outputFilePath: location where the output file must be saved.
"""
infoTable = landmarkModel.retrieveInfoTable()
outputLines = []
for vector in infoTable:
outputLines.append("\t%s\t%s\t%s\n" % (vector[0], vector[1], vector[2]))
with open(outputFilePath, 'w') as f:
f.writelines(outputLines)
[docs]def getDefocusFileFlag(defocusFilePath):
""" This method returns the flag that indicate the information contained in an IMOD defocus file. The flag value "is
the sum of:
1 if the file has astigmatism values
2 if the astigmatism axis angle is in radians, not degrees
4 if the file has phase shifts
8 if the phase shifts are in radians, not degrees
16 if tilt angles need to be inverted to match what the
program expects (what Ctfplotter would produce)
with the -invert option
32 if the file has cut-on frequencies attenuating the phase
at low frequencies"
from https://bio3d.colorado.edu/imod/doc/man/ctfphaseflip.html """
with open(defocusFilePath) as f:
lines = f.readlines()
" File contains only defocus information (no astigmatism, no phase shift, no cut-on frequency) "
if len(lines) == 1:
return 0
elif len(lines[1].split()) == 5:
return 0
else:
" File contains more information apart "
return int(lines[0].split()[0])
[docs]def readDefocusFileAsTable(defocusFilePath):
""" This method takes an IMOD-based ctf estimation file path and returns a table containing the CTF estimation
information of each tilt-image (per line) belonging to the tilt-series. """
defocusTable = []
with open(defocusFilePath) as f:
lines = f.readlines()
for index, line in enumerate(lines):
vector = line.split()
[float(i) for i in vector]
if index == 0 and len(lines) == 1:
"CTF estimation is plain (no astigmatism, no phase shift, no cut-on frequency) and is the first line."
"Remove last element from the first line (it contains the mode of the estimation run). This case "
"considers that the estimation file only has one line. "
vector.pop()
defocusTable.append(vector)
elif index == 0 and len(lines[1].split()) == 5:
"CTF estimation is plain (no astigmatism, no phase shift, no cut-on frequency) and is the first line."
"Remove last element from the first line (it contains the mode of the estimation run). "
vector.pop()
defocusTable.append(vector)
elif index == 0 and len(lines[1].split()) != 5:
"CTF estimation is not plain and is the first line."
"Do not add this line to the table. Only contains flag and format info."
pass
else:
"Any posterior line that is not the first one is added to the table ."
defocusTable.append(vector)
return defocusTable
[docs]def readCTFEstimationInfoFile(defocusFilePath, flag):
""" This method takes an IMOD-based file path containing the information associated to a CTF estimation and
produces a set of dictionaries containing the information of each parameter for each tilt-image belonging to the
tilt-series. These dictionaries are readable information for Scipion, useful to generate the corresponding output
CTFTomoSeries object. """
# Read info as table
ctfInfoIMODTable = readDefocusFileAsTable(defocusFilePath)
if flag == 0:
# Plain estimation
return refactorCTFDefocusEstimationInfo(ctfInfoIMODTable)
elif flag == 1:
# Astigmatism estimation
return refactorCTFDesfocusAstigmatismEstimationInfo(ctfInfoIMODTable)
elif flag == 4:
# Phase-shift estimation
return refactorCTFDefocusPhaseShiftEstimationInfo(ctfInfoIMODTable)
elif flag == 5:
# Astigmatism and phase shift estimation
return refactorCTFDefocusAstigmatismPhaseShiftEstimationInfo(ctfInfoIMODTable)
elif flag == 37:
# Astigmatism, phase shift and cut-on frequency estimation
return refactorCTFDefocusAstigmatismPhaseShiftCutOnFreqEstimationInfo(ctfInfoIMODTable)
else:
raise Exception("Defocus file flag do not supported. Only supported formats corresponding to flags 0, "
"1, 4, 5, and 37.")
[docs]def refactorCTFDefocusEstimationInfo(ctfInfoIMODTable):
""" This method takes a table containing the information of an IMOD-based CTF estimation containing only defocus
information (5 columns) and produces a new dictionary containing the same information in a format readable for
Scipion. Flag 0. """
if len(ctfInfoIMODTable[0]) == 5:
defocusUDict = {}
for element in ctfInfoIMODTable:
# Segregate information from range
for index in range(int(element[0]), int(element[1]) + 1):
# CONVERT DEFOCUS VALUE TO ANGSTROMS (SCIPION CONVENTION)
defocus = float(element[4]) * 10
if index in defocusUDict.keys():
defocusUDict[index].append(pwobj.Float(defocus))
else:
defocusUDict[index] = [pwobj.Float(defocus)]
else:
raise Exception("Misleading file format, CTF estimation with no astigmatism should be 5 columns long")
return defocusUDict
[docs]def refactorCTFDesfocusAstigmatismEstimationInfo(ctfInfoIMODTable):
""" This method takes a table containing the information of an IMOD-based CTF estimation containing defocus and
astigmatism information (7 columns) and produces a set of dictionaries table containing the same information in a
format readable for Scipion. Flag 1. """
if len(ctfInfoIMODTable[0]) == 7:
defocusUDict = {}
defocusVDict = {}
defocusAngleDict = {}
for element in ctfInfoIMODTable:
# Segregate information from range
for index in range(int(element[0]), int(element[1]) + 1):
# Defocus U info
# CONVERT DEFOCUS VALUE TO ANGSTROMS (SCIPION CONVENTION)
defocusU = float(element[4]) * 10
if index in defocusUDict.keys():
defocusUDict[index].append(pwobj.Float(defocusU))
else:
defocusUDict[index] = [pwobj.Float(defocusU)]
# Defocus V info
# CONVERT DEFOCUS VALUE TO ANGSTROMS (SCIPION CONVENTION)
defocusV = float(element[5]) * 10
if index in defocusVDict.keys():
defocusVDict[index].append(pwobj.Float(defocusV))
else:
defocusVDict[index] = [pwobj.Float(defocusV)]
# Defocus angle info
if index in defocusAngleDict.keys():
defocusAngleDict[index].append(pwobj.Float(element[6]))
else:
defocusAngleDict[index] = [pwobj.Float(element[6])]
else:
raise Exception("Misleading file format, CTF estimation with astigmatism should be 7 columns long")
return defocusUDict, defocusVDict, defocusAngleDict
[docs]def refactorCTFDefocusPhaseShiftEstimationInfo(ctfInfoIMODTable):
""" This method takes a table containing the information of an IMOD-based CTF estimation containing defocus,
and phase shift information (6 columns) and produces a new set of dictionaries containing the same
information in a format readable for Scipion. Flag 4. """
if len(ctfInfoIMODTable[0]) == 6:
defocusUDict = {}
phaseShiftDict = {}
for element in ctfInfoIMODTable:
# Segregate information from range
for index in range(int(element[0]), int(element[1]) + 1):
# Defocus U info
# CONVERT DEFOCUS VALUE TO ANGSTROMS (SCIPION CONVENTION)
defocusU = float(element[4]) * 10
if index in defocusUDict.keys():
defocusUDict[index].append(pwobj.Float(defocusU))
else:
defocusUDict[index] = [pwobj.Float(defocusU)]
# Phase shift info
if index in phaseShiftDict.keys():
phaseShiftDict[index].append(pwobj.Float(element[5]))
else:
phaseShiftDict[index] = [pwobj.Float(element[5])]
else:
raise Exception("Misleading file format, CTF estimation with astigmatism and phase shift should be 6 columns "
"long")
return defocusUDict, phaseShiftDict
[docs]def refactorCTFDefocusAstigmatismPhaseShiftEstimationInfo(ctfInfoIMODTable):
""" This method takes a table containing the information of an IMOD-based CTF estimation containing defocus,
astigmatism and phase shift information (8 columns) and produces a new set of dictionaries containing the same
information in a format readable for Scipion. Flag 5. """
if len(ctfInfoIMODTable[0]) == 8:
defocusUDict = {}
defocusVDict = {}
defocusAngleDict = {}
phaseShiftDict = {}
for element in ctfInfoIMODTable:
# Segregate information from range
for index in range(int(element[0]), int(element[1]) + 1):
# Defocus U info
# CONVERT DEFOCUS VALUE TO ANGSTROMS (SCIPION CONVENTION)
defocusU = float(element[4]) * 10
if index in defocusUDict.keys():
defocusUDict[index].append(pwobj.Float(defocusU))
else:
defocusUDict[index] = [pwobj.Float(defocusU)]
# Defocus V info
# CONVERT DEFOCUS VALUE TO ANGSTROMS (SCIPION CONVENTION)
defocusV = float(element[5]) * 10
if index in defocusVDict.keys():
defocusVDict[index].append(pwobj.Float(defocusV))
else:
defocusVDict[index] = [pwobj.Float(defocusV)]
# Defocus angle info
if index in defocusAngleDict.keys():
defocusAngleDict[index].append(pwobj.Float(element[6]))
else:
defocusAngleDict[index] = [pwobj.Float(element[6])]
# Phase shift info
if index in phaseShiftDict.keys():
phaseShiftDict[index].append(pwobj.Float(element[7]))
else:
phaseShiftDict[index] = [pwobj.Float(element[7])]
else:
raise Exception("Misleading file format, CTF estiation with astigmatism and phase shift should be 8 columns "
"long")
return defocusUDict, defocusVDict, defocusAngleDict, phaseShiftDict
[docs]def refactorCTFDefocusAstigmatismPhaseShiftCutOnFreqEstimationInfo(ctfInfoIMODTable):
""" This method takes a table containing the information of an IMOD-based CTF estimation containing defocus,
astigmatism, phase shift information and cut-on frequency (8 columns) and produces a new set of dictionaries
containing the same information in a format readable for Scipion. Flag 37. """
if len(ctfInfoIMODTable[0]) == 9:
defocusUDict = {}
defocusVDict = {}
defocusAngleDict = {}
phaseShiftDict = {}
cutOnFreqDict = {}
for element in ctfInfoIMODTable:
# Segregate information from range
for index in range(int(element[0]), int(element[1]) + 1):
# Defocus U info
# CONVERT DEFOCUS VALUE TO ANGSTROMS (SCIPION CONVENTION)
defocusU = float(element[4]) * 10
if index in defocusUDict.keys():
defocusUDict[index].append(pwobj.Float(defocusU))
else:
defocusUDict[index] = [pwobj.Float(defocusU)]
# Defocus V info
# CONVERT DEFOCUS VALUE TO ANGSTROMS (SCIPION CONVENTION)
defocusV = float(element[5]) * 10
if index in defocusVDict.keys():
defocusVDict[index].append(pwobj.Float(defocusV))
else:
defocusVDict[index] = [pwobj.Float(defocusV)]
# Defocus angle info
if index in defocusAngleDict.keys():
defocusAngleDict[index].append(pwobj.Float(element[6]))
else:
defocusAngleDict[index] = [pwobj.Float(element[6])]
# Phase shift info
if index in phaseShiftDict.keys():
phaseShiftDict[index].append(pwobj.Float(element[7]))
else:
phaseShiftDict[index] = [pwobj.Float(element[7])]
# Cut-on frequency info
if index in cutOnFreqDict.keys():
cutOnFreqDict[index].append(pwobj.Float(element[8]))
else:
cutOnFreqDict[index] = [pwobj.Float(element[8])]
else:
raise Exception("Misleading file format, CTF estiation with astigmatism, phase shift and cut-on frequency "
"should be 8 columns long")
return defocusUDict, defocusVDict, defocusAngleDict, phaseShiftDict, cutOnFreqDict
[docs]def generateDefocusIMODFileFromObject(ctfTomoSeries, defocusFilePath, isRelion=False):
""" This methods takes a ctfTomoSeries object a generate a defocus information file in IMOD formatting containing
the same information in the specified location. """
tiltSeries = ctfTomoSeries.getTiltSeries()
# Check if there is CTF estimation information as list
if ctfTomoSeries.getFirstItem().hasEstimationInfoAsList():
flag = ctfTomoSeries.getIMODDefocusFileFlag()
if flag == 0:
# Plain estimation
defocusUDict = generateDefocusUDictionary(ctfTomoSeries)
nEstimationsInRange = ctfTomoSeries.getNumberOfEstimationsInRange()
# Write IMOD defocus file
with open(defocusFilePath, 'w') as f:
lines = []
pattern = "%d\t%d\t%.2f\t%.2f\t%d\n"
if isRelion:
lines.append(pattern % (0, 0, 0, 0, 2))
for index in defocusUDict.keys():
if index + nEstimationsInRange > len(defocusUDict.keys()):
break
# Dictionary keys is reversed because IMOD set indexes upside down Scipion (highest index for
# the tilt-image with the highest negative angle)
newLine = (pattern % (
index,
index + ctfTomoSeries.getNumberOfEstimationsInRange(),
round(tiltSeries[index + ctfTomoSeries.getNumberOfEstimationsInRange()].getTiltAngle(), 2),
round(tiltSeries[index].getTiltAngle(), 2),
# CONVERT DEFOCUS VALUE TO NANOMETERS (IMOD CONVENTION)
int(float(defocusUDict[index][0])/10)
))
lines.append(newLine)
if not isRelion:
# Finally, add flag to the first line of file
lines[0] = lines[0][0:-1] + "\t2\n"
f.writelines(lines)
elif flag == 1:
# Astigmatism estimation
defocusUDict = generateDefocusUDictionary(ctfTomoSeries)
defocusVDict = generateDefocusVDictionary(ctfTomoSeries)
defocusAngleDict = generateDefocusAngleDictionary(ctfTomoSeries)
# Write IMOD defocus file
with open(defocusFilePath, 'w') as f:
# This line is added at the beginning of the file in order to match the IMOD defocus file format.
lines = ["1\t0\t0.0\t0.0\t0.0\t3\n"]
for index in defocusUDict.keys():
if index + ctfTomoSeries.getNumberOfEstimationsInRange() > len(defocusUDict.keys()):
break
# Dictionary keys is reversed because IMOD set indexes upside down Scipion (highest index for
# the tilt-image with the highest negative angle)
newLine = ("%d\t%d\t%.2f\t%.2f\t%.1f\t%.1f\t%.2f\n" % (
index,
index + ctfTomoSeries.getNumberOfEstimationsInRange(),
round(tiltSeries[index + ctfTomoSeries.getNumberOfEstimationsInRange()].getTiltAngle(), 2),
round(tiltSeries[index].getTiltAngle(), 2),
# CONVERT DEFOCUS VALUE TO NANOMETERS (IMOD CONVENTION)
float(defocusUDict[index][0])/10,
# CONVERT DEFOCUS VALUE TO NANOMETERS (IMOD CONVENTION)
float(defocusVDict[index][0])/10,
float(defocusAngleDict[index][0]),
))
lines.append(newLine)
f.writelines(lines)
elif flag == 4:
# Phase-shift estimation
defocusUDict = generateDefocusUDictionary(ctfTomoSeries)
phaseShiftDict = generatePhaseShiftDictionary(ctfTomoSeries)
# Write IMOD defocus file
with open(defocusFilePath, 'w') as f:
# This line is added at the beginning of the file in order to match the IMOD defocus file format.
lines = ["4\t0\t0.0\t0.0\t0.0\t3\n"]
for index in defocusUDict.keys():
if index + ctfTomoSeries.getNumberOfEstimationsInRange() > len(defocusUDict.keys()):
break
# Dictionary keys is reversed because IMOD set indexes upside down Scipion (highest index for
# the tilt-image with the highest negative angle)
newLine = ("%d\t%d\t%.2f\t%.2f\t%.1f\t%.2f\n" % (
index,
index + ctfTomoSeries.getNumberOfEstimationsInRange(),
round(tiltSeries[index + ctfTomoSeries.getNumberOfEstimationsInRange()].getTiltAngle(), 2),
round(tiltSeries[index].getTiltAngle(), 2),
# CONVERT DEFOCUS VALUE TO NANOMETERS (IMOD CONVENTION)
float(defocusUDict[index][0])/10,
float(phaseShiftDict[index][0]),
))
lines.append(newLine)
f.writelines(lines)
elif flag == 5:
# Astigmatism and phase shift estimation
defocusUDict = generateDefocusUDictionary(ctfTomoSeries)
defocusVDict = generateDefocusVDictionary(ctfTomoSeries)
defocusAngleDict = generateDefocusAngleDictionary(ctfTomoSeries)
phaseShiftDict = generatePhaseShiftDictionary(ctfTomoSeries)
# Write IMOD defocus file
with open(defocusFilePath, 'w') as f:
# This line is added at the beginning of the file in order to match the IMOD defocus file format
lines = ["5\t0\t0.0\t0.0\t0.0\t3\n"]
for index in defocusUDict.keys():
if index + ctfTomoSeries.getNumberOfEstimationsInRange() > len(defocusUDict.keys()):
break
# Dictionary keys is reversed because IMOD set indexes upside down Scipion (highest index for
# the tilt-image with the highest negative angle)
newLine = ("%d\t%d\t%.2f\t%.2f\t%.1f\t%.1f\t%.2f\t%.2f\n" % (
index,
index + ctfTomoSeries.getNumberOfEstimationsInRange(),
round(tiltSeries[index + ctfTomoSeries.getNumberOfEstimationsInRange()].getTiltAngle(), 2),
round(tiltSeries[index].getTiltAngle(), 2),
# CONVERT DEFOCUS VALUE TO NANOMETERS (IMOD CONVENTION)
float(defocusUDict[index][0])/10,
# CONVERT DEFOCUS VALUE TO NANOMETERS (IMOD CONVENTION)
float(defocusVDict[index][0])/10,
float(defocusAngleDict[index][0]),
float(phaseShiftDict[index][0])
))
lines.append(newLine)
f.writelines(lines)
elif flag == 37:
# Astigmatism, phase shift and cut-on frequency estimation
defocusUDict = generateDefocusUDictionary(ctfTomoSeries)
defocusVDict = generateDefocusVDictionary(ctfTomoSeries)
defocusAngleDict = generateDefocusAngleDictionary(ctfTomoSeries)
phaseShiftDict = generatePhaseShiftDictionary(ctfTomoSeries)
cutOnFreqDict = generateCutOnFreqDictionary(ctfTomoSeries)
# Write IMOD defocus file
with open(defocusFilePath, 'w') as f:
# This line is added at the beginning of the file in order to match the IMOD defocus file format
lines = ["37\t0\t0.0\t0.0\t0.0\t3\n"]
for index in defocusUDict.keys():
if index + ctfTomoSeries.getNumberOfEstimationsInRange() > len(defocusUDict.keys()):
break
# Dictionary keys is reversed because IMOD set indexes upside down Scipion (highest index for
# the tilt-image with the highest negative angle)
newLine = ("%d\t%d\t%.2f\t%.2f\t%.1f\t%.1f\t%.2f\t%.2f\t%.4f\n" % (
index,
index + ctfTomoSeries.getNumberOfEstimationsInRange(),
round(tiltSeries[index + ctfTomoSeries.getNumberOfEstimationsInRange()].getTiltAngle(), 2),
round(tiltSeries[index].getTiltAngle(), 2),
# CONVERT DEFOCUS VALUE TO NANOMETERS (IMOD CONVENTION)
float(defocusUDict[index][0])/10,
# CONVERT DEFOCUS VALUE TO NANOMETERS (IMOD CONVENTION)
float(defocusVDict[index][0])/10,
float(defocusAngleDict[index][0]),
float(phaseShiftDict[index][0]),
float(cutOnFreqDict[index][0])
))
lines.append(newLine)
f.writelines(lines)
else:
raise Exception("Defocus file flag do not supported. Only supported formats corresponding to flags 0, "
"1, 4, 5, and 37.")
else:
# There is no information available as list (not an IMOD CTF estimation)
with open(defocusFilePath, 'w') as f:
lines = ["1\t0\t0.0\t0.0\t0.0\t3\n"]
# CtfTomoSeries is iterated inversely because IMOD set indexes upside down Scipion (highest index for
# the tilt-image with the highest negative angle)
for ctfTomo in ctfTomoSeries:
index = ctfTomo.getIndex().get()
newLine = ("%d\t%d\t%.2f\t%.2f\t%.1f\t%.1f\t%.2f\n" % (
index,
index,
tiltSeries[index].getTiltAngle(),
tiltSeries[index].getTiltAngle(),
# CONVERT DEFOCUS VALUE TO NANOMETERS (IMOD CONVENTION)
ctfTomo.getDefocusU()/10,
# CONVERT DEFOCUS VALUE TO NANOMETERS (IMOD CONVENTION)
ctfTomo.getDefocusV()/10,
ctfTomo.getDefocusAngle())
)
lines.append(newLine)
f.writelines(lines)
[docs]def generateDefocusUDictionary(ctfTomoSeries):
""" This method generates a dictionary containing the defocus U estimation information from a ctfTomoSeries
object. """
defocusUDict = {}
for ctfTomo in ctfTomoSeries:
defocusInfoList = ctfTomo.getDefocusUList() if hasattr(ctfTomo, "_defocusUList") \
else ctfTomo.getDefocusVList()
defocusInfoList = defocusInfoList.split(",")
index = ctfTomo.getIndex().get()
defocusUDict[index] = defocusInfoList
return defocusUDict
[docs]def generateDefocusVDictionary(ctfTomoSeries):
""" This method generates a dictionary containing the defocus V estimation information from a ctfTomoSeries
object. """
defocusVDict = {}
for ctfTomo in ctfTomoSeries:
defocusInfoList = ctfTomo.getDefocusVList()
defocusInfoList = defocusInfoList.split(",")
index = ctfTomo.getIndex().get()
defocusVDict[index] = defocusInfoList
return defocusVDict
[docs]def generateDefocusAngleDictionary(ctfTomoSeries):
""" This method generates a dictionary containing the defocus angle estimation information from a ctfTomoSeries
object. """
defocusAngleDict = {}
for ctfTomo in ctfTomoSeries:
defocusAngleList = ctfTomo.getDefocusAngleList()
defocusAngleList = defocusAngleList.split(",")
index = ctfTomo.getIndex().get()
defocusAngleDict[index] = defocusAngleList
return defocusAngleDict
[docs]def generatePhaseShiftDictionary(ctfTomoSeries):
""" This method generates a dictionary containing the phase shift estimation information from a ctfTomoSeries
object. """
phaseShiftDict = {}
for ctfTomo in ctfTomoSeries:
phaseShiftList = ctfTomo.getPhaseShiftList()
phaseShiftList = phaseShiftList.split(",")
index = ctfTomo.getIndex().get()
phaseShiftDict[index] = phaseShiftList
return phaseShiftDict
[docs]def generateCutOnFreqDictionary(ctfTomoSeries):
""" This method generates a dictionary containing the cut-on frequency estimation information from a ctfTomoSeries
object. """
cutOnFreqDict = {}
for ctfTomo in ctfTomoSeries:
cutOnFreqList = ctfTomo.getCutOnFreqList()
cutOnFreqList = cutOnFreqList.split(",")
index = ctfTomo.getIndex().get()
cutOnFreqDict[index] = cutOnFreqList
return cutOnFreqDict
[docs]def calculateRotationAngleFromTM(ts):
""" This method calculates que average tilt image rotation angle from its associated transformation matrix."""
avgRotationAngle = 0
for ti in ts:
tm = ti.getTransform().getMatrix()
cosRotationAngle = tm[0][0]
sinRotationAngle = tm[1][0]
avgRotationAngle += math.degrees(math.atan(sinRotationAngle/cosRotationAngle))
avgRotationAngle = avgRotationAngle / ts.getSize()
return avgRotationAngle
[docs]def generateDoseFileFromDoseTS(ts, doseFileOutputPath):
""" This method generates a file containing the dose information of a tilt series in the specified location from
the dose per tilt information. The format file consist in a single column with one dose value per line that must
coincide with each image from the tilt-series"""
ind = np.argsort([ti.getIndex() for ti in ts])
tiList = [ti for ti in ts]
doseInfoList = [tiList[i].getAcquisition().getDosePerFrame() for i in ind]
with open(doseFileOutputPath, 'w') as f:
for dose in doseInfoList:
f.writelines("%f\n" % dose)
[docs]def generateDoseFileFromAccDoseTS(ts, doseFileOutputPath):
""" This method generates a file containing the dose information of a tilt series in the specified location from
the accumulated dose per tilt information. The format file consist in a single column with one dose value per line
that must coincide with each image from the tilt-series"""
doseInfoList = []
for ti in ts:
doseInfoList.append(ti.getAcquisition().getAccumDose())
with open(doseFileOutputPath, 'w') as f:
for dose in doseInfoList:
f.writelines("%f\n" % dose)
[docs]def readExcludeViewsFile(excludeViewsFilePath):
""" Thie method retrieves from a input exclude views file path a matrix with two columns containing the tsId of
tilt-series from which exlude the views in the first column and in the second a string with the pattern of the
excluded views"""
excludedViews = []
with open(excludeViewsFilePath, 'r') as f:
lines = f.read().splitlines()
for line in lines:
vector = line.split()
excludedViews.append(vector)
return excludedViews