Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

# -*- coding: utf-8 -*- 

""" 

Defines the libmseed structures and blockettes. 

""" 

 

from distutils import sysconfig 

import ctypes as C 

import numpy as np 

import os 

import platform 

 

 

HPTERROR = -2145916800000000L 

 

ENDIAN = {0: '<', 1: '>'} 

 

# Import shared libmseed depending on the platform. 

# create library names 

lib_names = [ 

     # platform specific library name 

    'libmseed-%s-%s-py%s' % (platform.system(), platform.architecture()[0], 

        ''.join([str(i) for i in platform.python_version_tuple()[:2]])), 

     # fallback for pre-packaged libraries 

    'libmseed'] 

# get default file extension for shared objects 

lib_extension, = sysconfig.get_config_vars('SO') 

# initialize library 

clibmseed = None 

for lib_name in lib_names: 

    try: 

        clibmseed = C.CDLL(os.path.join(os.path.dirname(__file__), os.pardir, 

                                        'lib', lib_name + lib_extension)) 

    except Exception, e: 

        pass 

    else: 

        break 

if not clibmseed: 

    msg = 'Could not load shared library for obspy.mseed.\n\n %s' % (e) 

    raise ImportError(msg) 

 

 

# XXX: Do we still support Python 2.4 ???? 

# Figure out Py_ssize_t (PEP 353). 

# 

# Py_ssize_t is only defined for Python 2.5 and above, so it defaults to 

# ctypes.c_int for earlier versions. 

# 

# http://svn.python.org/projects/ctypes/trunk/ 

#           ctypeslib/ctypeslib/contrib/pythonhdr.py 

if hasattr(C.pythonapi, 'Py_InitModule4'): 

    Py_ssize_t = C.c_int 

elif hasattr(C.pythonapi, 'Py_InitModule4_64'): 

    Py_ssize_t = C.c_int64 

else: 

    raise TypeError("Cannot determine type of Py_ssize_t") 

 

# Valid control headers in ASCII numbers. 

SEED_CONTROL_HEADERS = [ord('V'), ord('A'), ord('S'), ord('T')] 

MINI_SEED_CONTROL_HEADERS = [ord('D'), ord('R'), ord('Q'), ord('M')] 

VALID_CONTROL_HEADERS = SEED_CONTROL_HEADERS + MINI_SEED_CONTROL_HEADERS 

 

# expected data types for libmseed id: (numpy, ctypes) 

DATATYPES = {"a": C.c_char, "i": C.c_int32, "f": C.c_float, "d": C.c_double} 

SAMPLESIZES = {'a': 1, 'i': 4, 'f': 4, 'd': 8} 

 

# Valid record lengths for Mini-SEED files. 

VALID_RECORD_LENGTHS = [256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 

                        131072, 262144, 524288, 1048576] 

 

# allowed encodings: 

# SEED id: SEED name, SEED sampletype a, i, f or d, default numpy type)} 

ENCODINGS = {0: ("ASCII", "a", np.dtype("|S1").type), 

             1: ("INT16", "i", np.dtype("int16")), 

             3: ("INT32", "i", np.dtype("int32")), 

             4: ("FLOAT32", "f", np.dtype("float32")), 

             5: ("FLOAT64", "d", np.dtype("float64")), 

             10: ("STEIM1", "i", np.dtype("int32")), 

             11: ("STEIM2", "i", np.dtype("int32"))} 

 

# Map the dtype to the samplecode. Redundant information but it is hard coded 

# for performance reasons. 

SAMPLETYPE = {"|S1": "a", 

              "int16": "i", 

              "int32": "i", 

              "float32": "f", 

              "float64": "d", 

              np.dtype("|S1").type: "a", 

              np.dtype("int16").type: "i", 

              np.dtype("int32").type: "i", 

              np.dtype("float32").type: "f", 

              np.dtype("float64").type: "d"} 

# as defined in libmseed.h 

MS_ENDOFFILE = 1 

MS_NOERROR = 0 

 

 

# SEED binary time 

class BTime(C.Structure): 

    _fields_ = [ 

        ('year', C.c_ushort), 

        ('day', C.c_ushort), 

        ('hour', C.c_ubyte), 

        ('min', C.c_ubyte), 

        ('sec', C.c_ubyte), 

        ('unused', C.c_ubyte), 

        ('fract', C.c_ushort), 

    ] 

 

 

