scipion-pyworkflow 3.7.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.
Files changed (140) hide show
  1. pyworkflow/__init__.py +33 -0
  2. pyworkflow/apps/__init__.py +29 -0
  3. pyworkflow/apps/pw_manager.py +37 -0
  4. pyworkflow/apps/pw_plot.py +51 -0
  5. pyworkflow/apps/pw_project.py +113 -0
  6. pyworkflow/apps/pw_protocol_list.py +143 -0
  7. pyworkflow/apps/pw_protocol_run.py +51 -0
  8. pyworkflow/apps/pw_run_tests.py +267 -0
  9. pyworkflow/apps/pw_schedule_run.py +322 -0
  10. pyworkflow/apps/pw_sleep.py +37 -0
  11. pyworkflow/apps/pw_sync_data.py +439 -0
  12. pyworkflow/apps/pw_viewer.py +78 -0
  13. pyworkflow/config.py +536 -0
  14. pyworkflow/constants.py +212 -0
  15. pyworkflow/exceptions.py +18 -0
  16. pyworkflow/gui/__init__.py +36 -0
  17. pyworkflow/gui/browser.py +726 -0
  18. pyworkflow/gui/canvas.py +1190 -0
  19. pyworkflow/gui/dialog.py +976 -0
  20. pyworkflow/gui/form.py +2627 -0
  21. pyworkflow/gui/graph.py +247 -0
  22. pyworkflow/gui/graph_layout.py +271 -0
  23. pyworkflow/gui/gui.py +566 -0
  24. pyworkflow/gui/matplotlib_image.py +233 -0
  25. pyworkflow/gui/plotter.py +247 -0
  26. pyworkflow/gui/project/__init__.py +25 -0
  27. pyworkflow/gui/project/base.py +192 -0
  28. pyworkflow/gui/project/constants.py +139 -0
  29. pyworkflow/gui/project/labels.py +205 -0
  30. pyworkflow/gui/project/project.py +484 -0
  31. pyworkflow/gui/project/searchprotocol.py +154 -0
  32. pyworkflow/gui/project/searchrun.py +181 -0
  33. pyworkflow/gui/project/steps.py +166 -0
  34. pyworkflow/gui/project/utils.py +332 -0
  35. pyworkflow/gui/project/variables.py +179 -0
  36. pyworkflow/gui/project/viewdata.py +472 -0
  37. pyworkflow/gui/project/viewprojects.py +510 -0
  38. pyworkflow/gui/project/viewprotocols.py +2093 -0
  39. pyworkflow/gui/project/viewprotocols_extra.py +560 -0
  40. pyworkflow/gui/text.py +771 -0
  41. pyworkflow/gui/tooltip.py +185 -0
  42. pyworkflow/gui/tree.py +684 -0
  43. pyworkflow/gui/widgets.py +307 -0
  44. pyworkflow/mapper/__init__.py +26 -0
  45. pyworkflow/mapper/mapper.py +222 -0
  46. pyworkflow/mapper/sqlite.py +1578 -0
  47. pyworkflow/mapper/sqlite_db.py +145 -0
  48. pyworkflow/object.py +1512 -0
  49. pyworkflow/plugin.py +712 -0
  50. pyworkflow/project/__init__.py +31 -0
  51. pyworkflow/project/config.py +451 -0
  52. pyworkflow/project/manager.py +179 -0
  53. pyworkflow/project/project.py +1990 -0
  54. pyworkflow/project/scripts/clean_projects.py +77 -0
  55. pyworkflow/project/scripts/config.py +92 -0
  56. pyworkflow/project/scripts/create.py +77 -0
  57. pyworkflow/project/scripts/edit_workflow.py +90 -0
  58. pyworkflow/project/scripts/fix_links.py +39 -0
  59. pyworkflow/project/scripts/load.py +87 -0
  60. pyworkflow/project/scripts/refresh.py +83 -0
  61. pyworkflow/project/scripts/schedule.py +111 -0
  62. pyworkflow/project/scripts/stack2volume.py +41 -0
  63. pyworkflow/project/scripts/stop.py +81 -0
  64. pyworkflow/protocol/__init__.py +38 -0
  65. pyworkflow/protocol/bibtex.py +48 -0
  66. pyworkflow/protocol/constants.py +86 -0
  67. pyworkflow/protocol/executor.py +334 -0
  68. pyworkflow/protocol/hosts.py +313 -0
  69. pyworkflow/protocol/launch.py +270 -0
  70. pyworkflow/protocol/package.py +42 -0
  71. pyworkflow/protocol/params.py +744 -0
  72. pyworkflow/protocol/protocol.py +2554 -0
  73. pyworkflow/resources/Imagej.png +0 -0
  74. pyworkflow/resources/chimera.png +0 -0
  75. pyworkflow/resources/fa-exclamation-triangle_alert.png +0 -0
  76. pyworkflow/resources/fa-info-circle_alert.png +0 -0
  77. pyworkflow/resources/fa-search.png +0 -0
  78. pyworkflow/resources/fa-times-circle_alert.png +0 -0
  79. pyworkflow/resources/file_vol.png +0 -0
  80. pyworkflow/resources/loading.gif +0 -0
  81. pyworkflow/resources/no-image128.png +0 -0
  82. pyworkflow/resources/scipion_bn.png +0 -0
  83. pyworkflow/resources/scipion_icon.png +0 -0
  84. pyworkflow/resources/scipion_icon.svg +397 -0
  85. pyworkflow/resources/scipion_icon_proj.png +0 -0
  86. pyworkflow/resources/scipion_icon_projs.png +0 -0
  87. pyworkflow/resources/scipion_icon_prot.png +0 -0
  88. pyworkflow/resources/scipion_logo.png +0 -0
  89. pyworkflow/resources/scipion_logo_normal.png +0 -0
  90. pyworkflow/resources/scipion_logo_small.png +0 -0
  91. pyworkflow/resources/sprites.png +0 -0
  92. pyworkflow/resources/sprites.xcf +0 -0
  93. pyworkflow/resources/wait.gif +0 -0
  94. pyworkflow/template.py +322 -0
  95. pyworkflow/tests/__init__.py +29 -0
  96. pyworkflow/tests/test_utils.py +25 -0
  97. pyworkflow/tests/tests.py +341 -0
  98. pyworkflow/utils/__init__.py +38 -0
  99. pyworkflow/utils/dataset.py +414 -0
  100. pyworkflow/utils/echo.py +104 -0
  101. pyworkflow/utils/graph.py +196 -0
  102. pyworkflow/utils/log.py +284 -0
  103. pyworkflow/utils/path.py +527 -0
  104. pyworkflow/utils/process.py +132 -0
  105. pyworkflow/utils/profiler.py +92 -0
  106. pyworkflow/utils/progressbar.py +154 -0
  107. pyworkflow/utils/properties.py +627 -0
  108. pyworkflow/utils/reflection.py +129 -0
  109. pyworkflow/utils/utils.py +877 -0
  110. pyworkflow/utils/which.py +229 -0
  111. pyworkflow/viewer.py +328 -0
  112. pyworkflow/webservices/__init__.py +8 -0
  113. pyworkflow/webservices/config.py +11 -0
  114. pyworkflow/webservices/notifier.py +162 -0
  115. pyworkflow/webservices/repository.py +59 -0
  116. pyworkflow/webservices/workflowhub.py +74 -0
  117. pyworkflow/wizard.py +64 -0
  118. pyworkflowtests/__init__.py +51 -0
  119. pyworkflowtests/bibtex.py +51 -0
  120. pyworkflowtests/objects.py +830 -0
  121. pyworkflowtests/protocols.py +154 -0
  122. pyworkflowtests/tests/__init__.py +0 -0
  123. pyworkflowtests/tests/test_canvas.py +72 -0
  124. pyworkflowtests/tests/test_domain.py +45 -0
  125. pyworkflowtests/tests/test_logs.py +74 -0
  126. pyworkflowtests/tests/test_mappers.py +392 -0
  127. pyworkflowtests/tests/test_object.py +507 -0
  128. pyworkflowtests/tests/test_project.py +42 -0
  129. pyworkflowtests/tests/test_protocol_execution.py +72 -0
  130. pyworkflowtests/tests/test_protocol_export.py +78 -0
  131. pyworkflowtests/tests/test_protocol_output.py +158 -0
  132. pyworkflowtests/tests/test_streaming.py +47 -0
  133. pyworkflowtests/tests/test_utils.py +210 -0
  134. scipion_pyworkflow-3.7.0.dist-info/LICENSE.txt +674 -0
  135. scipion_pyworkflow-3.7.0.dist-info/METADATA +107 -0
  136. scipion_pyworkflow-3.7.0.dist-info/RECORD +140 -0
  137. scipion_pyworkflow-3.7.0.dist-info/WHEEL +5 -0
  138. scipion_pyworkflow-3.7.0.dist-info/dependency_links.txt +1 -0
  139. scipion_pyworkflow-3.7.0.dist-info/entry_points.txt +5 -0
  140. scipion_pyworkflow-3.7.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,507 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # **************************************************************************
