Repository: pyvista/pyvista

Issue:
streamlines_from_source produce ERROR:root:
**Describe the bug, what's wrong, and what you expect:**
Right now I'm trying to draw vector  magnetic field snapshots from simulations.
So I prepared the data in following  pyvista guide, eg.
I have the mesh grid
xm,ym,zm = broadcast_arrays( xm, ym, zm)
where xm,ym,zm corresponds to the spherical coordinates r,theta,phi. There the components of the magnetic field vector are defined
So I defined two meshes:
mesh = pv.StructuredGrid(xm, ym, zm)
sour = pv.StructuredGrid(xsee, ysee, zsee)
the second mesh defines the seed points (around B-field extrema). Similarly I attached the vector field to the mesh
dir = np.empty((xm.size, 3))
dir[:,0]=bxx.ravel('F')
dir[:,1]=byy.ravel('F')
dir[:,2]=bzz.ravel('F')
mesh['mf'] = dir
Then I tried to  compute streamlines and get
streamlines=mesh.streamlines_from_source(sour, vectors='mf',
                                                     integration_direction='both',
                                                     surface_streamlines=False,
                                                     initial_step_length=0.5,
                                                     step_unit='cl',
                                                     min_step_length=0.01,
                                                     max_step_length=1.0,
                                                     max_steps=2000,
                                                     terminal_speed=1e-06,
                                                     max_error=1e-10,
                                                     max_time=None,
                                                     interpolator_type='point')

In spyder shell I got :
ERROR:root:The update extent specified in the information for output port 0 on algorithm vtkTrivialProducer(0x5622ed828100) is 0 55 0 199 0 47, which is outside the whole extent 0 202 0 0 0 0.QApplication: invalid style override passed, ignoring it.
    Available styles: Windows, Fusion
2021-06-11 15:28:40.435 ( 910,928s) [        607EE740]vtkStreamingDemandDrive:871    ERR| vtkStreamingDemandDrivenPipeline (0x5622eca4f1d0): The update extent specified in the information for output port 0 on algorithm vtkTrivialProducer(0x5622ecf99900) is 0 55 0 199 0 47, which is outside the whole extent 0 202 0 0 0 0.
2021-06-11 15:31:47.492 (1097,985s) [        607EE740]vtkStreamingDemandDrive:871    ERR| vtkStreamingDemandDrivenPipeline (0x5622ed8187f0): The update extent specified in the information for output port 0 on algorithm vtkTrivialProducer(0x5622ed0f99d0) is 0 149 0 149 0 149, which is outside the whole extent 0 202 0 0 0 0.
2021-06-11 15:32:25.581 (1136,073s) [        607EE740]vtkStreamingDemandDrive:871    ERR| vtkStreamingDemandDrivenPipeline (0x5622f320cad0): The update extent specified in the information for output port 0 on algorithm vtkTrivialProducer(0x5622ecf99900) is 0 149 0 149 0 149, which is outside the whole extent 0 202 0 0 0 0.
2021-06-11 15:33:00.451 (1170,944s) [        607EE740]vtkStreamingDemandDrive:871    ERR| vtkStreamingDemandDrivenPipeline (0x5622f320e0a0): The update extent specified in the information for output port 0 on algorithm vtkTrivialProducer(0x5622ed0f99d0) is 0 149 0 149 0 149, which is outside the whole extent 0 202 0 0 0 0.
2021-06-11 15:52:09.607 (2320,100s) [        607EE740]vtkStreamingDemandDrive:871    ERR| vtkStreamingDemandDrivenPipeline (0x5622ed853570): The update extent specified in the information for output port 0 on algorithm vtkTrivialProducer(0x5622ed828100) is 0 55 0 199 0 47, which is outside the whole extent 0 202 0 0 0 0.
A clear and concise description of what you expected to happen.

-----

**To Reproduce**

Please include a code snippet to reproduce the bug in the block below:


from numpy import *
from scipy import special

#### Calculate the field ####################################################
radius = 1  # Radius of the coils

