scipion-em-xmipp 24.6.0.0__py3-none-any.whl → 24.12.2__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.
Files changed (56) hide show
  1. {scipion_em_xmipp-24.6.0.0.dist-info → scipion_em_xmipp-24.12.2.dist-info}/METADATA +8 -7
  2. {scipion_em_xmipp-24.6.0.0.dist-info → scipion_em_xmipp-24.12.2.dist-info}/RECORD +51 -47
  3. {scipion_em_xmipp-24.6.0.0.dist-info → scipion_em_xmipp-24.12.2.dist-info}/WHEEL +1 -1
  4. xmipp3/__init__.py +110 -92
  5. xmipp3/checkProtocolsConf.py +117 -0
  6. xmipp3/constants.py +3 -0
  7. xmipp3/convert/convert.py +31 -10
  8. xmipp3/protocols/__init__.py +4 -2
  9. xmipp3/protocols/protocol_apply_tilt_to_ctf.py +114 -0
  10. xmipp3/protocols/protocol_cl2d.py +1 -1
  11. xmipp3/protocols/protocol_cl2d_clustering.py +303 -0
  12. xmipp3/protocols/protocol_classify_pca.py +3 -1
  13. xmipp3/protocols/protocol_classify_pca_streaming.py +1 -0
  14. xmipp3/protocols/protocol_compare_reprojections.py +2 -2
  15. xmipp3/protocols/protocol_convert_pdb.py +9 -4
  16. xmipp3/protocols/protocol_create_gallery.py +84 -12
  17. xmipp3/protocols/protocol_ctf_consensus.py +186 -273
  18. xmipp3/protocols/protocol_ctf_defocus_group.py +4 -4
  19. xmipp3/protocols/protocol_ctf_micrographs.py +12 -1
  20. xmipp3/protocols/protocol_deep_center.py +2 -2
  21. xmipp3/protocols/protocol_deep_center_predict.py +140 -0
  22. xmipp3/protocols/protocol_extract_particles.py +1 -1
  23. xmipp3/protocols/protocol_flexalign.py +46 -47
  24. xmipp3/protocols/protocol_mics_defocus_balancer.py +341 -0
  25. xmipp3/protocols/protocol_movie_alignment_consensus.py +1 -1
  26. xmipp3/protocols/protocol_movie_dose_analysis.py +159 -77
  27. xmipp3/protocols/protocol_movie_gain.py +5 -1
  28. xmipp3/protocols/protocol_movie_max_shift.py +246 -178
  29. xmipp3/protocols/protocol_reconstruct_fourier.py +29 -14
  30. xmipp3/protocols/protocol_reconstruct_highres.py +15 -2
  31. xmipp3/protocols/protocol_simulate_ctf.py +1 -1
  32. xmipp3/protocols/protocol_subtract_projection.py +89 -28
  33. xmipp3/protocols/protocol_tilt_analysis.py +95 -191
  34. xmipp3/protocols/protocol_trigger_data.py +22 -12
  35. xmipp3/protocols/protocol_validate_fscq.py +1 -1
  36. xmipp3/protocols/protocol_volume_adjust_sub.py +0 -4
  37. xmipp3/protocols/protocol_volume_local_sharpening.py +34 -24
  38. xmipp3/protocols.conf +141 -115
  39. xmipp3/tests/test_protocols_deepcenter_predict.py +66 -0
  40. xmipp3/tests/test_protocols_xmipp_2d.py +27 -7
  41. xmipp3/tests/test_protocols_xmipp_3d.py +16 -755
  42. xmipp3/tests/test_protocols_xmipp_mics.py +43 -4
  43. xmipp3/tests/test_protocols_xmipp_movies.py +0 -169
  44. xmipp3/version.py +38 -0
  45. xmipp3/viewers/__init__.py +3 -1
  46. xmipp3/viewers/viewer_apply_tilt_to_ctf.py +81 -0
  47. xmipp3/viewers/viewer_cl2d_clustering.py +131 -0
  48. xmipp3/viewers/viewer_movie_alignment.py +3 -9
  49. xmipp3/protocols/protocol_angular_resolution_alignment.py +0 -204
  50. xmipp3/protocols/protocol_movie_opticalflow.py +0 -416
  51. xmipp3/tests/test_protocols_angular_resolution_alignment.py +0 -88
  52. xmipp3/tests/test_protocols_mixed_movies.py +0 -149
  53. xmipp3/viewers/viewer_angular_resolution_alignment.py +0 -148
  54. {scipion_em_xmipp-24.6.0.0.dist-info → scipion_em_xmipp-24.12.2.dist-info}/LICENSE +0 -0
  55. {scipion_em_xmipp-24.6.0.0.dist-info → scipion_em_xmipp-24.12.2.dist-info}/entry_points.txt +0 -0
  56. {scipion_em_xmipp-24.6.0.0.dist-info → scipion_em_xmipp-24.12.2.dist-info}/top_level.txt +0 -0
