or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

astrophysics.mddetector.mdfrequencyseries.mdindex.mdplotting.mdsegments.mdsignal-processing.mdspectrogram.mdtimeseries.md

detector.mddocs/

0

# Detector Utilities

1

2

Detector-specific utilities for channel management, timezone handling, and interferometer-specific configurations. These tools provide essential metadata and configuration information for working with data from different gravitational-wave detectors worldwide.

3

4

## Capabilities

5

6

### Channel - Detector Channel Representation

7

8

Represents a data channel from a gravitational-wave detector with metadata and query capabilities.

9

10

```python { .api }

11

from gwpy.detector import Channel

12

13

class Channel:

14

def __init__(self, name, sample_rate=None, unit=None, type=None, **kwargs):

15

"""

16

Create a detector channel object.

17

18

Parameters:

19

- name: str, channel name (e.g., 'H1:LSC-DARM_ERR_DBL_DQ')

20

- sample_rate: float, sampling rate in Hz

21

- unit: str or Unit, physical unit of the data

22

- type: str, channel data type

23

"""

24

25

@classmethod

26

def query(cls, name, **kwargs):

27

"""

28

Query channel information from detector databases.

29

30

Parameters:

31

- name: str, channel name to query

32

- **kwargs: additional query parameters

33

34

Returns:

35

Channel object with metadata

36

"""

37

38

@property

39

def name(self):

40

"""Channel name string."""

41

42

@property

43

def ifo(self):

44

"""Interferometer code (e.g., 'H1', 'L1', 'V1')."""

45

46

@property

47

def system(self):

48

"""Detector subsystem (e.g., 'LSC', 'ASC', 'CAL')."""

49

50

@property

51

def subsystem(self):

52

"""Detector subsystem component."""

53

54

@property

55

def signal(self):

56

"""Signal name within subsystem."""

57

58

@property

59

def sample_rate(self):

60

"""Channel sampling rate in Hz."""

61

62

@property

63

def unit(self):

64

"""Physical unit of channel data."""

65

66

@property

67

def type(self):

68

"""Channel data type."""

69

70

def __str__(self):

71

"""String representation of channel."""

72

73

def __repr__(self):

74

"""Detailed string representation."""

75

```

76

77

### ChannelList - Collection of Channels

78

79

List container for managing multiple detector channels with batch operations.

80

81

```python { .api }

82

from gwpy.detector import ChannelList

83

84

class ChannelList(list):

85

def __init__(self, channels=None):

86

"""

87

Create a list of detector channels.

88

89

Parameters:

90

- channels: iterable, initial Channel objects

91

"""

92

93

@classmethod

94

def query(cls, names, **kwargs):

95

"""

96

Query multiple channels from detector databases.

97

98

Parameters:

99

- names: list, channel names to query

100

101

Returns:

102

ChannelList with metadata for all channels

103

"""

104

105

def find(self, name):

106

"""

107

Find channel by name.

108

109

Parameters:

110

- name: str, channel name to find

111

112

Returns:

113

Channel object or None if not found

114

"""

115

116

def sieve(self, **kwargs):

117

"""

118

Filter channels by criteria.

119

120

Parameters:

121

- sample_rate: float, filter by sampling rate

122

- unit: str, filter by unit

123

- ifo: str, filter by interferometer

124

125

Returns:

126

Filtered ChannelList

127

"""

128

```

129

130

### Timezone Functions

131

132

Functions for handling interferometer-specific timezone information.

133

134

```python { .api }

135

from gwpy.detector import get_timezone, get_timezone_offset, TIMEZONE

136

137

def get_timezone(ifo):

138

"""

139

Get timezone object for interferometer.

140

141

Parameters:

142

- ifo: str, interferometer code ('H1', 'L1', 'V1', 'G1', 'C1')

143

144

Returns:

145

datetime.timezone object for the interferometer location

146

147

Raises:

148

ValueError: if interferometer code is not recognized

149

"""

150

151

def get_timezone_offset(ifo, dt=None):

152

"""

153

Get timezone offset for interferometer.

154

155

Parameters:

156

- ifo: str, interferometer code

157

- dt: datetime, specific date/time for offset calculation

158

159

Returns:

160

float, timezone offset in seconds from UTC

161

"""

162

163

# Timezone mapping constant

164

TIMEZONE = {

165

'C1': 'US/Pacific', # Caltech 40m prototype

166

'G1': 'Europe/Berlin', # GEO600

167

'H1': 'US/Pacific', # LIGO Hanford

168

'L1': 'US/Central', # LIGO Livingston

169

'V1': 'Europe/Rome' # Virgo

170

}

171

```

172

173

### Usage Examples

174

175

#### Channel Information and Metadata

176

177