x, y, z = [e.astype(float32) for e in
            ogrid[-2:2:50j, -2:2:50j, -2:2:50j]]

# express the coordinates in polar form
rho = sqrt(x ** 2 + y ** 2)
x_proj = x / rho
y_proj = y / rho

E = special.ellipe((4 * radius * rho) / ((radius + rho) ** 2 + z ** 2))
K = special.ellipk((4 * radius * rho) / ((radius + rho) ** 2 + z ** 2))
Bz = 1 / sqrt((radius + rho) ** 2 + z ** 2) * (
                K
                + E * (radius ** 2 - rho ** 2 - z ** 2) /
                    ((radius - rho) ** 2 + z ** 2)
            )
Brho = z / (rho * sqrt((radius + rho) ** 2 + z ** 2)) * (
                - K
                + E * (radius ** 2 + rho ** 2 + z ** 2) /
                    ((radius - rho) ** 2 + z ** 2)
            )
del E, K, rho
# On the axis of the coil we get a divided by zero. This returns a
# NaN, where the field is actually zero :
Brho[isnan(Brho)] = 0

Bx, By = x_proj * Brho, y_proj * Brho

del x_proj, y_proj, Brho
# In[]:
# define seed points concentrated to the pole on the sphere of r=1
xch=real(special.orthogonal.p_roots(8)[0])
phi=linspace(0,2*pi,16)
xse=zeros((8,16));yse=zeros((8,16));zse=zeros((8,16));
for i in range(8):
    xse[i,:]=sin(xch[i])*cos(phi);
    yse[i,:]=sin(xch[i])*sin(phi);
    zse[i,:]=cos(xch[i]);
# In[]:
import pyvista as pv
x, y, z = mgrid[-2.:2.:50j,-2.:2.:50j,-2.:2.:50j] 

mesh = pv.StructuredGrid(x, y, z)
sour = pv.StructuredGrid(xse, yse, zse)

# In[]:
vec = empty((x.size, 3))
vec[:,0]=Bx.ravel('F')
vec[:,1]=By.ravel('F')
vec[:,2]=Bz.ravel('F')
mesh['mf'] = vec
# In[]:
stream, src = mesh.streamlines('mf', return_source=True,
                               terminal_speed=0, n_points=120,
                               source_radius=0.99)
cpos = [(5, 5, 5), (-0.0, -0.0, -0.0), (0.0, 0.0, 1.0)]
stream.tube(radius=0.015).plot(cpos=cpos)

# In[]:
streamlines=mesh.streamlines_from_source(sour, vectors='mf',integrator_type=2,
                                                     integration_direction='both', 
                                                     surface_streamlines=False, 
                                                     initial_step_length=0.5, 
                                                     step_unit='cl', 
                                                     min_step_length=0.01,
                                                     max_step_length=1.0, 
                                                     max_steps=200, 
                                                     terminal_speed=1e-06, 
                                                     max_error=1e-06, 
                                                     max_time=None, 
                                                     interpolator_type='point')    



# Insert code here

```

**Screenshots**
If applicable, add screenshots to help explain your problem.

-----

I have the latest version of manjaro linux, gnome, I'm working in spyder5.03
```py
# Get system info
import pyvista as pv
print(pv.Report())
```
Output from spyder call 'get_namespace_view':

--------------------------------------------------------------------------------
  Date: Пт июн 11 18:20:23 2021 +08

                OS : Linux
            CPU(s) : 4
           Machine : x86_64
      Architecture : 64bit
               RAM : 23.2 GiB
       Environment : IPython
        GPU Vendor : Intel
      GPU Renderer : Mesa Intel(R) HD Graphics 620 (KBL GT2)
       GPU Version : 4.6 (Core Profile) Mesa 21.1.2

  Python 3.9.5 (default, May 24 2021, 12:50:35)  [GCC 11.1.0]

           pyvista : 0.31.0
               vtk : Version unknown
             numpy : 1.20.3
           imageio : 2.9.0
           appdirs : 1.4.4
            scooby : 0.5.7
            meshio : 4.4.5
        matplotlib : 3.4.1
             PyQt5 : 5.12.3
           IPython : 7.24.0
             scipy : 1.6.3
              tqdm : 4.61.0
--------------------------------------------------------------------------------

```txt
# Paste system info here