@@ -4,6 +4,7 @@
4
4
  # * Roberto Marabini (roberto@cnb.csic.es)
5
5
  # * Tomas Majtner (tmajtner@cnb.csic.es) -- streaming version
6
6
  # * Amaya Jimenez (ajimenez@cnb.csic.es)
7
+ # * Daniel Marchan (da.marchan@cnb.csic.es) --refactor streaming
7
8
  # *
8
9
  # * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
9
10
  # *
@@ -41,7 +42,7 @@ import pyworkflow.utils as pwutils
41
42
  from pwem.protocols import ProtCTFMicrographs
42
43
  from pwem.emlib.metadata import Row
43
44
  from pyworkflow.protocol.constants import (STATUS_NEW)
44
- from pyworkflow import BETA, UPDATED, NEW, PROD
45
+ from pyworkflow import UPDATED
45
46
 
46
47
  from pwem import emlib
47
48
  import xmipp3
@@ -52,6 +53,11 @@ DISCARDED = 'Discarded'
52
53
  INPUT1 = 1
53
54
  INPUT2 = 2
54
55
 
56
+ OUTPUT_CTF = "outputCTF"
57
+ OUTPUT_MICS = "outputMicrographs"
58
+ OUTPUT_CTF_DISCARDED = "outputCTFDiscarded"
59
+ OUTPUT_MICS_DISCARDED = "outputMicrographsDiscarded"
60
+
55
61
  class XmippProtCTFConsensus(ProtCTFMicrographs):
56
62
  """
57
63
  Protocol to make a selection of meaningful CTFs in basis of the defocus
@@ -59,13 +65,18 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
59
65
  the agreement with a secondary CTF for the same set of micrographs.
60
66
  """
61
67
  _label = 'ctf consensus'
62
- _devStatus = PROD
68
+ _devStatus = UPDATED
63
69
  _lastUpdateVersion = VERSION_3_0
70
+ _possibleOutputs = {OUTPUT_MICS: SetOfMicrographs,
71
+ OUTPUT_MICS_DISCARDED: SetOfMicrographs,
72
+ OUTPUT_CTF: SetOfCTF,
73
+ OUTPUT_CTF_DISCARDED: SetOfCTF
74
+ }
75
+
64
76
 
65
77
  def __init__(self, **args):
66
78
  ProtCTFMicrographs.__init__(self, **args)
67
79
  self._freqResol = {}
68
- self.stepsExecutionMode = params.STEPS_PARALLEL
69
80
 
70
81
  def _defineParams(self, form):
71
82
  form.addSection(label='Input')
@@ -191,29 +202,30 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
191
202
  'If *No*, only the primary metadata (plus consensus '
192
203
  'scores) will be in the resulting CTF.')
193
204
 
194
- form.addParallelSection(threads=4, mpi=1)
195
205
 
196
206
  # --------------------------- INSERT steps functions -------------------------
197
207
  def _insertAllSteps(self):
198
208
  self.initializeParams()
199
209
  if self.calculateConsensus:
200
210
  self.ctfFn2 = self.inputCTF2.get().getFileName()
201
- self.allCtf2 = {}
202
211
 
203
- self._insertFunctionStep('createOutputStep',
204
- prerequisites=[], wait=True)
212
+ self._insertFunctionStep(self.createOutputStep,
213
+ prerequisites=[], wait=True, needsGPU=False)
205
214
 
206
215
  def createOutputStep(self):
207
216
  self._closeOutputSet()
208
217
 
209
218
  def initializeParams(self):
210
219
  self.finished = False
211
- self.insertedDict = {}
220
+ self.isStreamClosed = False
221
+ # Important to have both:
222
+ self.insertedIds = [] # Contains images that have been inserted in a Step (checkNewInput).
223
+ # Contains images that have been processed in a Step (checkNewOutput).
224
+ self.acceptedIds = {}
225
+ self.discardedIds = {}
212
226
  self.initializeRejDict()
213
227
  self.setSecondaryAttributes()
214
228
  self.ctfFn1 = self.inputCTF.get().getFileName()
215
- self.allCtf1 = {}
216
- pwutils.makePath(self._getExtraPath('DONE'))
217
229
 
218
230
  def _getFirstJoinStepName(self):
219
231
  # This function will be used for streaming, to check which is
@@ -228,43 +240,15 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
228
240
  return s
229
241
  return None
230
242
 
231
-
232
- def _insertNewCtfsSteps(self, newIDs1, newIDs2, insertedDict):
243
+ def _insertNewCtfsSteps(self, newIds):
233
244
  deps = []
