# Rfstats function returns empty string

**URL:** https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019
**Category:** Related: rf
**Created:** [October 17, 2024, 1:38pm UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019 "2024-10-17T13:38:51Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![Ali\_Aslanli](https://discourse.obspy.org/user_avatar/discourse.obspy.org/ali_aslanli/32/894_2.png) [@Ali\_Aslanli](https://discourse.obspy.org/u/Ali_Aslanli)
#### Post date: [October 17, 2024, 1:38pm UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/1 "2024-10-17T13:38:51Z")

</div>

Hey fellas,

Fairly new to the seismology domain, trying to calculate receiver functions using RF package (making some experiments with local high frequency events), however, I get an empty array after executing rfstats() function. Tried to analyse the source code, but could not understand what I am missing. Maybe I am lacking some header information? Below are the stats for one trace:

```
       network: HP
      station: SERG
     location: 
      channel: HHE
    starttime: 2011-09-27T06:15:52.002500Z
      endtime: 2011-09-27T06:16:52.002500Z
sampling_rate: 100.0
        delta: 0.01
         npts: 6001
        calib: 1.0
      _format: SAC
  event_depth: 10.52

```

event\_latitude: 38.3777  
event\_longitude: 22.0568  
event\_magnitude: 3.43  
event\_time: 2011-09-27T06:16:08.999499Z  
sac: AttribDict({‘delta’: 0.01, ‘depmin’: -5680819.0, ‘depmax’: 5710203.0, ‘scale’: 1.0, ‘b’: 0.0005, ‘e’: 60.0005, ‘o’: 16.9975, ‘stla’: 38.4133, ‘stlo’: 22.0566, ‘evla’: 38.3777, ‘evlo’: 22.0568, ‘evdp’: 10.52, ‘mag’: 3.43, ‘depmen’: -6413.086, ‘nzyear’: 2011, ‘nzjday’: 270, ‘nzhour’: 6, ‘nzmin’: 15, ‘nzsec’: 52, ‘nzmsec’: 2, ‘nvhdr’: 6, ‘npts’: 6001, ‘iftype’: 1, ‘iztype’: 9, ‘leven’: 1, ‘lpspol’: 1, ‘lovrok’: 1, ‘lcalda’: 0, ‘kstnm’: ‘SERG’, ‘kcmpnm’: ‘HHE’, ‘knetwk’: ‘HP’})  
station\_latitude: 38.4133  
station\_longitude: 22.0566

---

<div class="post-metadata">

### Author: ![trichter](https://discourse.obspy.org/user_avatar/discourse.obspy.org/trichter/32/226_2.png) [@trichter](https://discourse.obspy.org/u/trichter)
#### Post date: [October 19, 2024, 10:28pm UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/2 "2024-10-19T22:28:27Z")

</div>

Hi Ali!

Please check out the documentation of the rfstats function [here](https://rf.readthedocs.io/en/latest/api.html#rf.rfstream.rfstats):

> Returns: [`Stats`](https://docs.obspy.org/packages/autogen/obspy.core.trace.Stats.html#obspy.core.trace.Stats) object with event and station attributes, distance, back\_azimuth, inclination, onset and slowness or **None** if epicentral distance is not in the given interval. Stream instance if stream was specified instead of stats.

In your case, station and event are too close to each other, therefore rfstats returns `None`.

---

<div class="post-metadata">

### Author: ![Ali\_Aslanli](https://discourse.obspy.org/user_avatar/discourse.obspy.org/ali_aslanli/32/894_2.png) [@Ali\_Aslanli](https://discourse.obspy.org/u/Ali_Aslanli)
#### Post date: [October 28, 2024, 11:07am UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/3 "2024-10-28T11:07:01Z")

</div>

Thanks Tom, it is more clear now.

My objective is to make use of local microseismicity, meaning for sure the events will be significantly closer to the station compared to teleseismic events.

Tried testing it while specifying the range I need but now it seems that Taupy can’t calculate the P arrival phase. Could it be that iasp91 model is not suitable for the task?

Can you suggest any workaround?

rfstats(stream, phase = ‘P’, dist\_range=(0.01,80))

_Exception Traceback (most recent call last)_  
_Cell In[84], line 5_

- 

```
 1 #print(stream)*

```

- 

```
 2 #print(stream[0].stats.station_latitude)*

```

- 

```
 3 #rfstats(stream, phase='P', dist_range=(10,80))*

```

- 

```
 4 #print(rfstats)*

```

_----\> 5 rfstats(stream, phase = ‘P’, dist\_range=(0.01,80))_

_File ~\anaconda3\Lib\site-packages\rf\rfstream.py:683, in rfstats(obj, event, station, phase, dist\_range, tt\_model, pp\_depth, pp\_phase, model)_

- 681 traces = \*
- 682 for tr in stream:\*  
\*–\> 683 if rfstats(tr.stats, \*_kwargs) is not None:_
- 684 traces.append(tr)\*
- 685 stream.traces = traces\*

_File ~\anaconda3\Lib\site-packages\rf\rfstream.py:704, in rfstats(obj, event, station, phase, dist\_range, tt\_model, pp\_depth, pp\_phase, model)_

- 702 arrivals = tt\_model.get\_travel\_times(stats.event\_depth, dist, (phase,))\*
- 703 if len(arrivals) == 0:\*  
 _→ 704 raise Exception(‘TauPy does not return phase %s at distance %s’ %_
- 705 (phase, dist))\*
- 706 if len(arrivals) \> 1:\*
- 707 msg = ('TauPy returns more than one arrival for phase %s at '\*
- 708 ‘distance %s → take first arrival’)\*

_Exception: TauPy does not return phase P at distance 0.03553634879672242_

---

<div class="post-metadata">

### Author: ![trichter](https://discourse.obspy.org/user_avatar/discourse.obspy.org/trichter/32/226_2.png) [@trichter](https://discourse.obspy.org/u/trichter)
#### Post date: [October 29, 2024, 9:30am UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/4 "2024-10-29T09:30:05Z")

</div>

Not sure if rf will be working for such a local setting. With such small distances the P wave will not be going downwards from the source, but upwards. After nomenclature, the phase is p, not P. Therefore, you can try out setting `phase='p'` instead of `phase='P'` in the rftsats call.

Please check out how to correctly format code example and tracebacks. This will enhance readability. Thanks.

---

<div class="post-metadata">

### Author: ![Ali\_Aslanli](https://discourse.obspy.org/user_avatar/discourse.obspy.org/ali_aslanli/32/894_2.png) [@Ali\_Aslanli](https://discourse.obspy.org/u/Ali_Aslanli)
#### Post date: [October 30, 2024, 11:12am UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/5 "2024-10-30T11:12:00Z")

</div>

Your suggestion worked! Setting phase argument to ‘p’ solved the arrival problem, although by simple visual checking it is obvious that the picking is not accurate (i guess it is related to iasp91 model). But where did you check it? Is this nomenclature related to Taupy library?

Another thing if I may, while calculating RFs I have _ValueError: Invalid number of source components. 0 not equal to one._

How to implement the parameters for source\_components in rf function? Tried checking the source but couldn’t find info on that.

---

<div class="post-metadata">

### Author: ![trichter](https://discourse.obspy.org/user_avatar/discourse.obspy.org/trichter/32/226_2.png) [@trichter](https://discourse.obspy.org/u/trichter)
#### Post date: [November 4, 2024, 1:07pm UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/6 "2024-11-04T13:07:31Z")

</div>

No, this is standard seismological convention. I double-checked with ObsPy’s TauPy module, which is used by rf:

```python
from obspy.taup import TauPyModel
model = TauPyModel()
print(model.get_ray_paths(10, 0.1))

17 arrivals
        p phase arrival at 2.577 seconds
        sP phase arrival at 4.342 seconds
        s phase arrival at 4.449 seconds
        PcP phase arrival at 509.544 seconds
        ScP phase arrival at 720.440 seconds
        ...

```

Yes, the relative time error using the iasp91 model will be greater for waves traveling a shorter distance. You can also manually adjust the metadata using manual picks, but that should usually not be necessary.

To help you with the `ValuError`, I would need to see some code and maybe some output from `print(stream)`.

I have never really used the rf method on local data. I do not know if this makes sense.

---

<div class="post-metadata">

### Author: ![Ali\_Aslanli](https://discourse.obspy.org/user_avatar/discourse.obspy.org/ali_aslanli/32/894_2.png) [@Ali\_Aslanli](https://discourse.obspy.org/u/Ali_Aslanli)
#### Post date: [November 5, 2024, 8:43am UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/7 "2024-11-05T08:43:45Z")

</div>

Thanks Tom for all your time.

The code is pretty simple from RF’s minimal tutorial. With teleseismic data I can make it work without issues. Having a difficulty to adapt it to my local data, trying to experiment with its high freq. content, bear with me 🙂

**stream = read\_rf(path)**  
**print(stream.str(extended=True))**

_21 Trace(s) in Stream:_  
_HP.SERG..HHE | 2011-09-27T06:15:52.002500Z - 2011-09-27T06:16:52.002500Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHN | 2011-09-27T06:15:52.000400Z - 2011-09-27T06:16:52.000400Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHZ | 2011-09-27T06:15:52.004300Z - 2011-09-27T06:16:52.004300Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHE | 2011-09-08T12:22:47.002500Z - 2011-09-08T12:23:47.002500Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHN | 2011-09-08T12:22:47.003800Z - 2011-09-08T12:23:47.003800Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHZ | 2011-09-08T12:22:47.000500Z - 2011-09-08T12:23:47.000500Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHE | 2014-06-10T03:58:11.002700Z - 2014-06-10T03:59:11.002700Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHN | 2014-06-10T03:58:11.002700Z - 2014-06-10T03:59:11.002700Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHZ | 2014-06-10T03:58:11.004700Z - 2014-06-10T03:59:11.004700Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHE | 2014-06-21T14:42:37.004700Z - 2014-06-21T14:43:37.004700Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHN | 2014-06-21T14:42:37.003000Z - 2014-06-21T14:43:37.003000Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHZ | 2014-06-21T14:42:37.002900Z - 2014-06-21T14:43:37.002900Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHE | 2014-06-27T00:47:05.000000Z - 2014-06-27T00:48:05.000000Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHN | 2014-06-27T00:47:05.000600Z - 2014-06-27T00:48:05.000600Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHZ | 2014-06-27T00:47:05.000000Z - 2014-06-27T00:48:05.000000Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHE | 2017-01-07T15:00:51.000000Z - 2017-01-07T15:01:51.000000Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHN | 2017-01-07T15:00:51.000000Z - 2017-01-07T15:01:51.000000Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HHZ | 2017-01-07T15:00:51.000000Z - 2017-01-07T15:01:51.000000Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HNE | 2022-06-05T19:23:24.000000Z - 2022-06-05T19:24:24.000000Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HNN | 2022-06-05T19:23:24.000000Z - 2022-06-05T19:24:24.000000Z | 100.0 Hz, 6001 samples_  
_HP.SERG..HNZ | 2022-06-05T19:23:24.000000Z - 2022-06-05T19:24:24.000000Z | 100.0 Hz, 6001 samples_

**rfstats(stream, phase = ‘p’, dist\_range=(0.01,80))**  
**print(stream.str(extended=True))**

_21 Trace(s) in Stream:_  
_HP.SERG..HHE | -18.9s - 41.1s onset:2011-09-27T06:16:10.936825Z | 100.0 Hz, 6001 samples | mag:3.4 dist:0.0 baz:179.7 slow:6.73_  
_HP.SERG..HHN | -18.9s - 41.1s onset:2011-09-27T06:16:10.936925Z | 100.0 Hz, 6001 samples | mag:3.4 dist:0.0 baz:179.7 slow:6.73_  
_HP.SERG..HHZ | -18.9s - 41.1s onset:2011-09-27T06:16:10.937026Z | 100.0 Hz, 6001 samples | mag:3.4 dist:0.0 baz:179.7 slow:6.73_  
_HP.SERG..HHE | -18.8s - 41.2s onset:2011-09-08T12:23:05.839951Z | 100.0 Hz, 6001 samples | mag:3.1 dist:0.1 baz:156.7 slow:11.17_  
_HP.SERG..HHN | -18.8s - 41.2s onset:2011-09-08T12:23:05.839650Z | 100.0 Hz, 6001 samples | mag:3.1 dist:0.1 baz:156.7 slow:11.17_  
_HP.SERG..HHZ | -18.8s - 41.2s onset:2011-09-08T12:23:05.839951Z | 100.0 Hz, 6001 samples | mag:3.1 dist:0.1 baz:156.7 slow:11.17_  
_HP.SERG..HHE | -20.2s - 39.8s onset:2014-06-10T03:58:31.203030Z | 100.0 Hz, 6001 samples | mag:3.5 dist:0.1 baz:179.0 slow:11.72_  
_HP.SERG..HHN | -20.2s - 39.8s onset:2014-06-10T03:58:31.203030Z | 100.0 Hz, 6001 samples | mag:3.5 dist:0.1 baz:179.0 slow:11.72_  
_HP.SERG..HHZ | -20.2s - 39.8s onset:2014-06-10T03:58:31.203031Z | 100.0 Hz, 6001 samples | mag:3.5 dist:0.1 baz:179.0 slow:11.72_  
_HP.SERG..HHE | -19.1s - 40.9s onset:2014-06-21T14:42:56.111751Z | 100.0 Hz, 6001 samples | mag:3.0 dist:0.0 baz:208.1 slow:6.35_  
_HP.SERG..HHN | -19.1s - 40.9s onset:2014-06-21T14:42:56.112450Z | 100.0 Hz, 6001 samples | mag:3.0 dist:0.0 baz:208.1 slow:6.35_  
_HP.SERG..HHZ | -19.1s - 40.9s onset:2014-06-21T14:42:56.111551Z | 100.0 Hz, 6001 samples | mag:3.0 dist:0.0 baz:208.1 slow:6.35_  
_HP.SERG..HHE | -20.0s - 40.0s onset:2014-06-27T00:47:24.988258Z | 100.0 Hz, 6001 samples | mag:3.4 dist:0.1 baz:248.7 slow:9.28_  
_HP.SERG..HHN | -20.0s - 40.0s onset:2014-06-27T00:47:24.987657Z | 100.0 Hz, 6001 samples | mag:3.4 dist:0.1 baz:248.7 slow:9.28_  
_HP.SERG..HHZ | -20.0s - 40.0s onset:2014-06-27T00:47:24.988258Z | 100.0 Hz, 6001 samples | mag:3.4 dist:0.1 baz:248.7 slow:9.28_  
_HP.SERG..HHE | -19.1s - 40.9s onset:2017-01-07T15:01:10.122370Z | 100.0 Hz, 6001 samples | mag:3.6 dist:0.1 baz:237.9 slow:9.61_  
_HP.SERG..HHN | -19.1s - 40.9s onset:2017-01-07T15:01:10.122370Z | 100.0 Hz, 6001 samples | mag:3.6 dist:0.1 baz:237.9 slow:9.61_  
_HP.SERG..HHZ | -19.1s - 40.9s onset:2017-01-07T15:01:10.122370Z | 100.0 Hz, 6001 samples | mag:3.6 dist:0.1 baz:237.9 slow:9.61_  
_HP.SERG..HNE | -18.9s - 41.1s onset:2022-06-05T19:23:42.893538Z | 100.0 Hz, 6001 samples | mag:3.1 dist:0.1 baz:182.2 slow:8.41_  
_HP.SERG..HNN | -18.9s - 41.1s onset:2022-06-05T19:23:42.893538Z | 100.0 Hz, 6001 samples | mag:3.1 dist:0.1 baz:182.2 slow:8.41_  
_HP.SERG..HNZ | -18.9s - 41.1s onset:2022-06-05T19:23:42.893538Z | 100.0 Hz, 6001 samples | mag:3.1 dist:0.1 baz:182.2 slow:8.41_

**rf\_iter = stream.copy().rf(deconvolve=‘iterative’,rotate=‘NE-\>RT’).moveout()**

_ValueError Traceback (most recent call last)_  
_Cell In[12], line 1_  
_----\> 1 rf\_iter = stream.copy().rf(deconvolve=‘iterative’,rotate=‘NE-\>RT’).moveout()_

\*File ~\anaconda3\Lib\site-packages\decorator.py:232, in decorate..fun(\*args, \*_kw)_

- 230 if not kwsyntax:\*
- 231 args, kw = fix(args, kw, sig)\*  
\*–\> 232 return caller(func, \*(extras + args), \*_kw)_

\*File ~\anaconda3\Lib\site-packages\rf\util.py:243, in \_add\_processing\_info(_func_, \*args, \*_kwargs)_

- 240 arguments = [‘%s=%s’ % (k, repr(v)) if not isinstance(v, str) else\*
- 241 “%s=‘%s’” % (k, v) for k, v in kw.items()]\*
- 242 info = info % ‘::’.join(sorted(arguments))\*  
\*–\> 243 stream = _func_(\*args, \*_kwargs)_
- 244 try:\*
- 245 for tr in stream:\*

\*File ~\anaconda3\Lib\site-packages\rf\rfstream.py:340, in RFStream.rf(self, method, filter, trim, downsample, rotate, deconvolve, source\_components, \*_kwargs)_

- 338 for stream3c in iter3c(self):\*
- 339 kwargs.setdefault(‘winsrc’, method)\*  
 _→ 340 stream3c.deconvolve(method=deconvolve,_
- 341 source\_components=source\_components,\*
- 342 \*_kwargs)_
- 343 # Mirrow Q/R and T component at 0s for S-receiver method for a better\*
- 344 # comparison with P-receiver method (converted Sp wave arrives before\*
- 345 # S wave, but converted Ps wave arrives after P wave)\*
- 346 if method == ‘S’:\*

\*File ~\anaconda3\Lib\site-packages\rf\rfstream.py:258, in RFStream.deconvolve(self, \*args, \*_kwargs)_

- 251 def deconvolve(self, \*args, \*_kwargs):_
- 252 “”"\*
- 253 Deconvolve source component of stream.\*
- 254 \*
- 255 All args and kwargs are passed to the function\*
- 256 `~rf.deconvolve.deconvolve()`.\*
- 257 “”"\*  
\*–\> 258 rsp = deconvolve(self, \*args, \*_kwargs)_
- 259 self.traces = rsp.traces\*
- 260 return self\*

\*File ~\anaconda3\Lib\site-packages\decorator.py:232, in decorate..fun(\*args, \*_kw)_

- 230 if not kwsyntax:\*
- 231 args, kw = fix(args, kw, sig)\*  
\*–\> 232 return caller(func, \*(extras + args), \*_kw)_

\*File ~\anaconda3\Lib\site-packages\rf\util.py:243, in \_add\_processing\_info(_func_, \*args, \*_kwargs)_

- 240 arguments = [‘%s=%s’ % (k, repr(v)) if not isinstance(v, str) else\*
- 241 “%s=‘%s’” % (k, v) for k, v in kw.items()]\*
- 242 info = info % ‘::’.join(sorted(arguments))\*  
\*–\> 243 stream = _func_(\*args, \*_kwargs)_
- 244 try:\*
- 245 for tr in stream:\*

\*File ~\anaconda3\Lib\site-packages\rf\deconvolve.py:83, in deconvolve(stream, method, func, source\_components, response\_components, winsrc, \*_kwargs)_

- 

```
81 if len(src) != 1:*

```

- 

```
82 msg = 'Invalid number of source components. %d not equal to one.'*

```

_—\> 83 raise ValueError(msg % len(src))_

- 

```
84 src = src[0]*

```

- 

```
85 rsp = [tr for tr in stream if response_components is None or*

```

- 

```
86 tr.stats.channel[-1] in response_components]*

```

_ValueError: Invalid number of source components. 0 not equal to one._

---

<div class="post-metadata">

### Author: ![trichter](https://discourse.obspy.org/user_avatar/discourse.obspy.org/trichter/32/226_2.png) [@trichter](https://discourse.obspy.org/u/trichter)
#### Post date: [November 5, 2024, 9:41am UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/8 "2024-11-05T09:41:35Z")

</div>

Hi, this looks all good.

Not sure, what is the problem. I can have a look at the data if you like. It would be enough if you sent me data from a single event by pm.

By the way, please, use code markers ````` to post code (readability).

---

<div class="post-metadata">

### Author: ![trichter](https://discourse.obspy.org/user_avatar/discourse.obspy.org/trichter/32/226_2.png) [@trichter](https://discourse.obspy.org/u/trichter)
#### Post date: [November 5, 2024, 12:29pm UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/9 "2024-11-05T12:29:50Z")

</div>

I checked your data.

The `rf()` method iterates through the stream. It uses the `stats.onset` attribute to find out which traces belong to the same event.

The problem with your data is, that the event origin time is not the same for each three traces that belong to one event. The onsets then also differ slightly.

One straight-forward way to fix this in your script is:

```python
for i in range(len(stream) // 3):
    for tr in stream[3*i:3*i+3]:
        tr.stats.event_time = stream[3*i].stats.event_time

```

---

<div class="post-metadata">

### Author: ![Ali\_Aslanli](https://discourse.obspy.org/user_avatar/discourse.obspy.org/ali_aslanli/32/894_2.png) [@Ali\_Aslanli](https://discourse.obspy.org/u/Ali_Aslanli)
#### Post date: [November 5, 2024, 1:30pm UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/10 "2024-11-05T13:30:33Z")

</div>

Amazing, thank you!

I’ll keep you posted once I have my results for the project. Have a nice day!

---

<div class="post-metadata">

### Author: ![trichter](https://discourse.obspy.org/user_avatar/discourse.obspy.org/trichter/32/226_2.png) [@trichter](https://discourse.obspy.org/u/trichter)
#### Post date: [November 5, 2024, 1:49pm UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/11 "2024-11-05T13:49:04Z")

</div>

You are welcome 🙂  
Have a nice day, too!

---

<div class="post-metadata">

### Author: ![josette\_leonard16](https://discourse.obspy.org/letter_avatar_proxy/v4/letter/j/bb73d2/32.png) [@josette\_leonard16](https://discourse.obspy.org/u/josette_leonard16)
#### Post date: [August 10, 2026, 12:05pm UTC](https://discourse.obspy.org/t/rfstats-function-returns-empty-string/2019/12 "2026-08-10T12:05:06Z")

</div>

Velocity models like iasp91 aren’t really built for events that close to the station. Taupy’s just gonna struggle there. You could bump up your minimum distance or manually pick the arrivals instead.
