res2df 1.2.3__tar.gz → 1.3.1__tar.gz

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 (258) hide show
  1. {res2df-1.2.3 → res2df-1.3.1}/.github/workflows/codecov.yml +2 -2
  2. {res2df-1.2.3 → res2df-1.3.1}/.github/workflows/res2df.yml +4 -19
  3. {res2df-1.2.3 → res2df-1.3.1}/.pre-commit-config.yaml +2 -2
  4. res2df-1.3.1/CONTRIBUTING.md +30 -0
  5. {res2df-1.2.3 → res2df-1.3.1}/PKG-INFO +14 -4
  6. {res2df-1.2.3 → res2df-1.3.1}/README.md +1 -1
  7. res2df-1.3.1/ci/testkomodo.sh +13 -0
  8. {res2df-1.2.3 → res2df-1.3.1}/res2df/common.py +9 -8
  9. {res2df-1.2.3 → res2df-1.3.1}/res2df/compdat.py +3 -6
  10. {res2df-1.2.3 → res2df-1.3.1}/res2df/csv2res.py +1 -2
  11. {res2df-1.2.3 → res2df-1.3.1}/res2df/equil.py +1 -1
  12. {res2df-1.2.3 → res2df-1.3.1}/res2df/grid.py +1 -4
  13. {res2df-1.2.3 → res2df-1.3.1}/res2df/gruptree.py +15 -2
  14. {res2df-1.2.3 → res2df-1.3.1}/res2df/pvt.py +1 -1
  15. {res2df-1.2.3 → res2df-1.3.1}/res2df/rft.py +5 -5
  16. {res2df-1.2.3 → res2df-1.3.1}/res2df/satfunc.py +8 -7
  17. {res2df-1.2.3 → res2df-1.3.1}/res2df/summary.py +4 -4
  18. {res2df-1.2.3 → res2df-1.3.1}/res2df/version.py +2 -2
  19. {res2df-1.2.3 → res2df-1.3.1}/res2df.egg-info/PKG-INFO +14 -4
  20. {res2df-1.2.3 → res2df-1.3.1}/res2df.egg-info/SOURCES.txt +1 -0
  21. {res2df-1.2.3 → res2df-1.3.1}/setup.py +1 -1
  22. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/EIGHTCELLS.DATA +2 -2
  23. {res2df-1.2.3 → res2df-1.3.1}/tests/test_equil.py +3 -1
  24. {res2df-1.2.3 → res2df-1.3.1}/tests/test_gruptree.py +14 -14
  25. {res2df-1.2.3 → res2df-1.3.1}/tests/test_rft.py +15 -8
  26. {res2df-1.2.3 → res2df-1.3.1}/tests/test_summary_restarts.py +13 -4
  27. res2df-1.2.3/ci/testkomodo.sh +0 -7
  28. {res2df-1.2.3 → res2df-1.3.1}/.codacy.yml +0 -0
  29. {res2df-1.2.3 → res2df-1.3.1}/.github/workflows/style.yml +0 -0
  30. {res2df-1.2.3 → res2df-1.3.1}/.github/workflows/typing.yml +0 -0
  31. {res2df-1.2.3 → res2df-1.3.1}/.gitignore +0 -0
  32. {res2df-1.2.3 → res2df-1.3.1}/LICENSE +0 -0
  33. {res2df-1.2.3 → res2df-1.3.1}/SECURITY.md +0 -0
  34. {res2df-1.2.3 → res2df-1.3.1}/docs/_static/equinor-logo.png +0 -0
  35. {res2df-1.2.3 → res2df-1.3.1}/docs/_static/equinor-logo2.jpg +0 -0
  36. {res2df-1.2.3 → res2df-1.3.1}/docs/_static/equinor_logo.jpg +0 -0
  37. {res2df-1.2.3 → res2df-1.3.1}/docs/_static/equinor_logo_only.jpg +0 -0
  38. {res2df-1.2.3 → res2df-1.3.1}/docs/_templates/layout.html +0 -0
  39. {res2df-1.2.3 → res2df-1.3.1}/docs/conf.py +0 -0
  40. {res2df-1.2.3 → res2df-1.3.1}/docs/contribution.rst +0 -0
  41. {res2df-1.2.3 → res2df-1.3.1}/docs/csv2res.rst +0 -0
  42. {res2df-1.2.3 → res2df-1.3.1}/docs/glossary.rst +0 -0
  43. {res2df-1.2.3 → res2df-1.3.1}/docs/history.rst +0 -0
  44. {res2df-1.2.3 → res2df-1.3.1}/docs/index.rst +0 -0
  45. {res2df-1.2.3 → res2df-1.3.1}/docs/installation.rst +0 -0
  46. {res2df-1.2.3 → res2df-1.3.1}/docs/introduction.rst +0 -0
  47. {res2df-1.2.3 → res2df-1.3.1}/docs/res2csv.rst +0 -0
  48. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/compdat.csv +0 -0
  49. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/compdat.rst +0 -0
  50. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/equil-example.csv +0 -0
  51. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/equil.rst +0 -0
  52. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/fipnum.inc +0 -0
  53. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/fipreports-example.csv +0 -0
  54. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/fipreports-example.txt +0 -0
  55. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/fipreports.rst +0 -0
  56. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/grid.csv +0 -0
  57. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/grid.rst +0 -0
  58. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/gruptree.csv +0 -0
  59. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/gruptree.rst +0 -0
  60. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/gruptreenet.csv +0 -0
  61. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/images/injectoranalysis.png +0 -0
  62. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/images/multibranch-rftanalysis.png +0 -0
  63. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/nnc.csv +0 -0
  64. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/nnc.rst +0 -0
  65. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/outflow.csv +0 -0
  66. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/pillars-dyn1-stacked.csv +0 -0
  67. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/pillars-dyn1-unstacked.csv +0 -0
  68. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/pillars-example1.csv +0 -0
  69. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/pillars.rst +0 -0
  70. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/pvt.csv +0 -0
  71. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/pvt.rst +0 -0
  72. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/rft.rst +0 -0
  73. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/rft_columns.csv +0 -0
  74. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/satfunc.csv +0 -0
  75. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/satfunc.rst +0 -0
  76. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/summary.csv +0 -0
  77. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/summary.rst +0 -0
  78. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/trans-boundaries.csv +0 -0
  79. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/trans-group.csv +0 -0
  80. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/trans.rst +0 -0
  81. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/trans1.csv +0 -0
  82. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/wcon.csv +0 -0
  83. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/wcon.rst +0 -0
  84. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/well_connection_status.csv +0 -0
  85. {res2df-1.2.3 → res2df-1.3.1}/docs/usage/wellconnstatus.rst +0 -0
  86. {res2df-1.2.3 → res2df-1.3.1}/docs/usage.rst +0 -0
  87. {res2df-1.2.3 → res2df-1.3.1}/mypy.ini +0 -0
  88. {res2df-1.2.3 → res2df-1.3.1}/py.typed +0 -0
  89. {res2df-1.2.3 → res2df-1.3.1}/res2df/__init__.py +0 -0
  90. {res2df-1.2.3 → res2df-1.3.1}/res2df/__version__.py +0 -0
  91. {res2df-1.2.3 → res2df-1.3.1}/res2df/config_jobs/CSV2RES +0 -0
  92. {res2df-1.2.3 → res2df-1.3.1}/res2df/config_jobs/RES2CSV +0 -0
  93. {res2df-1.2.3 → res2df-1.3.1}/res2df/constants.py +0 -0
  94. {res2df-1.2.3 → res2df-1.3.1}/res2df/faults.py +0 -0
  95. {res2df-1.2.3 → res2df-1.3.1}/res2df/fipreports.py +0 -0
  96. {res2df-1.2.3 → res2df-1.3.1}/res2df/hook_implementations/__init__.py +0 -0
  97. {res2df-1.2.3 → res2df-1.3.1}/res2df/hook_implementations/jobs.py +0 -0
  98. {res2df-1.2.3 → res2df-1.3.1}/res2df/inferdims.py +0 -0
  99. {res2df-1.2.3 → res2df-1.3.1}/res2df/nnc.py +0 -0
  100. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/BRANPROP +0 -0
  101. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/COMPDAT +0 -0
  102. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/COMPLUMP +0 -0
  103. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/COMPSEGS +0 -0
  104. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/DENSITY +0 -0
  105. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/EQLDIMS +0 -0
  106. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/EQUIL +0 -0
  107. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/FAULTS +0 -0
  108. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/GRUPNET +0 -0
  109. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/GRUPTREE +0 -0
  110. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/NODEPROP +0 -0
  111. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/PBVD +0 -0
  112. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/PDVD +0 -0
  113. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/PVDG +0 -0
  114. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/PVDO +0 -0
  115. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/PVTG +0 -0
  116. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/PVTO +0 -0
  117. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/PVTW +0 -0
  118. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/ROCK +0 -0
  119. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/RSVD +0 -0
  120. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/RVVD +0 -0
  121. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/SGFN +0 -0
  122. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/SGOF +0 -0
  123. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/SGWFN +0 -0
  124. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/SLGOF +0 -0
  125. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/SOF2 +0 -0
  126. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/SOF3 +0 -0
  127. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/SWFN +0 -0
  128. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/SWOF +0 -0
  129. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/TABDIMS +0 -0
  130. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/VFPINJ +0 -0
  131. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/VFPPROD +0 -0
  132. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/WCONHIST +0 -0
  133. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/WCONINJE +0 -0
  134. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/WCONINJH +0 -0
  135. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/WCONPROD +0 -0
  136. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/WELOPEN +0 -0
  137. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/WELSEGS +0 -0
  138. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/WELSPECS +0 -0
  139. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/WLIST +0 -0
  140. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/WSEGAICD +0 -0
  141. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/WSEGSICD +0 -0
  142. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/WSEGVALV +0 -0
  143. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/readme +0 -0
  144. {res2df-1.2.3 → res2df-1.3.1}/res2df/opmkeywords/runmetoupdate.sh +0 -0
  145. {res2df-1.2.3 → res2df-1.3.1}/res2df/parameters.py +0 -0
  146. {res2df-1.2.3 → res2df-1.3.1}/res2df/pillars.py +0 -0
  147. {res2df-1.2.3 → res2df-1.3.1}/res2df/res2csv.py +0 -0
  148. {res2df-1.2.3 → res2df-1.3.1}/res2df/res2csvlogger.py +0 -0
  149. {res2df-1.2.3 → res2df-1.3.1}/res2df/resdatafiles.py +0 -0
  150. {res2df-1.2.3 → res2df-1.3.1}/res2df/svg_color_keyword_names.txt +0 -0
  151. {res2df-1.2.3 → res2df-1.3.1}/res2df/trans.py +0 -0
  152. {res2df-1.2.3 → res2df-1.3.1}/res2df/vfp/__init__.py +0 -0
  153. {res2df-1.2.3 → res2df-1.3.1}/res2df/vfp/_vfp.py +0 -0
  154. {res2df-1.2.3 → res2df-1.3.1}/res2df/vfp/_vfpcommon.py +0 -0
  155. {res2df-1.2.3 → res2df-1.3.1}/res2df/vfp/_vfpdefs.py +0 -0
  156. {res2df-1.2.3 → res2df-1.3.1}/res2df/vfp/_vfpinj.py +0 -0
  157. {res2df-1.2.3 → res2df-1.3.1}/res2df/vfp/_vfpprod.py +0 -0
  158. {res2df-1.2.3 → res2df-1.3.1}/res2df/wcon.py +0 -0
  159. {res2df-1.2.3 → res2df-1.3.1}/res2df/wellcompletiondata.py +0 -0
  160. {res2df-1.2.3 → res2df-1.3.1}/res2df/wellconnstatus.py +0 -0
  161. {res2df-1.2.3 → res2df-1.3.1}/res2df.egg-info/dependency_links.txt +0 -0
  162. {res2df-1.2.3 → res2df-1.3.1}/res2df.egg-info/entry_points.txt +0 -0
  163. {res2df-1.2.3 → res2df-1.3.1}/res2df.egg-info/not-zip-safe +0 -0
  164. {res2df-1.2.3 → res2df-1.3.1}/res2df.egg-info/requires.txt +0 -0
  165. {res2df-1.2.3 → res2df-1.3.1}/res2df.egg-info/top_level.txt +0 -0
  166. {res2df-1.2.3 → res2df-1.3.1}/ruff.toml +0 -0
  167. {res2df-1.2.3 → res2df-1.3.1}/setup.cfg +0 -0
  168. {res2df-1.2.3 → res2df-1.3.1}/test_requirements.txt +0 -0
  169. {res2df-1.2.3 → res2df-1.3.1}/tests/__init__.py +0 -0
  170. {res2df-1.2.3 → res2df-1.3.1}/tests/conftest.py +0 -0
  171. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/EIGHTCELLS.EGRID +0 -0
  172. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/EIGHTCELLS.INIT +0 -0
  173. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/EIGHTCELLS.INSPEC +0 -0
  174. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/EIGHTCELLS.PRT +0 -0
  175. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/EIGHTCELLS.RFT +0 -0
  176. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/EIGHTCELLS.RSSPEC +0 -0
  177. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/EIGHTCELLS.SMSPEC +0 -0
  178. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/EIGHTCELLS.UNRST +0 -0
  179. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/EIGHTCELLS.UNSMRY +0 -0
  180. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/eightcells_duplicated_summary_vector/EIGHTCELLS_DUPES.DATA +0 -0
  181. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/eightcells_duplicated_summary_vector/EIGHTCELLS_DUPES.SMSPEC +0 -0
  182. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/eightcells_duplicated_summary_vector/EIGHTCELLS_DUPES.UNSMRY +0 -0
  183. {res2df-1.2.3 → res2df-1.3.1}/tests/data/eightcells/zones.lyr +0 -0
  184. {res2df-1.2.3 → res2df-1.3.1}/tests/data/fipreports/TEST1.PRT +0 -0
  185. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/grid/reek.faults +0 -0
  186. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/grid/reek.grid +0 -0
  187. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/grid/reek.multflt +0 -0
  188. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/grid/reek.multz +0 -0
  189. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/grid/reek.perm +0 -0
  190. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/grid/reek.poro +0 -0
  191. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/props/let-sgof.txt +0 -0
  192. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/props/let-swof.txt +0 -0
  193. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/props/reek.endpoints +0 -0
  194. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/props/reek.pvt +0 -0
  195. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/props/reek.swatinit +0 -0
  196. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/props/sgof.txt +0 -0
  197. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/props/swof.inc +0 -0
  198. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/props/swof.txt +0 -0
  199. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/regions/reek.eqlnum +0 -0
  200. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/regions/reek.fipnum +0 -0
  201. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/schedule/op6_aicd1_gp.sch +0 -0
  202. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/schedule/op6_icd1_gp.sch +0 -0
  203. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/schedule/op6_valve1_gp.sch +0 -0
  204. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/schedule/reek_history.sch +0 -0
  205. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/solution/reek.equil +0 -0
  206. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/include/summary/reek.smry +0 -0
  207. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/2_R001_REEK-0-OPMFLOW.PRT +0 -0
  208. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/2_R001_REEK-0.DATA +0 -0
  209. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/2_R001_REEK-0.ECLEND +0 -0
  210. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/2_R001_REEK-0.EGRID +0 -0
  211. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/2_R001_REEK-0.INIT +0 -0
  212. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/2_R001_REEK-0.LOG +0 -0
  213. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/2_R001_REEK-0.PRT +0 -0
  214. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/2_R001_REEK-0.RFT +0 -0
  215. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/2_R001_REEK-0.SMSPEC +0 -0
  216. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/2_R001_REEK-0.UNRST +0 -0
  217. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/2_R001_REEK-0.UNSMRY +0 -0
  218. {res2df-1.2.3 → res2df-1.3.1}/tests/data/reek/eclipse/model/zones.lyr +0 -0
  219. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP.DATA +0 -0
  220. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP.SMSPEC +0 -0
  221. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP.UNSMRY +0 -0
  222. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP_LONG.DATA +0 -0
  223. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP_LONG.SMSPEC +0 -0
  224. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP_LONG.UNSMRY +0 -0
  225. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP.DATA +0 -0
  226. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP.SMSPEC +0 -0
  227. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP.UNSMRY +0 -0
  228. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP_LONG.DATA +0 -0
  229. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP_LONG.SMSPEC +0 -0
  230. {res2df-1.2.3 → res2df-1.3.1}/tests/data/timesteps/SHORT_STEP_WITH_TIMESTEP_LONG.UNSMRY +0 -0
  231. {res2df-1.2.3 → res2df-1.3.1}/tests/test_common.py +0 -0
  232. {res2df-1.2.3 → res2df-1.3.1}/tests/test_compdat.py +0 -0
  233. {res2df-1.2.3 → res2df-1.3.1}/tests/test_eclfiles.py +0 -0
  234. {res2df-1.2.3 → res2df-1.3.1}/tests/test_ert_hooks.py +0 -0
  235. {res2df-1.2.3 → res2df-1.3.1}/tests/test_faults.py +0 -0
  236. {res2df-1.2.3 → res2df-1.3.1}/tests/test_fipreports.py +0 -0
  237. {res2df-1.2.3 → res2df-1.3.1}/tests/test_grid.py +0 -0
  238. {res2df-1.2.3 → res2df-1.3.1}/tests/test_hook_implementations.py +0 -0
  239. {res2df-1.2.3 → res2df-1.3.1}/tests/test_inferdims.py +0 -0
  240. {res2df-1.2.3 → res2df-1.3.1}/tests/test_init.py +0 -0
  241. {res2df-1.2.3 → res2df-1.3.1}/tests/test_integration.py +0 -0
  242. {res2df-1.2.3 → res2df-1.3.1}/tests/test_logging.py +0 -0
  243. {res2df-1.2.3 → res2df-1.3.1}/tests/test_nnc.py +0 -0
  244. {res2df-1.2.3 → res2df-1.3.1}/tests/test_parameters.py +0 -0
  245. {res2df-1.2.3 → res2df-1.3.1}/tests/test_pillars.py +0 -0
  246. {res2df-1.2.3 → res2df-1.3.1}/tests/test_pvt.py +0 -0
  247. {res2df-1.2.3 → res2df-1.3.1}/tests/test_satfunc.py +0 -0
  248. {res2df-1.2.3 → res2df-1.3.1}/tests/test_summary.py +0 -0
  249. {res2df-1.2.3 → res2df-1.3.1}/tests/test_trans.py +0 -0
  250. {res2df-1.2.3 → res2df-1.3.1}/tests/test_userapi.py +0 -0
  251. {res2df-1.2.3 → res2df-1.3.1}/tests/test_vfp.py +0 -0
  252. {res2df-1.2.3 → res2df-1.3.1}/tests/test_wcon.py +0 -0
  253. {res2df-1.2.3 → res2df-1.3.1}/tests/test_wellcompletiondata.py +0 -0
  254. {res2df-1.2.3 → res2df-1.3.1}/tests/test_wellconnstatus.py +0 -0
  255. {res2df-1.2.3 → res2df-1.3.1}/tests/test_welopen.py +0 -0
  256. {res2df-1.2.3 → res2df-1.3.1}/tests/test_wlist.py +0 -0
  257. {res2df-1.2.3 → res2df-1.3.1}/tests/test_zonemap.py +0 -0
  258. {res2df-1.2.3 → res2df-1.3.1}/types_requirements.txt +0 -0