# Fixed section data of header 

class fsdh_s(C.Structure): 

    _fields_ = [ 

        ('sequence_number', C.c_char * 6), 

        ('dataquality', C.c_char), 

        ('reserved', C.c_char), 

        ('station', C.c_char * 5), 

        ('location', C.c_char * 2), 

        ('channel', C.c_char * 3), 

        ('network', C.c_char * 2), 

        ('start_time', BTime), 

        ('numsamples', C.c_ushort), 

        ('samprate_fact', C.c_short), 

        ('samprate_mult', C.c_short), 

        ('act_flags', C.c_ubyte), 

        ('io_flags', C.c_ubyte), 

        ('dq_flags', C.c_ubyte), 

        ('numblockettes', C.c_ubyte), 

        ('time_correct', C.c_int), 

        ('data_offset', C.c_ushort), 

        ('blockette_offset', C.c_ushort), 

    ] 

 

 

# Blockette 100, Sample Rate (without header) 

class blkt_100_s(C.Structure): 

    _fields_ = [ 

        ('samprate', C.c_float), 

        ('flags', C.c_byte), 

        ('reserved', C.c_ubyte * 3), 

    ] 

blkt_100 = blkt_100_s 

 

 

# Blockette 200, Generic Event Detection (without header) 

class blkt_200_s(C.Structure): 

    _fields_ = [ 

        ('amplitude', C.c_float), 

        ('period', C.c_float), 

        ('background_estimate', C.c_float), 

        ('flags', C.c_ubyte), 

        ('reserved', C.c_ubyte), 

        ('time', BTime), 

        ('detector', C.c_char * 24), 

    ] 

 

 

#Blockette 201, Murdock Event Detection (without header) 

class blkt_201_s(C.Structure): 

    _fields_ = [ 

        ('amplitude', C.c_float), 

        ('period', C.c_float), 

        ('background_estimate', C.c_float), 

        ('flags', C.c_ubyte), 

        ('reserved', C.c_ubyte), 

        ('time', BTime), 

        ('snr_values', C.c_ubyte * 6), 

        ('loopback', C.c_ubyte), 

        ('pick_algorithm', C.c_ubyte), 

        ('detector', C.c_char * 24), 

    ] 

 

 

#Blockette 300, Step Calibration (without header) 

class blkt_300_s(C.Structure): 

    _fields_ = [ 

        ('time', BTime), 

        ('numcalibrations', C.c_ubyte), 

        ('flags', C.c_ubyte), 

        ('step_duration', C.c_uint), 

        ('interval_duration', C.c_uint), 

        ('amplitude', C.c_float), 

        ('input_channel', C.c_char * 3), 

        ('reserved', C.c_ubyte), 

        ('reference_amplitude', C.c_uint), 

        ('coupling', C.c_char * 12), 

        ('rolloff', C.c_char * 12), 

    ] 

 

 

# Blockette 310, Sine Calibration (without header) 

class blkt_310_s(C.Structure): 

    _fields_ = [ 

        ('time', BTime), 

        ('reserved1', C.c_ubyte), 

        ('flags', C.c_ubyte), 

        ('duration', C.c_uint), 

        ('period', C.c_float), 

        ('amplitude', C.c_float), 

        ('input_channel', C.c_char * 3), 

        ('reserved2', C.c_ubyte), 

        ('reference_amplitude', C.c_uint), 

        ('coupling', C.c_char * 12), 

        ('rolloff', C.c_char * 12), 

    ] 

 

 

#Blockette 320, Pseudo-random Calibration (without header) 

class blkt_320_s(C.Structure): 

    _fields_ = [ 

        ('time', BTime), 

        ('reserved1', C.c_ubyte), 

        ('flags', C.c_ubyte), 

        ('duration', C.c_uint), 

        ('ptp_amplitude', C.c_float), 

        ('input_channel', C.c_char * 3), 

        ('reserved2', C.c_ubyte), 

        ('reference_amplitude', C.c_uint), 

        ('coupling', C.c_char * 12), 

        ('rolloff', C.c_char * 12), 

        ('noise_type', C.c_char * 8), 

    ] 

 

 