```


Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/pyvista/pyvista/pull/1374?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyvista) Report
> Merging [#1374](https://codecov.io/gh/pyvista/pyvista/pull/1374?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyvista) (a6a38a1) into [master](https://codecov.io/gh/pyvista/pyvista/commit/aefb4df72450bedab5078d13d71978b61be2f915?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyvista) (aefb4df) will **not change** coverage.
> The diff coverage is `n/a`.

```diff
@@           Coverage Diff           @@
##           master    #1374   +/-   ##
=======================================
  Coverage   90.07%   90.07%           
=======================================
  Files          58       58           
  Lines       12267    12267           
=======================================
  Hits        11049    11049           
  Misses       1218     1218           
```

MatthewFlamm: I'm glad I pushed the test first, before the fix.  The test _passes_ on the CI, yet it _fails_ on my local machine when testing the single test at a time.  I suspect there is some cross-talk in the logging between tests when interacting with vtk objects, but I'm not sure.  I'm going to mark this draft for now.
MatthewFlamm: This is probably the same issue with testing as https://github.com/pyvista/pyvista/pull/1229#issuecomment-803463509
MatthewFlamm: Here is the result in the logs of the CI before I push the fix for the expected failing test, example [here](https://dev.azure.com/pyvista/PyVista/_build/results?buildId=5989&view=logs&j=2e703997-b85c-5955-fe15-cdf93bef6757&t=0940cea9-959b-5bdb-a4d8-01c570473871&l=1022)

```txt
==================================== ERRORS ====================================
______ ERROR at teardown of test_streamlines_from_source_structured_grids ______

caplog = <_pytest.logging.LogCaptureFixture object at 0x1231c4c10>

    @fixture()
    def check_vtk_error(caplog):
        """Ensure that no VTK error is thrown."""
        yield
        for record in caplog.get_records("call"):
            if record.levelno == logging.ERROR:
>               fail("VTK error recorded")
E               Failed: VTK error recorded