@@ -13,7 +13,7 @@ jobs:
13
13
  os: [ubuntu-latest]
14
14
  env:
15
15
  OS: ${{ matrix.os }}
16
- PYTHON: '3.8'
16
+ PYTHON: '3.11'
17
17
 
18
18
  steps:
19
19
  - uses: actions/checkout@v4
@@ -21,7 +21,7 @@ jobs:
21
21
  - name: Setup Python
22
22
  uses: actions/setup-python@v5
23
23
  with:
24
- python-version: 3.8
24
+ python-version: 3.11
25
25
  cache: "pip"
26
26
  cache-dependency-path: |
27
27
  setup.py
@@ -19,21 +19,13 @@ jobs:
19
19
  runs-on: ubuntu-latest
20
20
  strategy:
21
21
  matrix:
22
- python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
23
- pandas-version: ['pandas>2']
22
+ python-version: ['3.11', '3.12']
24
23
  include:
25
24
  # For one of the Python versions we
26
25
  # install the extra dependency ert
27
26
  # (in order to not double the job matrix)
28
-
29
- # Only test with pandas < 2 for py38 and py311
30
- # No wheels for python3.12 for pandas<2
31
- - python-version: '3.8'
32
- install-ert: true
33
- - python-version: '3.8'
34
- pandas-version: 'pandas<2'
35
27
  - python-version: '3.11'