#Blockette 390, Generic Calibration (without header) 

class blkt_390_s(C.Structure): 

    _fields_ = [ 

        ('time', BTime), 

        ('reserved1', C.c_ubyte), 

        ('flags', C.c_ubyte), 

        ('duration', C.c_uint), 

        ('amplitude', C.c_float), 

        ('input_channel', C.c_char * 3), 

        ('reserved2', C.c_ubyte), 

    ] 

 

 

#Blockette 395, Calibration Abort (without header) 

class blkt_395_s(C.Structure): 

    _fields_ = [ 

        ('time', BTime), 

        ('reserved', C.c_ubyte * 2), 

    ] 

 

 

#Blockette 400, Beam (without header) 

class blkt_400_s(C.Structure): 

    _fields_ = [ 

        ('azimuth', C.c_float), 

        ('slowness', C.c_float), 

        ('configuration', C.c_ushort), 

        ('reserved', C.c_ubyte * 2), 

    ] 

 

 

#Blockette 405, Beam Delay (without header) 

class blkt_405_s(C.Structure): 

    _fields_ = [ 

        ('delay_values', C.c_ushort * 1), 

    ] 

 

 

#Blockette 500, Timing (without header) 

class blkt_500_s(C.Structure): 

    _fields_ = [ 

        ('vco_correction', C.c_float), 

        ('time', BTime), 

        ('usec', C.c_byte), 

        ('reception_qual', C.c_ubyte), 

        ('exception_count', C.c_uint), 

        ('exception_type', C.c_char * 16), 

        ('clock_model', C.c_char * 32), 

        ('clock_status', C.c_char * 128), 

    ] 

 

 

# Blockette 1000, Data Only SEED (without header) 

class blkt_1000_s(C.Structure): 

    _fields_ = [ 

        ('encoding', C.c_ubyte), 

        ('byteorder', C.c_ubyte), 

        ('reclen', C.c_ubyte), 

        ('reserved', C.c_ubyte), 

    ] 

 

 

# Blockette 1001, Data Extension (without header) 

class blkt_1001_s(C.Structure): 

    _fields_ = [ 

        ('timing_qual', C.c_ubyte), 

        ('usec', C.c_byte), 

        ('reserved', C.c_ubyte), 

        ('framecnt', C.c_ubyte), 

    ] 

blkt_1001 = blkt_1001_s 

 

 

#Blockette 2000, Opaque Data (without header) 

class blkt_2000_s(C.Structure): 

    _fields_ = [ 

        ('length', C.c_ushort), 

        ('data_offset', C.c_ushort), 

        ('recnum', C.c_uint), 

        ('byteorder', C.c_ubyte), 

        ('flags', C.c_ubyte), 

        ('numheaders', C.c_ubyte), 

        ('payload', C.c_char * 1), 

    ] 

 

 

# Blockette chain link, generic linkable blockette index 

class blkt_link_s(C.Structure): 

    pass 

 

blkt_link_s._fields_ = [ 

    ('blktoffset', C.c_ushort),       # Blockette offset 

    ('blkt_type', C.c_ushort),        # Blockette type 

    ('next_blkt', C.c_ushort),        # Offset to next blockette 

    ('blktdata', C.POINTER(None)),    # Blockette data 

    ('blktdatalen', C.c_ushort),      # Length of blockette data in bytes 

    ('next', C.POINTER(blkt_link_s))] 

BlktLink = blkt_link_s 

 

 

class StreamState_s(C.Structure): 

    _fields_ = [ 

        ('packedrecords', C.c_longlong),  # Count of packed records 

        ('packedsamples', C.c_longlong),  # Count of packed samples 

        ('lastintsample', C.c_int),       # Value of last integer sample packed 

        ('comphistory', C.c_byte),        # Control use of lastintsample for 

                                          # compression history 

    ] 

StreamState = StreamState_s 

 

 

class MSRecord_s(C.Structure): 

    pass 

 

