scipion-em-xmipp 24.12.2__py3-none-any.whl → 25.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {scipion_em_xmipp-24.12.2.dist-info → scipion_em_xmipp-25.6.0.dist-info}/METADATA +10 -10
- scipion_em_xmipp-25.6.0.dist-info/RECORD +255 -0
- {scipion_em_xmipp-24.12.2.dist-info → scipion_em_xmipp-25.6.0.dist-info}/WHEEL +1 -1
- {scipion_em_xmipp-24.12.2.dist-info → scipion_em_xmipp-25.6.0.dist-info}/entry_points.txt +0 -1
- xmipp3/__init__.py +106 -73
- xmipp3/base.py +2 -1
- xmipp3/convert/convert.py +1 -1
- xmipp3/legacy/protocols/protocol_angular_resolution_alignment.py +204 -0
- xmipp3/legacy/protocols/protocol_apply_deformation_zernike3d.py +113 -0
- xmipp3/legacy/protocols/protocol_classification_gpuCorr.py +821 -0
- xmipp3/legacy/protocols/protocol_classification_gpuCorr_full.py +1014 -0
- xmipp3/legacy/protocols/protocol_classification_gpuCorr_semi.py +462 -0
- xmipp3/legacy/protocols/protocol_classify_kmeans2d.py +285 -0
- xmipp3/legacy/protocols/protocol_deep_align.py +859 -0
- xmipp3/legacy/protocols/protocol_deep_denoising.py +425 -0
- xmipp3/legacy/protocols/protocol_kmeans_clustering.py +122 -0
- xmipp3/legacy/protocols/protocol_metaprotocol_create_output.py +146 -0
- xmipp3/legacy/protocols/protocol_metaprotocol_create_subset.py +96 -0
- xmipp3/legacy/protocols/protocol_metaprotocol_discrete_heterogeneity_scheduler.py +516 -0
- xmipp3/legacy/protocols/protocol_metaprotocol_golden_highres.py +663 -0
- xmipp3/legacy/protocols/protocol_mltomo.py +576 -0
- xmipp3/legacy/protocols/protocol_movie_average.py +202 -0
- xmipp3/legacy/protocols/protocol_movie_opticalflow.py +416 -0
- xmipp3/legacy/protocols/protocol_particle_boxsize.py +133 -0
- xmipp3/legacy/protocols/protocol_reconstruct_heterogeneous.py +1031 -0
- xmipp3/legacy/protocols/protocol_rotational_spectra.py +212 -0
- xmipp3/legacy/protocols/protocol_solid_angles.py +632 -0
- xmipp3/legacy/protocols/protocol_split_volume.py +112 -0
- xmipp3/legacy/protocols/protocol_split_volume_hierarchical_cluster.py +865 -0
- xmipp3/legacy/protocols/protocol_subtract_projection.py +265 -0
- xmipp3/legacy/tests/test_protocol_deep_denoising.py +64 -0
- xmipp3/legacy/tests/test_protocols_angular_resolution_alignment.py +88 -0
- xmipp3/legacy/tests/test_protocols_gpuCorr_classifier.py +141 -0
- xmipp3/legacy/tests/test_protocols_gpuCorr_fullStreaming.py +172 -0
- xmipp3/legacy/tests/test_protocols_gpuCorr_semiStreaming.py +68 -0
- xmipp3/legacy/tests/test_protocols_metaprotocol_golden_highres.py +96 -0
- xmipp3/legacy/tests/test_protocols_metaprotocol_heterogeneity.py +78 -0
- xmipp3/legacy/tests/test_protocols_mixed_movies.py +148 -0
- xmipp3/legacy/tests/test_protocols_solid_angles.py +161 -0
- xmipp3/legacy/tests/test_protocols_subtract_projection.py +595 -0
- xmipp3/legacy/tests/test_protocols_xmipp_movies.py +229 -0
- xmipp3/legacy/viewers/viewer_angular_resolution_alignment.py +148 -0
- xmipp3/legacy/viewers/viewer_deep_align.py +121 -0
- xmipp3/legacy/viewers/viewer_metaprotocol_golden_highres.py +140 -0
- xmipp3/legacy/viewers/viewer_mltomo.py +297 -0
- xmipp3/legacy/viewers/viewer_solid_angles.py +91 -0
- xmipp3/legacy/viewers/viewer_split_volume.py +57 -0
- xmipp3/protocols/__init__.py +1 -2
- xmipp3/protocols/protocol_align_volume.py +34 -8
- xmipp3/protocols/protocol_apply_alignment.py +1 -1
- xmipp3/protocols/protocol_apply_tilt_to_ctf.py +2 -3
- xmipp3/protocols/protocol_apply_zernike3d.py +2 -1
- xmipp3/protocols/protocol_assignment_tilt_pair.py +1 -2
- xmipp3/protocols/protocol_center_particles.py +1 -1
- xmipp3/protocols/protocol_cl2d.py +1 -2
- xmipp3/protocols/protocol_cl2d_align.py +1 -1
- xmipp3/protocols/protocol_cl2d_clustering.py +1 -1
- xmipp3/protocols/protocol_classify_pca.py +25 -9
- xmipp3/protocols/protocol_classify_pca_streaming.py +67 -42
- xmipp3/protocols/protocol_compute_likelihood.py +368 -0
- xmipp3/protocols/protocol_consensus_local_ctf.py +1 -1
- xmipp3/protocols/protocol_convert_pdb.py +9 -1
- xmipp3/protocols/protocol_create_gallery.py +1 -1
- xmipp3/protocols/protocol_ctf_consensus.py +14 -8
- xmipp3/protocols/protocol_ctf_correct_wiener2d.py +1 -1
- xmipp3/protocols/protocol_ctf_micrographs.py +1 -1
- xmipp3/protocols/protocol_deep_center_predict.py +10 -1
- xmipp3/protocols/protocol_deep_hand.py +19 -2
- xmipp3/protocols/protocol_deep_micrograph_screen.py +1 -1
- xmipp3/protocols/protocol_extract_asymmetric_unit.py +1 -1
- xmipp3/protocols/protocol_extract_particles.py +22 -10
- xmipp3/protocols/protocol_extract_particles_movies.py +1 -1
- xmipp3/protocols/protocol_extract_particles_pairs.py +1 -1
- xmipp3/protocols/protocol_flexalign.py +3 -4
- xmipp3/protocols/protocol_helical_parameters.py +1 -4
- xmipp3/protocols/protocol_movie_alignment_consensus.py +122 -40
- xmipp3/protocols/protocol_movie_dose_analysis.py +79 -82
- xmipp3/protocols/protocol_movie_max_shift.py +6 -2
- xmipp3/protocols/protocol_movie_split_frames.py +165 -88
- xmipp3/protocols/protocol_particle_pick_automatic.py +1 -2
- xmipp3/protocols/protocol_particle_pick_consensus.py +7 -0
- xmipp3/protocols/protocol_particle_pick_pairs.py +1 -1
- xmipp3/protocols/protocol_phantom_create.py +1 -1
- xmipp3/protocols/protocol_pick_noise.py +1 -1
- xmipp3/protocols/protocol_postProcessing_deepPostProcessing.py +5 -5
- xmipp3/protocols/protocol_preprocess/protocol_crop_resize.py +3 -2
- xmipp3/protocols/protocol_preprocess/protocol_filter.py +2 -2
- xmipp3/protocols/protocol_preprocess/protocol_image_operate.py +2 -2
- xmipp3/protocols/protocol_preprocess/protocol_mask.py +1 -1
- xmipp3/protocols/protocol_preprocess/protocol_preprocess.py +6 -4
- xmipp3/protocols/protocol_preprocess/protocol_process.py +20 -7
- xmipp3/protocols/protocol_preprocess_micrographs.py +3 -2
- xmipp3/protocols/protocol_projmatch/projmatch_steps.py +1 -1
- xmipp3/protocols/protocol_projmatch/protocol_projmatch.py +1 -1
- xmipp3/protocols/protocol_random_conical_tilt.py +1 -2
- xmipp3/protocols/protocol_ransac.py +41 -37
- xmipp3/protocols/protocol_reconstruct_fourier.py +5 -1
- xmipp3/protocols/protocol_reconstruct_highres.py +13 -7
- xmipp3/protocols/protocol_reconstruct_significant.py +14 -21
- xmipp3/protocols/protocol_resolution3d.py +1 -1
- xmipp3/protocols/protocol_resolution_deepres.py +1 -1
- xmipp3/protocols/protocol_resolution_directional.py +1 -1
- xmipp3/protocols/protocol_resolution_fso.py +1 -1
- xmipp3/protocols/protocol_resolution_monogenic_signal.py +19 -4
- xmipp3/protocols/protocol_rotate_volume.py +1 -1
- xmipp3/protocols/protocol_screen_deepConsensus.py +25 -5
- xmipp3/protocols/protocol_shift_volume.py +1 -1
- xmipp3/protocols/protocol_simulate_ctf.py +5 -3
- xmipp3/protocols/protocol_structure_map.py +9 -1
- xmipp3/protocols/protocol_subtract_projection.py +25 -10
- xmipp3/protocols/protocol_tilt_analysis.py +3 -3
- xmipp3/protocols/protocol_validate_fscq.py +2 -2
- xmipp3/protocols/protocol_validate_nontilt.py +1 -1
- xmipp3/protocols/protocol_volume_adjust_sub.py +8 -4
- xmipp3/protocols/protocol_volume_deform_zernike3d.py +1 -1
- xmipp3/protocols/protocol_volume_local_sharpening.py +1 -1
- xmipp3/protocols/protocol_volume_strain.py +1 -1
- xmipp3/protocols.conf +1 -3
- xmipp3/tests/test_protocol_likelihood.py +240 -0
- xmipp3/tests/test_protocol_split_frames.py +136 -0
- xmipp3/tests/test_protocol_validate_fscq.py +2 -2
- xmipp3/tests/test_protocols_highres.py +44 -5
- xmipp3/tests/test_protocols_xmipp_2d.py +1 -48
- xmipp3/tests/test_protocols_xmipp_mics.py +20 -16
- xmipp3/tests/test_protocols_xmipp_movies.py +4 -4
- xmipp3/version.py +5 -5
- xmipp3/viewers/__init__.py +1 -1
- xmipp3/viewers/viewer_LL_matrix.py +273 -0
- xmipp3/viewers/viewer_deep_consensus.py +1 -7
- xmipp3/viewers/viewer_dose_analysis.py +18 -2
- xmipp3/viewers/viewer_resolution_fso.py +18 -6
- xmipp3/viewers/viewer_structure_map.py +53 -11
- xmipp3/wizards.py +3 -2
- xmipp3/xmipp_logo_devel.png +0 -0
- scipion_em_xmipp-24.12.2.dist-info/RECORD +0 -210
- {scipion_em_xmipp-24.12.2.dist-info → scipion_em_xmipp-25.6.0.dist-info}/LICENSE +0 -0
- {scipion_em_xmipp-24.12.2.dist-info → scipion_em_xmipp-25.6.0.dist-info}/top_level.txt +0 -0
- /xmipp3/{protocols → legacy/protocols}/protocol_enrich.py +0 -0
- /xmipp3/{protocols → legacy/protocols}/protocol_screen_deeplearning.py +0 -0
|
@@ -0,0 +1,1014 @@
|
|
|
1
|
+
# ******************************************************************************
|
|
2
|
+
# *
|
|
3
|
+
# * Authors: Amaya Jimenez Moreno (ajimenez@cnb.csic.es)
|
|
4
|
+
# *
|
|
5
|
+
# * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
|
|
6
|
+
# *
|
|
7
|
+
# * This program is free software; you can redistribute it and/or modify
|
|
8
|
+
# * it under the terms of the GNU General Public License as published by
|
|
9
|
+
# * the Free Software Foundation; either version 2 of the License, or
|
|
10
|
+
# * (at your option) any later version.
|
|
11
|
+
# *
|
|
12
|
+
# * This program is distributed in the hope that it will be useful,
|
|
13
|
+
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# * GNU General Public License for more details.
|
|
16
|
+
# *
|
|
17
|
+
# * You should have received a copy of the GNU General Public License
|
|
18
|
+
# * along with this program; if not, write to the Free Software
|
|
19
|
+
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
20
|
+
# * 02111-1307 USA
|
|
21
|
+
# *
|
|
22
|
+
# * All comments concerning this program package may be sent to the
|
|
23
|
+
# * e-mail address 'scipion@cnb.csic.es'
|
|
24
|
+
# *
|
|
25
|
+
# ******************************************************************************
|
|
26
|
+
|
|
27
|
+
from shutil import copy
|
|
28
|
+
from os.path import exists, getmtime, splitext
|
|
29
|
+
from datetime import datetime
|
|
30
|
+
from os import system, popen, mkdir, listdir, remove
|
|
31
|
+
from os.path import join
|
|
32
|
+
from random import randint
|
|
33
|
+
import os
|
|
34
|
+
|
|
35
|
+
from pyworkflow import VERSION_2_0
|
|
36
|
+
import pyworkflow.protocol.params as params
|
|
37
|
+
from pyworkflow.utils import prettyTime, cleanPath
|
|
38
|
+
from pyworkflow.protocol.constants import STATUS_NEW
|
|
39
|
+
import pyworkflow.protocol.constants as const
|
|
40
|
+
|
|
41
|
+
from pwem.objects import SetOfParticles, Set
|
|
42
|
+
from pwem.protocols import ProtAlign2D
|
|
43
|
+
from pwem.constants import ALIGN_2D, ALIGN_NONE
|
|
44
|
+
import pwem.emlib.metadata as md
|
|
45
|
+
|
|
46
|
+
from pwem import emlib
|
|
47
|
+
from pwem.emlib import Image, MD_APPEND, DT_DOUBLE
|
|
48
|
+
|
|
49
|
+
from xmipp3.constants import CUDA_ALIGN_SIGNIFICANT
|
|
50
|
+
from xmipp3.convert import (writeSetOfParticles, xmippToLocation,
|
|
51
|
+
rowToAlignment, rowToParticle)
|
|
52
|
+
from xmipp3.base import isXmippCudaPresent
|
|
53
|
+
|
|
54
|
+
HASH_SIZE = 100
|
|
55
|
+
|
|
56
|
+
class HashTableDict:
|
|
57
|
+
def __init__(self, Ndict=HASH_SIZE):
|
|
58
|
+
self.Ndict = Ndict
|
|
59
|
+
self.dict = [{}]*Ndict
|
|
60
|
+
|
|
61
|
+
def isItemPresent(self, idx):
|
|
62
|
+
return idx in self.dict[idx % self.Ndict]
|
|
63
|
+
|
|
64
|
+
def pushItem(self, idx):
|
|
65
|
+
idxDict = idx % self.Ndict
|
|
66
|
+
if not idx in self.dict[idxDict]:
|
|
67
|
+
self.dict[idxDict][idx]=1
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class XmippProtStrGpuCrrCL2D(ProtAlign2D):
|
|
71
|
+
""" 2D alignment in full streaming using Xmipp GPU Correlation.
|
|
72
|
+
The set of classes will be growing whilst new particle images are
|
|
73
|
+
received."""
|
|
74
|
+
_label = 'gl2d streaming'
|
|
75
|
+
_lastUpdateVersion = VERSION_2_0
|
|
76
|
+
_stepsCheckSecs = 10
|
|
77
|
+
|
|
78
|
+
# --------------------------- DEFINE param functions -----------------------
|
|
79
|
+
def _defineAlignParams(self, form):
|
|
80
|
+
form.addHidden(params.GPU_LIST, params.StringParam, default='0',
|
|
81
|
+
expertLevel=const.LEVEL_ADVANCED,
|
|
82
|
+
label="Choose GPU IDs",
|
|
83
|
+
help="Add a list of GPU devices that can be used")
|
|
84
|
+
form.addParam('maxShift', params.IntParam, default=10,
|
|
85
|
+
label='Maximum shift (%):',
|
|
86
|
+
help='Maximum shift allowed during the alignment as '
|
|
87
|
+
'percentage of the input set size',
|
|
88
|
+
expertLevel=const.LEVEL_ADVANCED)
|
|
89
|
+
form.addParam('keepBest', params.IntParam, default=1,
|
|
90
|
+
label='Number of best images:',
|
|
91
|
+
help='Number of classes to assign every input image '
|
|
92
|
+
'during the alignment',
|
|
93
|
+
expertLevel=const.LEVEL_ADVANCED)
|
|
94
|
+
form.addParam('numberOfSplitIterations', params.IntParam, default=2,
|
|
95
|
+
label='Number of iterations in split stage:',
|
|
96
|
+
help='Maximum number of iterations in split stage',
|
|
97
|
+
expertLevel=const.LEVEL_ADVANCED)
|
|
98
|
+
form.addParam('numberOfClassifyIterations', params.IntParam, default=2,
|
|
99
|
+
label='Number of iterations in classify stage:',
|
|
100
|
+
help='Maximum number of iterations when the classification'
|
|
101
|
+
' of the whole image set is carried out',
|
|
102
|
+
expertLevel=const.LEVEL_ADVANCED)
|
|
103
|
+
form.addParam('imageSize', params.IntParam, default=64,
|
|
104
|
+
label='Image size',
|
|
105
|
+
help='The image size can be downsampled to accelerate '
|
|
106
|
+
'the classification',
|
|
107
|
+
expertLevel=const.LEVEL_ADVANCED)
|
|
108
|
+
form.addParam('threshold', params.IntParam, default=500,
|
|
109
|
+
label='Threshold to split',
|
|
110
|
+
help='The threshold in the number of images assigned '
|
|
111
|
+
'to one class to make a spliting of that class',
|
|
112
|
+
expertLevel=const.LEVEL_ADVANCED)
|
|
113
|
+
form.addParam('blockSize', params.IntParam, default=5000,
|
|
114
|
+
label='Block size',
|
|
115
|
+
help='The inputs will be processed in a block-by-block '
|
|
116
|
+
'basis of this size',
|
|
117
|
+
expertLevel=const.LEVEL_ADVANCED)
|
|
118
|
+
form.addParam('numClasses', params.IntParam, default=1000,
|
|
119
|
+
label='Maximum number of classes',
|
|
120
|
+
help='Maximum number of classes to be generated',
|
|
121
|
+
expertLevel=const.LEVEL_ADVANCED)
|
|
122
|
+
form.addParam('useCL2D', params.BooleanParam, default=True,
|
|
123
|
+
label='Use CL2D',
|
|
124
|
+
help='If you set to *Yes*, you will use CL2D (CPU) '
|
|
125
|
+
'to make the split process',
|
|
126
|
+
expertLevel=const.LEVEL_ADVANCED,)
|
|
127
|
+
form.addParallelSection(threads=0, mpi=8)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# --------------------------- INSERT steps functions -----------------------
|
|
131
|
+
def _insertAllSteps(self):
|
|
132
|
+
"""" Mainly prepare the command line for calling cuda corrrelation
|
|
133
|
+
program"""
|
|
134
|
+
self._readingCheckPoint()
|
|
135
|
+
|
|
136
|
+
self.listInFn = []
|
|
137
|
+
self.listOutFn = []
|
|
138
|
+
self.listOutSplitFn = []
|
|
139
|
+
self.doneListFn = []
|
|
140
|
+
self.lastDate = 0
|
|
141
|
+
self.imgsExp = self._getExtraPath('imagesExp.xmd')
|
|
142
|
+
self.listNumImgs = []
|
|
143
|
+
self.listNameImgs = []
|
|
144
|
+
self.listRefImgs = []
|
|
145
|
+
self.particlesToProcess = []
|
|
146
|
+
self.randRef = None
|
|
147
|
+
self.htAlreadyProcessed = HashTableDict()
|
|
148
|
+
xOrig = self.inputParticles.get().getXDim()
|
|
149
|
+
self.maximumShift = int(self.maxShift.get() * xOrig / 100)
|
|
150
|
+
|
|
151
|
+
self._loadInputList()
|
|
152
|
+
|
|
153
|
+
self.changeSampling = False
|
|
154
|
+
xO = self.listOfParticles[0].getXDim()
|
|
155
|
+
newSize = self.imageSize.get()
|
|
156
|
+
self.newSamplingRate = self.listOfParticles[0].getSamplingRate()
|
|
157
|
+
if xO != newSize:
|
|
158
|
+
self.changeSampling=True
|
|
159
|
+
factor = float(xO) / float(newSize)
|
|
160
|
+
self.newSamplingRate = self.newSamplingRate * factor
|
|
161
|
+
|
|
162
|
+
deps = []
|
|
163
|
+
numBlk, rem = divmod(float(len(self.listOfParticles)),
|
|
164
|
+
float(self.blockSize.get()))
|
|
165
|
+
numBlk = int(numBlk)
|
|
166
|
+
rem = int(rem)
|
|
167
|
+
if rem > 0:
|
|
168
|
+
numBlk += 1
|
|
169
|
+
for i in range(numBlk):
|
|
170
|
+
if i==0:
|
|
171
|
+
deps += self._insertStepsForParticles(True, False)
|
|
172
|
+
else:
|
|
173
|
+
deps += self._insertStepsForParticles(False, True)
|
|
174
|
+
|
|
175
|
+
self._insertFunctionStep('createOutputStep', prerequisities=deps,
|
|
176
|
+
wait=True)
|
|
177
|
+
|
|
178
|
+
def _insertStepsForParticles(self, flagSplit, reclassification):
|
|
179
|
+
|
|
180
|
+
inputImgs = self._getInputFn()
|
|
181
|
+
deps = []
|
|
182
|
+
|
|
183
|
+
stepIdClassify = self._insertFunctionStep\
|
|
184
|
+
('classifyStep', inputImgs, flagSplit, reclassification,
|
|
185
|
+
prerequisites=[])
|
|
186
|
+
deps.append(stepIdClassify)
|
|
187
|
+
|
|
188
|
+
return deps
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
# --------------------------- STEPS functions --------------------------
|
|
192
|
+
|
|
193
|
+
def _stepsCheck(self):
|
|
194
|
+
self._checkNewInput()
|
|
195
|
+
self._checkNewOutput()
|
|
196
|
+
|
|
197
|
+
def createOutputStep(self):
|
|
198
|
+
self._createFinalMetadata()
|
|
199
|
+
self._createFinalClasses()
|
|
200
|
+
|
|
201
|
+
def _checkNewInput(self):
|
|
202
|
+
""" Check if there are new particles to be processed and add
|
|
203
|
+
the necessary steps."""
|
|
204
|
+
particlesFile = self.inputParticles.get().getFileName()
|
|
205
|
+
|
|
206
|
+
now = datetime.now()
|
|
207
|
+
self.lastCheck = getattr(self, 'lastCheck', now)
|
|
208
|
+
mTime = datetime.fromtimestamp(getmtime(particlesFile))
|
|
209
|
+
self.debug('Last check: %s, modification: %s'
|
|
210
|
+
% (prettyTime(self.lastCheck),
|
|
211
|
+
prettyTime(mTime)))
|
|
212
|
+
|
|
213
|
+
# If the input have not changed since our last check,
|
|
214
|
+
# it does not make sense to check for new input data
|
|
215
|
+
if self.lastCheck > mTime and hasattr(self, 'listOfParticles'):
|
|
216
|
+
return None
|
|
217
|
+
|
|
218
|
+
self.lastCheck = now
|
|
219
|
+
outputStep = self._getFirstJoinStep()
|
|
220
|
+
|
|
221
|
+
# Open input and close it as soon as possible
|
|
222
|
+
self._loadInputList()
|
|
223
|
+
if len(self.listOfParticles)==0:
|
|
224
|
+
return None
|
|
225
|
+
|
|
226
|
+
deps=[]
|
|
227
|
+
numBlk, rem = divmod(float(len(self.listOfParticles)),
|
|
228
|
+
float(self.blockSize.get()))
|
|
229
|
+
numBlk = int(numBlk)
|
|
230
|
+
rem = int(rem)
|
|
231
|
+
if rem>0:
|
|
232
|
+
numBlk+=1
|
|
233
|
+
for i in range(numBlk):
|
|
234
|
+
deps += self._insertStepsForParticles(False, True)
|
|
235
|
+
|
|
236
|
+
if outputStep is not None:
|
|
237
|
+
outputStep.addPrerequisites(*deps)
|
|
238
|
+
self.updateSteps()
|
|
239
|
+
|
|
240
|
+
def _checkNewOutput(self):
|
|
241
|
+
""" Check for already done files and update the output set. """
|
|
242
|
+
|
|
243
|
+
newDone = self._readDoneList()
|
|
244
|
+
|
|
245
|
+
# We have finished when there is not more inputs (stream closed)
|
|
246
|
+
# and the number of processed particles is equal to the number of inputs
|
|
247
|
+
self.finished = (self.isStreamClosed == Set.STREAM_CLOSED
|
|
248
|
+
and len(newDone) == 0)
|
|
249
|
+
streamMode = Set.STREAM_CLOSED if self.finished else Set.STREAM_OPEN
|
|
250
|
+
|
|
251
|
+
if newDone:
|
|
252
|
+
self._updateOutputSet(streamMode)
|
|
253
|
+
self.doneListFn += newDone
|
|
254
|
+
|
|
255
|
+
elif not self.finished:
|
|
256
|
+
# If we are not finished and no new output have been produced
|
|
257
|
+
# it does not make sense to proceed and updated the outputs
|
|
258
|
+
# so we exit from the function here
|
|
259
|
+
return
|
|
260
|
+
|
|
261
|
+
if self.finished: # Unlock createOutputStep if finished all jobs
|
|
262
|
+
outputStep = self._getFirstJoinStep()
|
|
263
|
+
if outputStep and outputStep.isWaiting():
|
|
264
|
+
outputStep.setStatus(STATUS_NEW)
|
|
265
|
+
|
|
266
|
+
def classifyStep(self, expImgMd, flag_split, reclassification):
|
|
267
|
+
|
|
268
|
+
auxList=[]
|
|
269
|
+
for im in range(len(self.listOfParticles)):
|
|
270
|
+
idx = self.listOfParticles[im].getObjId()
|
|
271
|
+
if not self.htAlreadyProcessed.isItemPresent(idx):
|
|
272
|
+
auxList.append(self.listOfParticles[im])
|
|
273
|
+
self.htAlreadyProcessed.pushItem(idx)
|
|
274
|
+
|
|
275
|
+
self.particlesToProcess+=auxList
|
|
276
|
+
if len(self.particlesToProcess)==0:
|
|
277
|
+
return
|
|
278
|
+
|
|
279
|
+
if len(self.particlesToProcess)<self.blockSize.get():
|
|
280
|
+
particlesToProcessAux = self.particlesToProcess
|
|
281
|
+
lastIm = len(self.particlesToProcess)-1
|
|
282
|
+
else:
|
|
283
|
+
particlesToProcessAux = self.particlesToProcess[:self.blockSize.get()]
|
|
284
|
+
lastIm = self.blockSize.get()-1
|
|
285
|
+
|
|
286
|
+
self.generateInput(expImgMd, flag_split, reclassification,
|
|
287
|
+
particlesToProcessAux)
|
|
288
|
+
|
|
289
|
+
if flag_split:
|
|
290
|
+
refImgMd = self._getExtraPath('split_last_classes.xmd')
|
|
291
|
+
else:
|
|
292
|
+
refImgMd = self._getExtraPath('last_classes.xmd')
|
|
293
|
+
|
|
294
|
+
i=0
|
|
295
|
+
while i <self.numberOfClassifyIterations:
|
|
296
|
+
outImgs, refImgMd = self.iterationStep(refImgMd, expImgMd, i, False)
|
|
297
|
+
|
|
298
|
+
if flag_split==False and i+1 < self.numberOfClassifyIterations:
|
|
299
|
+
classesFnPrev = self._getExtraPath('last_classes.xmd')
|
|
300
|
+
self.averageClasses(refImgMd, classesFnPrev, refImgMd, True)
|
|
301
|
+
i += 1
|
|
302
|
+
|
|
303
|
+
self.generateOutputClasses(refImgMd, flag_split)
|
|
304
|
+
|
|
305
|
+
self.checkSplit()
|
|
306
|
+
|
|
307
|
+
self.lastDate = self.particlesToProcess[lastIm].getObjCreation()
|
|
308
|
+
self._saveCreationTimeFile(self.lastDate)
|
|
309
|
+
|
|
310
|
+
for p in range(len(particlesToProcessAux)):
|
|
311
|
+
self.particlesToProcess.pop(0)
|
|
312
|
+
|
|
313
|
+
self._savingCheckPoint()
|
|
314
|
+
|
|
315
|
+
# --------------------------- UTILS functions ------------------------------
|
|
316
|
+
|
|
317
|
+
def splitStep(self, expImgMd):
|
|
318
|
+
i=0
|
|
319
|
+
classesOut=None
|
|
320
|
+
while i <self.numberOfSplitIterations:
|
|
321
|
+
outImgs,classesOut = self.iterationStep(classesOut,expImgMd,i,True)
|
|
322
|
+
i+=1
|
|
323
|
+
length = md.getSize(classesOut)
|
|
324
|
+
if length == 1:
|
|
325
|
+
i = 0
|
|
326
|
+
|
|
327
|
+
self.generateMdForClassification(classesOut)
|
|
328
|
+
|
|
329
|
+
def generateInput(self, inputImgs, flag_split, reclassification,
|
|
330
|
+
particlesToProcess):
|
|
331
|
+
|
|
332
|
+
inputStack = inputImgs.replace('xmd','stk')
|
|
333
|
+
newSize = self.imageSize.get()
|
|
334
|
+
if self.changeSampling:
|
|
335
|
+
writeSetOfParticles(particlesToProcess, inputImgs,
|
|
336
|
+
alignType=ALIGN_NONE)
|
|
337
|
+
args = "-i %s -o %s --save_metadata_stack --fourier %d " % (
|
|
338
|
+
inputImgs, inputStack, newSize)
|
|
339
|
+
self.runJob("xmipp_image_resize", args, numberOfMpi=1)
|
|
340
|
+
else:
|
|
341
|
+
writeSetOfParticles(particlesToProcess, inputImgs,
|
|
342
|
+
alignType=ALIGN_NONE)
|
|
343
|
+
|
|
344
|
+
if reclassification and len(self.listNumImgs)!=0:
|
|
345
|
+
self.randRef = randint(1, len(self.listNumImgs))
|
|
346
|
+
self._unionReclassification(self.randRef, inputImgs)
|
|
347
|
+
|
|
348
|
+
if flag_split:
|
|
349
|
+
self.splitStep(inputImgs)
|
|
350
|
+
|
|
351
|
+
def generateMdForClassification(self, classesOut):
|
|
352
|
+
|
|
353
|
+
listNameImgs = self.listNameImgs
|
|
354
|
+
listNumImgs = self.listNumImgs
|
|
355
|
+
|
|
356
|
+
count = 1
|
|
357
|
+
# Construct the new classes with the renumerated old classes
|
|
358
|
+
mdNewClasses = md.MetaData()
|
|
359
|
+
for i in range(len(listNumImgs)):
|
|
360
|
+
if listNumImgs[i] != -1:
|
|
361
|
+
name = listNameImgs[i]
|
|
362
|
+
fn = name[name.find('@') + 1:-4] + '.xmd'
|
|
363
|
+
numRef = int(name[0:6])
|
|
364
|
+
|
|
365
|
+
mdClass = md.MetaData("classes@" + fn)
|
|
366
|
+
for row in md.iterRows(mdClass):
|
|
367
|
+
if mdClass.getValue(md.MDL_REF, row.getObjId()) == numRef:
|
|
368
|
+
row.setValue(md.MDL_REF, count)
|
|
369
|
+
row.addToMd(mdNewClasses)
|
|
370
|
+
count += 1
|
|
371
|
+
|
|
372
|
+
# Add the two new classes to the list of renumerated classes
|
|
373
|
+
mdClass = md.MetaData("classes@" + classesOut)
|
|
374
|
+
rows = md.iterRows(mdClass)
|
|
375
|
+
for row in rows:
|
|
376
|
+
row.setValue(md.MDL_REF, count)
|
|
377
|
+
row.addToMd(mdNewClasses)
|
|
378
|
+
count += 1
|
|
379
|
+
mdNewClasses.write('classes@'
|
|
380
|
+
+ self._getExtraPath('split_last_classes.xmd'),
|
|
381
|
+
MD_APPEND)
|
|
382
|
+
|
|
383
|
+
# Generate the intermediate images and the blocks of the intermediate
|
|
384
|
+
# classes for the unchanged classes
|
|
385
|
+
count=1
|
|
386
|
+
for i in range(len(listNumImgs)):
|
|
387
|
+
if listNumImgs[i] != -1:
|
|
388
|
+
# Read the list of images in this class
|
|
389
|
+
mdImgsInClass = md.MetaData(self._getExtraPath(
|
|
390
|
+
'dataClass%06d.xmd' % (i+1)))
|
|
391
|
+
mdImgsInClass.fillConstant(md.MDL_REF, count)
|
|
392
|
+
mdImgsInClass.write(self._getExtraPath('dataClass%06d.xmd' %
|
|
393
|
+
count))
|
|
394
|
+
count += 1
|
|
395
|
+
|
|
396
|
+
# Add the two new classes
|
|
397
|
+
for newRef in range(0, 2):
|
|
398
|
+
mdImgsInClass = md.MetaData(
|
|
399
|
+
'class%06d_images@%s' % (newRef + 1, classesOut))
|
|
400
|
+
mdImgsInClass.fillConstant(md.MDL_REF, count)
|
|
401
|
+
mdImgsInClass.write(self._getExtraPath('dataClass%06d.xmd' % count))
|
|
402
|
+
count+=1
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
def averageClasses(self, finalMetadata, lastMetadata, newMetadata,
|
|
406
|
+
flag_iter):
|
|
407
|
+
|
|
408
|
+
metadataItemLast = md.MetaData(lastMetadata)
|
|
409
|
+
metadataItemNew = md.MetaData(newMetadata)
|
|
410
|
+
if flag_iter:
|
|
411
|
+
metadataFinal = md.MetaData(finalMetadata)
|
|
412
|
+
finalName = metadataFinal.getValue(md.MDL_IMAGE, 1)
|
|
413
|
+
finalName = finalName[7:-3]+'stk'
|
|
414
|
+
else:
|
|
415
|
+
finalName = finalMetadata
|
|
416
|
+
|
|
417
|
+
total=[]
|
|
418
|
+
newRef = 1
|
|
419
|
+
i = 1
|
|
420
|
+
for itemLast, itemNew in zip(metadataItemLast, metadataItemNew):
|
|
421
|
+
listToMultiply = []
|
|
422
|
+
numImgsLastClasses = metadataItemLast.getValue(
|
|
423
|
+
md.MDL_CLASS_COUNT, itemLast)
|
|
424
|
+
nameRefLastClasses = metadataItemLast.getValue(md.MDL_IMAGE,
|
|
425
|
+
itemLast)
|
|
426
|
+
nameRefNewClasses = metadataItemNew.getValue(md.MDL_IMAGE,
|
|
427
|
+
itemNew)
|
|
428
|
+
numImgsNewClasses = metadataItemNew.getValue(md.MDL_CLASS_COUNT,
|
|
429
|
+
itemNew)
|
|
430
|
+
if flag_iter==False and i==self.randRef:
|
|
431
|
+
total.append(numImgsNewClasses)
|
|
432
|
+
else:
|
|
433
|
+
total.append(numImgsLastClasses + numImgsNewClasses)
|
|
434
|
+
i += 1
|
|
435
|
+
|
|
436
|
+
if (numImgsLastClasses + numImgsNewClasses)==0:
|
|
437
|
+
continue
|
|
438
|
+
|
|
439
|
+
if numImgsNewClasses==0:
|
|
440
|
+
im1 = Image(nameRefLastClasses)
|
|
441
|
+
im1.write('%06d@' % newRef + finalName)
|
|
442
|
+
newRef += 1
|
|
443
|
+
continue
|
|
444
|
+
if numImgsLastClasses==0:
|
|
445
|
+
im2 = Image(nameRefNewClasses)
|
|
446
|
+
im2.write('%06d@' % newRef + finalName)
|
|
447
|
+
newRef += 1
|
|
448
|
+
continue
|
|
449
|
+
|
|
450
|
+
listToMultiply.append(float(numImgsLastClasses)/
|
|
451
|
+
float(numImgsLastClasses + numImgsNewClasses))
|
|
452
|
+
listToMultiply.append(float(numImgsNewClasses)/
|
|
453
|
+
float(numImgsLastClasses + numImgsNewClasses))
|
|
454
|
+
|
|
455
|
+
im1 = Image(nameRefLastClasses)
|
|
456
|
+
im2 = Image(nameRefNewClasses)
|
|
457
|
+
im2 = emlib.image_align(im1, im2)
|
|
458
|
+
|
|
459
|
+
im1.inplaceMultiply(listToMultiply[0])
|
|
460
|
+
im2.inplaceMultiply(listToMultiply[1])
|
|
461
|
+
im1.convert2DataType(DT_DOUBLE)
|
|
462
|
+
im2.convert2DataType(DT_DOUBLE)
|
|
463
|
+
im1.inplaceAdd(im2) # Aligned
|
|
464
|
+
im1.write('%06d@' % newRef + finalName)
|
|
465
|
+
newRef+=1
|
|
466
|
+
|
|
467
|
+
return total
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def generateOutputClasses(self, classesOut, firstTime):
|
|
471
|
+
|
|
472
|
+
if firstTime:
|
|
473
|
+
self._saveFileDataClasses(classesOut, self._getExtraPath(
|
|
474
|
+
'last_classes.xmd'))
|
|
475
|
+
# Add the two new classes
|
|
476
|
+
for i in range(1, 3):
|
|
477
|
+
mdImgsInClass = md.MetaData(
|
|
478
|
+
'class%06d_images@%s' % (i,classesOut))
|
|
479
|
+
mdImgsInClass.write(self._getExtraPath('dataClass%06d.xmd' % i))
|
|
480
|
+
return
|
|
481
|
+
|
|
482
|
+
finalMetadata = self._getExtraPath('aux_classes.stk')
|
|
483
|
+
lastMetadata = self._getExtraPath('last_classes.xmd')
|
|
484
|
+
newMetadata = classesOut
|
|
485
|
+
|
|
486
|
+
total = self.averageClasses(finalMetadata, lastMetadata, newMetadata,
|
|
487
|
+
False)
|
|
488
|
+
|
|
489
|
+
copy(self._getExtraPath('aux_classes.stk'),
|
|
490
|
+
self._getExtraPath('last_classes.stk'))
|
|
491
|
+
|
|
492
|
+
mdAll = md.MetaData()
|
|
493
|
+
newRef=1
|
|
494
|
+
for i in total:
|
|
495
|
+
if i != 0:
|
|
496
|
+
row = md.Row()
|
|
497
|
+
row.setValue(md.MDL_REF, newRef)
|
|
498
|
+
row.setValue(md.MDL_IMAGE, '%06d@'%newRef + finalMetadata)
|
|
499
|
+
row.setValue(md.MDL_CLASS_COUNT, i)
|
|
500
|
+
row.addToMd(mdAll)
|
|
501
|
+
newRef+=1
|
|
502
|
+
mdAll.write('classes@'+finalMetadata[:-3] + 'xmd', MD_APPEND)
|
|
503
|
+
|
|
504
|
+
copy(self._getExtraPath('aux_classes.xmd'),
|
|
505
|
+
self._getExtraPath('last_classes.xmd'))
|
|
506
|
+
|
|
507
|
+
newRef=1
|
|
508
|
+
for i, val in enumerate(total):
|
|
509
|
+
if val != 0:
|
|
510
|
+
self._unionDataClass(classesOut, i+1, newRef)
|
|
511
|
+
newRef+=1
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
def iterationStep (self, refSet, imgsExp, iter, flag_split):
|
|
515
|
+
|
|
516
|
+
if flag_split:
|
|
517
|
+
outImgs, classesOut = self._getOutputSplitFn()
|
|
518
|
+
else:
|
|
519
|
+
outImgs, classesOut = self._getOutputClassFn()
|
|
520
|
+
|
|
521
|
+
outDirName = splitext(imgsExp)[0]
|
|
522
|
+
if iter==0 and flag_split==True:
|
|
523
|
+
|
|
524
|
+
# First step: divide the metadata input file to generate
|
|
525
|
+
# a couple of references
|
|
526
|
+
self._params = {'imgsExp': imgsExp,
|
|
527
|
+
'outDir': outDirName}
|
|
528
|
+
args = ('-i %(imgsExp)s -n 2 --oroot %(outDir)s')
|
|
529
|
+
self.runJob("xmipp_metadata_split", args % self._params,
|
|
530
|
+
numberOfMpi=1)
|
|
531
|
+
|
|
532
|
+
# Second step: calculate the means of the previous metadata
|
|
533
|
+
expSet1 = outDirName + '000001.xmd'
|
|
534
|
+
avg1 = outDirName + '_000001'
|
|
535
|
+
expSet2 = outDirName + '000002.xmd'
|
|
536
|
+
avg2 = outDirName + '_000002'
|
|
537
|
+
self._params = {'imgsSet': expSet1,
|
|
538
|
+
'outputAvg': avg1}
|
|
539
|
+
args = ('-i %(imgsSet)s --save_image_stats %(outputAvg)s -v 0')
|
|
540
|
+
self.runJob("xmipp_image_statistics", args % self._params,
|
|
541
|
+
numberOfMpi=1)
|
|
542
|
+
|
|
543
|
+
self._params = {'imgsSet': expSet2,
|
|
544
|
+
'outputAvg': avg2}
|
|
545
|
+
args = ('-i %(imgsSet)s --save_image_stats %(outputAvg)s -v 0')
|
|
546
|
+
self.runJob("xmipp_image_statistics", args % self._params,
|
|
547
|
+
numberOfMpi=1)
|
|
548
|
+
|
|
549
|
+
# Third step: generate a single metadata with the two previous avgs
|
|
550
|
+
refSet = self._getExtraPath('refSet.xmd')
|
|
551
|
+
self._params = {'avg1': avg1 + 'average.xmp',
|
|
552
|
+
'avg2': avg2 + 'average.xmp',
|
|
553
|
+
'outputMd': refSet}
|
|
554
|
+
args = ('-i %(avg1)s --set union %(avg2)s -o %(outputMd)s')
|
|
555
|
+
self.runJob("xmipp_metadata_utilities", args % self._params,
|
|
556
|
+
numberOfMpi=1)
|
|
557
|
+
|
|
558
|
+
# Fourth step: calling program xmipp_cuda_align_significant
|
|
559
|
+
metadataRef = md.MetaData(refSet)
|
|
560
|
+
if metadataRef.containsLabel(md.MDL_REF) is False:
|
|
561
|
+
args = ('-i %(outputMd)s --fill ref lineal 1 1 -o %(outputMd)s')
|
|
562
|
+
self.runJob("xmipp_metadata_utilities", args % self._params,
|
|
563
|
+
numberOfMpi=1)
|
|
564
|
+
|
|
565
|
+
count = 0
|
|
566
|
+
GpuListCuda = ''
|
|
567
|
+
if self.useQueueForSteps() or self.useQueue():
|
|
568
|
+
GpuList = os.environ["CUDA_VISIBLE_DEVICES"]
|
|
569
|
+
GpuList = GpuList.split(",")
|
|
570
|
+
for elem in GpuList:
|
|
571
|
+
GpuListCuda = GpuListCuda + str(count) + ' '
|
|
572
|
+
count += 1
|
|
573
|
+
else:
|
|
574
|
+
GpuListAux = ''
|
|
575
|
+
for elem in self.getGpuList():
|
|
576
|
+
GpuListCuda = GpuListCuda + str(count) + ' '
|
|
577
|
+
GpuListAux = GpuListAux + str(elem) + ','
|
|
578
|
+
count += 1
|
|
579
|
+
os.environ["CUDA_VISIBLE_DEVICES"] = GpuListAux
|
|
580
|
+
|
|
581
|
+
if flag_split:
|
|
582
|
+
fileTocopy = classesOut.replace('.xmd', '_classes.xmd')
|
|
583
|
+
fileTocopy = fileTocopy.replace('extra/', 'extra/level_00/')
|
|
584
|
+
self._params = {'imgsRef': refSet,
|
|
585
|
+
'imgsExp': imgsExp,
|
|
586
|
+
'maxshift': self.maximumShift,
|
|
587
|
+
'Nrefs': md.getSize(refSet),
|
|
588
|
+
'outDir': self._getExtraPath(),
|
|
589
|
+
'outImgCuda': self._getExtraPath("images.xmd"),
|
|
590
|
+
'rootFn': classesOut.split('/')[-1].replace('.xmd', ''),
|
|
591
|
+
'keepBest': self.keepBest.get(),
|
|
592
|
+
'outClassesCuda': fileTocopy,
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
args = '-i %(imgsExp)s --ref0 %(imgsRef)s --nref %(Nrefs)d ' \
|
|
596
|
+
'--iter 1 --distance correlation --classicalMultiref ' \
|
|
597
|
+
'--maxShift %(maxshift)d --odir %(outDir)s --oroot %(' \
|
|
598
|
+
'rootFn)s --dontMirrorImages '
|
|
599
|
+
self.runJob("xmipp_classify_CL2D",
|
|
600
|
+
args % self._params, numberOfMpi=self.numberOfMpi.get())
|
|
601
|
+
copy(fileTocopy, classesOut)
|
|
602
|
+
copy(self._getExtraPath("images.xmd"), outImgs)
|
|
603
|
+
|
|
604
|
+
else:
|
|
605
|
+
self._params = {'imgsRef': refSet,
|
|
606
|
+
'imgsExp': imgsExp,
|
|
607
|
+
'outputFile': outImgs,
|
|
608
|
+
'keepBest': self.keepBest.get(),
|
|
609
|
+
'maxshift': self.maximumShift,
|
|
610
|
+
'outputClassesFile': classesOut,
|
|
611
|
+
'device': GpuListCuda,
|
|
612
|
+
'outputClassesFileNoExt': splitext(classesOut)[0],
|
|
613
|
+
'auxOut': self._getExtraPath('flipReferences%06d.xmd'%iter),
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
args = '-i %(imgsExp)s -r %(imgsRef)s -o %(outputFile)s ' \
|
|
617
|
+
'--keepBestN 1 --oUpdatedRefs %(outputClassesFileNoExt)s --dev %(device)s '
|
|
618
|
+
self.runJob(CUDA_ALIGN_SIGNIFICANT, args % self._params,
|
|
619
|
+
numberOfMpi=1)
|
|
620
|
+
|
|
621
|
+
if exists(outDirName + '000001.xmd'):
|
|
622
|
+
cleanPath(expSet1)
|
|
623
|
+
cleanPath(expSet2)
|
|
624
|
+
cleanPath(avg1 + 'average.xmp')
|
|
625
|
+
cleanPath(avg2 + 'average.xmp')
|
|
626
|
+
cleanPath(avg1 + 'stddev.xmp')
|
|
627
|
+
cleanPath(avg2 + 'stddev.xmp')
|
|
628
|
+
|
|
629
|
+
return outImgs, classesOut
|
|
630
|
+
|
|
631
|
+
def checkSplit(self):
|
|
632
|
+
|
|
633
|
+
outSet = self._getExtraPath('last_classes.xmd')
|
|
634
|
+
|
|
635
|
+
self.listNameImgs = []
|
|
636
|
+
self.listNumImgs = []
|
|
637
|
+
self.listRefImgs = []
|
|
638
|
+
|
|
639
|
+
metadataItem = md.MetaData(outSet)
|
|
640
|
+
for item in metadataItem:
|
|
641
|
+
nameImg = metadataItem.getValue(md.MDL_IMAGE, item)
|
|
642
|
+
self.listNameImgs.append(nameImg)
|
|
643
|
+
numImgs = metadataItem.getValue(md.MDL_CLASS_COUNT, item)
|
|
644
|
+
self.listNumImgs.append(numImgs)
|
|
645
|
+
refImg = metadataItem.getValue(md.MDL_REF, item)
|
|
646
|
+
self.listRefImgs.append(refImg)
|
|
647
|
+
|
|
648
|
+
i=0
|
|
649
|
+
auxList = sorted(self.listNumImgs, reverse=True)
|
|
650
|
+
while i<len(self.listNumImgs):
|
|
651
|
+
|
|
652
|
+
if len(self.listNumImgs) < self.numClasses.get(): #inside the while
|
|
653
|
+
# just in case we lose some class we want to allow one more
|
|
654
|
+
# split
|
|
655
|
+
if auxList[i] < (1.75 * self.threshold.get()):
|
|
656
|
+
i+=1
|
|
657
|
+
continue
|
|
658
|
+
|
|
659
|
+
maxValue = auxList[i]
|
|
660
|
+
maxPos = self.listNumImgs.index(maxValue)
|
|
661
|
+
|
|
662
|
+
self.listNumImgs[maxPos] = -1
|
|
663
|
+
bestRef = self.listRefImgs[maxPos]
|
|
664
|
+
|
|
665
|
+
outputMd = self._getExtraPath('dataClass%06d.xmd' % bestRef)
|
|
666
|
+
self.splitStep(outputMd)
|
|
667
|
+
|
|
668
|
+
i=0
|
|
669
|
+
outSet = self._getExtraPath('split_last_classes.xmd')
|
|
670
|
+
|
|
671
|
+
self.listNameImgs = []
|
|
672
|
+
self.listNumImgs = []
|
|
673
|
+
self.listRefImgs = []
|
|
674
|
+
|
|
675
|
+
metadataItem = md.MetaData(outSet)
|
|
676
|
+
for item in metadataItem:
|
|
677
|
+
nameImg = metadataItem.getValue(md.MDL_IMAGE, item)
|
|
678
|
+
self.listNameImgs.append(nameImg)
|
|
679
|
+
numImgs = metadataItem.getValue(md.MDL_CLASS_COUNT, item)
|
|
680
|
+
self.listNumImgs.append(numImgs)
|
|
681
|
+
refImg = metadataItem.getValue(md.MDL_REF, item)
|
|
682
|
+
self.listRefImgs.append(refImg)
|
|
683
|
+
|
|
684
|
+
copy(outSet, self._getExtraPath('last_classes.xmd'))
|
|
685
|
+
auxList = sorted(self.listNumImgs, reverse=True)
|
|
686
|
+
i=0
|
|
687
|
+
|
|
688
|
+
else:
|
|
689
|
+
break
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
def _loadInputList(self):
|
|
693
|
+
""" Load the input set of ctfs and create a list. """
|
|
694
|
+
particlesSet = self._loadInputParticleSet()
|
|
695
|
+
lastDate = self._readCreationTimeFile()
|
|
696
|
+
self.isStreamClosed = particlesSet.getStreamState()
|
|
697
|
+
self.listOfParticles = []
|
|
698
|
+
|
|
699
|
+
for p in particlesSet.iterItems(orderBy='creation',
|
|
700
|
+
where="creation>'%s'"
|
|
701
|
+
% lastDate):
|
|
702
|
+
idx = p.getObjId()
|
|
703
|
+
if not self.htAlreadyProcessed.isItemPresent(idx):
|
|
704
|
+
newPart = p.clone()
|
|
705
|
+
newPart.setObjCreation(p.getObjCreation())
|
|
706
|
+
self.listOfParticles.append(newPart)
|
|
707
|
+
|
|
708
|
+
particlesSet.close()
|
|
709
|
+
self.debug("Closed db.")
|
|
710
|
+
|
|
711
|
+
def _loadInputParticleSet(self):
|
|
712
|
+
partSetFn = self.inputParticles.get().getFileName()
|
|
713
|
+
updatedSet = SetOfParticles(filename=partSetFn)
|
|
714
|
+
copyPartSet = SetOfParticles()
|
|
715
|
+
updatedSet.loadAllProperties()
|
|
716
|
+
copyPartSet.copy(updatedSet)
|
|
717
|
+
updatedSet.close()
|
|
718
|
+
return copyPartSet
|
|
719
|
+
|
|
720
|
+
def _getUniqueFn(self, basename, list):
|
|
721
|
+
if list == []:
|
|
722
|
+
fn = basename + "_1.xmd"
|
|
723
|
+
else:
|
|
724
|
+
number = int(list[-1].split("_")[-1].split(".")[0]) + 1
|
|
725
|
+
fn = basename + "_%s.xmd" % number
|
|
726
|
+
list.append(fn)
|
|
727
|
+
return fn
|
|
728
|
+
|
|
729
|
+
def _getInputFn(self):
|
|
730
|
+
basename = self._getExtraPath('imagesExp')
|
|
731
|
+
return self._getUniqueFn(basename, self.listInFn)
|
|
732
|
+
|
|
733
|
+
def _getOutputSplitFn(self):
|
|
734
|
+
nameImages = self._getExtraPath('split_general_images')
|
|
735
|
+
imagesFn = self._getUniqueFn(nameImages, self.listOutSplitFn)
|
|
736
|
+
classesFn = imagesFn.replace('images', 'classes')
|
|
737
|
+
return imagesFn, classesFn
|
|
738
|
+
|
|
739
|
+
def _getOutputClassFn(self):
|
|
740
|
+
nameImages = self._getExtraPath('class_general_images')
|
|
741
|
+
imagesFn = self._getUniqueFn(nameImages, self.listOutFn)
|
|
742
|
+
classesFn = imagesFn.replace('images', 'classes')
|
|
743
|
+
return imagesFn, classesFn
|
|
744
|
+
|
|
745
|
+
def _readDoneList(self):
|
|
746
|
+
return [fn for fn in self.listOutFn if fn not in self.doneListFn]
|
|
747
|
+
|
|
748
|
+
def _getFirstJoinStep(self):
|
|
749
|
+
for s in self._steps:
|
|
750
|
+
if s.funcName == 'createOutputStep':
|
|
751
|
+
return s
|
|
752
|
+
return None
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
def _createFinalClasses(self):
|
|
756
|
+
# Here the defineOutputs function will call the write() method
|
|
757
|
+
outputSet = self._createSetOfClasses2D(self.inputParticles)
|
|
758
|
+
self._fillClasses(outputSet)
|
|
759
|
+
self._defineOutputs(**{'outputClasses': outputSet})
|
|
760
|
+
self._defineSourceRelation(self.inputParticles, outputSet)
|
|
761
|
+
self._store(outputSet)
|
|
762
|
+
# Close set databaset to avoid locking it
|
|
763
|
+
outputSet.close()
|
|
764
|
+
|
|
765
|
+
def _updateOutputSet(self, state=Set.STREAM_OPEN):
|
|
766
|
+
|
|
767
|
+
setFile = self._getPath('averages.sqlite')
|
|
768
|
+
if exists(setFile):
|
|
769
|
+
cleanPath(setFile)
|
|
770
|
+
inputs = self.inputParticles.get()
|
|
771
|
+
# Here the defineOutputs function will call the write() method
|
|
772
|
+
outputAvg = self._createSetOfAverages()
|
|
773
|
+
outputAvg.copyInfo(inputs)
|
|
774
|
+
self._fillAverages(outputAvg)
|
|
775
|
+
self._defineOutputs(**{'outputAverages': outputAvg})
|
|
776
|
+
self._defineSourceRelation(self.inputParticles, outputAvg)
|
|
777
|
+
self._store(outputAvg)
|
|
778
|
+
# Close set databaset to avoid locking it
|
|
779
|
+
outputAvg.close()
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
def _updateParticle(self, item, row):
|
|
783
|
+
item.setClassId(row.getValue(md.MDL_REF))
|
|
784
|
+
item.setTransform(rowToAlignment(row, ALIGN_2D))
|
|
785
|
+
|
|
786
|
+
def _updateClass(self, item):
|
|
787
|
+
classId = item.getObjId()
|
|
788
|
+
if classId in self._classesInfo:
|
|
789
|
+
index, fn, _ = self._classesInfo[classId]
|
|
790
|
+
item.setAlignment2D()
|
|
791
|
+
rep = item.getRepresentative()
|
|
792
|
+
rep.setLocation(index, fn)
|
|
793
|
+
rep.setSamplingRate(self.newSamplingRate)
|
|
794
|
+
|
|
795
|
+
def _loadClassesInfo(self, filename):
|
|
796
|
+
""" Read some information about the produced 2D classes
|
|
797
|
+
from the metadata file.
|
|
798
|
+
"""
|
|
799
|
+
self._classesInfo = {} # store classes info, indexed by class id
|
|
800
|
+
mdClasses = md.MetaData(filename)
|
|
801
|
+
for classNumber, row in enumerate(md.iterRows(mdClasses)):
|
|
802
|
+
index, fn = xmippToLocation(row.getValue(md.MDL_IMAGE))
|
|
803
|
+
self._classesInfo[classNumber + 1] = (index, fn, row.clone())
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
def _fillClasses(self, clsSet):
|
|
807
|
+
""" Create the SetOfClasses2D from a given iteration. """
|
|
808
|
+
myFileParticles = self._getExtraPath('last_images.xmd')
|
|
809
|
+
myFileClasses = self._getExtraPath('last_classes.xmd')
|
|
810
|
+
self._loadClassesInfo(myFileClasses)
|
|
811
|
+
xmpMd = myFileParticles
|
|
812
|
+
iterator = md.SetMdIterator(xmpMd, sortByLabel=md.MDL_ITEM_ID,
|
|
813
|
+
updateItemCallback=self._updateParticle,
|
|
814
|
+
skipDisabled=True)
|
|
815
|
+
clsSet.classifyItems(updateItemCallback=iterator.updateItem,
|
|
816
|
+
updateClassCallback=self._updateClass)
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
def _fillAverages(self, avgSet):
|
|
820
|
+
""" Create the SetOfAverages from a given metadata """
|
|
821
|
+
myFileClasses = "classes@" + self._getExtraPath('last_classes.xmd')
|
|
822
|
+
repSet = md.MetaData(myFileClasses)
|
|
823
|
+
for rep in md.iterRows(repSet):
|
|
824
|
+
particle = rowToParticle(rep)
|
|
825
|
+
repId = rep.getValue(md.MDL_REF) #rep.getObjId()
|
|
826
|
+
particle.setObjId(repId)
|
|
827
|
+
avgSet.append(particle)
|
|
828
|
+
|
|
829
|
+
|
|
830
|
+
def _saveFileDataClasses(self, fn, fnSave):
|
|
831
|
+
|
|
832
|
+
line = ""
|
|
833
|
+
numLine = 0
|
|
834
|
+
while not line.startswith('data_class0'):
|
|
835
|
+
numLine += 1
|
|
836
|
+
line = popen('sed -n %ip %s' % (numLine, fn)).read()
|
|
837
|
+
system('head -%i %s >> %s' % (numLine - 1, fn, fnSave))
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
def _createFinalMetadata(self):
|
|
841
|
+
fnClasses = self._getExtraPath('last_classes.xmd')
|
|
842
|
+
numClasses = md.getSize(fnClasses)
|
|
843
|
+
|
|
844
|
+
for i in range(numClasses):
|
|
845
|
+
num=i+1
|
|
846
|
+
fn = self._getExtraPath('dataClass%06d.xmd' % num)
|
|
847
|
+
if exists(fn):
|
|
848
|
+
line = ""
|
|
849
|
+
numLine = 0
|
|
850
|
+
while not line.startswith(' '):
|
|
851
|
+
numLine += 1
|
|
852
|
+
line = popen('sed -n %ip %s' % (numLine, fn)).read()
|
|
853
|
+
aux = self._getExtraPath('aux.xmd')
|
|
854
|
+
system('head -%i %s >> %s' % (numLine - 1, fn, aux))
|
|
855
|
+
|
|
856
|
+
dataHeader = self._getExtraPath('dataHeader.xmd')
|
|
857
|
+
fp = open(aux, 'r')
|
|
858
|
+
fout = open(dataHeader, 'w')
|
|
859
|
+
for i, line in enumerate(fp):
|
|
860
|
+
if i<2:
|
|
861
|
+
continue
|
|
862
|
+
if not line.startswith('data_noname'):
|
|
863
|
+
fout.write(line)
|
|
864
|
+
else:
|
|
865
|
+
line = line.replace('noname', 'class%06d_images'%num)
|
|
866
|
+
fout.write(line)
|
|
867
|
+
fp.close()
|
|
868
|
+
fout.close()
|
|
869
|
+
cleanPath(aux)
|
|
870
|
+
fnOut = self._getExtraPath('dataImages%06d.xmd' % num)
|
|
871
|
+
system('tail -n +%i %s >> %s' % (i+2, fn, aux))
|
|
872
|
+
system('cat %s %s >> %s'%(dataHeader, aux, fnOut))
|
|
873
|
+
if num==1:
|
|
874
|
+
system('cat %s >> %s' % (fn,
|
|
875
|
+
self._getExtraPath('last_images.xmd')))
|
|
876
|
+
else:
|
|
877
|
+
system('cat %s >> %s' %(aux,
|
|
878
|
+
self._getExtraPath('last_images.xmd')))
|
|
879
|
+
cleanPath(aux)
|
|
880
|
+
cleanPath(dataHeader)
|
|
881
|
+
system('cat %s >> %s' % (fnOut,
|
|
882
|
+
self._getExtraPath('last_classes.xmd')))
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
def _unionDataClass(self, fn, refOld, refNew):
|
|
886
|
+
|
|
887
|
+
fnNew = self._getExtraPath('dataClass%06d.xmd' % refNew)
|
|
888
|
+
fnOld = self._getExtraPath('dataClass%06d.xmd' % refOld)
|
|
889
|
+
if refOld != refNew and exists(fnOld):
|
|
890
|
+
mdOld = md.MetaData(fnOld)
|
|
891
|
+
mdOld.fillConstant(md.MDL_REF, refNew)
|
|
892
|
+
mdOld.write(fnOld)
|
|
893
|
+
|
|
894
|
+
if exists(fnOld):
|
|
895
|
+
fnAux = self._getExtraPath('aux.xmd')
|
|
896
|
+
mdImgsInClass = md.MetaData('class%06d_images@%s' % (refOld, fn))
|
|
897
|
+
if not mdImgsInClass.isEmpty():
|
|
898
|
+
if refOld != refNew:
|
|
899
|
+
mdImgsInClass.fillConstant(md.MDL_REF, refNew)
|
|
900
|
+
mdImgsInClass.write(fnAux)
|
|
901
|
+
line = ""
|
|
902
|
+
numLine = 0
|
|
903
|
+
while not line.startswith(' '):
|
|
904
|
+
numLine += 1
|
|
905
|
+
line = popen('sed -n %ip %s' % (numLine, fnAux)).read()
|
|
906
|
+
fnSave = self._getExtraPath('newDataClass%06d.xmd'%refNew)
|
|
907
|
+
system('tail -n +%i %s >> %s' % (numLine, fnAux, fnSave))
|
|
908
|
+
cleanPath(fnAux)
|
|
909
|
+
if refOld==refNew:
|
|
910
|
+
system('cat %s >> %s' % (fnSave, fnNew))
|
|
911
|
+
else:
|
|
912
|
+
if exists(fnNew):
|
|
913
|
+
cleanPath(fnNew)
|
|
914
|
+
system('cat %s %s >> %s' %(fnOld, fnSave, fnNew))
|
|
915
|
+
cleanPath(fnSave)
|
|
916
|
+
else:
|
|
917
|
+
if refOld!=refNew:
|
|
918
|
+
if exists(fnNew):
|
|
919
|
+
cleanPath(fnNew)
|
|
920
|
+
copy(fnOld, fnNew)
|
|
921
|
+
else:
|
|
922
|
+
mdImgsInClass = md.MetaData('class%06d_images@%s' % (refOld, fn))
|
|
923
|
+
if refOld != refNew:
|
|
924
|
+
mdImgsInClass.fillConstant(md.MDL_REF, refNew)
|
|
925
|
+
mdImgsInClass.write(fnNew)
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
def _unionReclassification(self, ref, inputImgs):
|
|
929
|
+
|
|
930
|
+
fn1 = self._getExtraPath('dataClass%06d.xmd' % ref)
|
|
931
|
+
line = ""
|
|
932
|
+
numLine = 0
|
|
933
|
+
while not line.startswith(' '):
|
|
934
|
+
numLine += 1
|
|
935
|
+
line = popen('sed -n %ip %s' % (numLine, fn1)).read()
|
|
936
|
+
fnSave = self._getExtraPath('aux.xmd')
|
|
937
|
+
system('tail -n +%i %s >> %s' % (numLine, fn1, fnSave))
|
|
938
|
+
system('cat %s >> %s' % (fnSave, inputImgs))
|
|
939
|
+
cleanPath(fnSave)
|
|
940
|
+
cleanPath(fn1)
|
|
941
|
+
|
|
942
|
+
|
|
943
|
+
def _saveCreationTimeFile(self, cTime):
|
|
944
|
+
fn = open(self._getExtraPath('creation.txt'),'w')
|
|
945
|
+
fn.write(cTime)
|
|
946
|
+
fn.close()
|
|
947
|
+
|
|
948
|
+
def _readCreationTimeFile(self):
|
|
949
|
+
if exists(self._getExtraPath('creation.txt')):
|
|
950
|
+
fn = open(self._getExtraPath('creation.txt'), 'r')
|
|
951
|
+
cTime = fn.readline()
|
|
952
|
+
fn.close()
|
|
953
|
+
else:
|
|
954
|
+
cTime = 0
|
|
955
|
+
return cTime
|
|
956
|
+
|
|
957
|
+
def _savingCheckPoint(self):
|
|
958
|
+
if not exists(join(self._getExtraPath(), 'checkpoint')):
|
|
959
|
+
mkdir(join(self._getExtraPath(), 'checkpoint'))
|
|
960
|
+
|
|
961
|
+
listFolder = listdir(self._getExtraPath())
|
|
962
|
+
for fn in listFolder:
|
|
963
|
+
if fn.startswith('dataClass'):
|
|
964
|
+
copy(join(self._getExtraPath(),fn),
|
|
965
|
+
self._getExtraPath(join('checkpoint',fn)))
|
|
966
|
+
copy(self._getExtraPath('last_classes.xmd'),
|
|
967
|
+
self._getExtraPath(join('checkpoint', 'last_classes.xmd')))
|
|
968
|
+
if exists(self._getExtraPath('last_classes.stk')):
|
|
969
|
+
copy(self._getExtraPath('last_classes.stk'),
|
|
970
|
+
self._getExtraPath(join('checkpoint', 'last_classes.stk')))
|
|
971
|
+
|
|
972
|
+
def _readingCheckPoint(self):
|
|
973
|
+
if exists(join(self._getExtraPath(), 'checkpoint')):
|
|
974
|
+
listFolder = listdir(join(self._getExtraPath(), 'checkpoint'))
|
|
975
|
+
for fn in listFolder:
|
|
976
|
+
copy(self._getExtraPath(join('checkpoint',fn)),
|
|
977
|
+
self._getExtraPath(fn))
|
|
978
|
+
|
|
979
|
+
# --------------------------- INFO functions -------------------------------
|
|
980
|
+
def _validate(self):
|
|
981
|
+
errors = []
|
|
982
|
+
newSize = self.imageSize.get()
|
|
983
|
+
x, y, _ = self.inputParticles.get().getDim()
|
|
984
|
+
if newSize>x or newSize>y:
|
|
985
|
+
errors.append('The image size must be smaller than the size of '
|
|
986
|
+
'the input images')
|
|
987
|
+
|
|
988
|
+
return errors
|
|
989
|
+
|
|
990
|
+
def _summary(self):
|
|
991
|
+
summary = []
|
|
992
|
+
if not hasattr(self, 'outputClasses'):
|
|
993
|
+
summary.append("Output alignment not ready yet.")
|
|
994
|
+
else:
|
|
995
|
+
summary.append("Input Particles: %s"
|
|
996
|
+
% self.inputParticles.get().getSize())
|
|
997
|
+
summary.append("Aligned in streaming.")
|
|
998
|
+
return summary
|
|
999
|
+
|
|
1000
|
+
def _citations(self):
|
|
1001
|
+
return ['Sorzano2010a']
|
|
1002
|
+
|
|
1003
|
+
def _methods(self):
|
|
1004
|
+
methods = []
|
|
1005
|
+
if not hasattr(self, 'outputClasses'):
|
|
1006
|
+
methods.append("Output alignment not ready yet.")
|
|
1007
|
+
else:
|
|
1008
|
+
methods.append(
|
|
1009
|
+
"We aligned images %s in streaming using CL2D "
|
|
1010
|
+
"[Sorzano2010a] and GPU correlation methods " %
|
|
1011
|
+
self.getObjectTag('inputParticles'))
|
|
1012
|
+
methods.append(" and produced %s images."
|
|
1013
|
+
% self.getObjectTag('outputClasses'))
|
|
1014
|
+
return methods
|