36
- pandas-version: 'pandas<2'
28
+ install-ert: true
37
29
 
38
30
  steps:
39
31
  - name: Checkout commit locally
@@ -58,13 +50,6 @@ jobs:
58
50
  pip install --upgrade pip
59
51
  pip install ".[tests, docs]"
60
52
 
61
- - name: Install numpy<2 if pandas<2
62
- if: matrix.pandas-version == 'pandas<2'
63
- run: pip install "numpy<2"
64
-
65
- - name: Check pandas version
66
- run: |
67
- pip install "${{matrix.pandas-version}}"
68
53
 
69
54
  - name: Install ert
70
55
  if: matrix.install-ert
@@ -87,7 +72,7 @@ jobs:
87
72
  python setup.py build_sphinx
88
73
 
89
74
  - name: Update GitHub pages
90
- if: github.repository_owner == 'equinor' && github.ref == 'refs/heads/master' && matrix.python-version == '3.8' && matrix.pandas-version == 'pandas>2'
75
+ if: github.repository_owner == 'equinor' && github.ref == 'refs/heads/master' && matrix.python-version == '3.11'
91
76
  run: |
92
77
  cp -R ./build/sphinx/html ../html
93
78
 
@@ -110,7 +95,7 @@ jobs:
110
95
  fi