245
+ stepId = self._insertFunctionStep(self.selectCtfStep, newIds, needsGPU=False,
246
+ prerequisites=[])
247
+ deps.append(stepId)
234
248
 
235
- newIDs = list(set(newIDs1).intersection(set(newIDs2)))
236
- md1 = emlib.MetaData()
237
- md2 = emlib.MetaData()
238
-
239
- for ctfID in newIDs:
240
- if ctfID not in insertedDict:
241
- ctf1 = self.allCtf1.get(ctfID)
242
- ctf2 = self.allCtf2.get(ctfID)
243
- try:
244
- self._ctfToMd(ctf1, md1)
245
- self._ctfToMd(ctf2, md2)
246
- self._freqResol[ctfID] = emlib.errorMaxFreqCTFs2D(md1, md2)
247
- except TypeError as exc:
248
- print("Error reading ctf for id:%s. %s" % (ctfID, exc))
249
- self._freqResol[ctfID] = 9999
250
-
251
- stepId = self._insertFunctionStep('selectCtfStep', ctfID,
252
- prerequisites=[])
253
- deps.append(stepId)
254
- insertedDict[ctfID] = stepId
255
-
256
- return deps
249
+ for ctfId in newIds:
250
+ self.insertedIds.append(ctfId)
257
251
 
258
- def _insertNewSelectionSteps(self, insertedDict, newIDs):
259
- deps = []
260
- # For each ctf insert the step to process it
261
- for ctfID in newIDs:
262
-
263
- if ctfID not in insertedDict:
264
- stepId = self._insertFunctionStep('selectCtfStep', ctfID,
265
- prerequisites=[])
266
- deps.append(stepId)
267
- insertedDict[ctfID] = stepId
268
252
  return deps
269
253
 
270
254
  def _stepsCheck(self):
@@ -282,88 +266,70 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
282
266
  pwutils.prettyTime(mTime)))
283
267
  # If the input movies.sqlite have not changed since our last check,
284
268
  # it does not make sense to check for new input data
285
- if self.lastCheck > mTime and (hasattr(self, 'outputCTF') or hasattr(self, "outputCTFDiscarded")):
269
+ if self.lastCheck > mTime and self.insertedIds: # If this is empty it is dut to a static "continue" action or it is the first round
286
270
  return None
287
271
 
288
272
  ctfsSet1 = self._loadInputCtfSet(self.ctfFn1)
289
273
  ctfsSet2 = self._loadInputCtfSet(self.ctfFn2)
290
274
 
291
- ctfDict1 = {ctf.getObjId(): ctf.clone() for ctf
292
- in ctfsSet1.iterItems()}
293
-
294
- ctfDict2 = {ctf.getObjId(): ctf.clone() for ctf
295
- in ctfsSet2.iterItems()}
275
+ ctfSet1Ids = ctfsSet1.getIdSet()
276
+ ctfSet2Ids = ctfsSet2.getIdSet()
296
277
 
297
- newIds1 = [idCTF1 for idCTF1 in ctfDict1.keys() if idCTF1 not in self.insertedDict]
298
- self.allCtf1.update(ctfDict1)
278
+ newIds1 = [idCTF for idCTF in ctfSet1Ids if idCTF not in self.insertedIds]
279
+ newIds2 = [idCTF for idCTF in ctfSet2Ids if idCTF not in self.insertedIds]
299
280
 
300
- newIds2 = [idCTF2 for idCTF2 in ctfDict2.keys() if idCTF2 not in self.insertedDict]
301
- self.allCtf2.update(ctfDict2)
281
+ newIds = list(set(newIds1).intersection(set(newIds2)))
302
282
 
303
283
  self.lastCheck = datetime.now()
304
284
  self.isStreamClosed = ctfsSet1.isStreamClosed() and \
305
285
  ctfsSet2.isStreamClosed()
306
286
  ctfsSet1.close()
307
287
  ctfsSet2.close()
308
-
309
- outputStep = self._getFirstJoinStep()
310
- if len(set(self.allCtf1)) > len(set(self.insertedDict)) and \
311
- len(set(self.allCtf2)) > len(set(self.insertedDict)):
312
- fDeps = self._insertNewCtfsSteps(newIds1, newIds2,
313
- self.insertedDict)
314
- if outputStep is not None:
315
- outputStep.addPrerequisites(*fDeps)
316
- self.updateSteps()
317
288
  else:
318
- now = datetime.now()
319
- self.lastCheck = getattr(self, 'lastCheck', now)
289
+ self.lastCheck = getattr(self, 'lastCheck', datetime.now())
320
290
  mTime = datetime.fromtimestamp(os.path.getmtime(self.ctfFn1))
321
291
  self.debug('Last check: %s, modification: %s'
322
292
  % (pwutils.prettyTime(self.lastCheck),
323
293
  pwutils.prettyTime(mTime)))
