parseq 1.0.0__zip → 2024.5.0__zip

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 (189) hide show
  1. {parseq-1.0.0 → parseq-2024.5.0}/PKG-INFO +48 -19
  2. {parseq-1.0.0 → parseq-2024.5.0}/parseq/__init__.py +22 -22
  3. parseq-2024.5.0/parseq/core/__init__.py +425 -0
  4. {parseq-1.0.0 → parseq-2024.5.0}/parseq/core/commons.py +17 -10
  5. {parseq-1.0.0 → parseq-2024.5.0}/parseq/core/config.py +8 -1
  6. parseq-2024.5.0/parseq/core/correction.py +65 -0
  7. {parseq-1.0.0 → parseq-2024.5.0}/parseq/core/logger.py +15 -1
  8. {parseq-1.0.0 → parseq-2024.5.0}/parseq/core/nodes.py +11 -4
  9. {parseq-1.0.0 → parseq-2024.5.0}/parseq/core/plotExport.py +28 -8
  10. {parseq-1.0.0 → parseq-2024.5.0}/parseq/core/save_restore.py +116 -14
  11. {parseq-1.0.0 → parseq-2024.5.0}/parseq/core/singletons.py +9 -2
  12. {parseq-1.0.0 → parseq-2024.5.0}/parseq/core/spectra.py +492 -154
  13. {parseq-1.0.0 → parseq-2024.5.0}/parseq/core/transforms.py +93 -61
  14. {parseq-1.0.0 → parseq-2024.5.0}/parseq/description.py +30 -20
  15. parseq-2024.5.0/parseq/fits/__init__.py +2 -0
  16. parseq-2024.5.0/parseq/fits/basefit.py +616 -0
  17. parseq-2024.5.0/parseq/fits/exafsfit.py +574 -0
  18. parseq-2024.5.0/parseq/fits/functionfit.py +171 -0
  19. parseq-2024.5.0/parseq/fits/lcf.py +289 -0
  20. parseq-2024.5.0/parseq/gui/_images/icon-add-correction-delete-24.png +0 -0
  21. parseq-2024.5.0/parseq/gui/_images/icon-add-correction-delete-32.png +0 -0
  22. parseq-2024.5.0/parseq/gui/_images/icon-add-correction-scale-24.png +0 -0
  23. parseq-2024.5.0/parseq/gui/_images/icon-add-correction-scale-32.png +0 -0
  24. parseq-2024.5.0/parseq/gui/_images/icon-add-correction-spline-24.png +0 -0
  25. parseq-2024.5.0/parseq/gui/_images/icon-add-correction-spline-32.png +0 -0
  26. parseq-2024.5.0/parseq/gui/_images/icon-add-correction-step-24.png +0 -0
  27. parseq-2024.5.0/parseq/gui/_images/icon-add-correction-step-32.png +0 -0
  28. parseq-2024.5.0/parseq/gui/_images/icon-fit-32.png +0 -0
  29. parseq-2024.5.0/parseq/gui/_images/icon-fit-64.png +0 -0
  30. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/aboutDialog.py +96 -22
  31. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/calibrateEnergy.py +21 -15
  32. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/columnFormat.py +19 -7
  33. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/combineSpectra.py +3 -1
  34. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/dataRebin.py +1 -30
  35. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/dataTreeModelView.py +44 -8
  36. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/fileDialogs.py +25 -3
  37. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/fileTreeModelView.py +86 -55
  38. parseq-2024.5.0/parseq/gui/fits/__init__.py +1 -0
  39. parseq-2024.5.0/parseq/gui/fits/gbasefit.py +344 -0
  40. parseq-2024.5.0/parseq/gui/fits/gexafsfit.py +843 -0
  41. parseq-2024.5.0/parseq/gui/fits/gfunctionfit.py +414 -0
  42. parseq-2024.5.0/parseq/gui/fits/glcf.py +480 -0
  43. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/gcommons.py +106 -1
  44. parseq-2024.5.0/parseq/gui/gcorrection.py +930 -0
  45. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/mainWindow.py +44 -28
  46. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/nodeWidget.py +321 -96
  47. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/plot.py +35 -0
  48. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/propWidget.py +79 -39
  49. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/propsOfData.py +9 -7
  50. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/roi.py +174 -35
  51. parseq-1.0.0/parseq/gui/transformer.py → parseq-2024.5.0/parseq/gui/tasker.py +10 -10
  52. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/webWidget.py +8 -3
  53. parseq-2024.5.0/parseq/help/_images/XAS-foils.gif +0 -0
  54. parseq-2024.5.0/parseq/help/_images/pipeline-data-tree.png +0 -0
  55. parseq-2024.5.0/parseq/help/_images/pipeline-file-tree.png +0 -0
  56. parseq-2024.5.0/parseq/help/_images/pipeline-fit-EXAFS.png +0 -0
  57. parseq-2024.5.0/parseq/help/_images/pipeline-graph-XAS.png +0 -0
  58. parseq-2024.5.0/parseq/help/_images/pipeline-line-props.png +0 -0
  59. parseq-2024.5.0/parseq/help/_images/pipeline-proj-load.png +0 -0
  60. parseq-2024.5.0/parseq/help/_images/pipeline-proj-save.png +0 -0
  61. parseq-2024.5.0/parseq/help/_images/pipeline-timing.png +0 -0
  62. parseq-2024.5.0/parseq/help/_images/pipeline-transform-apply.png +0 -0
  63. parseq-2024.5.0/parseq/help/_images/pipeline-undo.png +0 -0
  64. parseq-2024.5.0/parseq/help/_static/animation.js +48 -0
  65. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_static/thumbnail.css +3 -3
  66. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_themes/mytheme/static/mycss.css_t +4 -0
  67. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_themes/parseq/static/default.css_t +23 -4
  68. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_themes/parseq/static/utils.js +6 -5
  69. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/exts/animation.py +59 -29
  70. parseq-2024.5.0/parseq/help/fits.rst +10 -0
  71. parseq-2024.5.0/parseq/help/history.rst +24 -0
  72. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/index.rst +1 -1
  73. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/top.rst +1 -1
  74. parseq-2024.5.0/parseq/tests/data/BFT-Cu-foil_EXAFS_23070.txt.gz +0 -0
  75. parseq-2024.5.0/parseq/tests/data/Ce-CeRu2.bft +366 -0
  76. parseq-2024.5.0/parseq/tests/data/Ru-CeRu2.bft +614 -0
  77. parseq-2024.5.0/parseq/tests/data/cu-ref-mix.res +1251 -0
  78. parseq-2024.5.0/parseq/tests/data/fitTestEXAFS.h5 +0 -0
  79. parseq-2024.5.0/parseq/tests/data/pb-ref-mix.res +614 -0
  80. parseq-2024.5.0/parseq/tests/data/zn-ref-mix.res +1251 -0
  81. parseq-2024.5.0/parseq/tests/test_dataCorrection.py +95 -0
  82. parseq-2024.5.0/parseq/tests/test_fileTreeModelView.py +83 -0
  83. parseq-2024.5.0/parseq/tests/test_fit.py +279 -0
  84. parseq-2024.5.0/parseq/tests/test_fit_EXAFS.py +276 -0
  85. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_hdf5.py +4 -3
  86. parseq-2024.5.0/parseq/utils/__init__.py +1 -0
  87. parseq-2024.5.0/parseq/utils/constants.py +5 -0
  88. {parseq-1.0.0 → parseq-2024.5.0}/parseq/utils/ft.py +6 -4
  89. {parseq-1.0.0 → parseq-2024.5.0}/parseq/utils/h5reduce.py +2 -0
  90. {parseq-1.0.0 → parseq-2024.5.0}/parseq/utils/math.py +1 -1
  91. {parseq-1.0.0 → parseq-2024.5.0}/parseq/version.py +2 -2
  92. {parseq-1.0.0 → parseq-2024.5.0}/parseq.egg-info/PKG-INFO +48 -19
  93. {parseq-1.0.0 → parseq-2024.5.0}/parseq.egg-info/SOURCES.txt +50 -9
  94. {parseq-1.0.0 → parseq-2024.5.0}/parseq.egg-info/requires.txt +2 -0
  95. {parseq-1.0.0 → parseq-2024.5.0}/setup.py +4 -3
  96. parseq-1.0.0/parseq/core/__init__.py +0 -142
  97. parseq-1.0.0/parseq/gui/__init__.py +0 -150
  98. parseq-1.0.0/parseq/help/_images/XAS_icon.ico +0 -0
  99. parseq-1.0.0/parseq/help/_images/XES_dispersive_icon.ico +0 -0
  100. parseq-1.0.0/parseq/help/_images/XES_scan_icon.ico +0 -0
  101. parseq-1.0.0/parseq/help/_images/node1.png +0 -0
  102. parseq-1.0.0/parseq/help/_images/node2.png +0 -0
  103. parseq-1.0.0/parseq/help/_images/node3.png +0 -0
  104. parseq-1.0.0/parseq/help/_images/node4.png +0 -0
  105. parseq-1.0.0/parseq/help/_static/animation.js +0 -48
  106. parseq-1.0.0/parseq/help/notesgui.rst +0 -3
  107. parseq-1.0.0/parseq/tests/test_fileTreeModelView.py +0 -54
  108. {parseq-1.0.0 → parseq-2024.5.0}/LICENSE +0 -0
  109. {parseq-1.0.0 → parseq-2024.5.0}/parseq/CODERULES.txt +0 -0
  110. {parseq-1.0.0/parseq/help → parseq-2024.5.0/parseq/gui}/__init__.py +0 -0
  111. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-help.png +0 -0
  112. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-info.png +0 -0
  113. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-1dim-32.png +0 -0
  114. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-1dim-64.png +0 -0
  115. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-1dim-busy-32.png +0 -0
  116. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-1dim-busy-64.png +0 -0
  117. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-2dim-32.png +0 -0
  118. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-2dim-64.png +0 -0
  119. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-2dim-busy-32.png +0 -0
  120. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-2dim-busy-64.png +0 -0
  121. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-3dim-32.png +0 -0
  122. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-3dim-64.png +0 -0
  123. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-3dim-busy-32.png +0 -0
  124. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-3dim-busy-64.png +0 -0
  125. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-ndim-32.png +0 -0
  126. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-ndim-64.png +0 -0
  127. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-ndim-busy-32.png +0 -0
  128. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-item-ndim-busy-64.png +0 -0
  129. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-load-proj.png +0 -0
  130. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-redo.png +0 -0
  131. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-save-proj.png +0 -0
  132. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-save-text.png +0 -0
  133. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/icon-undo.png +0 -0
  134. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/_images/parseq.ico +0 -0
  135. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/plotOptions.py +0 -0
  136. {parseq-1.0.0 → parseq-2024.5.0}/parseq/gui/undoredo.py +0 -0
  137. {parseq-1.0.0/parseq/third_party → parseq-2024.5.0/parseq/help}/__init__.py +0 -0
  138. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_images/mickey-rtfm.gif +0 -0
  139. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_images/parseq.ico +0 -0
  140. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_images/parseq_big.png +0 -0
  141. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_templates/layout.html +0 -0
  142. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_themes/mytheme/layout.html +0 -0
  143. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_themes/mytheme/theme.conf +0 -0
  144. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_themes/parseq/layout.html +0 -0
  145. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_themes/parseq/page.html +0 -0
  146. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_themes/parseq/static/math_config_win32.js +0 -0
  147. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/_themes/parseq/theme.conf +0 -0
  148. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/conf.py +0 -0
  149. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/conf_doc.py +0 -0
  150. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/data.rst +0 -0
  151. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/howto.rst +0 -0
  152. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/license.rst +0 -0
  153. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/make.bat +0 -0
  154. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/nodes.rst +0 -0
  155. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/transforms.rst +0 -0
  156. {parseq-1.0.0 → parseq-2024.5.0}/parseq/help/widgets.rst +0 -0
  157. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/__init__.py +0 -0
  158. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/circles-rect.png +0 -0
  159. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/circles.png +0 -0
  160. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/modeltest.py +0 -0
  161. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_QSortFilterProxyModel.py +0 -0
  162. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_ROI.py +0 -0
  163. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_aboutWidget.py +0 -0
  164. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_calibrateEnergyWidget.py +0 -0
  165. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_columnStrings.py +0 -0
  166. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_combineSpectraWidget.py +0 -0
  167. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_commons.py +0 -0
  168. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_curve_shear.py +0 -0
  169. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_dataRebinWidget.py +0 -0
  170. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_dataTreeModelView.py +0 -0
  171. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_fileDialog.py +0 -0
  172. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_flowLayout.py +0 -0
  173. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_mainWindow.py +0 -0
  174. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_node.py +0 -0
  175. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_nodeWidget.py +0 -0
  176. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_plotInteractiveImageROIwithKeys.py +0 -0
  177. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_plotInteractiveImageSingleROI.py +0 -0
  178. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_plotOptions.py +0 -0
  179. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_slice.py +0 -0
  180. {parseq-1.0.0 → parseq-2024.5.0}/parseq/tests/test_stateButtons.py +0 -0
  181. {parseq-1.0.0 → parseq-2024.5.0}/parseq/third_party/XAFSmass.py +0 -0
  182. {parseq-1.0.0/parseq/utils → parseq-2024.5.0/parseq/third_party}/__init__.py +0 -0
  183. {parseq-1.0.0 → parseq-2024.5.0}/parseq/third_party/data/Energies.txt +0 -0
  184. {parseq-1.0.0 → parseq-2024.5.0}/parseq/third_party/xrt.py +0 -0
  185. {parseq-1.0.0 → parseq-2024.5.0}/parseq/utils/format.py +0 -0
  186. {parseq-1.0.0 → parseq-2024.5.0}/parseq.egg-info/dependency_links.txt +0 -0
  187. {parseq-1.0.0 → parseq-2024.5.0}/parseq.egg-info/not-zip-safe +0 -0
  188. {parseq-1.0.0 → parseq-2024.5.0}/parseq.egg-info/top_level.txt +0 -0
  189. {parseq-1.0.0 → parseq-2024.5.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: parseq
3
- Version: 1.0.0
3
+ Version: 2024.5.0
4
4
  Summary: ParSeq is a python software library for Parallel execution of Sequential data analysis.
5
5
  Home-page: http://parseq.readthedocs.io
6
6
  Author: Konstantin Klementiev
@@ -21,24 +21,45 @@ Classifier: Topic :: Software Development
21
21
  Classifier: Topic :: Software Development :: User Interfaces
22
22
  Description-Content-Type: text/x-rst
23
23
  License-File: LICENSE
24
+ Requires-Dist: numpy>=1.8.0
25
+ Requires-Dist: scipy>=0.17.0
26
+ Requires-Dist: matplotlib>=2.0.0
27
+ Requires-Dist: sphinx>=1.6.2
28
+ Requires-Dist: sphinxcontrib-jquery
29
+ Requires-Dist: autopep8
30
+ Requires-Dist: h5py
31
+ Requires-Dist: silx>=1.1.0
32
+ Requires-Dist: hdf5plugin
33
+ Requires-Dist: psutil
34
+ Requires-Dist: pyqtwebengine
35
+ Requires-Dist: docutils
36
+ Requires-Dist: distro
37
+ Requires-Dist: colorama
24
38
 
25
39
  Package ParSeq is a python software library for **Par**\ allel execution of
26
40
  **Seq**\ uential data analysis. It implements a general analysis framework that
27
41
  consists of transformation nodes -- intermediate stops along the data pipeline
28
- to visualize data, display status and provide user input -- and transformations
29
- that connect the nodes. It provides an adjustable data model (supports
30
- grouping, renaming, moving and drag-and-drop), tunable data format definitions,
31
- plotters for 1D, 2D and 3D data, cross-data analysis routines and flexible
32
- widget work space suitable for single- and multi-screen computers. It also
33
- defines a structure to implement particular analysis pipelines as relatively
34
- lightweight Python packages.
42
+ for data visualization, cross-data operations (e.g. taking average), providing
43
+ user input and displaying status -- and transformations that connect the nodes.
44
+
45
+ It provides an adjustable data tree model (supports grouping, renaming, moving
46
+ and drag-and-drop arrangement), tunable data format definitions, plotters for
47
+ 1D, 2D and 3D data, cross-data analysis routines and flexible widget work space
48
+ suitable for single- and multi-screen computers. It also defines a structure to
49
+ implement particular analysis pipelines as lightweight Python packages.
35
50
 
36
51
  ParSeq is intended for synchrotron based techniques, first of all spectroscopy.
37
52
 
53
+ A screenshot of ParSeq-XAS (an EXAFS analysis pipeline) as an application
54
+ example:
55
+
56
+ .. image:: _images/XAS-foils.gif
57
+ :scale: 50 %
58
+
38
59
  Main features
39
60
  -------------
40
61
 
41
- - ParSeq allows creating analysis pipelines as lightweight modules.
62
+ - ParSeq allows creating analysis pipelines as lightweight Python packages.
42
63
 
43
64
  - Flexible use of screen area by detachable/dockable transformation nodes
44
65
  (parts of analysis pipeline).
@@ -57,12 +78,21 @@ Main features
57
78
  possibility of termination of the parental data at any selected downstream
58
79
  node.
59
80
 
60
- - Parallel execution of data analysis with multiprocessing or multithreading
61
- (can be opted by the pipeline application).
81
+ - General data correction routines for 1D data: range deletion, scaling,
82
+ replacement by a spline and jump correction.
83
+
84
+ - Parallel execution of data transformations with multiprocessing or
85
+ multithreading (can be opted by the pipeline application).
86
+
87
+ - Optional curve fitting solvers, also executed in parallel for multiple data
88
+ items.
62
89
 
63
90
  - Informative error handling that provides alerts and stack traceback -- the
64
91
  type and location of the occurred error.
65
92
 
93
+ - Optional time profiling of the pipeline, as controlled by a command-line
94
+ argument.
95
+
66
96
  - Export of the workflow into a project file. Export of data into various data
67
97
  formats with accompanied Python scripts that visualize the exported data for
68
98
  the user to tune their publication plots.
@@ -75,23 +105,22 @@ Main features
75
105
  from the analysis widget doc strings. The help pages are built by Sphinx at
76
106
  the startup time.
77
107
 
78
- - The pipeline can be operated via scripts or GUI.
108
+ - The pipeline can be operated by the GUI or from a Python script without GUI.
79
109
 
80
110
  - Optional automatic loading of new data during a measurement time.
81
111
 
82
- The mechanisms for creating nodes and transformations, connecting them together
83
- and creating Qt widgets for the transformations are exemplified by separately
84
- installed analysis packages:
112
+ The mechanisms for creating nodes, transformations and curve fitting solvers,
113
+ connecting them together and creating Qt widgets for the transformations and
114
+ and curve fits are exemplified by separately installed analysis packages:
85
115
 
86
- - `ParSeq-XES-scan <https://github.com/kklmn/ParSeq-XES-scan>`_
87
- - `ParSeq-XES-dispersive <https://github.com/kklmn/ParSeq-XES-dispersive>`_
88
116
  - `ParSeq-XAS <https://github.com/kklmn/ParSeq-XAS>`_
117
+ - `ParSeq-XES-scan <https://github.com/kklmn/ParSeq-XES-scan>`_
89
118
 
90
119
  Dependencies
91
120
  ------------
92
121
 
93
- - `silx <https://github.com/silx-kit/silx>`_ -- for plotting and Qt imports
94
- - `sphinx <https://github.com/sphinx-doc/sphinx>`_ -- for building html documentation
122
+ - `silx <https://github.com/silx-kit/silx>`_ -- plotting, hdf5 handling, Qt
123
+ - `sphinx <https://github.com/sphinx-doc/sphinx>`_ -- building documentation
95
124
 
96
125
  Launch an example
97
126
  -----------------
@@ -1,22 +1,22 @@
1
- # -*- coding: utf-8 -*-
2
- u"""
3
- ParSeq implements a general analysis framework with a data model, plotter,
4
- cross-data analysis and tunable widget work space. It also sets a structure to
5
- implement particular analysis pipelines as relatively lightweight Python
6
- packages.
7
-
8
- ParSeq is intended for synchrotron based techniques, first of all spectroscopy.
9
- """
10
-
11
- # !!! SEE CODERULES.TXT !!!
12
-
13
- from .version import __versioninfo__, __version__, __date__
14
-
15
- __module__ = "parseq"
16
- __author__ = "Konstantin Klementiev (MAX IV Laboratory)"
17
- __email__ = "first dot last at gmail dot com"
18
- __license__ = "MIT license"
19
- __synopsis__ = "ParSeq is a python software library for Parallel execution of"\
20
- " Sequential data analysis"
21
-
22
- #__all__ = ['core']
1
+ # -*- coding: utf-8 -*-
2
+ u"""
3
+ ParSeq implements a general analysis framework with a data model, plotter,
4
+ cross-data analysis and tunable widget work space. It also sets a structure to
5
+ implement particular analysis pipelines as relatively lightweight Python
6
+ packages.
7
+
8
+ ParSeq is intended for synchrotron based techniques, first of all spectroscopy.
9
+ """
10
+
11
+ # !!! SEE CODERULES.TXT !!!
12
+
13
+ from .version import __versioninfo__, __version__, __date__
14
+
15
+ __module__ = "parseq"
16
+ __author__ = "Konstantin Klementiev (MAX IV Laboratory)"
17
+ __email__ = "first dot last at gmail dot com"
18
+ __license__ = "MIT license"
19
+ __synopsis__ = "ParSeq is a python software library for Parallel execution of"\
20
+ " Sequential data analysis"
21
+
22
+ #__all__ = ['core']
@@ -0,0 +1,425 @@
1
+ # -*- coding: utf-8 -*-
2
+ u"""
3
+ Create analysis pipeline
4
+ ========================
5
+
6
+ Consider `parseq_XES_scan` and `parseq_XAS` as examples for the development
7
+ steps described below.
8
+
9
+ Centralized facilities
10
+ ----------------------
11
+
12
+ Nodes and transformations
13
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
14
+
15
+ .. imagezoom:: _images/pipeline-graph-XAS.png
16
+ :align: right
17
+ :alt: &ensp;A pipeline for data processing of XAS spectra. This pipeline has
18
+ multiple entry nodes and three fitting routines. It partially operates
19
+ in multithreading and multiprocessing.
20
+
21
+ Analysis pipeline is a chain of data transformations with a set of intermediate
22
+ stops -- nodes -- where the results can be visualized and assessed and the
23
+ transformations can be steered. See an example on the right.
24
+
25
+ Data nodes define array names that will appear as attributes of data objects.
26
+ The array values will be read from files or calculated from other arrays. The
27
+ pipeline can be used with or without GUI widgets. In the former case, the
28
+ defined node arrays will appear in the node plot: 1D, 2D or 3D (a stack of 2D
29
+ plots).
30
+
31
+ .. imagezoom:: _images/pipeline-data-tree.png
32
+ :alt: &ensp;EXAFS spectra arranged in a tree. The item tooltips present data
33
+ flow information, array sizes and error messages.
34
+
35
+ The data tree model (as in the Qt's `Model/View Programming
36
+ <https://doc.qt.io/qt-6/model-view-programming.html>`_ concept) is a single
37
+ object throughout the pipeline. In contrast, data tree widgets, see an example
38
+ on the left, are present in *each* data node, not as a single tree instance,
39
+ with the idea to also serve as a plot legend. The data tree can be populated
40
+ from the file tree by using the popup menu or by a drag-and-drop action. The
41
+ newly loaded data get their set of transformation parameters from the currently
42
+ active data item (or the first of them if several items were active). If no
43
+ items have been previously loaded, the parameters are read from the ini file.
44
+ If the ini file does not exist yet, the parameters get their values from
45
+ `defaultParams` dictionary defined in each transformation class.
46
+
47
+ Data can be rearranged by the user: ordered, renamed, grouped and removed. User
48
+ selection in the data model is common for all transformation nodes. For 1D data
49
+ the line color is the same in all data nodes. 1D data plotting can optionally
50
+ be done for several curves simultaneously: for those selected either
51
+ dynamically (via mouse selection) or statically (via check boxes). This
52
+ behavior is set by clicking on the header of the visibility column: it toggles
53
+ between the icon with one eye or many eyes. 2D and 3D data plotting is always
54
+ done for one selected data object -- the first one among selected data items.
55
+
56
+ Each transformation class defines a dictionary of transformation parameters and
57
+ default values for them. It also defines a static method that calculates data
58
+ arrays. The transformation parameters are attributed to each data object. The
59
+ parameter values are supposed to be changed in GUI widgets. This change can be
60
+ done simultaneously for one or several active data objects. Alternatively, any
61
+ parameter can be copied to one or several later selected data.
62
+
63
+ .. imagezoom:: _images/pipeline-transform-apply.png
64
+ :align: right
65
+ :alt: &ensp;An example of the apply/reset popup menu on a control element.
66
+
67
+ Each transformation can optionally define the number of threads or processes
68
+ that will start in parallel to run the transformation of several data items.
69
+ The multiprocessing python API requires the main transformation method as a
70
+ *static* or *class* method (not an instance method). Additionally, for the sake
71
+ of inter-process data transfer in multiprocessing, all input and output node
72
+ arrays have to be added to ``inArrays`` and ``outArrays`` lists (attributes of
73
+ the transformation class).
74
+
75
+ In the pipeline GUI widgets, all interactive GUI elements can be registered
76
+ using a few dedicated methods of the base class :class:`PropWidget`. The
77
+ registration will enable (a) automatic GUI update from the active data and will
78
+ run transformations given the updated GUI elements, so no
79
+ `signal slots <https://doc.qt.io/qt-6/signalsandslots.html>`_
80
+ are typically required. The registration will also enable (b) copying
81
+ transformation parameters to other data by means of popup menus on each GUI
82
+ element, see on the right.
83
+
84
+ Docked node widgets
85
+ ~~~~~~~~~~~~~~~~~~~
86
+
87
+ With the idea of flexible usage of screen area, the node widgets were made
88
+ detachable and dockable into the main ParSeq window. To do this, drag a node
89
+ widget by its caption bar. To dock it back, hover it over the main window or
90
+ use the dock button at the right end of the caption bar.
91
+
92
+ The state of each node widget (docked or floating) and its floating geometry is
93
+ saved in ini file and project files.
94
+
95
+ Undo and redo
96
+ ~~~~~~~~~~~~~
97
+
98
+ .. imagezoom:: _images/pipeline-undo.png
99
+ :align: left
100
+ :alt: &ensp;The undo menu where individual actions can be reverted or
101
+ deleted. The most typical way of using undo is to sequentially reverse
102
+ actions from the top of the undo stack, either by the Undo button or the
103
+ standard key combination Ctrl+Z.
104
+
105
+ The change of any transformation parameter can be reverted or redone again by
106
+ using undo/redo actions. Adding or deleting data items can also be reverted.
107
+ Parseq will keep reference to the deleted data items. In order to free up RAM
108
+ from the deleted items, the undo or redo list can manually be emptied.
109
+
110
+ File tree views and file formats
111
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
112
+
113
+ Each transformation node has its own file tree view with a data format widget
114
+ at its bottom. The file tree is by default visible only in the pipeline head
115
+ node(s). It can be made visible/hidden by the vertical button of the leftmost
116
+ splitter widget "files & containers".
117
+
118
+ The file tree model is a joint model of the standard Qt's `QFileSystemModel`
119
+ and the silx's `Hdf5TreeModel`, which means that hdf5 files are displayed in
120
+ the same file tree as subdirectories.
121
+
122
+ When an entry in the data tree is clicked, the corresponding file or hdf5 entry
123
+ gets highlighted in the starting transformation node widget. When the file tree
124
+ is browsed, the highlight color is green if this entry can be loaded, i.e. the
125
+ data format fields in the data format widget are defined and valid.
126
+
127
+ .. imagezoom:: _images/pipeline-file-tree.png
128
+ :align: right
129
+ :alt: &ensp;The file tree of a node. Visible is an expanded entry of an hdf5
130
+ file. The sum of the two selected arrays will define I0 array.
131
+
132
+ ParSeq works with two file types: column text files and hdf5 files.
133
+
134
+ For column files, the format definitions are expressions of variables `Col0`,
135
+ `Col1` etc, e.g. as `Col3+Col4`. The expressions may include numpy functions:
136
+ `np.log(Col6/Col7)`. The file header can optionally be defined by the number of
137
+ header lines, by the leading comment character or a key word present in the
138
+ last header line. The whole header will serve as metadata for the corresponding
139
+ data item.
140
+
141
+ For hdf5 files, the format definitions are relative hdf5 paths or expressions
142
+ of a data dictionary `d`, whose keys are relative hdf5 paths:
143
+ `d["measurement/albaem-01_ch1"] + d["measurement/albaem-01_ch2"]`. The easiest
144
+ way to build these expressions is to use the popup menu in the file tree view,
145
+ see the image on the right. String or scalar hdf5 entries can be inserted into
146
+ the list of metadata items, again by using the popup menu. Note that you can
147
+ use hdf5 data sets from various hdf5 data groups or even hdf5 data files, not
148
+ necessarily from one data group when you load one data item.
149
+
150
+ The format definitions will be restored at the next program start. The data
151
+ format widget updates upon data selection change. So if several data formats
152
+ are in use in one session, the selection of a right data item is a way to
153
+ activate the right data format before loading the next similar data item.
154
+ The format definitions can also be saved into an ini file (.parseq/formats.ini)
155
+ and later restored from it using the popup menu when right-clicked on a data
156
+ file.
157
+
158
+ Automatic data loading can be activated by the check box "auto load new data
159
+ from current location", which is a useful feature during beam times.
160
+
161
+ Metadata
162
+ ~~~~~~~~
163
+
164
+ Metadata widget joins the metadata string variables, see the previous section.
165
+ The widget can also be used to examine text files for column positions, use the
166
+ popup menu in the file tree view for that. The widget is hidden by default and
167
+ is located below the node plot.
168
+
169
+ Plots
170
+ ~~~~~
171
+
172
+ .. imagezoom:: _images/pipeline-line-props.png
173
+ :align: right
174
+ :alt: &ensp;Line properties accessed from the header of a node's data tree.
175
+
176
+ The node plots are used to display data and to host a few analysis widgets:
177
+ regions of interest (ROIs) and data correction widgets. The 1D, 2D and 3D (2D
178
+ stacks) plots are adopted from silx with a few customizations.
179
+
180
+ Bear in mind that if several items have the same alias, silx displays only one
181
+ of them, so make sure aliases are unique. Parseq will try to append a numbered
182
+ suffix to the alias if the added data have the same file name. Aliases can
183
+ always be changed by the user.
184
+
185
+ In 1D plotting window, clicking on a curve will select the corresponding data
186
+ item in the data tree widget. Auxiliary curves can be added in user-defined
187
+ transformation widgets by specifying a method `extraPlot()`. The curves should
188
+ have their `legend` property defined in the following format: the data item
189
+ alias followed by a dot followed by a sub-name. If this convention is followed,
190
+ the curves become clickable, which will select the corresponding data item in
191
+ the data tree. Selected data items are plotted on top of the others.
192
+
193
+ Default plot settings for 1D curves can be set in the definitions of node
194
+ arrays. The GUI can also change it from any data tree view, see on the right.
195
+
196
+ The silx's plots may define a plot *backend*. Currently silx implements
197
+ 'matplotlib' and 'opengl'. The former one is default in ParSeq as it looks
198
+ better in almost all scenarios, the latter one is quicker, especially for 2D
199
+ and 3D plots. The user is free to select either backend by CLI parameters of
200
+ the pipeline starter.
201
+
202
+ Fits
203
+ ~~~~
204
+
205
+ Data nodes can optionally host curve fitting routines. If one or more fit
206
+ widgets were specified for a given node, they appear in separate splitters
207
+ under the node's plot. In the initial view, the splitters are collapsed.
208
+
209
+ .. imagezoom:: _images/pipeline-fit-EXAFS.png
210
+ :align: right
211
+ :alt: &ensp;EXAFS fit widget as an example of ParSeq fit widgets. It was
212
+ built on top of the ParSeq base fit and base fit widget classes.
213
+
214
+ Similarly to transformations, fitting solvers can run in parallel for several
215
+ data items. Fitting parameters can be constrained or tied to other parameters,
216
+ also to parameters of another data item fit. See an example fit widget on the
217
+ right.
218
+
219
+ ParSeq implements a base fit class :class:`parseq.fits.basefit.Fit` and its
220
+ widget mate :class:`parseq.gui.fits.gbasefit.FitWidget`. These are parent
221
+ classes for ParSeq's Liner Combination Fit, Function Fit and EXAFS Fit.
222
+
223
+ The actual fit worker for each fit process or thread is
224
+ `scipy.optimize.curve_fit
225
+ <https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html>`_.
226
+ Its performance figures are displayed at the bottom of each fit widget.
227
+
228
+ Cross-data combinations
229
+ ~~~~~~~~~~~~~~~~~~~~~~~
230
+
231
+ Data of equal shapes can be combined to produce joint secondary data: average,
232
+ sum, rms deviation and PCA components (to appear in a next release). The
233
+ current implementation asserts equal shapes and averages the abscissas of the
234
+ contributing data. Interpolation options will be added in later releases.
235
+
236
+ Whenever the contributing data have been modified in an upstream
237
+ transformation, the combined data will also update.
238
+
239
+ Standard data corrections
240
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
241
+
242
+ ParSeq data pipelines perform data evolution in specialized *transformations*.
243
+ ParSeq also implements a few standard data *corrections*, intended for
244
+ amendment of experimental 1D data curves. These include (a) range deletion,
245
+ (b) range vertical scaling, (c) replacement by a spline and (d) a step
246
+ correction.
247
+
248
+ Although data can flow in ParSeq without GUIs, data corrections are most
249
+ conveniently done using the mouse.
250
+
251
+ Project saving with data export and plot script generation
252
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
253
+
254
+ .. imagezoom:: _images/pipeline-proj-load.png
255
+ :align: left
256
+ :alt: &ensp;The Load project dialog. In the right panel is an image browser
257
+ of the project plots.
258
+
259
+ .. imagezoom:: _images/pipeline-proj-save.png
260
+ :align: right
261
+ :alt: &ensp;The Save project dialog. The bottom panel is a widget for data
262
+ export options.
263
+
264
+ There are a few example projects files coming with each pipeline application.
265
+ A ParSeq project file (.pspj) defines the data tree and all parameters for all
266
+ transformations and fits. It has an `ini file structure
267
+ <https://docs.python.org/3/library/configparser.html>`_. At its saving time
268
+ ParSeq also saves all relevant plot views that can be browsed in the Load
269
+ project dialog, see on the left.
270
+
271
+ Before starting the Save project dialog, select the data items to be exported.
272
+ In the dialog, select the nodes to export from, data format(s) and whether a
273
+ plotting script is wanted. The script will plot the *exported data* and
274
+ preserve the plotting settings from the analysis pipeline. The idea of the
275
+ script generation is twofold: to demonstrate the access to the saved data and
276
+ to give a possibility to tune the resulting figures. The scripts have a few
277
+ comments inside about tuning axis ranges, axis labels and curve legends.
278
+
279
+ In the saved project, file path to each data item is saved in two versions: as
280
+ an absolute path and as a relative path in respect to the project location.
281
+ When the project is copied together with the files to a new location, the
282
+ project should be directly loadable. When copied from a GPFS location at a
283
+ beamline, this may not work, and the relative paths have to be manually edited
284
+ by a Search/Replace operation in a text file editor.
285
+
286
+ Error handling
287
+ ~~~~~~~~~~~~~~
288
+
289
+ Should an error occur during a transformation, this error is caught by ParSeq.
290
+ The corresponding data item turns to a bad state displayed by a red background
291
+ in the data tree. The caught error is displayed in the tooltip of that data
292
+ tree item where it names the transformation, the data item and the involved
293
+ python module. The error can be copied to clipboard.
294
+
295
+ Command-line interface and start options
296
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
297
+
298
+ The available command line options of the starter script can be revealed with a
299
+ :command:`--help` key. Most of them are intended for development purpose.
300
+
301
+ Performance profiling
302
+ ~~~~~~~~~~~~~~~~~~~~~
303
+
304
+ If the starter script is started with an elevated verbosity level (e.g. with a
305
+ key :command:`--verbosity 100`), the terminal output prints the timing results
306
+ for each relevant invocation of transformation and plotting methods, see below.
307
+ This functionality is meant as a tool for data pipeline development.
308
+
309
+ .. imagezoom:: _images/pipeline-timing.png
310
+ :align: none
311
+ :alt: &ensp;An example of the terminal output with timing figures, enabled
312
+ by the CLI option `--verbosity` (*or* `-v`).
313
+
314
+ Help system
315
+ ~~~~~~~~~~~
316
+
317
+ The transformation class docstrings are built by ParSeq at the application
318
+ start up time using `Sphinx <https://www.sphinx-doc.org>`_ into an html file
319
+ and displayed in a help panel close to the transformation widget.
320
+
321
+ The main application help files are also built at the start up time if ParSeq
322
+ file have been modified.
323
+
324
+ About dialog
325
+ ~~~~~~~~~~~~
326
+
327
+ The about dialog displays the connectivity between the pipeline nodes in a
328
+ dynamically created svg graph. If a fit is defined in a node, it is also
329
+ displayed here.
330
+
331
+ Prepare pipeline metadata and images
332
+ ------------------------------------
333
+
334
+ Create a project directory for the pipeline. Create `__init__.py` file that
335
+ defines metadata about the project. Note that pipeline applications and ParSeq
336
+ itself use the module `parseq.core.singletons` as a means to store global
337
+ variables; the pipeline's `__init__.py` module defines a few of them. Together
338
+ with the docstrings of the module, these metadata will appear in the About
339
+ dialog.
340
+
341
+ Create `doc/_images` directory and put an application icon there. The pipeline
342
+ transformations will have class docstrings that may also include images; those
343
+ images should be located here, in `doc/_images`.
344
+
345
+ Make data nodes
346
+ ---------------
347
+
348
+ To define a node class means to name all plot arrays, define their roles,
349
+ labels and units. The data containers may also have other array attributes that
350
+ do not participate in plots; these are not to be declared.
351
+
352
+ Make data transformations
353
+ -------------------------
354
+
355
+ Start making a transformation class with defining a dictionary `defaultParams`
356
+ of default parameter values. Decide on using multiprocessing/multithreading by
357
+ specifying `nThreads` or `nProcesses`. If any of these numbers is > 1 (the
358
+ default values are both 1), specify two lists of array names: `inArrays` and
359
+ `outArrays`. Define a static or a class method :meth:`.Transform.run_main`.
360
+ Note, it can have a few signatures. Within the method, get the actual
361
+ transformation parameters from the dictionary `data.transformParams` and get
362
+ data arrays as attributes of `data`, e.g. ``data.x``.
363
+
364
+ For expensive transformations, you should update the *progress* status.
365
+
366
+ For accessing arrays of other data objects, use a different signature of
367
+ :meth:`.Transform.run_main` that contains the *allData* argument. Note that in
368
+ this case multiprocessing is not possible.
369
+
370
+ Make GUI widgets
371
+ ----------------
372
+
373
+ The widgets that control transformation parameters are descendants of
374
+ :class:`.PropWidget`. The main methods of that class are
375
+ :meth:`.PropWidget.registerPropWidget` and
376
+ :meth:`.PropWidget.registerPropGroup`. They use the Qt signal/slot mechanism to
377
+ update the corresponding transformation parameters; the user does not have to
378
+ explicitly implement the reaction slots. Additionally, these methods enable
379
+ copying transformation parameters to other data by means of popup menus, update
380
+ the GUI upon selecting data objects in the data tree, start the corresponding
381
+ transformation and operate undo and redo lists.
382
+
383
+ Because each transformation already has a set of default parameter values,
384
+ these GUI widgets can gradually grow during the development time, without
385
+ compromising the data pipeline functionality.
386
+
387
+ Provide docstrings in reStructuredText markup. They will be built by Sphinx and
388
+ displayed near the corresponding widgets.
389
+
390
+ Make fitting worker classes
391
+ ---------------------------
392
+
393
+ Similarly to a transformation class, a fitting class defines multiprocessing /
394
+ multithreading needs and a static or a class method :meth:`.Fit.run_main`. It
395
+ also defines in a few class dictionaries the data array to be fitted and the
396
+ fit parameters.
397
+
398
+ Make data pipeline
399
+ ------------------
400
+
401
+ This is a small module that instantiates the above nodes, transformations, fits
402
+ and widgets and connects them together.
403
+
404
+ Create test data tree
405
+ ---------------------
406
+
407
+ Put a few data files in a local folder (i.e. `data`) and create a module that
408
+ defines a function that loads the data into a :ref:`data tree <data>`, defines
409
+ suitable transformation parameters and launches the first transformation (the
410
+ next ones will start automatically).
411
+
412
+ Create pipeline starter
413
+ -----------------------
414
+
415
+ The starter should understand command line arguments and prepare options for
416
+ loading the test data and to run the pipeline with and without GUI.
417
+
418
+ Creating development versions of analysis application
419
+ -----------------------------------------------------
420
+
421
+ Copy the whole folder of the application to the same level but with a different
422
+ name, e.g. append a version suffix. In the import section in the start script
423
+ change the import name to the above created folder name. Done.
424
+
425
+ """
@@ -15,8 +15,12 @@ MIME_TYPE_HDF5 = 'parseq-hdf5-model-items'
15
15
  COMBINE_NONE, COMBINE_AVE, COMBINE_SUM, COMBINE_PCA, COMBINE_RMS = range(5)
16
16
  combineNames = '', 'ave', 'sum', 'PCA', 'RMS'
17
17
 
18
- (DATA_STATE_GOOD, DATA_STATE_BAD, DATA_STATE_UNDEFINED, DATA_STATE_NOTFOUND,
19
- DATA_STATE_MATHERROR) = 1, 0, -1, -2, -3
18
+ DATA_STATE_GOOD = 1
19
+ DATA_STATE_BAD = 0
20
+ DATA_STATE_UNDEFINED = -1
21
+ DATA_STATE_NOTFOUND = -2
22
+ DATA_STATE_MATHERROR = -3
23
+ DATA_STATE_MARKED_FOR_DELETION = -4
20
24
 
21
25
 
22
26
  def expandDotAttr(attr):
@@ -205,7 +209,7 @@ def make_int_ranges(iterable):
205
209
  # -> "(02..05)"
206
210
 
207
211
 
208
- def get_header(fname, readkwargs):
212
+ def get_header(fname, readkwargs, searchAllLines=False):
209
213
  skipUntil = readkwargs.pop('lastSkipRowContains', '')
210
214
  headerLen = -1
211
215
  if 'skiprows' not in readkwargs:
@@ -221,13 +225,16 @@ def get_header(fname, readkwargs):
221
225
  else:
222
226
  headerLen = readkwargs['skiprows']
223
227
  header = []
224
- with open(fname, 'r', encoding="utf-8") as f:
225
- for il, line in enumerate(f):
226
- if il == MAX_HEADER_LINES:
227
- break
228
- if ((headerLen >= 0) and (il <= headerLen)) or \
229
- line.startswith('#'):
230
- header.append(line)
228
+ try:
229
+ with open(fname, 'r', encoding="utf-8") as f:
230
+ for il, line in enumerate(f):
231
+ if il == MAX_HEADER_LINES and not searchAllLines:
232
+ break
233
+ if ((headerLen >= 0) and (il <= headerLen)) or \
234
+ line.startswith('#'):
235
+ header.append(line)
236
+ except FileNotFoundError as e:
237
+ print('core.commons.get_header():', e)
231
238
  return header
232
239
 
233
240
 
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  __author__ = "Konstantin Klementiev"
3
- __date__ = "2 Apr 2021"
3
+ __date__ = "5 May 2021"
4
4
  # !!! SEE CODERULES.TXT !!!
5
5
 
6
6
  import os
@@ -28,6 +28,10 @@ iniFileTransforms = (os.path.join(iniDir, 'transforms.ini'))
28
28
  configTransforms = ConfigParser()
29
29
  configTransforms.read(iniFileTransforms, encoding=encoding)
30
30
 
31
+ iniFileFits = (os.path.join(iniDir, 'fits.ini'))
32
+ configFits = ConfigParser()
33
+ configFits.read(iniFileFits, encoding=encoding)
34
+
31
35
  iniFileFormats = (os.path.join(iniDir, 'formats.ini'))
32
36
  configFormats = ConfigParser()
33
37
  configFormats.read(iniFileFormats, encoding=encoding)
@@ -65,6 +69,9 @@ def write_configs(what='all'): # in mainWindow's closeEvent
65
69
  if (what == 'all') or ('transform' in whatl):
66
70
  with open(iniFileTransforms, 'w+', encoding=encoding) as cf:
67
71
  configTransforms.write(cf)
72
+ if (what == 'all') or ('fit' in whatl):
73
+ with open(iniFileFits, 'w+', encoding=encoding) as cf:
74
+ configFits.write(cf)
68
75
  if (what == 'all') or ('format' in whatl):
69
76
  with open(iniFileFormats, 'w+', encoding=encoding) as cf:
70
77
  configFormats.write(cf)