111
96
 
112
97
  - name: Build python package and publish to pypi
113
- if: github.event_name == 'release' && matrix.python-version == '3.8' && matrix.pandas-version == 'pandas>2'
98
+ if: github.event_name == 'release' && matrix.python-version == '3.11'
114
99
  env:
115
100
  TWINE_USERNAME: __token__
116
101
  TWINE_PASSWORD: ${{ secrets.res2df_pypi_token }}
@@ -1,6 +1,6 @@
1
1
  repos:
2
2
  - repo: https://github.com/pre-commit/pre-commit-hooks
3
- rev: v4.6.0
3
+ rev: v5.0.0
4
4
  hooks:
5
5
  - id: no-commit-to-branch
6
6
  args: ['--branch', 'master']
@@ -13,7 +13,7 @@ repos:
13
13
  - id: trailing-whitespace
14
14
 
15
15
  - repo: https://github.com/astral-sh/ruff-pre-commit
16
- rev: v0.5.7
16
+ rev: v0.9.2
17
17
  hooks:
18
18
  - id: ruff
19
19
  args: [ --fix ]
@@ -0,0 +1,30 @@
1
+ # Contributing
2
+
3
+ The following is a set of guidelines for contributing to `res2df`.
4
+
5
+ There are several important ways you can help; here are some examples:
6
+
7
+ - Submitting bug reports and feature requests: see [Issues](https://github.com/equinor/res2df/issues).
8
+ - Proposing code for bug fixes and new features, then [making a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
9
+ - Fixing typos and generally improving the documentation.
10
+ - Writing tutorials, examples, and how-to documents.
11
+
12
+
13
+ ## Commits
14
+
15
+ We strive to keep a consistent and clean git history and all contributions should adhere to the following:
16
+
17
+ 1. All tests should pass on all commits
18
+ 1. A commit should do one atomic change on the repository
19
+ 1. The commit headline should be descriptive and in the imperative
20
+
21
+ Please note that we use [`black`](https://black.readthedocs.io/en/stable/) and [`isort`](https://pycqa.github.io/isort/) for code formatting.
22
+
23
+
24
+ ## Pull request process
25
+
26
+ 1. Work on your own fork of the main repo.
27
+ 1. Push your commits and make a draft pull request using the pull request template.
28
+ 1. Check that your pull request passes all tests.
29
+ 1. When all tests have passed and your are happy with your changes, change your pull request to "ready for review", and ask for a code review.
30
+ 1. When your code has been approved you should rebase, squash and merge your changes.
@@ -1,12 +1,12 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: res2df
3
- Version: 1.2.3
3
+ Version: 1.3.1
4
4
  Summary: Convert reservoir simulator input and output to DataFrames
5
5
  Home-page: http://github.com/equinor/res2df
6
6
  Author: Håvard Berland
7
7
  Author-email: havb@equinor.com
8
8
  License: GPLv3
9
- Requires-Python: >=3.8
9
+ Requires-Python: >=3.11
10
10
  Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
12
  Requires-Dist: resdata>=5.0.0-b0
@@ -41,10 +41,20 @@ Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
41
41
  Requires-Dist: sphinx_rtd_theme; extra == "docs"
42
42
  Provides-Extra: ert
43
43
  Requires-Dist: ert>=10.2.0b13; extra == "ert"
44
+ Dynamic: author
45
+ Dynamic: author-email
46
+ Dynamic: description
47
+ Dynamic: description-content-type
48
+ Dynamic: home-page
49
+ Dynamic: license
50
+ Dynamic: provides-extra
51
+ Dynamic: requires-dist
52
+ Dynamic: requires-python
53
+ Dynamic: summary
44
54
 
45
55
  [![Build Status](https://img.shields.io/github/workflow/status/equinor/res2df/res2df)](https://github.com/equinor/res2df/actions?query=workflow%3Ares2df)
46
56
  [![codecov](https://codecov.io/gh/equinor/res2df/graph/badge.svg?token=3sZBGGu5VG)](https://codecov.io/gh/equinor/res2df)
47
- [![Python 3.8-3.12](https://img.shields.io/badge/python-3.8%20|%203.9%20|%203.10%20|%203.11%20|%203.12-blue.svg)](https://www.python.org)
57
+ [![Python 3.11-3.12](https://img.shields.io/badge/python-3.11%20|%203.12-blue.svg)](https://www.python.org)
48
58
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
49
59
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
50
60
 
@@ -1,6 +1,6 @@
1
1
  [![Build Status](https://img.shields.io/github/workflow/status/equinor/res2df/res2df)](https://github.com/equinor/res2df/actions?query=workflow%3Ares2df)
2
2
  [![codecov](https://codecov.io/gh/equinor/res2df/graph/badge.svg?token=3sZBGGu5VG)](https://codecov.io/gh/equinor/res2df)
3
- [![Python 3.8-3.12](https://img.shields.io/badge/python-3.8%20|%203.9%20|%203.10%20|%203.11%20|%203.12-blue.svg)](https://www.python.org)
3
+ [![Python 3.11-3.12](https://img.shields.io/badge/python-3.11%20|%203.12-blue.svg)](https://www.python.org)
4
4
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
5
5
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
6
6
 
@@ -0,0 +1,13 @@
1
+ install_test_dependencies () {
2
+ pip install -r test_requirements.txt
3
+ }
4
+
5
+ start_tests () {
6
+ SHELLOPTS_BEFORE=$(set +o)
7
+ set +e
8
+ # (this script becomes flaky if set -e is active)
9
+ source /prog/res/ecl/script/eclrun.bash
10
+ eval "$SHELLOPTS_BEFORE"
11
+
12
+ pytest --run-eclipse-simulator
13
+ }
@@ -10,6 +10,7 @@ import re
10
10
  import shlex
11
11
  import signal
12
12
  import sys
13
+ from collections import defaultdict
13
14
  from pathlib import Path
14
15
  from typing import Any, Dict, List, Optional, Set, Union
15
16
 
@@ -397,7 +398,7 @@ def merge_zones(
397
398
  zone_df.index.name = "K"
398
399
  zone_df.reset_index(inplace=True)
399
400
 
400
- df[zoneheader] = df[kname].map(zonedict)
401
+ df[zoneheader] = df[kname].map(defaultdict(lambda: None, zonedict))
401
402
  return df
402
403
 
403
404
 
@@ -476,7 +477,7 @@ def fill_reverse_parser(
476
477
  """
477
478
  parser.add_argument(
478
479
  "csvfile",
479
- help="Name of CSV file with " + modulename + " data with " "res2df format",
480
+ help="Name of CSV file with " + modulename + " data with res2df format",
480
481
  )
481
482
  parser.add_argument(
482
483
  "-o",
@@ -690,7 +691,7 @@ def generic_deck_table(
690
691
 
691
692
  # NaN or Nones are assumed to be defaulted, which in Eclipse terminology is
692
693
  # the string "1*":
693
- dframe.fillna(value="1*", inplace=True)
694
+ dframe = dframe.fillna(value="1*")
694
695
 
695
696
  if drop_trailing_columns:
696
697
  for col_name in reversed(relevant_columns):
@@ -709,9 +710,9 @@ def generic_deck_table(
709
710
  }
710
711
  for int_col in integer_cols.intersection(dframe.columns):
711
712
  defaulted_rows = dframe[int_col] == "1*"
712
- dframe.loc[~defaulted_rows, int_col] = (
713
- dframe.loc[~defaulted_rows, int_col].astype(int).astype(str)
714
- )
713
+ integer_values = dframe.loc[~defaulted_rows, int_col].astype(int)
714
+ dframe[int_col] = dframe[int_col].astype(str)
715
+ dframe.loc[~defaulted_rows, int_col] = integer_values
715
716
 
716
717
  # Quote all string data. This is not always needed, but needed
717
718
  # for some colums, for example well-names containing a slash.
@@ -826,9 +827,9 @@ def stack_on_colnames(
826
827
  dframe.columns = pd.MultiIndex.from_tuples(
827
828
  tuplecolumns, names=["dummy", stackcolname]
828
829
  )
829
- dframe = dframe.stack()
830
+ dframe = dframe.stack(future_stack=True)
830
831
  staticcols = [col[0] for col in tuplecolumns if len(col) == 1]
831
- dframe[staticcols] = dframe[staticcols].fillna(method="ffill")
832
+ dframe[staticcols] = dframe[staticcols].ffill()
832
833
  dframe.reset_index(inplace=True)
833
834
  # Drop rows stemming from the NaNs in the second tuple-element for
834
835
  # static columns:
@@ -615,8 +615,7 @@ def expand_wlist(wlist_df: pd.DataFrame) -> pd.DataFrame:
615
615
  and wlist_record["NAME"] not in currentstate
616
616
  ):
617
617
  raise ValueError(
618
- "WLIST ADD/DEL only works on existing well lists: "
619
- f"{str(wlist_record)}"
618
+ f"WLIST ADD/DEL only works on existing well lists: {str(wlist_record)}"
620
619
  )
621
620
  if wlist_record["ACTION"] == "ADD":
622
621
  currentstate[wlist_record["NAME"]] = " ".join(
@@ -888,14 +887,12 @@ def applywelopen(
888
887
  ].drop_duplicates(subset=["I", "J", "K1", "K2"], keep="last")
889
888
  else:
890
889
  raise ValueError(
891
- "A WELOPEN keyword contains data that could not be parsed. "
892
- f"\n {row} "
890
+ f"A WELOPEN keyword contains data that could not be parsed. \n {row} "
893
891
  )
894
892
 
895
893
  if previous_state.empty:
896
894
  raise ValueError(
897
- "A WELOPEN keyword is not acting on any existing connection. "
898
- f"\n {row} "
895
+ f"A WELOPEN keyword is not acting on any existing connection. \n {row} "
899
896
  )
900
897
 
901
898
  new_state = previous_state
@@ -90,8 +90,7 @@ def get_parser() -> argparse.ArgumentParser:
90
90
  "satfunc",
91
91
  help="Write saturation function include files",
92
92
  description=(
93
- "Write saturation function include files from CSV files with "
94
- "res2df format."
93
+ "Write saturation function include files from CSV files with res2df format."
95
94
  ),
96
95
  )
97
96
  satfunc_fill_reverse_parser(satfunc_parser)
@@ -298,7 +298,7 @@ def fill_parser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
298
298
  "-o",
299
299
  "--output",
300
300
  type=str,
301
- help=("Name of output csv file. " "Use '-' for stdout."),
301
+ help=("Name of output csv file. Use '-' for stdout."),
302
302
  default="equil.csv",
303
303
  )
304
304
  parser.add_argument(
@@ -686,10 +686,7 @@ def df2res(
686
686
 
687
687
  if "GLOBAL_INDEX" not in grid_df:
688
688
  logger.warning(
689
- (
690
- "Global index not found in grid dataframe. "
691
- "Assumes all cells are active"
692
- )
689
+ ("Global index not found in grid dataframe. Assumes all cells are active")
693
690
  )
694
691
  # Drop NaN rows for columns to be used (triggered by stacked
695
692
  # dates and no global index, unlikely)
@@ -9,6 +9,7 @@ import sys
9
9
  import warnings
10
10
  from typing import Any, Dict, List, Optional, Tuple, Union
11
11
 
12
+ import numpy as np
12
13
  import pandas as pd
13
14
  import treelib
14
15
 
@@ -19,6 +20,7 @@ with contextlib.suppress(ImportError):
19
20
  import opm.io
20
21
 
21
22
  from .common import (
23
+ OPMKEYWORDS,
22
24
  parse_opmio_date_rec,
23
25
  parse_opmio_deckrecord,
24
26
  parse_opmio_tstep_rec,
@@ -91,7 +93,7 @@ def df(
91
93
  # Flags which will tell when a new network related keyword
92
94
  # has been encountered
93
95
  keywords = ["GRUPTREE", "BRANPROP", "WELSPECS", "GRUPNET", "NODEPROP"]
94
- found_keywords = {key: False for key in keywords}
96
+ found_keywords = dict.fromkeys(keywords, False)
95
97
  for kword in deck:
96
98
  if kword.name in ["DATES", "START", "TSTEP"]:
97
99
  # Whenever we encounter a new DATES, it means that
@@ -107,7 +109,7 @@ def df(
107
109
  edgerecords += _write_edgerecords(
108
110
  currentedges, nodedata, wellspecsedges, found_keywords, date
109
111
  )
110
- found_keywords = {key: False for key in keywords}
112
+ found_keywords = dict.fromkeys(keywords, False)
111
113
  # Done dumping the data for the previous date, parse the fresh
112
114
  # date:
113
115
  if kword.name in ["DATES", "START"]:
@@ -164,6 +166,17 @@ def df(
164
166
  currentedges, nodedata, wellspecsedges, found_keywords, date
165
167
  )
166
168
  dframe = pd.DataFrame(edgerecords)
169
+
170
+ string_cols = {"PARENT", "CHILD"}
171
+ for keyword in ["GRUPTREE", "BRANPROP", "NODEPROP", "GRUPNET", "WELSPECS"]:
172
+ string_cols |= {
173
+ item["name"]
174
+ for item in OPMKEYWORDS[keyword]["items"]
175
+ if item["value_type"] == "STRING"
176
+ }
177
+ for col in string_cols:
178
+ if col in dframe:
179
+ dframe[col] = dframe[col].replace(np.nan, None)
167
180
  if "DATE" in dframe:
168
181
  dframe["DATE"] = pd.to_datetime(dframe["DATE"])
169
182
 
@@ -375,7 +375,7 @@ def df2res_rock(dframe: pd.DataFrame, comment: Optional[str] = None) -> str:
375
375
  return "-- No data!"
376
376
  string = "ROCK\n"
377
377
  string += comment_formatter(comment)
378
- string += "-- {'PRESSURE':^21} {'COMPRESSIBILITY':^21}\n"
378
+ string += f"-- {'PRESSURE':^21} {'COMPRESSIBILITY':^21}\n"
379
379
  # Use everything if KEYWORD not in dframe..
380
380
  subset = dframe if "KEYWORD" not in dframe else dframe[dframe["KEYWORD"] == "ROCK"]
381
381
  if "PVTNUM" not in subset:
@@ -90,8 +90,8 @@ def _rftrecords2df(rftfile: ResdataFile) -> pd.DataFrame:
90
90
  nav_df.loc[nav_df["recordname"] == "TIME", "timeindex"] = nav_df[
91
91
  nav_df["recordname"] == "TIME"
92
92
  ].index
93
- nav_df.fillna(
94
- method="ffill", inplace=True
93
+ nav_df.ffill(
94
+ inplace=True
95
95
  ) # forward fill (because any record is associated to the previous TIME record)
96
96
  nav_df["timeindex"] = nav_df["timeindex"].astype(int)
97
97
  logger.info(
@@ -242,7 +242,7 @@ def process_seg_topology(seg_data: pd.DataFrame) -> pd.DataFrame:
242
242
  seg_data = seg_data.sort_values("SEGIDX")
243
243
  # For the first segment, None is allowed as SEGNXT, which excludes
244
244
  # int as a Pandas type. Convert to 0 for the moment
245
- seg_data["SEGNXT"] = seg_data["SEGNXT"].fillna(value=0).astype(int)
245
+ seg_data["SEGNXT"] = seg_data["SEGNXT"].fillna(value="0").astype(int)
246
246
 
247
247
  # Outer merge first to add the upstream segment information to every row.
248
248
  merged = pd.merge(
@@ -481,14 +481,14 @@ def add_extras(dframe: pd.DataFrame, inplace: bool = True) -> pd.DataFrame:
481
481
  dframe = dframe.copy()
482
482
 
483
483
  if "CONPRES" in dframe and "SEGPRES" in dframe:
484
- dframe["COMPLETION_DP"] = 0
484
+ dframe["COMPLETION_DP"] = 0.0
485
485
  nonzero_pres = (dframe["CONPRES"] > 0) & (dframe["SEGPRES"] > 0)
486
486
  dframe.loc[nonzero_pres, "COMPLETION_DP"] = (
487
487
  dframe.loc[nonzero_pres, "CONPRES"] - dframe.loc[nonzero_pres, "SEGPRES"]
488
488
  )
489
489
 
490
490
  if not dframe.empty:
491
- dframe["DRAWDOWN"] = 0 # Set a default so that the column always exists
491
+ dframe["DRAWDOWN"] = 0.0 # Set a default so that the column always exists
492
492
 
493
493
  if "CONPRES" in dframe and "PRESSURE" in dframe:
494
494
  nonzero_conpres = dframe["CONPRES"] > 0
@@ -144,9 +144,9 @@ def interpolate_defaults(dframe: pd.DataFrame) -> pd.DataFrame:
144
144
  can consist of multiple SATNUMs.
145
145
  """
146
146
  sat_cols: set = {"SW", "SO", "SG", "SL"}.intersection(dframe.columns)
147
- assert (
148
- len(sat_cols) == 1
149
- ), f"Could not determine a single saturation column in {dframe.columns}"
147
+ assert len(sat_cols) == 1, (
148
+ f"Could not determine a single saturation column in {dframe.columns}"
149
+ )
150
150
  sat_col = list(sat_cols)[0]
151
151
 
152
152
  if dframe[sat_col].isna().any():
@@ -154,11 +154,12 @@ def interpolate_defaults(dframe: pd.DataFrame) -> pd.DataFrame:
154
154
 
155
155
  filled_frames = []
156
156
  for _, subframe in dframe.groupby("SATNUM"):
157
- filled_frames.append(
158
- subframe.set_index(sat_col)
159
- .interpolate(method="index", limit_area="inside")
160
- .reset_index()
157
+ subframe.set_index(sat_col, inplace=True)
158
+ numeric_columns = subframe.select_dtypes(include=["float", "int"]).columns
159
+ subframe[numeric_columns] = subframe[numeric_columns].interpolate(
160
+ method="index", limit_area="inside"
161
161
  )
162
+ filled_frames.append(subframe.reset_index())
162
163
  return pd.concat(filled_frames)
163
164
 
164
165
 
@@ -461,7 +461,9 @@ def _ensure_unique_datetime_index(dframe: pd.DataFrame) -> pd.DataFrame:
461
461
 
462
462
  if dframe.attrs["meta"]["TIMESTEP"]["unit"] == "DAYS":
463
463
  for idx in np.where(index_duplicates)[0]:
464
- index_as_list[idx] += dt.timedelta(days=dframe["TIMESTEP"][idx])
464
+ index_as_list[idx] += dt.timedelta(
465
+ days=dframe["TIMESTEP"].iloc[idx]
466
+ )
465
467
  elif dframe.attrs["meta"]["TIMESTEP"]["unit"] == "HOURS":
466
468
  for idx in np.where(index_duplicates)[0]:
467
469
  index_as_list[idx] += dt.timedelta(hours=dframe["TIMESTEP"][idx])
@@ -761,9 +763,7 @@ def fill_parser(parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
761
763
  "-o",
762
764
  "--output",
763
765
  type=str,
764
- help=(
765
- "Name of output file. Use '-' to write to stdout. " "Default 'summary.csv'"
766
- ),
766
+ help=("Name of output file. Use '-' to write to stdout. Default 'summary.csv'"),
767
767
  default="summary.csv",
768
768
  )
769
769
  parser.add_argument("--arrow", action="store_true", help="Write to pyarrow format")
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.2.3'
16
- __version_tuple__ = version_tuple = (1, 2, 3)
15
+ __version__ = version = '1.3.1'
16
+ __version_tuple__ = version_tuple = (1, 3, 1)
@@ -1,12 +1,12 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: res2df
3
- Version: 1.2.3
3
+ Version: 1.3.1
4
4
  Summary: Convert reservoir simulator input and output to DataFrames
5
5
  Home-page: http://github.com/equinor/res2df
6
6
  Author: Håvard Berland
7
7
  Author-email: havb@equinor.com
8
8
  License: GPLv3
9
- Requires-Python: >=3.8
9
+ Requires-Python: >=3.11
10
10
  Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
12
  Requires-Dist: resdata>=5.0.0-b0
@@ -41,10 +41,20 @@ Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
41
41
  Requires-Dist: sphinx_rtd_theme; extra == "docs"
42
42
  Provides-Extra: ert
43
43
  Requires-Dist: ert>=10.2.0b13; extra == "ert"
44
+ Dynamic: author
45
+ Dynamic: author-email
46
+ Dynamic: description
47
+ Dynamic: description-content-type
48
+ Dynamic: home-page
49
+ Dynamic: license
50
+ Dynamic: provides-extra
51
+ Dynamic: requires-dist
52
+ Dynamic: requires-python
53
+ Dynamic: summary
44
54
 
45
55
  [![Build Status](https://img.shields.io/github/workflow/status/equinor/res2df/res2df)](https://github.com/equinor/res2df/actions?query=workflow%3Ares2df)
46
56
  [![codecov](https://codecov.io/gh/equinor/res2df/graph/badge.svg?token=3sZBGGu5VG)](https://codecov.io/gh/equinor/res2df)
47
- [![Python 3.8-3.12](https://img.shields.io/badge/python-3.8%20|%203.9%20|%203.10%20|%203.11%20|%203.12-blue.svg)](https://www.python.org)
57
+ [![Python 3.11-3.12](https://img.shields.io/badge/python-3.11%20|%203.12-blue.svg)](https://www.python.org)
48
58
  [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
49
59
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
50
60
 
@@ -1,6 +1,7 @@
1
1
  .codacy.yml
2
2
  .gitignore
3
3
  .pre-commit-config.yaml
4
+ CONTRIBUTING.md
4
5
  LICENSE
5
6
  README.md
6
7
  SECURITY.md
@@ -85,5 +85,5 @@ setup(
85
85
  install_requires=REQUIREMENTS,
86
86
  setup_requires=SETUP_REQUIREMENTS,
87
87
  extras_require=EXTRAS_REQUIRE,
88
- python_requires=">=3.8",
88
+ python_requires=">=3.11",
89
89
  )
@@ -17,7 +17,7 @@ EQLDIMS
17
17
  1 /
18
18
 
19
19
  WELLDIMS
20
- 1 /
20
+ 1 1 1 1 /
21
21
 
22
22
  WSEGDIMS
23
23
  1 10 10 /
@@ -161,7 +161,7 @@ WELSEGS
161
161
  COMPSEGS
162
162
  OP1 /
163
163
  --i j k branch len
164
- 1 1 1 1 10 10 Z /
164
+ 1 1 1 1 10 20 Z /
165
165
  /
166
166
 
167
167
  WRFTPLT
@@ -446,7 +446,7 @@ RSVD
446
446
  pd.testing.assert_frame_equal(rsvd_df, rsvd_df_fromcsv)
447
447
 
448
448
 
449
- def test_ntequl():
449
+ def test_ntequl_no_eqldims():
450
450
  """Test that we can infer NTEQUL when not supplied"""
451
451
  deckstr = """
452
452
  GAS
@@ -479,6 +479,8 @@ EQUIL
479
479
  with pytest.raises((ValueError, RuntimeError)):
480
480
  equil.df(deckstr, ntequl=3)
481
481
 
482
+
483
+ def test_ntequl_with_eqldims():
482
484
  deckstr = """
483
485
  GAS
484
486
  OIL
@@ -31,7 +31,7 @@ def test_eightcells_dataset():
31
31
 
32
32
  expected_dframe = pd.DataFrame(
33
33
  [
34
- ["2000-01-01", "FIELD", "GRUPTREE", np.nan],
34
+ ["2000-01-01", "FIELD", "GRUPTREE", None],
35
35
  ["2000-01-01", "OP1", "WELSPECS", "OPS"],
36
36
  ["2000-01-01", "OPS", "GRUPTREE", "FIELD"],
37
37
  ],
@@ -291,7 +291,7 @@ GRUPNET
291
291
  {"CHILD": "FIELDB", "PARENT": None, "TERMINAL_PRESSURE": 80},
292
292
  {"CHILD": "FIELDA", "PARENT": None, "TERMINAL_PRESSURE": 90},
293
293
  {"CHILD": "OP", "PARENT": "FIELDA", "TERMINAL_PRESSURE": 100},
294
- {"CHILD": "OPX", "PARENT": "FIELDB", "TERMINAL_PRESSURE": None},
294
+ {"CHILD": "OPX", "PARENT": "FIELDB", "TERMINAL_PRESSURE": np.nan},
295
295
  ]
296
296
  ),
297
297
  """
@@ -588,12 +588,12 @@ BRANPROP
588
588
  """,
589
589
  pd.DataFrame(
590
590
  [
591
- ["2000-01-01", "FIELD", "GRUPTREE", np.nan, np.nan, np.nan],
591
+ ["2000-01-01", "FIELD", "GRUPTREE", None, np.nan, np.nan],
592
592
  ["2000-01-01", "TMPL_A", "GRUPTREE", "FIELD", np.nan, np.nan],
593
- ["2000-01-01", "FIELD", "BRANPROP", np.nan, np.nan, 20],
593
+ ["2000-01-01", "FIELD", "BRANPROP", None, np.nan, 20],
594
594
  ["2000-01-01", "NODE_A", "BRANPROP", "FIELD", 1, np.nan],
595
595
  ["2000-01-01", "TMPL_A", "BRANPROP", "NODE_A", 2, np.nan],
596
- ["2000-02-01", "FIELD", "BRANPROP", np.nan, np.nan, 20],
596
+ ["2000-02-01", "FIELD", "BRANPROP", None, np.nan, 20],
597
597
  ["2000-02-01", "NODE_A", "BRANPROP", "FIELD", 1, np.nan],
598
598
  ["2000-02-01", "NODE_B", "BRANPROP", "FIELD", 3, np.nan],
599
599
  ["2000-02-01", "TMPL_A", "BRANPROP", "NODE_B", 4, np.nan],
@@ -636,13 +636,13 @@ NODEPROP
636
636
  """,
637
637
  pd.DataFrame(
638
638
  [
639
- ["2000-01-01", "FIELD", "GRUPTREE", np.nan, np.nan, np.nan],
640
- ["2000-01-01", "TMPL_A", "GRUPTREE", "FIELD", np.nan, np.nan],
641
- ["2000-01-01", "FIELD", "BRANPROP", np.nan, 20, "NO"],
642
- ["2000-01-01", "NODE_A", "BRANPROP", "FIELD", np.nan, np.nan],
639
+ ["2000-01-01", "FIELD", "GRUPTREE", None, np.nan, None],
640
+ ["2000-01-01", "TMPL_A", "GRUPTREE", "FIELD", None, None],
641
+ ["2000-01-01", "FIELD", "BRANPROP", None, 20, "NO"],
642
+ ["2000-01-01", "NODE_A", "BRANPROP", "FIELD", np.nan, None],
643
643
  ["2000-01-01", "TMPL_A", "BRANPROP", "NODE_A", np.nan, "YES"],
644
- ["2000-02-01", "FIELD", "BRANPROP", np.nan, 22, "YES"],
645
- ["2000-02-01", "NODE_A", "BRANPROP", "FIELD", np.nan, np.nan],
644
+ ["2000-02-01", "FIELD", "BRANPROP", None, 22, "YES"],
645
+ ["2000-02-01", "NODE_A", "BRANPROP", "FIELD", np.nan, None],
646
646
  ["2000-02-01", "TMPL_A", "BRANPROP", "NODE_A", np.nan, "YES"],
647
647
  ],
648
648
  columns=[
@@ -699,15 +699,15 @@ NODEPROP
699
699
  # where there are two trees
700
700
  pd.DataFrame(
701
701
  [
702
- ["2000-01-01", "FIELD", "GRUPTREE", np.nan],
702
+ ["2000-01-01", "FIELD", "GRUPTREE", None],
703
703
  ["2000-01-01", "TMPL_A", "GRUPTREE", "FIELD"],
704
704
  ["2000-01-01", "WELL_2", "WELSPECS", "TMPL_B"],
705
705
  ["2000-01-01", "TMPL_B", "GRUPTREE", "FIELD"],
706
- ["2000-01-01", "FIELD", "BRANPROP", np.nan],
706
+ ["2000-01-01", "FIELD", "BRANPROP", None],
707
707
  ["2000-01-01", "NODE_A", "BRANPROP", "FIELD"],
708
708
  ["2000-01-01", "TMPL_A", "BRANPROP", "NODE_A"],
709
709
  ["2000-01-01", "WELL_1", "WELSPECS", "TMPL_A"],
710
- ["2000-02-01", "FIELD", "BRANPROP", np.nan],
710
+ ["2000-02-01", "FIELD", "BRANPROP", None],
711
711
  ["2000-02-01", "NODE_A", "BRANPROP", "FIELD"],
712
712
  ["2000-02-01", "TMPL_A", "BRANPROP", "NODE_A"],
713
713
  ["2000-02-01", "WELL_1", "WELSPECS", "TMPL_A"],