Getting calibration blockette information from obspy.core read

Hello Users,

Has anyone used the obspy read routine to pull out calibration blockette information? Setting details=True seems to show when a calibration blockette exists and which type of calibration it is, but I am also trying to get the additional fields. Perhaps they are sitting somewhere else?

For example something like the following when there is the existence of a 310 blockette.

Found a Sine Calibration Blockette

Starting Time: 2014,329 16:32:57.5695

Calibration Duration: 2400 seconds

Sine Period: 250.000000

Calibration Amplitude: -36.000000

Calibration Input Channel: BC0

Reference Amplitude: 0.000000

Coupling Method: resistive

Filtering Type: 3DB@10Hz

Calibration Flags: 14

Thanks for any help anyone can give,

Adam

Hi Adam,

sorry for the late response.

So this is not possible right now with the obspy.read function. If read with details=True, it does store the calibration type in tr.stats.mseed.calibration_type but nothing more. If there is enough interest we might consider adding that functionality to ObsPy.

To do this right now you’ll have to do a bit of manual work. ObsPy ships with an “obspy-mseed-recordanalyzer” script:

$ obspy-mseed-recordanalyzer -n 1 CN.RES…BHE.mseed
FILE: CN.RES…BHE.mseed
Record Offset: 512 byte
Header Endianness: Big Endian

FIXED SECTION OF DATA HEADER
Sequence number: 2
Data header/quality indicator: M
Station identifier code: RES
Location identifier:
Channel identifier: BHE
Network code: CN
Record start time: 2013-05-24T05:40:14.625000Z
Number of samples: 572
Sample rate factor: 40
Sample rate multiplier: 1
Activity flags: 0
I/O and clock flags: 0
Data quality flags: 0
Number of blockettes that follow: 1
Time correction: 0
Beginning of data: 64
First blockette: 48

BLOCKETTES
1000: Encoding Format: 11
Word Order: 1
Data Record Length: 9

CALCULATED VALUES
Corrected Starttime: 2013-05-24T05:40:14.625000Z

See “$ obspy-mseed-recordanalyer -h” for more details.

You can find the source of script here: https://github.com/obspy/obspy/blob/master/obspy/mseed/scripts/recordanalyzer.py

To get Blockette 310 you’ll just need to add a couple of lines to this function here:
https://github.com/obspy/obspy/blob/master/obspy/mseed/scripts/recordanalyzer.py#L197-220

This is a bit complex so if there is broader interest in reading arbitrary MiniSEED blockettes we’ll have to think of a way to add it to ObsPy.

All the best!

Lion

Hello Lion,

Thanks so much. I ended up taking a similar approach (see below). I would guess there aren’t many people using this type of information.

However, it is good to know there is a recordanalyzer in obspy!

Thanks for all of your help,
Adam

def get_calibrations(file_name):
calibrations = []

#Read the first file and get the record length from blockette 1000
fh = open(file_name, ‘rb’)
record = fh.read(256)
index = struct.unpack(’>H’, record[46:48])[0]
file_stats = os.stat(file_name)
record_length = 2 ** struct.unpack(’>B’, record[index+6:index+7])[0]

#Get the total number of records
total_records = file_stats[stat.ST_SIZE] / record_length

#Now loop through the records and look for calibration blockettes
for rec_idx in xrange(0,total_records):
fh.seek(rec_idx * record_length,0)
record = fh.read(record_length)
next_blockette = struct.unpack(’>H’, record[46:48])[0]
while next_blockette != 0:
index = next_blockette
blockette_type, next_blockette = struct.unpack(’>HH’, record[index:index+4])
if blockette_type in (300, 310, 320, 390):
if debug:
print ‘We have a calibration blockette’
year,jday,hour,minute,sec,,tmsec,,cal_flags,duration = tuple(struct.unpack(’>HHBBBBHBBL’, record[index+4:index+20]))
stime = UTCDateTime(year=year,julday=jday,hour=hour,minute=minute,second=sec)
if debug:
print(stime.ctime())
if blockette_type == 300:
step_count,,,ntrvl_duration,amplitude,cal_input = struct.unpack(’>BBLLf3s’, record[index+14:index+31])
calibrations.append({‘type’:‘step’,‘amplitude’: amplitude,‘number’:step_count,‘start_time’:stime,‘duration’:duration/10000,‘inteveral_duration’:ntrvl_duration})
if blockette_type == 310:
signal_period,amplitude,cal_input = struct.unpack(’>ff3s’, record[index+20:index+31])
calibrations.append({‘type’:‘sine’,‘amplitude’: amplitude, ‘period’: signal_period,‘start_time’:stime,‘duration’:duration/10000})
if blockette_type in (320, 390):
amplitude,cal_input = struct.unpack(’>f3s’, record[index+20:index+27])
calibrations.append({‘type’:‘random’,‘amplitude’: amplitude,‘start_time’:stime,‘duration’:duration/10000})
fh.close()
return calibrations