codecov-io: # [Codecov](https://codecov.io/gh/sdepy/sdepy/pull/13?src=pr&el=h1) Report
> Merging [#13](https://codecov.io/gh/sdepy/sdepy/pull/13?src=pr&el=desc) into [master](https://codecov.io/gh/sdepy/sdepy/commit/b90667045d3d2480b39151152ee7ba4b429fec19?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/sdepy/sdepy/pull/13/graphs/tree.svg?width=650&token=sXNigQjlFY&height=150&src=pr)](https://codecov.io/gh/sdepy/sdepy/pull/13?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master      #13   +/-   ##
=======================================
  Coverage   91.58%   91.58%           
=======================================
  Files           7        7           
  Lines        1877     1877           
  Branches      272      272           
=======================================
  Hits         1719     1719           
  Misses         96       96           
  Partials       62       62
```


| [Impacted Files](https://codecov.io/gh/sdepy/sdepy/pull/13?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [sdepy/infrastructure.py](https://codecov.io/gh/sdepy/sdepy/pull/13/diff?src=pr&el=tree#diff-c2RlcHkvaW5mcmFzdHJ1Y3R1cmUucHk=) | `88.75% <ø> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/sdepy/sdepy/pull/13?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/sdepy/sdepy/pull/13?src=pr&el=footer). Last update [b906670...7843e22](https://codecov.io/gh/sdepy/sdepy/pull/13?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/sdepy/infrastructure.py b/sdepy/infrastructure.py
index dc873b3..d557ea4 100644
--- a/sdepy/infrastructure.py
+++ b/sdepy/infrastructure.py
@@ -796,7 +796,8 @@ class process(np.ndarray):
         the minimum process value attained across paths.
         """
         return process(t=self.t,
-                       v=self.min(axis=-1, out=out))
+                       x=self.min(axis=-1, out=out,
+                                  keepdims=True))
 
     def pmax(self, out=None):
         """
@@ -804,7 +805,8 @@ class process(np.ndarray):
         the maximum process value attained across paths.
         """
         return process(t=self.t,
-                       v=self.max(axis=-1, out=out))
+                       x=self.max(axis=-1, out=out,
+                                  keepdims=True))
 
     def psum(self, dtype=None, out=None):
         """
@@ -855,14 +857,16 @@ class process(np.ndarray):
         process value attained along time.
         """
         return process(t=self.t[:1],
-                       x=self.min(axis=0, out=out)[np.newaxis, ...])
+                       x=self.min(axis=0, out=out,
+                                  keepdims=True))
 
     def tmax(self, out=None):
         """Constant process exposing for each path the maximum
         process value attained along time.
         """
         return process(t=self.t[:1],
-                       x=self.max(axis=0, out=out)[np.newaxis, ...])
+                       x=self.max(axis=0, out=out,
+                                  keepdims=True))
 
     def tsum(self, dtype=None, out=None):
         """

Process methods 'pmin', 'pmax', 'tmin', 'tmax': bug in 'out' parameter handling
The ``out`` parameter of summary methods for the ``process`` class is expected to behave as the ``out`` parameter of the corresponding ``numpy.ndarray`` methods, to which it is actually passed through. In particular, its shape should match the shape of the resulting summarized process.

For the methods in question, a properly sized ``out`` array causes a ``ValueError`` to be raised in numpy, while omitting the leading or trailing one dimensional axis is in fact required. This behavior is in contrast with that of all other summary methods, and is regarded as a bug to be fixed.
diff --git a/sdepy/tests/test_process.py b/sdepy/tests/test_process.py
index 26bea8d..5a7f2ad 100644
--- a/sdepy/tests/test_process.py
+++ b/sdepy/tests/test_process.py
@@ -582,28 +582,63 @@ def test_summary():
 
     # summary across paths
     for f in funcs:
+        # test values
         a = getattr(p, 'p' + f)()
-        b = getattr(np, f)(p, axis=-1)
-        assert_allclose(a, b[..., np.newaxis], rtol=eps(p.dtype))
-        a = p.pmean(dtype=np.float32)
+        b = getattr(np, f)(p, axis=-1)[..., np.newaxis]
+        assert_allclose(a, b, rtol=eps(p.dtype))
+        # test out parameter
+        y = np.full((3, 5, 7, 1), np.nan)
+        a = getattr(p, 'p' + f)(out=y)
+        assert_(a.base is y)
+        assert_allclose(y, b, rtol=eps(p.dtype))
+    for f in ('sum', 'mean', 'var', 'std'):
+        # test dtype parameter
+        a = getattr(p, 'p' + f)(dtype=np.float32)
         assert_(a.dtype == np.float32)
-        b = p.pvar(ddof=1, out=a)
-        assert_allclose(b, p.var(ddof=1, axis=-1)[..., np.newaxis],
-                        rtol=eps(np.float32))
+    # test ddof parameter for pvar and pstd
+    a = p.pvar(ddof=1)
+    assert_allclose(a, p.var(ddof=1, axis=-1)[..., np.newaxis],
+                    rtol=eps(p.dtype))
+    a = p.pstd(ddof=1)
+    assert_allclose(a, p.std(ddof=1, axis=-1)[..., np.newaxis],
+                    rtol=eps(p.dtype))
 
     # summary along the timeline
     for f in funcs:
+        # test values
         a = getattr(p, 't' + f)()
-        b = getattr(np, f)(p, axis=0)
-        assert_allclose(a, b[np.newaxis, ...], rtol=eps(p.dtype))
-        a = p.tmean(dtype=np.float32)
-        assert_(a.dtype == np.float32)
-        b = p.tvar(ddof=1, out=a)
-        assert_allclose(b, p.var(ddof=1, axis=0)[np.newaxis, ...],
-                        rtol=eps(np.float32))
-        a = p.tcumsum()
-        b = np.cumsum(p, axis=0)
+        b = getattr(np, f)(p, axis=0)[np.newaxis, ...]
         assert_allclose(a, b, rtol=eps(p.dtype))
+        # test out parameter
+        y = np.full((1, 5, 7, 11), np.nan)
+        a = getattr(p, 't' + f)(out=y)
+        assert_(a.base is y)
+        assert_allclose(y, b, rtol=eps(p.dtype))
+    for f in ('sum', 'mean', 'var', 'std'):
+        # test dtype parameter
+        a = getattr(p, 't' + f)(dtype=np.float32)
+        assert_(a.dtype == np.float32)
+
+    # test ddof parameter for tvar and tstd
+    a = p.tvar(ddof=1)
+    assert_allclose(a, p.var(ddof=1, axis=0)[np.newaxis, ...],
+                    rtol=eps(p.dtype))
+    a = p.tstd(ddof=1)
+    assert_allclose(a, p.std(ddof=1, axis=0)[np.newaxis, ...],
+                    rtol=eps(p.dtype))
+
+    # test tcumsum values
+    a = p.tcumsum()
+    b = np.cumsum(p, axis=0)
+    assert_allclose(a, b, rtol=3*eps(p.dtype))
+    # test tcumsum out parameter
+    y = np.full((3, 5, 7, 11), np.nan)
+    a = p.tcumsum(out=y)
+    assert_(a.base is y)
+    assert_allclose(y, b, rtol=3*eps(p.dtype))
+    # test tcumsum dtype parameter
+    a = p.tcumsum(dtype=np.float32)
+    assert_(a.dtype == np.float32)
 
     # numpy summary operations
     for f in funcs:

pip install -e .
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.7
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
Babel==2.14.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
charset-normalizer==3.4.1
docutils==0.19
exceptiongroup==1.2.2
idna==3.10
imagesize==1.4.1
importlib-metadata==6.7.0
iniconfig==2.0.0
Jinja2==3.1.6
MarkupSafe==2.1.5
nose==1.3.7
numpy==1.21.6
numpydoc==1.5.0
packaging==24.0
pluggy==1.2.0
Pygments==2.17.2
pytest==7.4.4
pytz==2025.2
requests==2.31.0
scipy==1.7.3
-e git+https://github.com/sdepy/sdepy.git@b90667045d3d2480b39151152ee7ba4b429fec19#egg=sdepy
snowballstemmer==2.2.0
Sphinx==5.3.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
tomli==2.0.1
typing_extensions==4.7.1
urllib3==2.0.7
zipp==3.15.0

name: sdepy
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - babel==2.14.0
      - charset-normalizer==3.4.1
      - docutils==0.19
      - exceptiongroup==1.2.2
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - jinja2==3.1.6
      - markupsafe==2.1.5
      - nose==1.3.7
      - numpy==1.21.6
      - numpydoc==1.5.0
      - packaging==24.0
      - pluggy==1.2.0
      - pygments==2.17.2
      - pytest==7.4.4
      - pytz==2025.2
      - requests==2.31.0
      - scipy==1.7.3
      - snowballstemmer==2.2.0
      - sphinx==5.3.0
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - tomli==2.0.1
      - typing-extensions==4.7.1
      - urllib3==2.0.7
      - zipp==3.15.0
prefix: /opt/conda/envs/sdepy

sdepy/tests/test_process.py::test_summary
sdepy/tests/test_process.py::test_import sdepy/tests/test_process.py::test_constructor sdepy/tests/test_process.py::test_broadcasting sdepy/tests/test_process.py::test_interp sdepy/tests/test_process.py::test_interp_values sdepy/tests/test_process.py::test_t_getitem sdepy/tests/test_process.py::test_p_getitem sdepy/tests/test_process.py::test_v_getitem sdepy/tests/test_process.py::test_properties sdepy/tests/test_process.py::test_shapeas sdepy/tests/test_process.py::test_copy sdepy/tests/test_process.py::test_increments sdepy/tests/test_process.py::test_chf_cdf sdepy/tests/test_process.py::test_piecewise
sdepy/infrastructure.py
sdepy/infrastructure.py