324
294
  # If the input ctfs.sqlite have not changed since our last check,
325
295
  # it does not make sense to check for new input data
326
- if self.lastCheck > mTime and (hasattr(self, 'outputCTF') or hasattr(self, "outputCTFDiscarded")):
296
+ if self.lastCheck > mTime and self.insertedIds:
327
297
  return None
328
298
 
329
299
  # Open input ctfs.sqlite and close it as soon as possible
330
300
  ctfSet = self._loadInputCtfSet(self.ctfFn1)
331
- ctfDict = {ctf.getObjId(): ctf.clone() for ctf
332
- in ctfSet.iterItems()}
333
-
334
- newIds = [idCTF for idCTF in ctfDict.keys() if idCTF not in self.insertedDict]
335
- self.allCtf1.update(ctfDict)
301
+ ctfSetIds = ctfSet.getIdSet()
302
+ newIds = [idCTF for idCTF in ctfSetIds if idCTF not in self.insertedIds]
336
303
 
304
+ self.lastCheck = datetime.now()
337
305
  self.isStreamClosed = ctfSet.isStreamClosed()
338
306
  ctfSet.close()
339
307
 
340
- self.lastCheck = now
341
- newCtf = any(ctf.getObjId() not in
342
- self.insertedDict for ctf in self.allCtf1.values())
343
- outputStep = self._getFirstJoinStep()
308
+ outputStep = self._getFirstJoinStep()
344
309
 
345
- if newCtf:
346
- fDeps = self._insertNewSelectionSteps(self.insertedDict,
347
- newIds)
348
- if outputStep is not None:
349
- outputStep.addPrerequisites(*fDeps)
350
- self.updateSteps()
310
+ if self.isContinued() and not self.insertedIds: # For "Continue" action and the first round
311
+ doneIds, _, _, _ = self._getAllDoneIds()
312
+ skipIds = list(set(newIds).intersection(set(doneIds)))
313
+ newIds = list(set(newIds).difference(set(doneIds)))
314
+ self.info("Skipping CTFs with ID: %s, seems to be done" % skipIds)
315
+ self.insertedIds = doneIds # During the first round of "Continue" action it has to be filled
316
+
317
+ if newIds:
318
+ fDeps = self._insertNewCtfsSteps(newIds)
319
+ if outputStep is not None:
320
+ outputStep.addPrerequisites(*fDeps)
321
+ self.updateSteps()
351
322
 
352
323
 
353
324
  def _checkNewOutput(self):
354
325
  """ Check for already selected CTF and update the output set. """
355
-
356
- # Load previously done items (from text file)
357
- doneListDiscarded = self._readCertainDoneList(DISCARDED)
358
- doneListAccepted = self._readCertainDoneList(ACCEPTED)
359
-
326
+ _, _, doneListAccepted, doneListDiscarded = self._getAllDoneIds()
360
327
  # Check for newly done items