MSRecord_s._fields_ = [ 

    ('record', C.POINTER(C.c_char)),  # Mini-SEED record 

    ('reclen', C.c_int),              # Length of Mini-SEED record in bytes 

    # Pointers to SEED data record structures 

    ('fsdh', C.POINTER(fsdh_s)),      # Fixed Section of Data Header 

    ('blkts', C.POINTER(BlktLink)),   # Root of blockette chain 

    ('Blkt100', 

     C.POINTER(blkt_100_s)),          # Blockette 100, if present 

    ('Blkt1000', 

     C.POINTER(blkt_1000_s)),         # Blockette 1000, if present 

    ('Blkt1001', 

     C.POINTER(blkt_1001_s)),         # Blockette 1001, if present 

    # Common header fields in accessible form 

    ('sequence_number', C.c_int),     # SEED record sequence number 

    ('network', C.c_char * 11),       # Network designation, NULL terminated 

    ('station', C.c_char * 11),       # Station designation, NULL terminated 

    ('location', C.c_char * 11),      # Location designation, NULL terminated 

    ('channel', C.c_char * 11),       # Channel designation, NULL terminated 

    ('dataquality', C.c_char),        # Data quality indicator 

    ('starttime', C.c_longlong),      # Record start time, corrected (first 

                                      # sample) 

    ('samprate', C.c_double),         # Nominal sample rate (Hz) 

    ('samplecnt', C.c_int64),         # Number of samples in record 

    ('encoding', C.c_byte),           # Data encoding format 

    ('byteorder', C.c_byte),          # Byte order of record 

    # Data sample fields 

    ('datasamples', C.c_void_p),      # Data samples, 'numsamples' of type 

                                      # 'sampletype' 

    ('numsamples', C.c_int64),        # Number of data samples in datasamples 

    ('sampletype', C.c_char),         # Sample type code: a, i, f, d 

    # Stream oriented state information 

    ('ststate', 

     C.POINTER(StreamState)),         # Stream processing state information 

] 

MSRecord = MSRecord_s 

 

 

class MSTrace_s(C.Structure): 

    pass 

 

MSTrace_s._fields_ = [ 

    ('network', C.c_char * 11),       # Network designation, NULL terminated 

    ('station', C.c_char * 11),       # Station designation, NULL terminated 

    ('location', C.c_char * 11),      # Location designation, NULL terminated 

    ('channel', C.c_char * 11),       # Channel designation, NULL terminated 

    ('dataquality', C.c_char),        # Data quality indicator 

    ('type', C.c_char),               # MSTrace type code 

    ('starttime', C.c_longlong),      # Time of first sample 

    ('endtime', C.c_longlong),        # Time of last sample 

    ('samprate', C.c_double),         # Nominal sample rate (Hz) 

    ('samplecnt', C.c_int64),         # Number of samples in trace coverage 

    ('datasamples', C.c_void_p),      # Data samples, 'numsamples' of type 

                                      # 'sampletype' 

    ('numsamples', C.c_int64),        # Number of data samples in datasamples 

    ('sampletype', C.c_char),         # Sample type code: a, i, f, d 

    ('prvtptr', C.c_void_p),          # Private pointer for general use 

    ('ststate', 

     C.POINTER(StreamState)),         # Stream processing state information 

    ('next', C.POINTER(MSTrace_s)),   # Pointer to next trace 

] 

MSTrace = MSTrace_s 

 

 

class MSTraceGroup_s(C.Structure): 

    pass 

 

MSTraceGroup_s._fields_ = [ 

    ('numtraces', C.c_int),            # Number of MSTraces in the trace chain 

    ('traces', C.POINTER(MSTrace_s)),  # Root of the trace chain 

] 

MSTraceGroup = MSTraceGroup_s 

 

 

# Define the high precision time tick interval as 1/modulus seconds */ 

# Default modulus of 1000000 defines tick interval as a microsecond */ 

HPTMODULUS = 1000000.0 

 

 

# Reading Mini-SEED records from files 

class MSFileParam_s(C.Structure): 

    pass 

 

MSFileParam_s._fields_ = [ 

  ('fp', C.POINTER(Py_ssize_t)), 

  ('filename', C.c_char * 512), 

  ('rawrec', C.c_char_p), 

  ('readlen', C.c_int), 

  ('readoffset', C.c_int), 

  ('packtype', C.c_int), 

  ('packhdroffset', C.c_long), 

  ('filepos', C.c_long), 

  ('filesize', C.c_long), 

  ('recordcount', C.c_int), 

] 

