FK beam forming: attribute error

Hi!

I’m getting an error I don’t really understand when following the “Beamforming: FK Analysis” guide.

MWE (copied parameters into a dictionary to make it easier to read):

lat_dict = {1: 39.49957, 2: 39.49991, 3: 39.50027, 4: 39.5006, 5: 39.4979, 6: 39.50036, 7: 39.50117, 8: 39.49919, 9: 39.49883, 10: 39.49844, 11: 39.49874}

long_dict = {1: -116.50945, 2: -116.50838, 3: -116.50731, 4: -116.50623, 5: -116.50855, 6: -116.50994, 7: -116.51045, 8: -116.51052, 9: -116.51157, 10: -116.51262, 11: -116.5092}

elev_dict = {1: 1917, 2: 1917, 3: 1919, 4: 1920, 5: 1921, 6: 1915, 7: 1912, 8: 1921, 9: 1915, 10: 1914, 11: 1920}

stream = obspy.read('array_data/MINISEED/combinedvertical.mseed') #contains 12 traces, all vertical

for i in range(1,11): 
    stream[i].stats.paz = AttribDict({'poles': [(-21.9911+22.4355j), (-21.9911-22.4355j)], 'zeros': [0j, 0j], 'gain': 76})
    stream[i].stats.coordinates = AttribDict({'latitude':lat_dict[i], 'elevation':elev_dict[i], 'longitude':long_dict[i]})

    # Execute array_processing
kwargs = dict(
    # slowness grid: X min, X max, Y min, Y max, Slow Step
    sll_x=-3.0, slm_x=3.0, sll_y=-3.0, slm_y=3.0, sl_s=0.03,
    # sliding window properties
    win_len=1.0, win_frac=0.05,
    # frequency properties
    frqlow=1.0, frqhigh=8.0, prewhiten=0,
    # restrict output
    semb_thres=-1e9, vel_thres=-1e9,
    stime=t1,
    etime=t2
)
out = array_processing(stream, **kwargs)
returns the following error: 

  Cell In[99], line 1
    beamforming()

  File ~/Library/Mobile Documents/com~apple~CloudDocs/Work/Missions/ORX/array_analysis.py:101 in beamforming
    out = array_processing(stream, **kwargs)

  File ~/mambaforge/envs/cartopy-dev/lib/python3.12/site-packages/obspy/signal/array_analysis.py:917 in array_processing
    geometry = get_geometry(stream, coordsys=coordsys, verbose=verbose)

  File ~/mambaforge/envs/cartopy-dev/lib/python3.12/site-packages/obspy/signal/array_analysis.py:632 in get_geometry
    geometry[i, 0] = tr.stats.coordinates.longitude

  File ~/mambaforge/envs/cartopy-dev/lib/python3.12/site-packages/obspy/core/util/attribdict.py:142 in __getattr__
    raise AttributeError(e.args[0])

AttributeError: coordinates

range() stop value is not used in the loop, the for loop uses 10 as its last vlaue, the last entry from your dictionaries is never assigned. I totally recommend not using range() in for loops. You’re much better of with for loops vaguely like for item in iterable: or using enumerate():

for i, tr in enumerate(st):
    tr.stats.coordinates = ... lat_dict[i] ...

In this case, I would totally recommend to just use a list and not a dictionary, to be honest, since the “mapping” concept is not really a mapping but just enumerated indices and then the for loop can be written much nicer with zip() which also avoids confusion with indices (mixing ‘1’ as first index in combination with Python having ‘0’ as first index is asking for trouble…).

longs = [-116.50945, -116.50838, -116.50731, ...]

for tr, long, lat, elev in zip(st, longs, lats, elevs):
    tr.stats.coordinates = {'latitude': lat, ...}

Thanks! Stupid move on my part.

A follow-up: does this beamforming routine at some level implicitly assume a source below the stations? I am looking at a source in the atmosphere and the peak in the BAZ is 180 degrees out from what I expect.