361
- ctfListIdAccepted = self._readtCtfId(True)
362
- ctfListIdDiscarded = self._readtCtfId(False)
363
-
364
- newDoneAccepted = [ctfId for ctfId in ctfListIdAccepted
328
+ acceptedIds = list(self.acceptedIds)
329
+ discardedIds = list(self.discardedIds)
330
+ newDoneAccepted = [ctfId for ctfId in acceptedIds
365
331
  if ctfId not in doneListAccepted]
366
- newDoneDiscarded = [ctfId for ctfId in ctfListIdDiscarded
332
+ newDoneDiscarded = [ctfId for ctfId in discardedIds
367
333
  if ctfId not in doneListDiscarded]
368
334
 
369
335
  firstTimeAccepted = len(doneListAccepted) == 0
@@ -374,14 +340,21 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
374
340
  # We have finished when there is not more input ctf (stream closed)
375
341
  # and the number of processed ctf is equal to the number of inputs
376
342
  if self.calculateConsensus:
377
- maxCtfSize = min(len(self.allCtf1), len(self.allCtf2))
343
+ inputCtfSet = self._loadInputCtfSet(self.ctfFn1)
344
+ inputCtfSet2 = self._loadInputCtfSet(self.ctfFn2)
345
+ maxCtfSize = min(inputCtfSet.getSize(), inputCtfSet2.getSize())
378
346
  else:
379
- maxCtfSize = len(self.allCtf1)
347
+ maxCtfSize = self._loadInputCtfSet(self.ctfFn1).getSize()
380
348
 
381
349
  self.finished = (self.isStreamClosed and allDone == maxCtfSize)
382
350
 
383
351
  streamMode = Set.STREAM_CLOSED if self.finished else Set.STREAM_OPEN
384
352
 
353
+ if not self.finished and (not newDoneDiscarded and not newDoneAccepted):
354
+ # If we are not finished and no new output have been produced
355
+ # it does not make sense to proceed and updated the outputs
356
+ # so we exit from the function here
357
+ return
385
358
 
386
359
  def readOrCreateOutputs(doneList, newDone, label=''):
387
360
  if len(doneList) > 0 or len(newDone) > 0:
@@ -399,28 +372,20 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
399
372
  newDoneDiscarded,
400
373
  DISCARDED)
401
374
 
402
- if not self.finished and not newDoneDiscarded and not newDoneAccepted:
403
- # If we are not finished and no new output have been produced
404
- # it does not make sense to proceed and updated the outputs
405
- # so we exit from the function here
406
- return
407
-
408
375
  def updateRelationsAndClose(cSet, mSet, first, label=''):
409
376
 
410
377
  if os.path.exists(self._getPath('ctfs'+label+'.sqlite')):
411
378
 
412
- micsAttrName = 'outputMicrographs'+label
379
+ micsAttrName = OUTPUT_MICS+label
413
380
  self._updateOutputSet(micsAttrName, mSet, streamMode)
414
- # Set micrograph as pointer to protocol to prevent pointee end up as another attribute (String, Booelan,...)
381
+ # Set micrograph as pointer to protocol to prevent pointer end up as another attribute (String, Booelan,...)
415
382
  # that happens somewhere while scheduling.
416
383
  cSet.setMicrographs(Pointer(self, extended=micsAttrName))
417
384
 
418
- self._updateOutputSet('outputCTF'+label, cSet, streamMode)
385
+ self._updateOutputSet(OUTPUT_CTF+label, cSet, streamMode)
419
386
 
420
387
  if first:
421
- self._defineTransformRelation(self.inputCTF.get().getMicrographs(),
422
- mSet)
423
- # self._defineTransformRelation(cSet, mSet)
388
+ self._defineTransformRelation(self.inputCTF.get().getMicrographs(), mSet)
424
389
  self._defineTransformRelation(self.inputCTF, cSet)
425
390
  self._defineCtfRelation(mSet, cSet)
426
391
 
@@ -436,6 +401,8 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
436
401
  if outputStep and outputStep.isWaiting():
437
402
  outputStep.setStatus(STATUS_NEW)
438
403
 
404
+ self._store() # Update the summary dictionary
405
+
439
406
 
440
407
  def fillOutput(self, ctfSet, micSet, newDone, label):
441
408
  if newDone:
@@ -446,8 +413,8 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
446
413
  ctf = inputCtfSet[ctfId].clone()
447
414
  mic = ctf.getMicrograph().clone()
448
415
 
449
- ctf.setEnabled(self._getEnable(ctfId))
450
- mic.setEnabled(self._getEnable(ctfId))
416
+ ctf.setEnabled(self._getEnable(ctfId, label))
417
+ mic.setEnabled(self._getEnable(ctfId, label))
451
418
 
452
419
  if self.calculateConsensus:
453
420
  ctf2 = inputCtfSet2[ctfId]
@@ -502,7 +469,6 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
502
469
 
503
470
  ctfSet.append(ctf)
504
471
  micSet.append(mic)
505
- self._writeCertainDoneList(ctfId, label)
506
472
 
507
473
  inputCtfSet.close()
508
474
  if self.calculateConsensus:
@@ -573,18 +539,17 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
573
539
  setattr(self, "rejBy"+k, Integer(0))
574
540
  self._store()
575
541
 
576
- def selectCtfStep(self, ctfId):
577
- # Depending on the flags selected by the user, we set the values of
578
- # the params to compare with
579
-
580
- doneFn = self._getCTFDone(ctfId)
542
+ def selectCtfStep(self, ctfIds):
543
+ # Depending on the flags selected by the user, we set the values of the params to compare with
544
+ minDef, maxDef = self._getDefociValues()
545
+ maxAstig = self._getMaxAstisgmatism()
546
+ maxAstigPer = self._getMaxAstigmatismPer()
547
+ minResol = self._getMinResol()
581
548
 
582
- if self.isContinued() and self._isCTFDone(ctfId):
583
- self.info("Skipping CTF with ID: %s, seems to be done" % ctfId)
584
- return
549
+ inputCtfSet = self._loadInputCtfSet(self.ctfFn1)
585
550
 
586
- # Clean old finished files
587
- pwutils.cleanPath(doneFn)
551
+ if self.calculateConsensus:
552
+ inputCtfSet2 = self._loadInputCtfSet(self.ctfFn2)
588
553
 
589
554
  def compareValue(ctf, label, comp, crit):
590
555
  """ Returns True if the ctf.label NOT complain the crit by comp
@@ -603,125 +568,112 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
603
568
  self.discDict[label] += 1
604
569
  return discard
605
570
 
606
- minDef, maxDef = self._getDefociValues()
607
- maxAstig = self._getMaxAstisgmatism()
608
- maxAstigPer = self._getMaxAstigmatismPer()
609
- minResol = self._getMinResol()
571
+ for ctfId in ctfIds:
572
+ ctf = inputCtfSet.getItem("id", ctfId).clone()
610
573
 
611
- ctf = self.allCtf1.get(ctfId)
574
+ defocusU = ctf.getDefocusU()
575
+ defocusV = ctf.getDefocusV()
576
+ astigm = abs(defocusU - defocusV)
577
+ astigmPer = abs(defocusU - defocusV)/((defocusU+defocusV)/2)
578
+ resol = self._getCtfResol(ctf)
612
579
 
613
- defocusU = ctf.getDefocusU()
614
- defocusV = ctf.getDefocusV()
615
- astigm = abs(defocusU - defocusV)
616
- astigmPer = abs(defocusU - defocusV)/((defocusU+defocusV)/2)
617
- resol = self._getCtfResol(ctf)
580
+ defRangeCrit = (defocusU < minDef or defocusU > maxDef or
581
+ defocusV < minDef or defocusV > maxDef)
582
+ if defRangeCrit:
583
+ self.discDict['defocus'] += 1
618
584
 
619
- defRangeCrit = (defocusU < minDef or defocusU > maxDef or
620
- defocusV < minDef or defocusV > maxDef)
621
- if defRangeCrit:
622
- self.discDict['defocus'] += 1
585
+ astigCrit = astigm > maxAstig
586
+ if astigCrit:
587
+ self.discDict['astigmatism'] += 1
623
588
 
624
- astigCrit = astigm > maxAstig
625
- if astigCrit:
626
- self.discDict['astigmatism'] += 1
589
+ astigPer = (astigmPer > maxAstigPer)
590
+ if astigPer:
591
+ self.discDict['astigmatismPer'] += 1
627
592
 
628
- astigPer = (astigmPer > maxAstigPer)
629
- if astigPer:
630
- self.discDict['astigmatismPer'] += 1
593
+ singleResolCrit = resol > minResol
594
+ if singleResolCrit:
595
+ self.discDict['singleResolution'] += 1
631
596
 
632
- singleResolCrit = resol > minResol
633
- if singleResolCrit:
634
- self.discDict['singleResolution'] += 1
597
+ firstCondition = defRangeCrit or astigCrit or singleResolCrit or astigPer
635
598
 
636
- firstCondition = defRangeCrit or astigCrit or singleResolCrit or astigPer
599
+ consResolCrit = False
637
600
 
638
- consResolCrit = False
639
- if self.calculateConsensus:
640
- # FIXME: this conditional is to avoid an error, but it shouldn't happen!!!
641
- if ctfId in self._freqResol:
642
- consResolCrit = self.minConsResol < self._freqResol[ctfId]
601
+ if self.calculateConsensus:
602
+ ctf2 = inputCtfSet2.getItem("id", ctfId)
603
+ freqResolConsensus = self.calculateConsensusResolution(ctfId, ctf, ctf2)
604
+ consResolCrit = self.minConsResol < freqResolConsensus
643
605
  if consResolCrit:
644
606
  self.discDict['consensusResolution'] += 1
645
- else:
646
- consResolCrit = True
647
- self.discDict['consensusResolution'] += 1
648
- self._freqResol[ctfId] = 9999
649
-
650
- secondCondition = False
651
- if self.useCritXmipp:
652
- firstZero = self._getCritFirstZero()
653
- minFirstZero, maxFirstZero = self._getCritFirstZeroRatio()
654
- corr = self._getCritCorr()
655
- iceness = self._getIceness()
656
- ctfMargin = self._getCritCtfMargin()
657
- minNonAstigmatic, maxNonAstigmatic = \
658
- self._getCritNonAstigmaticValidity()
659
-
660
- if self.xmippCTF == INPUT1:
661
- ctfX = ctf
662
- else:
663
- ctfX = self.allCtf2.get(ctfId)
664
-
665
-
666
- secondCondition = (
667
- compareValue(ctfX, '_xmipp_ctfCritFirstZero', 'lt', firstZero) or
668
- compareValue(ctfX, '_xmipp_ctfCritfirstZeroRatio', 'lt', minFirstZero) or
669
- compareValue(ctfX, '_xmipp_ctfCritfirstZeroRatio', 'bt', maxFirstZero) or
670
- compareValue(ctfX, '_xmipp_ctfCritCorr13', 'lt', corr) or
671
- compareValue(ctfX, '_xmipp_ctfCritIceness', 'bt', iceness) or
672
- compareValue(ctfX, '_xmipp_ctfCritCtfMargin', 'lt', ctfMargin) or
673
- compareValue(ctfX, '_xmipp_ctfCritNonAstigmaticValidty', 'lt', minNonAstigmatic) or
674
- compareValue(ctfX, '_xmipp_ctfCritNonAstigmaticValidty', 'bt', maxNonAstigmatic))
675
-
676
- """ Write to a text file the items that have been done. """
677
- if firstCondition or consResolCrit or secondCondition:
678
- fn = self._getCtfSelecFileDiscarded()
679
- with open(fn, 'a') as f:
680
- f.write('%d F\n' % ctf.getObjId())
681
- else:
682
- if (ctf.isEnabled()):
683
- fn = self._getCtfSelecFileAccepted()
684
- with open(fn, 'a') as f:
685
- f.write('%d T\n' % ctf.getObjId())
686
- else:
687
- fn = self._getCtfSelecFileAccepted()
688
- with open(fn, 'a') as f:
689
- f.write('%d F\n' % ctf.getObjId())
690
-
691
- for k, v in self.discDict.items():
692
- setattr(self, "rejBy"+k, Integer(v))
693
-
694
- self._store()
695
- # Mark this ctf as finished
696
- open(doneFn, 'w').close()
697
-
698
607
 
699
- def _readDoneList(self):
700
- """ Read from a file the id's of the items that have been done. """
701
- doneFile = self._getAllDone()
702
- doneList = []
703
- # Check what items have been previously done
704
- if os.path.exists(doneFile):
705
- with open(doneFile) as f:
706
- doneList += [int(line.strip()) for line in f]
707
- return doneList
608
+ self._freqResol[ctfId] = freqResolConsensus
708
609
 
709
- def _getAllDone(self):
710
- return self._getExtraPath('DONE_all.TXT')
610
+ secondCondition = False
611
+ if self.useCritXmipp:
612
+ firstZero = self._getCritFirstZero()
613
+ minFirstZero, maxFirstZero = self._getCritFirstZeroRatio()
614
+ corr = self._getCritCorr()
615
+ iceness = self._getIceness()
616
+ ctfMargin = self._getCritCtfMargin()
617
+ minNonAstigmatic, maxNonAstigmatic = \
618
+ self._getCritNonAstigmaticValidity()
711
619
 
712
- def _writeDoneList(self, idList):
713
- """ Write to a text file the items that have been done. """
714
- with open(self._getAllDone(), 'a') as f:
715
- for id in idList:
716
- f.write('%d\n' % id)
620
+ if self.xmippCTF == INPUT1:
621
+ ctfX = ctf
622
+ else:
623
+ ctfX = ctf2
624
+
625
+ secondCondition = (
626
+ compareValue(ctfX, '_xmipp_ctfCritFirstZero', 'lt', firstZero) or
627
+ compareValue(ctfX, '_xmipp_ctfCritfirstZeroRatio', 'lt', minFirstZero) or
628
+ compareValue(ctfX, '_xmipp_ctfCritfirstZeroRatio', 'bt', maxFirstZero) or
629
+ compareValue(ctfX, '_xmipp_ctfCritCorr13', 'lt', corr) or
630
+ compareValue(ctfX, '_xmipp_ctfCritIceness', 'bt', iceness) or
631
+ compareValue(ctfX, '_xmipp_ctfCritCtfMargin', 'lt', ctfMargin) or
632
+ compareValue(ctfX, '_xmipp_ctfCritNonAstigmaticValidty', 'lt', minNonAstigmatic) or
633
+ compareValue(ctfX, '_xmipp_ctfCritNonAstigmaticValidty', 'bt', maxNonAstigmatic))
634
+
635
+ """ Write to a text file the items that have been done. """
636
+ if firstCondition or consResolCrit or secondCondition:
637
+ self.discardedIds[ctfId] = 'F'
638
+ else:
639
+ if (ctf.isEnabled()):
640
+ self.acceptedIds[ctfId] = 'T'
641
+ else:
642
+ self.acceptedIds[ctfId] = 'F'
717
643
 
718
- def _isCTFDone(self, id):
719
- """ A mic is done if the marker file exists. """
720
- return os.path.exists(self._getCTFDone(id))
644
+ for k, v in self.discDict.items():
645
+ setattr(self, "rejBy"+k, Integer(v))
721
646
 
722
- def _getCTFDone(self, id):
723
- """ Return the file that is used as a flag of termination. """
724
- return self._getExtraPath('DONE', 'ctf_%06d.TXT' % id)
647
+ def calculateConsensusResolution(self, ctfId, ctf1, ctf2):
648
+ md1 = emlib.MetaData()
649
+ md2 = emlib.MetaData()
650
+ try:
651
+ self._ctfToMd(ctf1, md1)
652
+ self._ctfToMd(ctf2, md2)
653
+ freqResol = emlib.errorMaxFreqCTFs2D(md1, md2)
654
+ except TypeError as exc:
655
+ print("Error reading ctf for id:%s. %s" % (ctfId, exc))
656
+ freqResol = 9999
657
+
658
+ return freqResol
659
+
660
+ def _getAllDoneIds(self):
661
+ doneIds = []
662
+ acceptedIds = []
663
+ discardedIds = []
664
+ sizeOutput = 0
665
+
666
+ if hasattr(self, OUTPUT_CTF):
667
+ sizeOutput += self.outputCTF.getSize()
668
+ acceptedIds.extend(list(self.outputCTF.getIdSet()))
669
+ doneIds.extend(acceptedIds)
670
+
671
+ if hasattr(self, OUTPUT_CTF_DISCARDED):
672
+ sizeOutput += self.outputCTFDiscarded.getSize()
673
+ discardedIds.extend(list(self.outputCTFDiscarded.getIdSet()))
674
+ doneIds.extend(discardedIds)
675
+
676
+ return doneIds, sizeOutput, acceptedIds, discardedIds
725
677
 
726
678
  def _citations(self):
727
679
  return ['Marabini2014a']
@@ -764,13 +716,13 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
764
716
  addDiscardedStr('astigmatismPer')))