```python

178

from gwpy.detector import Channel, ChannelList

179

180

# Create channel object

181

strain_channel = Channel('H1:DCS-CALIB_STRAIN_C02')

182

183

# Access channel properties

184

print(f"Interferometer: {strain_channel.ifo}")

185

print(f"System: {strain_channel.system}")

186

print(f"Signal: {strain_channel.signal}")

187

188

# Query channel metadata from databases

189

try:

190

channel_info = Channel.query('H1:LSC-DARM_ERR_DBL_DQ')

191

print(f"Sample rate: {channel_info.sample_rate} Hz")

192

print(f"Unit: {channel_info.unit}")

193

print(f"Type: {channel_info.type}")

194

except Exception as e:

195

print(f"Could not query channel metadata: {e}")

196

197

# Work with channel names

198

channels = ['H1:LSC-DARM_ERR_DBL_DQ',

199

'H1:CAL-DELTAL_EXTERNAL_DQ',

200

'H1:ASC-AS_A_RF45_I_ERR_DQ']

201

202

channel_list = ChannelList([Channel(name) for name in channels])

203

print(f"Number of channels: {len(channel_list)}")

204

205

# Filter channels by interferometer

206

h1_channels = channel_list.sieve(ifo='H1')

207

print(f"H1 channels: {len(h1_channels)}")

208

```

209

210

#### Multi-Detector Analysis Setup

211

212

```python

213

# Define channels for multi-detector analysis

214

detector_channels = {

215

'H1': ['H1:DCS-CALIB_STRAIN_C02',

216

'H1:LSC-DARM_ERR_DBL_DQ'],

217

'L1': ['L1:DCS-CALIB_STRAIN_C02',

218

'L1:LSC-DARM_ERR_DBL_DQ'],

219

'V1': ['V1:Hrec_hoft_16384Hz',

220

'V1:LSC_DARM_ERR_DQ']

221

}

222

223

# Create channel objects for each detector

224

all_channels = ChannelList()

225

for ifo, names in detector_channels.items():

226

for name in names:

227

all_channels.append(Channel(name))

228

229

# Find specific channels

230

strain_channels = []

231

for channel in all_channels:

232

if 'STRAIN' in channel.name or 'hoft' in channel.name:

233

strain_channels.append(channel)

234

235

print(f"Found {len(strain_channels)} strain channels")

236

for ch in strain_channels:

237

print(f" {ch.name}")

238

```

239

240

#### Timezone Handling for Different Detectors

241

242

```python

243

from gwpy.detector import get_timezone, get_timezone_offset, TIMEZONE

244

from datetime import datetime

245

import pytz

246

247

# Show timezone information for all detectors

248

print("Detector Timezones:")

249

for ifo, tz_name in TIMEZONE.items():

250

timezone = get_timezone(ifo)

251

print(f" {ifo}: {tz_name}")

252

253

# Get timezone offsets

254

reference_time = datetime(2015, 9, 14, 9, 50, 45) # GW150914 UTC time

255

256

print(f"\nTimezone offsets for {reference_time} UTC:")

257

for ifo in ['H1', 'L1', 'V1', 'G1']:

258

offset_sec = get_timezone_offset(ifo, reference_time)

259

offset_hours = offset_sec / 3600

260

print(f" {ifo}: {offset_hours:+.1f} hours")

261

262

# Convert GPS time to local times

263

gps_time = 1126259462.4 # GW150914 GPS time

264

utc_time = datetime.utcfromtimestamp(gps_time - 315964800) # GPS to UTC

265

266

print(f"\nGW150914 local times:")

267

print(f" GPS: {gps_time}")

268

print(f" UTC: {utc_time}")

269

270

for ifo in ['H1', 'L1', 'V1']:

271

tz = get_timezone(ifo)

272

local_time = utc_time.replace(tzinfo=pytz.UTC).astimezone(tz)

273

print(f" {ifo} local: {local_time.strftime('%Y-%m-%d %H:%M:%S %Z')}")

274

```

275

276

#### Channel Discovery and Selection

277

278

```python

279

# Common gravitational-wave analysis channels

280

analysis_channels = {

281

'strain': ['H1:DCS-CALIB_STRAIN_C02', 'L1:DCS-CALIB_STRAIN_C02'],

282

'calibration': ['H1:CAL-DELTAL_EXTERNAL_DQ', 'L1:CAL-DELTAL_EXTERNAL_DQ'],

283

'darm_error': ['H1:LSC-DARM_ERR_DBL_DQ', 'L1:LSC-DARM_ERR_DBL_DQ'],

284

'alignment': ['H1:ASC-AS_A_RF45_I_ERR_DQ', 'L1:ASC-AS_A_RF45_I_ERR_DQ'],

285

'environment': ['H1:PEM-BSC5_MIC_SEIS_Z_DQ', 'L1:PEM-EX_MIC_SEIS_Z_DQ']

286

}

287

288

# Create organized channel list

289

organized_channels = {}

290

for category, names in analysis_channels.items():

291

organized_channels[category] = ChannelList([Channel(name) for name in names])

292

293

print("Channel Categories:")

294

for category, channels in organized_channels.items():

295

print(f" {category}: {len(channels)} channels")

296

for ch in channels:

297

print(f" {ch.ifo}: {ch.system}-{ch.signal}")

298

```

