Repository: obspy/obspy

Issue:
Xseed parser does not allow reading mutiple blockette 55 into ResponseListResponseStage object
### Avoid duplicates

- [X] I searched existing issues

### Bug Summary

Posted this in the obspy forum and thanks for the answer @megies 

I copied it here for further potential discussion and added test files. Have a fix that seems to work and will add a PR.

I stumbled over a (legacy) dataless seed response file where the responses are defined as frequency, amplitude, phase list (FAP) values.

The issue: Obspy read_inventory() reads only the first part of the FAP list. It turned out that multiple blockette 55 entries existed dividing the FAP response into different subsequent frequency ranges.

According to the SEED manual this is allowed: “…This blockette could exceed the maximum of 9999 characters. If so, continue with another blockette [55] on the next record. Set field 3 the same, but ignore fields 4 and 5 in subsequent blockettes.”

It seems in obspy.io.xseed.parser this is not taken into account, i.e. only the first blockette 55 is read for each channel in the dataless seed file.

Test files attached include a anonymized inventory of the station (because I am not sure if it can be shared). If you open the stationxml you see that the FAP list goes until 10 Hz. If you read the seed file with obspy it stops at 3 Hz.

[test_files.zip](https://github.com/obspy/obspy/files/10908028/test_files.zip)

(I create the xml file after I fixed the seed parser)


### Code to Reproduce

```python
inv=read_inventory('dummy_test_station.seed')
print(inv)
for stage in inv[0][0][0].response.response_stages:
    for f in stage.response_list_elements: print(f.frequency)
```


### Error Traceback

_No response_

### ObsPy Version?

1.3.0

### Operating System?

Linux

### Python Version?

3.10.4

### Installation Method?

conda


Discussion:

Resolving patch:
diff --git a/obspy/io/xseed/parser.py b/obspy/io/xseed/parser.py
--- a/obspy/io/xseed/parser.py
+++ b/obspy/io/xseed/parser.py
@@ -1586,9 +1586,24 @@ def _list(value):
                     34, b55.stage_input_units)
                 o_u = self.resolve_abbreviation(
                     34, b55.stage_output_units)