765
717
 
766
718
  if self.useResolution:
767
- message.append(" - _Resolution_. Threshold: %.0f %s"
719
+ message.append(" - _Resolution_. Threshold: %.2f %s"
768
720
  % (self.resolution,
769
721
  addDiscardedStr('singleResolution')))
770
722
 
771
723
  if self.useCritXmipp:
772
724
  message.append("*Xmipp criteria*:")
773
- message.append(" - _First zero_. Threshold: %.0f %s"
725
+ message.append(" - _First zero_. Threshold: %.2f %s"
774
726
  % (self.critFirstZero,
775
727
  addDiscardedStr('_xmipp_ctfCritFirstZero')))
776
728
  message.append(" - _First zero astigmatism_. Range: %.2f - %.2f %s"
@@ -804,7 +756,7 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
804
756
  return infoStr
805
757
 
806
758
  message.append("*CTF consensus*:")
807
- message.append(" - _Consensus resolution. Threshold_: %.0f %s"
759
+ message.append(" - _Consensus resolution. Threshold_: %.2f %s"
808
760
  % (self.minConsResol,
809
761
  addDiscardedStr('consensusResolution')))
810
762
  message.append(" > _Primary CTF_: %s"
@@ -849,55 +801,16 @@ class XmippProtCTFConsensus(ProtCTFMicrographs):
849
801
  else:
850
802
  return 0
851
803
 
852
- def _readCertainDoneList(self, label):
853
- """ Read from a text file the id's of the items
854
- that have been done. """
855
- doneFile = self._getCertainDone(label)
856
- doneList = []
857
- # Check what items have been previously done
858
- if os.path.exists(doneFile):
859
- with open(doneFile) as f:
860
- doneList += [int(line.strip()) for line in f]
861
- return doneList
862
-
863
- def _writeCertainDoneList(self, ctfId, label):
864
- """ Write to a text file the items that have been done. """
865
- doneFile = self._getCertainDone(label)
866
- with open(doneFile, 'a') as f:
867
- f.write('%d\n' % ctfId)
868
-
869
- def _getCertainDone(self, label):
870
- return self._getExtraPath('DONE_'+label+'.TXT')
871
-
872
- def _getCtfSelecFileAccepted(self):
873
- return self._getExtraPath('selection-ctf-accepted.txt')
874
-
875
- def _getCtfSelecFileDiscarded(self):
876
- return self._getExtraPath('selection-ctf-discarded.txt')
877
-
878
- def _readtCtfId(self, accepted):
879
- if accepted:
880
- fn = self._getCtfSelecFileAccepted()
804
+ def _getEnable(self, ctfId, label):
805
+ if label == ACCEPTED:
806
+ enableValue = self.acceptedIds[ctfId]
807
+ else:
808
+ enableValue = self.discardedIds[ctfId]
809
+
810
+ if enableValue == 'T':
811
+ return True
881
812
  else:
882
- fn = self._getCtfSelecFileDiscarded()
883
- ctfList = []
884
- # Check what items have been previously done
885
- if os.path.exists(fn):
886
- with open(fn) as f:
887
- ctfList += [int(line.strip().split()[0]) for line in f]
888
- return ctfList
889
-
890
- def _getEnable(self, ctfId):
891
- fn = self._getCtfSelecFileAccepted()
892
- # Check what items have been previously done
893
- if os.path.exists(fn):
894
- with open(fn) as f:
895
- for line in f:
896
- if ctfId == int(line.strip().split()[0]):
897
- if line.strip().split()[1] == 'T':
898
- return True
899
- else:
900
- return False
813
+ return False
901
814
 
902
815
  def _loadInputCtfSet(self, ctfFn):
903
816
  self.debug("Loading input db: %s" % ctfFn)