MSFileParam = MSFileParam_s 

 

 

class U_DIFF(C.Union): 

    """ 

    Union for Steim objects. 

    """ 

    _fields_ = [ 

        ("byte", C.c_int8 * 4),       # 4 1-byte differences. 

        ("hw", C.c_int16 * 2),        # 2 halfword differences. 

        ("fw", C.c_int32),            # 1 fullword difference. 

    ] 

 

 

class FRAME(C.Structure): 

    """ 

    Frame in a seed data record. 

    """ 

    _fields_ = [ 

        ("ctrl", C.c_uint32),         # control word for frame. 

        ("w", U_DIFF * 14),           # compressed data. 

    ] 

 

 

# Declare function of libmseed library, argument parsing 

clibmseed.mst_init.argtypes = [C.POINTER(MSTrace)] 

clibmseed.mst_init.restype = C.POINTER(MSTrace) 

 

clibmseed.mst_free.argtypes = [C.POINTER(C.POINTER(MSTrace))] 

clibmseed.mst_free.restype = C.c_void_p 

 

clibmseed.mst_initgroup.argtypes = [C.POINTER(MSTraceGroup)] 

clibmseed.mst_initgroup.restype = C.POINTER(MSTraceGroup) 

 

clibmseed.mst_freegroup.argtypes = [C.POINTER(C.POINTER(MSTraceGroup))] 

clibmseed.mst_freegroup.restype = C.c_void_p 

 

clibmseed.msr_init.argtypes = [C.POINTER(MSRecord)] 

clibmseed.msr_init.restype = C.POINTER(MSRecord) 

 

clibmseed.ms_readmsr_r.argtypes = [ 

    C.POINTER(C.POINTER(MSFileParam)), C.POINTER(C.POINTER(MSRecord)), 

    C.c_char_p, C.c_int, C.POINTER(Py_ssize_t), C.POINTER(C.c_int), C.c_short, 

    C.c_short, C.c_short] 

clibmseed.ms_readmsr_r.restypes = C.c_int 

 

clibmseed.ms_readtraces.argtypes = [ 

    C.POINTER(C.POINTER(MSTraceGroup)), C.c_char_p, C.c_int, C.c_double, 

    C.c_double, C.c_short, C.c_short, C.c_short, C.c_short] 

clibmseed.ms_readtraces.restype = C.c_int 

 

clibmseed.ms_readtraces_timewin.argtypes = [ 

    C.POINTER(C.POINTER(MSTraceGroup)), C.c_char_p, C.c_int, C.c_double, 

    C.c_double, C.c_int64, C.c_int64, C.c_short, C.c_short, C.c_short, 

    C.c_short] 

clibmseed.ms_readtraces_timewin.restype = C.c_int 

 

clibmseed.msr_starttime.argtypes = [C.POINTER(MSRecord)] 

clibmseed.msr_starttime.restype = C.c_int64 

 

clibmseed.msr_endtime.argtypes = [C.POINTER(MSRecord)] 

clibmseed.msr_endtime.restype = C.c_int64 

 

clibmseed.ms_detect.argtypes = [C.c_char_p, C.c_int] 

clibmseed.ms_detect.restype = C.c_int 

 

clibmseed.msr_unpack_steim2.argtypes = [C.POINTER(FRAME), C.c_int, 

        C.c_int, C.c_int, 

        np.ctypeslib.ndpointer(dtype='int32', ndim=1, flags='C_CONTIGUOUS'), 

        np.ctypeslib.ndpointer(dtype='int32', ndim=1, flags='C_CONTIGUOUS'), 

        C.POINTER(C.c_int32), C.POINTER(C.c_int32), C.c_int, C.c_int] 

clibmseed.msr_unpack_steim2.restype = C.c_int 

 

clibmseed.msr_unpack_steim1.argtypes = [C.POINTER(FRAME), C.c_int, 

        C.c_int, C.c_int, 

        np.ctypeslib.ndpointer(dtype='int32', ndim=1, flags='C_CONTIGUOUS'), 

        np.ctypeslib.ndpointer(dtype='int32', ndim=1, flags='C_CONTIGUOUS'), 

        C.POINTER(C.c_int32), C.POINTER(C.c_int32), C.c_int, C.c_int] 