4
+ # *
5
+ # * Authors: J.M. De la Rosa Trevin (delarosatrevin@scilifelab.se) [1]
6
+ # *
7
+ # * [1] SciLifeLab, Stockholm University
8
+ # *
9
+ # * This program is free software: you can redistribute it and/or modify
10
+ # * it under the terms of the GNU General Public License as published by
11
+ # * the Free Software Foundation, either version 3 of the License, or
12
+ # * (at your option) any later version.
13
+ # *
14
+ # * This program is distributed in the hope that it will be useful,
15
+ # * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # * GNU General Public License for more details.
18
+ # *
19
+ # * You should have received a copy of the GNU General Public License
20
+ # * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
+ # *
22
+ # * All comments concerning this program package may be sent to the
23
+ # * e-mail address 'scipion@cnb.csic.es'
24
+ # *
25
+ # **************************************************************************
26
+ import datetime as dt
27
+ try:
28
+ from datetime import UTC # python 3.11+
29
+ except ImportError:
30
+ UTC = dt.timezone.utc
31
+ import os
32
+ from logging import DEBUG, lastResort
33
+ from time import sleep
34
+
35
+ import pyworkflow.object as pwobj
36
+ import pyworkflow.tests as pwtests
37
+ from pyworkflow.mapper.sqlite import ID, CREATION
38
+ from ..objects import (Complex, MockSetOfImages, MockImage, MockObject,
39
+ MockAcquisition, MockMicrograph)
40
+
41
+ IMAGES_STK = "images.stk"
42
+
43
+ NUMERIC_ATRIBUTE_NAME = "1"
44
+
45
+ NUMERIC_ATTRIBUTE_VALUE = "numeric_attribute"
46
+
47
+
48
+ class ListContainer(pwobj.Object):
49
+ def __init__(self, **args):
50
+ pwobj.Object.__init__(self, **args)
51
+ self.csv = pwobj.CsvList()
52
+
53
+
54
+ class TestObject(pwtests.BaseTest):
55
+ @classmethod
56
+ def setUpClass(cls):
57
+ pwtests.setupTestOutput(cls)
58
+
59
+ def test_ObjectsDict(self):
60
+ # Validate that the object dict is populated correctly
61
+ basicObjNames = [
62
+ 'Scalar', 'Integer', 'Float', 'String', 'Pointer', 'Boolean',
63
+ 'OrderedObject', 'List', 'CsvList', 'PointerList', 'Set'
64
+ ]
65
+ self.assertTrue(all(name in pwobj.OBJECTS_DICT
66
+ for name in basicObjNames))
67
+
68
+ def test_Object(self):
69
+ value = 2
70
+ i = pwobj.Integer(value)
71
+ self.assertEqual(value, i.get())
72
+ # compare objects
73
+ i2 = pwobj.Integer(value)
74
+ self.assertEqual(i, i2)
75
+
76
+ value = 2.
77
+ f = pwobj.Float(value)
78
+ self.assertAlmostEqual(value, f.get())
79
+
80
+ f.multiply(5)
81
+ self.assertAlmostEqual(value*5, f.get())
82
+
83
+ a = pwobj.Integer()
84
+ self.assertEqual(a.hasValue(), False)
85
+ c = Complex.createComplex()
86
+ # Check values are correct
87
+ self.assertEqual(c.imag.get(), Complex.cGold.imag)
88
+ self.assertEqual(c.real.get(), Complex.cGold.real)
89
+
90
+ # Test Boolean logic
91
+ b = pwobj.Boolean(False)
92
+ self.assertTrue(not b.get())
93
+
94
+ b.set('True')
95
+ self.assertTrue(b.get())
96
+
97
+ b = pwobj.Boolean()
98
+ b.set(False)
99
+ self.assertTrue(not b.get())
100
+
101
+ # CsvList should be empty if set to ''
102
+ l = pwobj.CsvList()
103
+ l.set('')
104
+ self.assertEqual(len(l), 0)
105
+
106
+ # Test emptiness
107
+ self.assertIsNotEmpty(b)
108
+
109
+ def testWithPointer(self):
110
+
111
+ obj = pwobj.Integer(10)
112
+
113
+ self.assertFalse(obj.hasPointer(),
114
+ "Default instantiation off Integer has a pointer.")
115
+
116
+ self.assertEqual(obj.get(), 10, "Integer.get(), without pointer fails.")
117
+
118
+ pointee = pwobj.Object()
119
+ setattr(pointee, "value", pwobj.Integer(20))
120
+
121
+ # Set a pointer (not a real case though, but enough here)
122
+ obj.setPointer(pwobj.Pointer(pointee, extended='value'))
123
+
124
+ self.assertEqual(obj.get(), 20, "Integer.get() fails with a pointer.")
125
+
126
+ def test_String(self):
127
+ value = 'thisisastring'
128
+ s = pwobj.String(value)
129
+ self.assertEqual(value, s.get())
130
+ self.assertEqual(s.hasValue(), True)
131
+
132
+ s2 = pwobj.String()
133
+ # None value is considered empty
134
+ self.assertTrue(s2.empty(), "s2 string should be empty if None")
135
+ s2.set(' ')
136
+ # Only spaces is also empty
137
+ self.assertTrue(s2.empty(), "s2 string should be empty if only spaces")
138
+ s2.set('something')
139
+ # No empty after some value
140
+ self.assertFalse(s2.empty(),
141
+ "s2 string should not be empty after value")
142
+
143
+ now = dt.datetime.now()
144
+ s.set(now)
145
+ self.assertEqual(now, s.datetime())
146
+
147
+ # Ranges and values
148
+ s2.set("1 2 3 4")
149
+ self.assertEqual(s2.getListFromValues(caster=float), [1.,2.,3.,4.])
150
+ self.assertEqual(s2.getListFromRange(), [1, 2, 3, 4])
151
+
152
+ # Values ...
153
+ s2.set("2x4, 4, 7")
154
+ self.assertEqual(s2.getListFromValues(), [4, 4, 4, 7])
155
+
156
+ # Values ...
157
+ self.assertEqual(s2.getListFromValues(caster=str), ["2x4", "4", "7"])
158
+
159
+ # Ranges
160
+ s2.set("2-8, 1-2, 7")
161
+ self.assertEqual(s2.getListFromRange(), [2, 3, 4, 5, 6, 7, 8, 1, 2, 7])
162
+
163
+ def test_Pointer(self):
164
+ c = Complex.createComplex()
165
+ p = pwobj.Pointer()
166
+ p.set(c)
167
+ p.setExtended('Name')
168
+ c.Name = pwobj.String('Paquito')
169
+
170
+ self.assertEqual(p.get(), 'Paquito')
171
+ stackFn = IMAGES_STK
172
+ mrcsFn = "images.mrcs"
173
+ fn = self.getOutputPath('test_images.sqlite')
174
+ imgSet = MockSetOfImages(filename=fn)
175
+ imgSet.setSamplingRate(1.0)
176
+ for i in range(10):
177
+ img = MockImage()
178
+ img.setLocation(i+1, stackFn)
179
+ imgSet.append(img)
180
+
181
+ imgSet.write()
182
+
183
+ # Test that image number 7 is correctly retrieved
184
+ # from the set
185
+ img7 = imgSet[7]
186
+ self.assertEqual(img7.getFileName(), stackFn)
187
+
188
+ # Modify some properties of image 7 to test update
189
+ img7.setFileName(mrcsFn)
190
+ img7.setSamplingRate(2.0)
191
+ imgSet.update(img7)
192
+ # Write changes after the image 7 update
193
+ imgSet.write()
194
+
195
+ # Read again the set to be able to retrieve elements
196
+ imgSet = MockSetOfImages(filename=fn)
197
+
198
+ # Validate that image7 was properly updated
199
+ img7 = imgSet[7]
200
+ self.assertEqual(img7.getFileName(), mrcsFn)
201
+
202
+ o = MockObject()
203
+
204
+ o.pointer = pwobj.Pointer()
205
+ o.pointer.set(imgSet)
206
+
207
+ # This is not true anymore and is allowed unless we see is needed
208
+ # The main reason is a boost in performance.
209
+ # o.refC = o.pointer.get()
210
+ # attrNames = [k for k, a in o.getAttributes()]
211
+ # # Check that 'refC' should not appear in attributes
212
+ # # since it is only an "alias" to an existing pointed value
213
+ # self.assertNotIn('refC', attrNames)
214
+
215
+ self.assertFalse(o.pointer.hasExtended(),
216
+ 'o.pointer should not have extended at this point')
217
+
218
+ o.pointer.setExtended(7)
219
+
220
+ self.assertTrue(o.pointer.hasExtended())
221
+ self.assertTrue(o.pointer.hasExtended())
222
+ self.assertEqual(o.pointer.getExtended(), "7")
223
+
224
+ # Check that the Item 7 of the set is properly
225
+ # retrieved by the pointer after setting the extended to 7
226
+ self.assertEqual(imgSet[7].getObjId(), o.pointer.get().getObjId())
227
+
228
+ # Test the keyword arguments of Pointer constructor
229
+ # repeat above tests with new pointer
230
+ ptr = pwobj.Pointer(value=imgSet, extended=7)
231
+ self.assertTrue(ptr.hasExtended())
232
+ self.assertTrue(ptr.hasExtended())
233
+ self.assertEqual(ptr.getExtended(), "7")
234
+
235
+ # Check that the Item 7 of the set is properly
236
+ # retrieved by the pointer after setting the extended to 7
237
+ self.assertEqual(imgSet[7], ptr.get())
238
+
239
+ o2 = pwobj.Object()
240
+ o2.outputImages = imgSet
241
+ ptr2 = pwobj.Pointer()
242
+ ptr2.set(o2)
243
+ # Test nested extended attributes
244
+ ptr2.setExtended('outputImages.7')
245
+ self.assertEqual(imgSet[7], ptr2.get())
246
+
247
+ # Same as ptr2, but setting extended in constructor
248
+ ptr3 = pwobj.Pointer(value=o2, extended='outputImages.7')
249
+ self.assertEqual(imgSet[7], ptr3.get())
250
+
251
+ # Test copy between pointer objects
252
+ ptr4 = pwobj.Pointer()
253
+ ptr4.copy(ptr3)
254
+ self.assertEqual(imgSet[7], ptr4.get())
255
+ self.assertEqual(ptr4.getExtended(), 'outputImages.7')
256
+
257
+ # Test numeric attributes.
258
+ setattr(o2, NUMERIC_ATRIBUTE_NAME, NUMERIC_ATTRIBUTE_VALUE)
259
+ ptr5 = pwobj.Pointer(value=o2, extended=NUMERIC_ATRIBUTE_NAME)
260
+ self.assertEqual(NUMERIC_ATTRIBUTE_VALUE, ptr5.get())
261
+
262
+ def test_Sets(self):
263
+ stackFn = IMAGES_STK
264
+ fn = self.getOutputPath('test_images2.sqlite')
265
+
266
+ imgSet = MockSetOfImages(filename=fn)
267
+
268
+ halfTimeStamp = None
269
+
270
+ for i in range(10):
271
+ img = MockImage()
272
+ img.setLocation(i + 1, stackFn)
273
+ img.setSamplingRate(i % 3)
274
+ imgSet.append(img)
275
+ if i == 4:
276
+ sleep(1)
277
+ halfTimeStamp = dt.datetime.now(UTC).replace(microsecond=0)
278
+ imgSet.write()
279
+
280
+ # Test size is 10
281
+ self.assertSetSize(imgSet, 10)
282
+
283
+ # Test hasChangedSince
284
+ timeStamp = dt.datetime.now()
285
+ self.assertFalse(imgSet.hasChangedSince(timeStamp), "Set.hasChangedSince returns true when it hasn't changed.")
286
+ # Remove 10 seconds
287
+ self.assertTrue(imgSet.hasChangedSince(timeStamp-dt.timedelta(0,10)), "Set.hasChangedSince returns false when it has changed.")
288
+
289
+ # PERFORMANCE functionality
290
+ def checkSetIteration(limit, skipRows=None):
291
+
292
+ expectedId = 1 if skipRows is None else skipRows+1
293
+ index = 0
294
+ for item in imgSet.iterItems(limit=(limit, skipRows)):
295
+ self.assertEqual(item.getIndex(), expectedId+index,
296
+ "Wrong item in set when using limits.")
297
+ index += 1
298
+
299
+ self.assertEqual(index, limit,
300
+ "Number of iterations wrong with limits")
301
+
302
+ # Check iteration with limit
303
+ checkSetIteration(2)
304
+
305
+ # Check iteration with limit and skip rows
306
+ checkSetIteration(3, 2)
307
+
308
+ # Tests unique method
309
+ # Requesting 1 unique value as string
310
+ result = imgSet.getUniqueValues("_samplingRate")
311
+ self.assertEqual(len(result), 3, "Unique values wrong for 1 attribute and 3 value")
312
+
313
+ # Requesting 1 unique value as list
314
+ result = imgSet.getUniqueValues(["_samplingRate"])
315
+ self.assertEqual(len(result), 3, "Unique values wrong for 1 attribute and one value as list")
316
+
317
+ # Requesting several unique values as string
318
+ result = imgSet.getUniqueValues("_index")
319
+ self.assertEqual(len(result), 10, "Unique values wrong for id attribute")
320
+
321
+ # Requesting several unique values with several columns
322
+ result = imgSet.getUniqueValues(["_filename", "_samplingRate"])
323
+ # Here we should have 2 keys containing 2 list
324
+ self.assertEqual(len(result), 2, "Unique values dictionary length wrong")
325
+ self.assertEqual(len(result["_filename"]), 3, "Unique values dict item size wrong")
326
+
327
+ # Requesting unique values with where
328
+ result = imgSet.getUniqueValues("_index",where="_samplingRate = 2")
329
+ # Here we should have 2 values
330
+ self.assertEqual(len(result), 3, "Unique values with filter not working")
331
+
332
+ # Request id list
333
+ result = imgSet.getUniqueValues(ID)
334
+ # Here we should have 10 values
335
+ self.assertEqual(len(result), 10, "Unique values with ID")
336
+
337
+ # Use creation timestamp
338
+ # Request id list
339
+ result = imgSet.getUniqueValues(ID, where="%s>=%s" % (CREATION, imgSet.fmtDate(halfTimeStamp)))
340
+ self.assertEqual(len(result), 5, "Unique values after a time stamp does not work")
341
+
342
+ # Test getIdSet
343
+ ids = imgSet.getIdSet()
344
+ self.assertIsInstance(ids, set, "getIdSet does not return a set")
345
+ self.assertIsInstance(next(iter(ids)), int, "getIdSet items are not integer")
346
+ self.assertEqual(len(ids), 10, "getIdSet does not return 10 items")
347
+
348
+ # Request item by id
349
+ item = imgSet[1]
350
+ self.assertEqual(item.getObjId(), 1, "Item accessed by [] and id does not work")
351
+
352
+ # Request item by field
353
+ item = imgSet.getItem("id", 2)
354
+ self.assertEqual(item.getObjId(), 2, "Item accessed field id does not work")
355
+
356
+ # Test load properties queries
357
+ from pyworkflow.mapper.sqlite_db import logger
358
+ logger.setLevel(DEBUG)
359
+ lastResort.setLevel(DEBUG)
360
+ imgSetVerbose = MockSetOfImages(filename=fn)
361
+ imgSetVerbose.loadAllProperties()
362
+
363
+ # Compare sets are "equal"
364
+ self.compareSetProperties(imgSet, imgSetVerbose, ignore=[])
365
+
366
+
367
+ def test_copyAttributes(self):
368
+ """ Check that after copyAttributes, the values
369
+ were properly copied.
370
+ """
371
+ c1 = Complex(imag=10., real=11.)
372
+ c2 = Complex(imag=0., real=1.0001)
373
+
374
+ # Float values are different, should not be equal
375
+ self.assertFalse(c1.equalAttributes(c2))
376
+ c2.copyAttributes(c1, 'imag', 'real')
377
+
378
+ self.assertTrue(c1.equalAttributes(c2),
379
+ 'Complex c1 and c2 have not equal attributes'
380
+ '\nc1: %s\nc2: %s\n' % (c1, c2))
381
+
382
+ c1.score = pwobj.Float(1.)
383
+
384
+ # If we copyAttributes again, score dynamic attribute should
385
+ # be set in c2
386
+ c2.copyAttributes(c1, 'score')
387
+ self.assertTrue(hasattr(c2, 'score'))
388
+
389
+ def test_equalAttributes(self):
390
+ """ Check that equal attributes function behaves well
391
+ to compare floats with a given precision.
392
+ """
393
+ c1 = Complex(imag=0., real=1.)
394
+ c2 = Complex(imag=0., real=1.0001)
395
+
396
+ # Since Float precision is 0.001, now c1 and c2
397
+ # should have equal attributes
398
+ self.assertTrue(c1.equalAttributes(c2))
399
+ # Now if we set a more restrictive precision
400
+ # c1 and c2 are not longer equals
401
+ pwobj.Float.setPrecision(0.0000001)
402
+ self.assertFalse(c1.equalAttributes(c2))
403
+
404
+ def test_formatString(self):
405
+ """ Test that Scalar objects behave well
406
+ when using string formatting such as: %f or %d
407
+ """
408
+ i = pwobj.Integer(10)
409
+ f = pwobj.Float(3.345)
410
+
411
+ s1 = "i = %d, f = %0.3f" % (i, f)
412
+
413
+ self.assertEqual(s1, "i = 10, f = 3.345")
414
+
415
+ def test_getObjDict(self):
416
+ """ Test retrieving an object dictionary with its attribute values."""
417
+ acq1 = MockAcquisition(magnification=50000,
418
+ voltage=200,
419
+ sphericalAberration=2.7,
420
+ dosePerFrame=1)
421
+ m1 = MockMicrograph(
422
+ 'my_movie.mrc', objId=1, objLabel='test micrograph',
423
+ objComment='Testing store and retrieve from dict.')
424
+ m1.setSamplingRate(1.6)
425
+ m1.setAcquisition(acq1)
426
+ m1Dict = m1.getObjDict(includeBasic=True)
427
+
428
+ goldDict1 = dict([
429
+ ('object.id', 1),
430
+ ('object.label', 'test micrograph'),
431
+ ('object.comment', 'Testing store and retrieve from dict.'),
432
+ ('_index', 0),
433
+ ('_filename', 'my_movie.mrc'),
434
+ ('_samplingRate', 1.6),
435
+ ('_micName', None),
436
+ ('_acquisition', None),
437
+ ('_acquisition._magnification', 50000.0),
438
+ ('_acquisition._voltage', 200.0),
439
+ ('_acquisition._sphericalAberration', 2.7),
440
+ ('_acquisition._amplitudeContrast', None),
441
+ ('_acquisition._doseInitial', 0.0),
442
+ ('_acquisition._dosePerFrame', 1.0),
443
+ ])
444
+
445
+ self.assertEqual(goldDict1, m1Dict)
446
+
447
+ def test_Dict(self):
448
+ d = pwobj.Dict(default='missing')
449
+ d.update({1: 'one', 2: 'two'})
450
+
451
+ # Return default value for any non-present key
452
+ self.assertEqual('missing', d[10])
453
+
454
+ # Return true for any 'contains' query
455
+ self.assertTrue(100 in d)
456
+
457
+
458
+ class TestUtils(pwtests.BaseTest):
459
+
460
+ @classmethod
461
+ def setUpClass(cls):
462
+ pwtests.setupTestOutput(cls)
463
+
464
+ def test_ListsFunctions(self):
465
+ """ Test of some methods that retrieve lists from string. """
466
+ from pyworkflow.utils import getListFromValues, getFloatListFromValues,\
467
+ getBoolListFromValues
468
+
469
+ results = [('2x1 2x2 4 5', getListFromValues, ['2x1', '2x2', '4', '5'], None),
470
+ ('2x1 2x2 4 5', getFloatListFromValues, [1., 1., 2., 2., 4., 5.],None),
471
+ ('1 2 3x3 0.5', getFloatListFromValues, [1., 2., 3., 3., 3., 0.5, 0.5, 0.5], 8),
472
+ ('3x1 3x0 1', getBoolListFromValues, [True, True, True, False, False, False, True, True],8),
473
+ ]
474
+
475
+ for s, func, goldList, length in results:
476
+
477
+ l = func(s, length=length)
478
+ for i in range(0,len(goldList)):
479
+ self.assertEqual(l[i], goldList[i])
480
+
481
+ self.assertEqual(len(goldList), len(l), )
482
+
483
+ def test_Environ(self):
484
+ """ Test the Environ class with its utilities. """
485
+ from pyworkflow.utils import Environ
486
+ env = Environ({'PATH': '/usr/bin:/usr/local/bin',
487
+ 'LD_LIBRARY_PATH': '/usr/lib:/usr/lib64'
488
+ })
489
+ env1 = Environ(env)
490
+ env1.set('PATH', '/usr/local/xmipp')
491
+ self.assertEqual(env1['PATH'], '/usr/local/xmipp')
492
+ self.assertEqual(env1['LD_LIBRARY_PATH'], env['LD_LIBRARY_PATH'])
493
+
494
+ env2 = Environ(env)
495
+ env2.set('PATH', '/usr/local/xmipp', position=Environ.BEGIN)
496
+ self.assertEqual(env2['PATH'], '/usr/local/xmipp' + os.pathsep +
497
+ env['PATH'])
498
+ self.assertEqual(env2['LD_LIBRARY_PATH'], env['LD_LIBRARY_PATH'])
499
+
500
+ env3 = Environ(env)
501
+ env3.update({'PATH': '/usr/local/xmipp',
502
+ 'LD_LIBRARY_PATH': '/usr/local/xmipp/lib'},
503
+ position=Environ.END)
504
+ self.assertEqual(env3['PATH'], env['PATH'] + os.pathsep +
505
+ '/usr/local/xmipp')
506
+ self.assertEqual(env3['LD_LIBRARY_PATH'], env['LD_LIBRARY_PATH'] +
507
+ os.pathsep + '/usr/local/xmipp/lib')
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env python
2
+ # **************************************************************************
3
+ # *
4
+ # * Authors: Pablo Conesa (pconesa@cnb.csic.es) [1]
5
+ # *
6
+ # * [1] Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
7
+ # *
8
+ # * This program is free software: you can redistribute it and/or modify
9
+ # * it under the terms of the GNU General Public License as published by
10
+ # * the Free Software Foundation, either version 3 of the License, or
11
+ # * (at your option) any later version.
12
+ # *
13
+ # * This program is distributed in the hope that it will be useful,
14
+ # * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # * GNU General Public License for more details.
17
+ # *
18
+ # * You should have received a copy of the GNU General Public License
19
+ # * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+ # *
21
+ # * All comments concerning this program package may be sent to the
22
+ # * e-mail address 'scipion@cnb.csic.es'
23
+ # *
24
+ # **************************************************************************
25
+
26
+ from pyworkflow.project.project import Project
27
+ from unittest import TestCase
28
+ from unittest.mock import patch
29
+
30
+
31
+ # NOTE: This test as it is might serve as a skeleton for future testing the fixLinks
32
+ # but as it is now it does not test anything at all. I leave it as an example of using patch (mock testing)
33
+ class TestProject(TestCase):
34
+
35
+ def test_fixlinks(self):
36
+ """ Test fixlinks call."""
37
+
38
+ with patch("pyworkflow.project.Project.getRuns") as getruns:
39
+
40
+ getruns.return_value = []
41
+ proj = Project("domain", "path")
42
+ proj.fixLinks("foo")
@@ -0,0 +1,72 @@
1
+ # -*- coding: utf-8 -*-
2
+ # **************************************************************************
3
+ # *
4
+ # * Authors: J.M. De la Rosa Trevin (delarosatrevin@scilifelab.se) [1]
5
+ # *
6
+ # * [1] SciLifeLab, Stockholm University
7
+ # *
8
+ # * This program is free software: you can redistribute it and/or modify
9
+ # * it under the terms of the GNU General Public License as published by
10
+ # * the Free Software Foundation, either version 3 of the License, or
11
+ # * (at your option) any later version.
12
+ # *
13
+ # * This program is distributed in the hope that it will be useful,
14
+ # * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # * GNU General Public License for more details.
17
+ # *
18
+ # * You should have received a copy of the GNU General Public License
19
+ # * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
+ # *
21
+ # * All comments concerning this program package may be sent to the
22
+ # * e-mail address 'scipion@cnb.csic.es'
23
+ # *
24
+ # **************************************************************************
25
+
26
+ import pyworkflow.tests as pwtests
27
+ import pyworkflow.mapper as pwmapper
28
+ import pyworkflow.protocol as pwprot
29
+ from pyworkflow.project import Project
30
+
31
+
32
+ # TODO: this test seems not to be finished.
33
+ from pyworkflowtests.protocols import SleepingProtocol
34
+ from pyworkflowtests import Domain
35
+
36
+
37
+ class TestProtocolExecution(pwtests.BaseTest):
38
+
39
+ @classmethod
40
+ def setUpClass(cls):
41
+ pwtests.setupTestOutput(cls)
42
+
43
+ def test_StepExecutor(self):
44
+ """Test the list with several Complex"""
45
+ fn = self.getOutputPath("protocol.sqlite")
46
+ print("Writing to db: %s" % fn)
47
+
48
+ # Discover objects and protocols
49
+ mapperDict = Domain.getMapperDict()
50
+
51
+ # Associate the project
52
+ proj = Project(Domain, path=self.getOutputPath(''))
53
+
54
+ # Check that the protocol has associated package
55
+ mapper = pwmapper.SqliteMapper(fn, mapperDict)
56
+ prot = SleepingProtocol(mapper=mapper, n=2, project= proj,
57
+ workingDir=self.getOutputPath(''))
58
+ domain = prot.getClassDomain()
59
+ domain.printInfo()
60
+
61
+ prot.setStepsExecutor(pwprot.StepExecutor(hostConfig=None))
62
+ prot.makeWorkingDir()
63
+ prot.run()
64
+ mapper.commit()
65
+ mapper.close()
66
+
67
+ self.assertEqual(prot._steps[0].getStatus(), pwprot.STATUS_FINISHED)
68
+
69
+ mapper2 = pwmapper.SqliteMapper(fn, mapperDict)
70
+ prot2 = mapper2.selectById(prot.getObjId())
71
+
72
+ self.assertEqual(prot.endTime.get(), prot2.endTime.get())
@@ -0,0 +1,78 @@
1
+ # **************************************************************************
2
+ # *
3
+ # * Authors: Pablo Conesa (pconesa@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 3 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
+ """ Module to test json exporting options"""
27
+ # from pyworkflow.em import Pointer, ProtMultiPointerTest
28
+ # from pyworkflow.object import PointerList, String
29
+ # from tests import *
30
+ #
31
+ # MY_OUTPUT = "myOutput"
32
+
33
+ # TODO: Check if some tests from pwem/protocol/protocol_tests can be moved here
34
+ # class TestProtocolExport(BaseTest):
35
+ #
36
+ # @classmethod
37
+ # def setUpClass(cls):
38
+ # setupTestProject(cls)
39
+ #
40
+ # def test_exportMultiPointerToSets(self):
41
+ # """Test how multipointers to are exported and imported"""
42
+ #
43
+ # protMpOutput = self.newProtocol(ProtMultiPointerTest,
44
+ # objLabel='multipointer for output')
45
+ #
46
+ # protMpOutput._defineOutputs(**{MY_OUTPUT: String("hola!")})
47
+ # self.saveProtocol(protMpOutput)
48
+ #
49
+ # # Add multiPointers with extended
50
+ # plWithExtended = PointerList()
51
+ # plWithExtended.append(Pointer(protMpOutput, extended=MY_OUTPUT))
52
+ #
53
+ # protMp = self.newProtocol(ProtMultiPointerTest,
54
+ # objLabel='multipointer with extended export to json',
55
+ # mpToAttr=plWithExtended)
56
+ #
57
+ # self.saveProtocol(protMp)
58
+ # # Trigger the refresh of the runsGraph!!
59
+ # self.proj._runsGraph = None
60
+ #
61
+ # protDict = self.proj.getProtocolsDict()
62
+ #
63
+ # # Get the multipointer params items for the second prot
64
+ # # Get the second prot
65
+ # # This has the shape of : (33, OrderedDict([('object.className', 'ProtMultiPointerTest'), ...) ])
66
+ # ndProtAttrs = protDict[protMp.getObjId()]
67
+ #
68
+ # # Look for the mpToAttr
69
+ # for key, value in ndProtAttrs.items():
70
+ #
71
+ # if key == "mpToAttr":
72
+ # self.assertEqual(1, len(value),
73
+ # "multipointer param items exceeds the "
74
+ # "expected number of items")
75
+ # self.assertEqual("%s.%s" % (protMpOutput.getObjId(), MY_OUTPUT),
76
+ # value[0],
77
+ # "Multipointer item value %s seems to be wrong."
78
+ # % value[0])