299

300

#### Channel-Based Data Reading

301

302

```python

303

from gwpy.timeseries import TimeSeries, TimeSeriesDict

304

305

# Read data using channel objects

306

start_time = 1126259446

307

end_time = 1126259478

308

309

# Single channel read

310

strain_ch = Channel('H1:DCS-CALIB_STRAIN_C02')

311

try:

312

strain_data = TimeSeries.get(strain_ch.name, start=start_time, end=end_time)

313

print(f"Read {strain_data.duration} seconds of {strain_ch.name}")

314

except Exception as e:

315

print(f"Could not read {strain_ch.name}: {e}")

316

317

# Multi-channel read using ChannelList

318

aux_channels = ChannelList([

319

Channel('H1:LSC-DARM_ERR_DBL_DQ'),

320

Channel('H1:CAL-DELTAL_EXTERNAL_DQ'),

321

Channel('H1:ASC-AS_A_RF45_I_ERR_DQ')

322

])

323

324

# Read all auxiliary channels

325

aux_data = {}

326

for channel in aux_channels:

327

try:

328

data = TimeSeries.get(channel.name, start=start_time, end=end_time)

329

aux_data[channel.name] = data

330

print(f"Successfully read {channel.name}")

331

except Exception as e:

332

print(f"Failed to read {channel.name}: {e}")

333

334

print(f"Successfully read {len(aux_data)} auxiliary channels")

335

```

336

337

#### Detector Configuration Management

338

339

```python

340

# Define standard detector configurations

341

DETECTOR_CONFIG = {

342

'LIGO': {

343

'sites': ['H1', 'L1'],

344

'strain_channels': {

345

'H1': 'H1:DCS-CALIB_STRAIN_C02',

346

'L1': 'L1:DCS-CALIB_STRAIN_C02'

347

},

348

'sample_rate': 16384,

349

'timezone_mapping': {

350

'H1': 'US/Pacific',

351

'L1': 'US/Central'

352

}

353

},

354

'Virgo': {

355

'sites': ['V1'],

356

'strain_channels': {

357

'V1': 'V1:Hrec_hoft_16384Hz'

358

},

359

'sample_rate': 16384,

360

'timezone_mapping': {

361

'V1': 'Europe/Rome'

362

}

363

}

364

}

365

366

def get_detector_config(detector_name):

367

"""Get configuration for a specific detector."""

368

return DETECTOR_CONFIG.get(detector_name, {})

369

370

def get_all_strain_channels():

371

"""Get all strain channels across detectors."""

372

channels = []

373

for config in DETECTOR_CONFIG.values():

374

for ifo, channel_name in config['strain_channels'].items():

375

channels.append(Channel(channel_name))

376

return ChannelList(channels)

377

378

# Use configuration

379

ligo_config = get_detector_config('LIGO')

380

print(f"LIGO sites: {ligo_config['sites']}")

381

382

all_strain = get_all_strain_channels()

383

print(f"All strain channels: {[ch.name for ch in all_strain]}")

384

```

385

386

#### Channel Name Parsing and Validation

387

388

```python

389

def parse_channel_name(channel_name):

390

"""Parse channel name into components."""

391

try:

392

parts = channel_name.split(':')

393

if len(parts) != 2:

394

raise ValueError("Invalid channel name format")

395

396

ifo = parts[0]

397

signal_parts = parts[1].split('-')

398

399

return {

400

'ifo': ifo,

401

'system': signal_parts[0] if signal_parts else None,

402

'subsystem': signal_parts[1] if len(signal_parts) > 1 else None,

403

'signal': '-'.join(signal_parts[2:]) if len(signal_parts) > 2 else None,

404

'full_name': channel_name

405

}

406

except Exception as e:

407

print(f"Error parsing channel name '{channel_name}': {e}")

408

return None

409

410

def validate_channel_names(channel_names):

411

"""Validate a list of channel names."""

412

valid_channels = []

413

invalid_channels = []

414

415

for name in channel_names:

416

parsed = parse_channel_name(name)

417

if parsed and parsed['ifo'] in TIMEZONE:

418

valid_channels.append(name)

419

else:

420

invalid_channels.append(name)

421

422

return valid_channels, invalid_channels

423

424

# Example usage

425

test_channels = [

426

'H1:DCS-CALIB_STRAIN_C02',

427

'L1:LSC-DARM_ERR_DBL_DQ',

428

'InvalidChannel',

429

'V1:Hrec_hoft_16384Hz',

430

'X1:FAKE-CHANNEL' # X1 is not a real detector

431

]

432

433

valid, invalid = validate_channel_names(test_channels)

434

print(f"Valid channels: {valid}")

435

print(f"Invalid channels: {invalid}")

436

437

# Parse valid channels

438

for name in valid:

439

info = parse_channel_name(name)

440

print(f"{name}:")

441

print(f" IFO: {info['ifo']}")

442

print(f" System: {info['system']}")

443

print(f" Signal: {info['signal']}")

444

```