tests/conftest.py:98: Failed
----------------------------- Captured stderr call -----------------------------
2021-06-11 17:57:42.373 (  32.618s) [            2938]vtkStreamingDemandDrive:878    ERR| vtkStreamingDemandDrivenPipeline (0x7fae3cfb9960): The update extent specified in the information for output port 0 on algorithm vtkTrivialProducer(0x7fae3cfb9490) is 0 39 0 39 0 39, which is outside the whole extent 0 3 0 3 0 3.
------------------------------ Captured log call -------------------------------
ERROR    root:errors.py:51 The update extent specified in the information for output port 0 on algorithm vtkTrivialProducer(0x7fae3cfb9490) is 0 39 0 39 0 39, which is outside the whole extent 0 3 0 3 0 3.
```
adeak: > I found that this is the offending line that swallows all vtk errors into the ERROR_OUTPUT.txt file for all tests: 

Good catch! The comment above it suggests that this isn't meant to be a global suppression, which makes sense because then it would have to go in something like `conftest.py`. So I'm pretty sure this is global by mistake. Whether or not it could be removed altogether I don't know; @banesullivan do you happen to remember what that `pyvista.set_error_output_file` call was meant to fix in https://github.com/pyvista/pyvista/commit/9c2554578d6dc6c9b7031dd178781409864686b7?

If the line is needed then whatever it does should be undone at the end of the module the latest. I don't really understand what that function does, especially how it should interact with logging (I know nothing about the latter).
MatthewFlamm: If this line was intended to test `set_error_output_file`, we should wrap it in a test, which should isolate it (but I haven't tested it).
whophil: > I could reproduce by doing `pytest tests/test_*`, but not `pytest tests/test_filters.py`, so it was a cross-communication between two test modules. By a one-by-one search, I found that this is the offending line that swallows all vtk errors into the `ERROR_OUTPUT.txt` file for _all_ tests:
> 
> https://github.com/pyvista/pyvista/blob/aefb4df72450bedab5078d13d71978b61be2f915/tests/test_utilities.py#L27
> 
> I don't see any other tests that inspect this file, so I assume we can just delete this line. Maybe this is here to suppress messages during testing from vtk? If so, can we reduce the suppression to just the vtk warnings, so we can catch the vtk Errors?
> 
> cc @whophil - this might be why your tests may have been failing/passing unintuitively in the past.

Wow, nice catch @MatthewFlamm . To leave some breadcrumbs, here is a link to discussion about the issue I was seeing in the past. https://github.com/pyvista/pyvista/pull/1229#discussion_r601028953
whophil: @MatthewFlamm I created a PR which adds VTK error handling (https://github.com/pyvista/pyvista/pull/1382), basically allowing us to do `check_vtk_error` outside of pytest. That PR may be helpful but certainly shouldn't block this one.
akaszynski: I'll review this once #1382 is merged and we've incorporated those changes.  There's no reason for the fixture (or at least most of the fixture) after that point, right?
MatthewFlamm: I agree, let's revisit once that one is merged.  We can either use the context manager directly in the test, or rework the fixture to use the context manager. 
MatthewFlamm: I'm also willing to rework this after #1385, which should be very straightforward here.  It might be messier if this is merged first.
akaszynski: > I'm also willing to rework this after #1385, which should be very straightforward here. It might be messier if this is merged first.

Pressing on #1385 to get it merged.  A refactor like that should get pushed quick and the rest of the PRs can fall in place.  I'll either work on it and merge it or abandon it if there's no work by Friday.

Patch:
diff --git a/pyvista/core/filters/data_set.py b/pyvista/core/filters/data_set.py
index 7afef320..cbefe87c 100644
--- a/pyvista/core/filters/data_set.py
+++ b/pyvista/core/filters/data_set.py
@@ -2038,6 +2038,11 @@ class DataSetFilters:
         if not isinstance(source, pyvista.DataSet):
             raise TypeError("source must be a pyvista.DataSet")
 
+        # vtk throws error with two Structured Grids
+        # See: https://github.com/pyvista/pyvista/issues/1373
+        if isinstance(dataset, pyvista.StructuredGrid) and isinstance(source, pyvista.StructuredGrid):
+            source = source.cast_to_unstructured_grid()
+
         # Build the algorithm
         alg = _vtk.vtkStreamTracer()
         # Inputs


Test patch:
diff --git a/tests/test_filters.py b/tests/test_filters.py
index a9b48c7d..473de672 100644
--- a/tests/test_filters.py
+++ b/tests/test_filters.py
@@ -756,6 +756,22 @@ def test_streamlines_from_source(uniform_vec):
     assert all([stream.n_points, stream.n_cells])
 
 
+def test_streamlines_from_source_structured_grids():
+    x, y, z = np.meshgrid(
+        np.arange(-10, 10, 0.5), np.arange(-10, 10, 0.5), np.arange(-10, 10, 0.5)
+    )
+    mesh = pyvista.StructuredGrid(x, y, z)
+    x2, y2, z2 = np.meshgrid(
+        np.arange(-1, 1, 0.5), np.arange(-1, 1, 0.5), np.arange(-1, 1, 0.5)
+    )
+    mesh2 = pyvista.StructuredGrid(x2, y2, z2)
+    mesh.vectors = np.ones([mesh.n_points, 3])
+    
+    with pyvista.VtkErrorCatcher(raise_errors=True):
+        stream = mesh.streamlines_from_source(mesh2)
+    assert all([stream.n_points, stream.n_cells])
+
+
 def test_sample_over_line():
     """Test that we get a sampled line."""
     name = 'values'