-                response_list = [
-                    ResponseListElement(f, a, p) for f, a, p in
-                    zip(b55.frequency, b55.amplitude, b55.phase_angle)]
+                if len([_i for _i in blkts if _i.id == 55]) == 1:
+                    response_list = [
+                        ResponseListElement(f, a, p) for f, a, p in
+                        zip(b55.frequency, b55.amplitude, b55.phase_angle)]
+                # allow mutiple blockette 55
+                else:
+                    _freq = []
+                    _amp = []
+                    _phase = []
+                    for _i in blkts:
+                        if _i.id == 55:
+                            _freq += _i.frequency
+                            _amp += _i.amplitude
+                            _phase += _i.phase_angle
+                    response_list = [
+                        ResponseListElement(f, a, p) for f, a, p in
+                        zip(_freq, _amp, _phase)]
+
                 response_stages.append(ResponseListResponseStage(
                     stage_sequence_number=b55.stage_sequence_number,
                     stage_gain=b58.sensitivity_gain if b58 else None,


Test patch:
diff --git a/obspy/io/xseed/tests/data/issue3275.seed b/obspy/io/xseed/tests/data/issue3275.seed
new file mode 100644
--- /dev/null
+++ b/obspy/io/xseed/tests/data/issue3275.seed
@@ -0,0 +1 @@
+000001V 010007102.410~~2023,066,09:21:37.786000000~IRIS DMC~Converted from XML~0110021001XXX  000003                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            000002A 0340018002V~Volts~0340044001M/S~Velocity in Meters per Second~0330011001~0300038Undefined data format~000109000                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         000003S 0500084XXX  +00.000000+000.000000+0000.00001000~0013210102000,001,00:00:00.0000~~NNO0520147  SHZ0000001~001000+00.000000+000.000000+0000.0000.0000.0-90.00001122.0000E+010.0000E+000000~2000,001,00:00:00.0000~2009,001,00:00:00.0000~N0550199010010020003+1.17200E-01+1.38495E-03+0.00000E+00-5.00000E+00+0.00000E+00+1.36700E-01+2.47239E-03+0.00000E+00-7.50000E+00+0.00000E+00+1.56300E-01+4.22287E-03+0.00000E+00-8.78000E+00+0.00000E+000550199010010020003+3.35940E+00+6.85493E+01+0.00000E+00-1.67300E+02+0.00000E+00+3.37890E+00+6.93155E+01+0.00000E+00-1.67440E+02+0.00000E+00+3.39840E+00+7.01340E+01+0.00000E+00-1.67560E+02+0.00000E+00058003501+1.00000E+00+1.00000E+0000058003500+1.70092E+10+1.00000E+0000
diff --git a/obspy/io/xseed/tests/data/issue3275.xml b/obspy/io/xseed/tests/data/issue3275.xml
new file mode 100644
--- /dev/null
+++ b/obspy/io/xseed/tests/data/issue3275.xml
@@ -0,0 +1,90 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<FDSNStationXML xmlns="http://www.fdsn.org/xml/station/1" schemaVersion="1.1">
+  <Source>ObsPy's obspy.io.xseed version 1.3.0</Source>
+  <Module>ObsPy 1.3.0</Module>
+  <ModuleURI>https://www.obspy.org</ModuleURI>
+  <Created>2023-03-15T16:41:27.495259Z</Created>
+  <Network code="NO">
+    <Station code="XXX" startDate="2000-01-01T00:00:00.000000Z">
+      <Latitude unit="DEGREES">0.0</Latitude>
+      <Longitude unit="DEGREES">0.0</Longitude>
+      <Elevation unit="METERS">0.0</Elevation>
+      <Site>
+        <Name></Name>
+      </Site>
+      <CreationDate>2023-03-07T09:21:37.786000Z</CreationDate>
+      <Channel code="SHZ" startDate="2000-01-01T00:00:00.000000Z" endDate="2009-01-01T00:00:00.000000Z" locationCode="">
+        <Latitude unit="DEGREES">0.0</Latitude>
+        <Longitude unit="DEGREES">0.0</Longitude>
+        <Elevation unit="METERS">0.0</Elevation>
+        <Depth unit="METERS">0.0</Depth>
+        <Azimuth unit="DEGREES">0.0</Azimuth>
+        <Dip unit="DEGREES">-90.0</Dip>
+        <SampleRate>20.0</SampleRate>
+        <Sensor>
+          <Type></Type>
+        </Sensor>
+        <Response>
+          <InstrumentSensitivity>
+            <Value>17009200000.0</Value>
+            <Frequency>1.0</Frequency>
+            <InputUnits>
+              <Name>M/S</Name>
+              <Description>Velocity in Meters per Second</Description>
+            </InputUnits>
+            <OutputUnits>
+              <Name>V</Name>
+              <Description>Volts</Description>
+            </OutputUnits>
+          </InstrumentSensitivity>
+          <Stage number="1">
+            <ResponseList>
+              <InputUnits>
+                <Name>M/S</Name>
+                <Description>Velocity in Meters per Second</Description>
+              </InputUnits>
+              <OutputUnits>
+                <Name>V</Name>
+                <Description>Volts</Description>
+              </OutputUnits>
+              <ResponseListElement>
+                <Frequency unit="HERTZ">0.1172</Frequency>
+                <Amplitude>0.00138495</Amplitude>
+                <Phase unit="DEGREES">-5.0</Phase>
+              </ResponseListElement>
+              <ResponseListElement>
+                <Frequency unit="HERTZ">0.1367</Frequency>
+                <Amplitude>0.00247239</Amplitude>
+                <Phase unit="DEGREES">-7.5</Phase>
+              </ResponseListElement>
+              <ResponseListElement>
+                <Frequency unit="HERTZ">0.1563</Frequency>
+                <Amplitude>0.00422287</Amplitude>
+                <Phase unit="DEGREES">-8.78</Phase>
+              </ResponseListElement>
+              <ResponseListElement>
+                <Frequency unit="HERTZ">3.3594</Frequency>
+                <Amplitude>68.5493</Amplitude>
+                <Phase unit="DEGREES">-167.3</Phase>
+              </ResponseListElement>
+              <ResponseListElement>
+                <Frequency unit="HERTZ">3.3789</Frequency>
+                <Amplitude>69.3155</Amplitude>
+                <Phase unit="DEGREES">-167.44</Phase>
+              </ResponseListElement>
+              <ResponseListElement>
+                <Frequency unit="HERTZ">3.3984</Frequency>
+                <Amplitude>70.134</Amplitude>
+                <Phase unit="DEGREES">-167.56</Phase>
+              </ResponseListElement>
+            </ResponseList>
+            <StageGain>
+              <Value>1.0</Value>
+              <Frequency>1.0</Frequency>
+            </StageGain>
+          </Stage>
+        </Response>
+      </Channel>
+    </Station>
+  </Network>
+</FDSNStationXML>
diff --git a/obspy/io/xseed/tests/test_parser.py b/obspy/io/xseed/tests/test_parser.py
--- a/obspy/io/xseed/tests/test_parser.py
+++ b/obspy/io/xseed/tests/test_parser.py
@@ -844,3 +844,19 @@ def test_parsing_resp_file_without_clear_blkt_separation(self, testdata):
         evresp = evalresp_for_frequencies(0.01, [0.0, 1.0, 10.0], filename,
                                           obspy.UTCDateTime(2015, 1, 2))
         np.testing.assert_allclose(obs_r, evresp)
+
+    def test_parsing_resp_file_with_mutiple_blockette55(self, testdata):
+        """
+        Test case for issue #3275. Allow reading mutiple blockette 55.
+        """
+        inv_xml = obspy.read_inventory(testdata['issue3275.xml'])
+        with warnings.catch_warnings(record=True):
+            warnings.filterwarnings("ignore", "Date is required")
+            inv_seed = obspy.read_inventory(testdata['issue3275.seed'])
+        freq_xml = [f.frequency for f in inv_xml[0][0][0].response
+                     .response_stages[0].response_list_elements]
+        # test file with two blockettes 55
+        freq_seed = [f.frequency for f in inv_seed[0][0][0].response
+                     .response_stages[0].response_list_elements]
+        assert len(freq_xml) == len(freq_seed)
+        assert freq_xml == freq_seed