clibmseed.msr_unpack_steim2.restype = C.c_int 

 

# tricky, C.POINTER(C.c_char) is a pointer to single character fields 

# this is completely different to C.c_char_p which is a string 

clibmseed.mst_packgroup.argtypes = [C.POINTER(MSTraceGroup), 

    C.CFUNCTYPE(C.c_void_p, C.POINTER(C.c_char), C.c_int, C.c_void_p), 

    C.c_void_p, C.c_int, C.c_short, C.c_short, C.POINTER(C.c_int), 

    C.c_short, C.c_short, C.POINTER(MSRecord)] 

clibmseed.mst_packgroup.restype = C.c_int 

 

clibmseed.msr_addblockette.argtypes = [C.POINTER(MSRecord), 

                                       C.POINTER(C.c_char), 

                                       C.c_int, C.c_int, C.c_int] 

clibmseed.msr_addblockette.restype = C.POINTER(BlktLink) 

 

clibmseed.msr_parse.argtypes = [C.POINTER(C.c_char), C.c_int, 

                                C.POINTER(C.POINTER(MSRecord)), 

                                C.c_int, C.c_int, C.c_int] 

clibmseed.msr_parse.restype = C.c_int 

 

 

PyFile_FromFile = C.pythonapi.PyFile_FromFile 

PyFile_FromFile.argtypes = [ 

    Py_ssize_t, C.c_char_p, C.c_char_p, C.CFUNCTYPE(C.c_int, Py_ssize_t)] 

PyFile_FromFile.restype = C.py_object 

 

 

##################################### 

# Define the C structures. 

##################################### 

 

 

# Container for a continuous trace segment, linkable 

class MSTraceSeg(C.Structure): 

    pass 

 

MSTraceSeg._fields_ = [ 

    ('starttime', C.c_longlong),      # Time of first sample 

    ('endtime', C.c_longlong),        # Time of last sample 

    ('samprate', C.c_double),         # Nominal sample rate (Hz) 

    ('samplecnt', C.c_int64),         # Number of samples in trace coverage 

    ('datasamples', C.c_void_p),      # Data samples, 'numsamples' of type 

                                      # 'sampletype' 

    ('numsamples', C.c_int64),        # Number of data samples in datasamples 

    ('sampletype', C.c_char),         # Sample type code: a, i, f, d 

    ('prvtptr', C.c_void_p),          # Private pointer for general use, unused 

                                      # by libmseed 

    ('prev', C.POINTER(MSTraceSeg)),  # Pointer to previous segment 

    ('next', C.POINTER(MSTraceSeg))   # Pointer to next segment 

    ] 

 

 

# Container for a trace ID, linkable 

class MSTraceID(C.Structure): 

    pass 

 

MSTraceID._fields_ = [ 

    ('network', C.c_char * 11),       # Network designation, NULL terminated 

    ('station', C.c_char * 11),       # Station designation, NULL terminated 

    ('location', C.c_char * 11),      # Location designation, NULL terminated 

    ('channel', C.c_char * 11),       # Channel designation, NULL terminated 

    ('dataquality', C.c_char),        # Data quality indicator 

    ('srcname', C.c_char * 45),       # Source name (Net_Sta_Loc_Chan_Qual), 

                                      # NULL terminated 

    ('type', C.c_char),               # Trace type code 

    ('earliest', C.c_longlong),       # Time of earliest sample 

    ('latest', C.c_longlong),         # Time of latest sample 

    ('prvtptr', C.c_void_p),          # Private pointer for general use, unused 

                                      # by libmseed 

    ('numsegments', C.c_int),         # Number of segments for this ID 

    ('first', 

     C.POINTER(MSTraceSeg)),          # Pointer to first of list of segments 

    ('last', C.POINTER(MSTraceSeg)),  # Pointer to last of list of segments 

    ('next', C.POINTER(MSTraceID))    # Pointer to next trace 

    ] 

 

 

# Container for a continuous trace segment, linkable 

class MSTraceList(C.Structure): 

    pass 

 

