Skip to content

Commit

Permalink
preserve pixelsize during deconvolution and prediction
Browse files Browse the repository at this point in the history
  • Loading branch information
procyontao committed Sep 25, 2021
1 parent 674f67f commit be24288
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 80 deletions.
111 changes: 55 additions & 56 deletions bin/isonet.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,26 @@ class ISONET:
"""
#log_file = "log.txt"

def prepare_star(self,folder_name, output_star='tomograms.star',pixel_size = 10.0, defocus = 0.0, number_subtomos = 100):
"""
\nThis command generates a tomograms.star file from a folder containing only tomogram files (.mrc or .rec).\n
isonet.py prepare_star folder_name [--output_star] [--pixel_size] [--defocus] [--number_subtomos]
:param folder_name: (None) directory containing tomogram(s). Usually 1-5 tomograms are sufficient.
:param output_star: (tomograms.star) star file similar to that from "relion". You can modify this file manually or with gui.
:param pixel_size: (10) pixel size in anstroms. Usually you want to bin your tomograms to about 10A pixel size.
:param pixel_size: (10) pixel size in anstroms. Usually you want to bin your tomograms to about 10A pixel size.
Too large or too small pixel sizes are not recommanded, since the target resolution on Z-axis of corrected tomograms should be about 30A.
:param defocus: (0.0) defocus in Angstrom. Only need for ctf deconvolution. For phase plate data, you can leave defocus 0.
:param defocus: (0.0) defocus in Angstrom. Only need for ctf deconvolution. For phase plate data, you can leave defocus 0.
If you have multiple tomograms with different defocus, please modify them in star file or with gui.
:param number_subtomos: (100) Number of subtomograms to be extracted in later processes.
:param number_subtomos: (100) Number of subtomograms to be extracted in later processes.
If you want to extract different number of subtomograms in different tomograms, you can modify them in the star file generated with this command or with gui.
"""
"""
md = MetaData()
md.addLabels('rlnIndex','rlnMicrographName','rlnPixelSize','rlnDefocus','rlnNumberSubtomo')
tomo_list = sorted(os.listdir(folder_name))
i = 0
for tomo in tomo_list:
print(tomo[-4:])
if tomo[-4:] == '.rec' or tomo[-4:] == '.mrc':
i+=1
it = Item()
Expand All @@ -57,13 +56,13 @@ def prepare_subtomo_star(self, folder_name, output_star='subtomo.star', pixel_si
"""
\nThis command generates a subtomo star file from a folder containing only subtomogram files (.mrc).
This command is usually not necessary in the traditional workflow, because "isonet.py extract" will generate this subtomo.star for you.\n
isonet.py prepare_subtomo_star folder_name [--output_star] [--cube_size]
isonet.py prepare_subtomo_star folder_name [--output_star] [--cube_size]
:param folder_name: (None) directory containing subtomogram(s).
:param output_star: (subtomo.star) output star file for subtomograms, will be used as input in refinement.
:param pixel_size: (10) The pixel size in angstrom of your subtomograms.
:param cube_size: (None) This is the size of the cubic volumes used for training. This values should be smaller than the size of subtomogram.
:param pixel_size: (10) The pixel size in angstrom of your subtomograms.
:param cube_size: (None) This is the size of the cubic volumes used for training. This values should be smaller than the size of subtomogram.
And the cube_size should be divisible by 8. If this value isn't set, cube_size is automatically determined as int(subtomo_size / 1.5 + 1)//16 * 16
"""
"""
#TODO check folder valid, logging
if not os.path.isdir(folder_name):
print("the folder does not exist")
Expand All @@ -73,7 +72,7 @@ def prepare_subtomo_star(self, folder_name, output_star='subtomo.star', pixel_si
subtomo_list = sorted(os.listdir(folder_name))
for i,subtomo in enumerate(subtomo_list):
subtomo_name = os.path.join(folder_name,subtomo)
try:
try:
with mrcfile.open(subtomo_name, mode='r') as s:
crop_size = s.header.nx
except:
Expand All @@ -97,10 +96,10 @@ def prepare_subtomo_star(self, folder_name, output_star='subtomo.star', pixel_si
# f.write(str(i+1)+' ' + os.path.join(folder_name,tomo) + '\n')
md.write(output_star)

def deconv(self, star_file: str,
deconv_folder:str="./deconv",
snrfalloff: float=None,
deconvstrength: float=None,
def deconv(self, star_file: str,
deconv_folder:str="./deconv",
snrfalloff: float=None,
deconvstrength: float=None,
highpassnyquist: float=0.02,
tile: tuple=(1,4,4),
overlap_rate = 0.25,
Expand All @@ -109,28 +108,28 @@ def deconv(self, star_file: str,
"""
\nCTF deconvolution for the tomograms.\n
isonet.py deconv star_file [--deconv_folder] [--snrfalloff] [--deconvstrength] [--highpassnyquist] [--tile] [--overlap_rate] [--ncpu] [--tomo_idx]
This step is recommanded because it enhances low resolution information for a better contrast. No need to do deconvolution for phase plate data.
This step is recommanded because it enhances low resolution information for a better contrast. No need to do deconvolution for phase plate data.
:param deconv_folder: (./deconv) Folder created to save deconvoluted tomograms.
:param star_file: (None) Star file for tomograms.
:param snrfalloff: (1.0) SNR fall rate with the frequency. High values means losing more high frequency.
If this value is not set, the program will look for the parameter in the star file.
:param snrfalloff: (1.0) SNR fall rate with the frequency. High values means losing more high frequency.
If this value is not set, the program will look for the parameter in the star file.
If this value is not set and not found in star file, the default value 1.0 will be used.
:param deconvstrength: (1.0) Strength of the deconvolution.
If this value is not set, the program will look for the parameter in the star file.
:param deconvstrength: (1.0) Strength of the deconvolution.
If this value is not set, the program will look for the parameter in the star file.
If this value is not set and not found in star file, the default value 1.0 will be used.
:param highpassnyquist: (0.02) Highpass filter for at very low frequency. We suggest to keep this default value.
:param tile: (1,4,4) The program crop the tomogram in multiple tiles (z,y,x) for multiprocessing and assembly them into one. e.g. (1,2,2)
:param overlap_rate: (None) The overlapping rate for adjecent tiles.
:param ncpu: (4) Number of cpus to use.
:param tomo_idx: (None) If this value is set, process only the tomograms listed in this index. e.g. 1,2,4 or 5-10,15,16
"""
:param ncpu: (4) Number of cpus to use.
:param tomo_idx: (None) If this value is set, process only the tomograms listed in this index. e.g. 1,2,4 or 5-10,15,16
"""
from IsoNet.util.deconvolution import deconv_one

logging.basicConfig(format='%(asctime)s, %(levelname)-8s %(message)s',
datefmt="%m-%d %H:%M:%S",level=logging.INFO,handlers=[logging.StreamHandler(sys.stdout)])
logging.info('\n######Isonet starts ctf deconvolve######\n')

try:
try:
md = MetaData()
md.read(star_file)
if not 'rlnSnrFalloff' in md.getLabels():
Expand All @@ -139,37 +138,37 @@ def deconv(self, star_file: str,
md._setItemValue(it,Label('rlnSnrFalloff'),1.0)
md._setItemValue(it,Label('rlnDeconvStrength'),1.0)
md._setItemValue(it,Label('rlnDeconvTomoName'),None)

if not os.path.isdir(deconv_folder):
os.mkdir(deconv_folder)

tomo_idx = idx2list(tomo_idx)
for it in md:
if tomo_idx is None or str(it.rlnIndex) in tomo_idx:
if snrfalloff is not None:
md._setItemValue(it,Label('rlnSnrFalloff'), snrfalloff)
if deconvstrength is not None:
md._setItemValue(it,Label('rlnDeconvStrength'),deconvstrength)

tomo_file = it.rlnMicrographName
base_name = os.path.basename(tomo_file)
base_name = os.path.basename(tomo_file)
deconv_tomo_name = '{}/{}'.format(deconv_folder,base_name)

deconv_one(it.rlnMicrographName,deconv_tomo_name,defocus=it.rlnDefocus/10000.0, pixel_size=it.rlnPixelSize,snrfalloff=it.rlnSnrFalloff, deconvstrength=it.rlnDeconvStrength,highpassnyquist=highpassnyquist,tile=tile,ncpu=ncpu)
md._setItemValue(it,Label('rlnDeconvTomoName'),deconv_tomo_name)
md.write(star_file)
logging.info('\n######Isonet done ctf deconvolve######\n')

except Exception:
error_text = traceback.format_exc()
f =open('log.txt','a+')
f.write(error_text)
f.close()
logging.error(error_text)

def make_mask(self,star_file,
mask_folder: str = 'mask',
patch_size: int=4,
def make_mask(self,star_file,
mask_folder: str = 'mask',
patch_size: int=4,
density_percentage: int=None,
std_percentage: int=None,
use_deconv_tomo:bool=True,
Expand All @@ -180,16 +179,16 @@ def make_mask(self,star_file,
isonet.py make_mask star_file [--mask_folder] [--patch_size] [--density_percentage] [--std_percentage] [--use_deconv_tomo] [--tomo_idx]
:param star_file: path to the tomogram or tomogram folder
:param mask_folder: path and name of the mask to save as
:param patch_size: (4) The size of the box from which the max-filter and std-filter are calculated.
:param density_percentage: (50) The approximate percentage of pixels to keep based on their local pixel density.
If this value is not set, the program will look for the parameter in the star file.
:param patch_size: (4) The size of the box from which the max-filter and std-filter are calculated.
:param density_percentage: (50) The approximate percentage of pixels to keep based on their local pixel density.
If this value is not set, the program will look for the parameter in the star file.
If this value is not set and not found in star file, the default value 50 will be used.
:param std_percentage: (50) The approximate percentage of pixels to keel based on their local standard deviation.
If this value is not set, the program will look for the parameter in the star file.
:param std_percentage: (50) The approximate percentage of pixels to keel based on their local standard deviation.
If this value is not set, the program will look for the parameter in the star file.
If this value is not set and not found in star file, the default value 50 will be used.
:param use_deconv_tomo: (True) If CTF deconvolved tomogram is found in tomogram.star, use that tomogram instead.
:param z_crop: If exclude the top and bottom regions of tomograms along z axis. For example, "--z_crop 0.2" will mask out the top 20% and bottom 20% region along z axis.
:param tomo_idx: (None) If this value is set, process only the tomograms listed in this index. e.g. 1,2,4 or 5-10,15,16
:param use_deconv_tomo: (True) If CTF deconvolved tomogram is found in tomogram.star, use that tomogram instead.
:param z_crop: If exclude the top and bottom regions of tomograms along z axis. For example, "--z_crop 0.2" will mask out the top 20% and bottom 20% region along z axis.
:param tomo_idx: (None) If this value is set, process only the tomograms listed in this index. e.g. 1,2,4 or 5-10,15,16
"""
from IsoNet.bin.make_mask import make_mask
logging.basicConfig(format='%(asctime)s, %(levelname)-8s %(message)s',
Expand All @@ -201,7 +200,7 @@ def make_mask(self,star_file,
# write star percentile threshold
md = MetaData()
md.read(star_file)
if not 'rlnMaskDensityPercentage' in md.getLabels():
if not 'rlnMaskDensityPercentage' in md.getLabels():
md.addLabels('rlnMaskDensityPercentage','rlnMaskStdPercentage','rlnMaskName')
for it in md:
md._setItemValue(it,Label('rlnMaskDensityPercentage'),50)
Expand Down Expand Up @@ -230,7 +229,7 @@ def make_mask(self,star_file,
percentile=it.rlnMaskDensityPercentage,
threshold=it.rlnMaskStdPercentage,
surface = z_crop)

md._setItemValue(it,Label('rlnMaskName'),mask_out_name)
md.write(star_file)
logging.info('\n######Isonet done making mask######\n')
Expand Down Expand Up @@ -259,11 +258,11 @@ def extract(self,
:param subtomo_star: (subtomo.star) star file for output subtomograms.
:param cube_size: (64) Size of cubes for training, should be divisible by 8, eg. 32, 64. The actual sizes of extracted subtomograms are 1.5 times of this value.
:param log_level: ("info") level of the output, either "info" or "debug"
:param use_deconv_tomo: (True) If CTF deconvolved tomogram is found in tomogram.star, use that tomogram instead.
:param use_deconv_tomo: (True) If CTF deconvolved tomogram is found in tomogram.star, use that tomogram instead.
"""
d = locals()
d_args = Arg(d)

if d_args.log_level == "debug":
logging.basicConfig(format='%(asctime)s, %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s'
,datefmt="%H:%M:%S",level=logging.DEBUG,handlers=[logging.StreamHandler(sys.stdout)])
Expand Down Expand Up @@ -331,7 +330,7 @@ def refine(self,
:param iterations: (30) Number of training iterations.
:param data_dir: (data) Temperary folder to save the generated data used for training.
:param log_level: (info) debug level, could be 'info' or 'debug'
:param continue_from: (None) A Json file to continue from. That json file is generated at each iteration of refine.
:param continue_from: (None) A Json file to continue from. That json file is generated at each iteration of refine.
:param result_dir: ('results') The name of directory to save refined neural network models and subtomograms
:param preprocessing_ncpus: (16) Number of cpu for preprocessing.
Expand All @@ -343,9 +342,9 @@ def refine(self,
************************Denoise settings************************
:param noise_level: (0.05,0.1,0.15,0.2) Level of noise STD(added noise)/STD(data) after the iteration defined in noise_start_iter.
:param noise_level: (0.05,0.1,0.15,0.2) Level of noise STD(added noise)/STD(data) after the iteration defined in noise_start_iter.
:param noise_start_iter: (11,16,21,26) Iteration that start to add noise of corresponding noise level.
:param noise_mode: (None) Filter names when generating noise volumes, can be 'ramp', 'hamming' and 'noFilter'
:param noise_mode: (None) Filter names when generating noise volumes, can be 'ramp', 'hamming' and 'noFilter'
************************Network settings************************
:param drop_out: (0.3) Drop out rate to reduce overfitting.
Expand Down Expand Up @@ -379,15 +378,15 @@ def predict(self, star_file: str, model: str, output_dir: str='./corrected_tomos
:param batch_size: The batch size of the cubes grouped into for network predicting
:param normalize_percentile: (True) if normalize the tomograms by percentile. Should be the same with that in refine parameter.
:param log_level: ("debug") level of message to be displayed, could be 'info' or 'debug'
:param tomo_idx: (None) If this value is set, process only the tomograms listed in this index. e.g. 1,2,4 or 5-10,15,16
:param use_deconv_tomo: (True) If CTF deconvolved tomogram is found in tomogram.star, use that tomogram instead.
:param tomo_idx: (None) If this value is set, process only the tomograms listed in this index. e.g. 1,2,4 or 5-10,15,16
:param use_deconv_tomo: (True) If CTF deconvolved tomogram is found in tomogram.star, use that tomogram instead.
:raises: AttributeError, KeyError
"""
d = locals()
d_args = Arg(d)
from IsoNet.bin.predict import predict


if d_args.log_level == "debug":
logging.basicConfig(format='%(asctime)s, %(levelname)-8s %(message)s',
datefmt="%m-%d %H:%M:%S",level=logging.DEBUG,handlers=[logging.StreamHandler(sys.stdout)])
Expand All @@ -402,15 +401,15 @@ def predict(self, star_file: str, model: str, output_dir: str='./corrected_tomos
f.write(error_text)
f.close()
logging.error(error_text)

def check(self):
from IsoNet.bin.predict import predict
from IsoNet.bin.refine import run
import skimage
import PyQt5
import PyQt5
import tqdm
print('IsoNet --version 0.1 installed')

def gui(self):
import IsoNet.gui.Isonet_star_app as app
app.main()
Expand All @@ -425,7 +424,7 @@ def pool_process(p_func,chunks_list,ncpu):
# results = p.map(partial_func,chunks_gpu_num_list,chunksize=1)
results = list(p.map(p_func,chunks_list))
# return results

if __name__ == "__main__":
core.Display = Display
# logging.basicConfig(format='%(asctime)s, %(levelname)-8s %(message)s',datefmt="%m-%d %H:%M:%S",level=logging.INFO)
Expand Down
Loading

0 comments on commit be24288

Please sign in to comment.