MSTraceList._fields_ = [ 

    ('numtraces', C.c_int),            # Number of traces in list 

    ('traces', C.POINTER(MSTraceID)),  # Pointer to list of traces 

    ('last', C.POINTER(MSTraceID))     # Pointer to last used trace in list 

    ] 

 

 

# Data selection structure time window definition containers 

class SelectTime(C.Structure): 

    pass 

 

SelectTime._fields_ = [ 

    ('starttime', C.c_longlong),      # Earliest data for matching channels 

    ('endtime', C.c_longlong),        # Latest data for matching channels 

    ('next', C.POINTER(SelectTime)) 

    ] 

 

 

# Data selection structure definition containers 

class Selections(C.Structure): 

    pass 

 

Selections._fields_ = [ 

    ('srcname', C.c_char * 100),      # Matching (globbing) source name: 

                                      # Net_Sta_Loc_Chan_Qual 

    ('timewindows', C.POINTER(SelectTime)), 

    ('next', C.POINTER(Selections)) 

    ] 

 

 

# Container for a continuous linked list of records. 

class ContinuousSegment(C.Structure): 

    pass 

 

ContinuousSegment._fields_ = [ 

    ('starttime', C.c_longlong), 

    ('endtime', C.c_longlong), 

    ('samprate', C.c_double), 

    ('sampletype', C.c_char), 

    ('hpdelta', C.c_longlong), 

    ('samplecnt', C.c_int64), 

    ('timing_quality', C.c_uint8), 

    ('calibration_type',  C.c_int8), 

    ('datasamples', C.c_void_p),      # Data samples, 'numsamples' of type 

                                      # 'sampletype' 

    ('firstRecord', C.c_void_p), 

    ('lastRecord', C.c_void_p), 

    ('next', C.POINTER(ContinuousSegment)), 

    ('previous', C.POINTER(ContinuousSegment)) 

    ] 

 

 

# A container for continuous segments with the same id 

class LinkedIDList(C.Structure): 

    pass 

 

LinkedIDList._fields_ = [ 

    ('network', C.c_char * 11),       # Network designation, NULL terminated 

    ('station', C.c_char * 11),       # Station designation, NULL terminated 

    ('location', C.c_char * 11),      # Location designation, NULL terminated 

    ('channel', C.c_char * 11),       # Channel designation, NULL terminated 

    ('dataquality', C.c_char),        # Data quality indicator 

    ('firstSegment', 

     C.POINTER(ContinuousSegment)),   # Pointer to first of list of segments 

    ('lastSegment', 

     C.POINTER(ContinuousSegment)),   # Pointer to last of list of segments 

    ('next', 

     C.POINTER(LinkedIDList)),        # Pointer to next id 

    ('previous', 

     C.POINTER(LinkedIDList)),        # Pointer to previous id 

    ] 

 

 

######################################## 

# Done with the C structures defintions. 

######################################## 

 

# Set the necessary arg- and restypes. 

clibmseed.readMSEEDBuffer.argtypes = [ 

    np.ctypeslib.ndpointer(dtype='b', ndim=1, flags='C_CONTIGUOUS'), 

    C.c_int, 

    C.POINTER(Selections), 

    C.c_int, 

    C.c_int, 

    C.c_int, 

    C.c_int, 

    C.CFUNCTYPE(C.c_long, C.c_int, C.c_char) 

    ] 

 

clibmseed.readMSEEDBuffer.restype = C.POINTER(LinkedIDList) 

 

clibmseed.msr_free.argtypes = [C.POINTER(C.POINTER(MSRecord))] 

clibmseed.msr_free.restype = C.c_void_p 

 

clibmseed.mstl_init.restype = C.POINTER(MSTraceList) 

clibmseed.mstl_free.argtypes = [C.POINTER(C.POINTER(MSTraceList)), C.c_int] 

 

 

clibmseed.lil_free.argtypes = [C.POINTER(LinkedIDList)] 

clibmseed.lil_free.restype = C.c_void_p 

 

 

# Python callback functions for C 

def __PyFile_callback(_f): 

    return 1 

_PyFile_callback = C.CFUNCTYPE(C.c_int, Py_ssize_t)(__PyFile_callback)