or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

file-operations.mdheader-operations.mdimage-operations.mdindex.mdtable-operations.md

table-operations.mddocs/

0

# Table Operations

1

2

FITS table data handling functionality supporting both binary and ASCII tables with advanced features including column operations, row filtering, variable-length columns, table modifications, and efficient data access patterns.

3

4

## Capabilities

5

6

### TableHDU Class

7

8

Handler for FITS binary table extensions with comprehensive table operations and data manipulation capabilities.

9

10

```python { .api }

11

class TableHDU:

12

def read(self, columns=None, rows=None, vstorage='fixed', **kwargs):

13

"""

14

Read table data as structured array.

15

16

Parameters:

17

- columns: list/str, column names to read

18

- rows: list/array, specific rows to read

19

- vstorage: str, variable length storage ('fixed' or 'object')

20

- **kwargs: additional read options

21

22

Returns:

23

numpy structured array

24

"""

25

26

def read_column(self, col, rows=None, vstorage='fixed', **kwargs):

27

"""

28

Read single column data.

29

30

Parameters:

31

- col: str/int, column name or number

32

- rows: list/array, specific rows to read

33

- vstorage: str, variable length storage method

34

- **kwargs: additional options

35

36

Returns:

37

numpy array

38

"""

39

40

def read_columns(self, columns, rows=None, **kwargs):

41

"""

42

Read multiple columns efficiently.

43

44

Parameters:

45

- columns: list, column names to read

46

- rows: list/array, specific rows to read

47

- **kwargs: additional options

48

49

Returns:

50

numpy structured array

51

"""

52

53

def read_rows(self, rows, columns=None, **kwargs):

54

"""

55

Read specific rows.

56

57

Parameters:

58

- rows: list/array, row indices to read

59

- columns: list, columns to include

60

- **kwargs: additional options

61

62

Returns:

63

numpy structured array

64

"""

65

66

def read_slice(self, firstrow, lastrow, columns=None, **kwargs):

67

"""

68

Read row range slice.

69

70

Parameters:

71

- firstrow: int, first row index

72

- lastrow: int, last row index

73

- columns: list, columns to include

74

- **kwargs: additional options

75

76

Returns:

77

numpy structured array

78

"""

79

80

def write(self, data, firstrow=0, **kwargs):

81

"""

82

Write/overwrite table data.

83

84

Parameters:

85

- data: structured array/dict/list, table data

86

- firstrow: int, starting row for writing

87

- **kwargs: additional write options

88

"""

89

90

def write_column(self, column, data, firstrow=0, **kwargs):

91

"""

92

Write single column data.

93

94

Parameters:

95

- column: str/int, column name or number

96

- data: array-like, column data

97

- firstrow: int, starting row

98

- **kwargs: additional options

99

"""

100

101

def write_var_column(self, column, data, **kwargs):

102

"""

103

Write variable length column.

104

105

Parameters:

106

- column: str/int, column name or number

107

- data: list/object array, variable length data

108

- **kwargs: additional options

109

"""

110

111

def append(self, data, **kwargs):

112

"""

113

Append rows to existing table.

114

115

Parameters:

116

- data: structured array/dict/list, new rows

117

- **kwargs: additional options

118

"""

119

120

def insert_column(self, name, data, colnum=None, **kwargs):

121

"""

122

Insert new column into table.

123

124

Parameters:

125

- name: str, column name

126

- data: array-like, column data

127

- colnum: int, column position (default: append)

128

- **kwargs: column format options

129

"""

130

131

def delete_rows(self, rows):

132

"""

133

Delete specified rows.

134

135

Parameters:

136

- rows: list/array, row indices to delete

137

"""

138

139

def resize(self, nrows, front=False):

140

"""

141

Change table size.

142

143

Parameters:

144

- nrows: int, new number of rows

145

- front: bool, add/remove rows at front

146

"""

147

148

def where(self, expression, **kwargs):

149

"""

150

Query table with WHERE expression.

151

152

Parameters:

153

- expression: str, SQL-like WHERE clause

154

- **kwargs: additional options

155

156

Returns:

157

numpy array, row indices matching expression

158

"""

159

160

def get_nrows(self):

161

"""

162

Get number of rows.

163

164

Returns:

165

int, number of rows

166

"""

167

168

def get_colnames(self):

169

"""

170

Get column names.

171

172

Returns:

173

list of str, column names

174

"""

175

176

def get_colname(self, colnum):

177

"""

178

Get column name by number.

179

180

Parameters:

181

- colnum: int, column number (0-based)

182

183

Returns:

184

str, column name

185

"""

186

187

def get_vstorage(self):

188

"""

189

Get variable length storage method.

190

191

Returns:

192

str, storage method ('fixed' or 'object')

193

"""

194

195

def get_rec_dtype(self, **kwargs):

196

"""

197

Get record array dtype.

198

199

Parameters:

200

- **kwargs: dtype options

201

202

Returns:

203

numpy dtype, structured array dtype

204

"""

205

206

def get_rec_column_descr(self):

207

"""

208

Get column descriptions for structured array.

209

210

Returns:

211

list, column descriptors

212

"""

213

214

def __getitem__(self, key):

215

"""

216

Access table data by column/row.

217

218

Parameters:

219

- key: str/int/tuple/slice, column name, row index, or slice

220

221

Returns:

222

numpy array or structured array

223

"""

224

225

def __iter__(self):

226

"""

227

Iterate over table rows with buffering.

228

229

Yields:

230

numpy structured array, individual rows

231

"""

232

233

# Inherited from HDUBase

234

def get_info(self):

235

"""Get complete HDU information."""

236

237

def get_offsets(self):

238

"""Get byte offsets (header_start, data_start, data_end)."""

239

240

def get_extnum(self):

241

"""Get extension number."""

242

243

def get_extname(self):

244

"""Get extension name."""

245

246

def get_extver(self):

247

"""Get extension version."""

248

249

def get_exttype(self, num=False):

250

"""Get extension type."""

251

252

def read_header(self):

253

"""Read header as FITSHDR object."""

254

255

def write_key(self, name, value, comment=""):

256

"""Write single header keyword."""

257

258

def write_keys(self, records, clean=True):

259

"""Write multiple header keywords."""

260

261

def write_checksum(self):

262

"""Write DATASUM/CHECKSUM keywords."""

263

264

def verify_checksum(self):

265

"""Verify data integrity."""

266

```

267

268

### AsciiTableHDU Class

269

270

Handler for FITS ASCII table extensions, inheriting from TableHDU with ASCII-specific operations.

271

272

```python { .api }

273

class AsciiTableHDU(TableHDU):

274

"""ASCII table HDU with same interface as TableHDU."""

275

```

276

277

### Table Data Types

278

279

```python { .api }

280

# Supported column data types:

281

# - 'L': Logical (boolean)

282

# - 'B': Unsigned byte (uint8)

283

# - 'I': 16-bit integer (int16)

284

# - 'J': 32-bit integer (int32)

285

# - 'K': 64-bit integer (int64)

286

# - 'A': Character string

287

# - 'E': Single precision float (float32)

288

# - 'D': Double precision float (float64)

289

# - 'C': Single precision complex (complex64)

290

# - 'M': Double precision complex (complex128)

291

# - 'P': Variable length array pointer

292

# - 'Q': Variable length array pointer (64-bit)

293

```

294

295

## HDU Type Constants

296

297

```python { .api }

298

BINARY_TBL = 2

299

ASCII_TBL = 1

300

```

301

302

## Usage Examples

303

304

### Reading Tables

305

306

```python

307

import fitsio

308

import numpy as np

309

310

# Read entire table

311

data = fitsio.read('catalog.fits', ext=1)

312

print(f"Table shape: {data.shape}")

313

print(f"Columns: {data.dtype.names}")

314

315

# Read specific columns

316

coords = fitsio.read('catalog.fits', ext=1, columns=['ra', 'dec'])

317

318

# Read specific rows

319

subset = fitsio.read('catalog.fits', ext=1, rows=[0, 10, 100])

320

321

# Read with FITS object for more control

322

with fitsio.FITS('catalog.fits') as fits:

323

table = fits[1]

324

325

# Get table information

326

nrows = table.get_nrows()

327

colnames = table.get_colnames()

328

329

print(f"Table has {nrows} rows and columns: {colnames}")

330

331

# Read different ways

332

all_data = table.read()

333

single_col = table.read_column('flux')

334

multi_col = table.read_columns(['x', 'y', 'flux'])

335

row_slice = table.read_slice(100, 200)

336

```

337

338

### Table Slicing and Access

339

340

```python

341

import fitsio

342

343

with fitsio.FITS('catalog.fits') as fits:

344

table = fits[1]

345

346

# Column access

347

x_values = table['x'][:] # All x values

348

y_values = table['y'][:] # All y values

349

coords = table['x', 'y'][:] # Multiple columns

350

351

# Row access

352

first_100 = table[:100] # First 100 rows

353

every_10th = table[::10] # Every 10th row

354

specific_rows = table[[5, 15, 25]] # Specific row indices

355

356

# Combined access

357

subset = table['flux'][100:200] # Column slice

358

multi_subset = table['x', 'y'][50:150] # Multiple columns, row range

359

```

360

361

### Writing Tables

362

363

```python

364

import fitsio

365

import numpy as np

366

367

# Create structured array

368

nrows = 1000

369

data = np.zeros(nrows, dtype=[

370

('id', 'i4'),

371

('ra', 'f8'),

372

('dec', 'f8'),

373

('flux', 'f4'),

374

('flag', 'bool'),

375

('name', 'U20')

376

])

377

378

# Fill with data

379

data['id'] = np.arange(nrows)

380

data['ra'] = np.random.uniform(0, 360, nrows)

381

data['dec'] = np.random.uniform(-90, 90, nrows)

382

data['flux'] = np.random.lognormal(0, 1, nrows)

383

data['flag'] = np.random.choice([True, False], nrows)

384

data['name'] = [f'object_{i:04d}' for i in range(nrows)]

385

386

# Write table

387

fitsio.write('new_catalog.fits', data)

388

389

# Write with header

390

header = fitsio.FITSHDR([

391

{'name': 'EXTNAME', 'value': 'CATALOG', 'comment': 'Table name'},

392

{'name': 'COORDSYS', 'value': 'EQUATORIAL', 'comment': 'Coordinate system'}

393

])

394

fitsio.write('catalog_with_header.fits', data, header=header)

395

```

396

397

### Table Modifications

398

399

```python

400

import fitsio

401

import numpy as np

402

403

with fitsio.FITS('catalog.fits', 'rw') as fits:

404

table = fits[1]

405

406

# Append new rows

407

new_data = np.zeros(50, dtype=table.get_rec_dtype())

408

new_data['id'] = np.arange(1000, 1050)

409

table.append(new_data)

410

411

# Insert new column

412

magnitudes = np.random.uniform(15, 25, table.get_nrows())

413

table.insert_column('magnitude', magnitudes)

414

415

# Overwrite specific rows

416

updated_rows = np.zeros(10, dtype=table.get_rec_dtype())

417

table.write(updated_rows, firstrow=100)

418

419

# Write to specific column

420

new_fluxes = np.random.lognormal(0, 1, table.get_nrows())

421

table.write_column('flux', new_fluxes)

422

423

# Delete rows

424

table.delete_rows([5, 15, 25]) # Delete specific rows

425

426

# Resize table

427

table.resize(800) # Truncate to 800 rows

428

```

429

430

### Variable Length Columns

431

432

```python

433

import fitsio

434

import numpy as np

435

436

# Create data with variable length arrays

437

nrows = 100

438

data = np.zeros(nrows, dtype=[

439

('id', 'i4'),

440

('measurements', 'O'), # Object array for variable length

441

('notes', 'O') # Object array for variable strings

442

])

443

444

data['id'] = np.arange(nrows)

445

446

# Variable length numeric arrays

447

for i in range(nrows):

448

n_measurements = np.random.randint(1, 20)

449

data['measurements'][i] = np.random.random(n_measurements)

450

data['notes'][i] = f"Object {i} has {n_measurements} measurements"

451

452

# Write with object storage

453

fitsio.write('variable_length.fits', data)

454

455

# Read with object storage

456

var_data = fitsio.read('variable_length.fits', vstorage='object')

457

print(f"First object measurements: {var_data['measurements'][0]}")

458

459

# Read with fixed storage (padded arrays)

460

fixed_data = fitsio.read('variable_length.fits', vstorage='fixed')

461

```

462

463

### Table Queries and Filtering

464

465

```python

466

import fitsio

467

468

with fitsio.FITS('catalog.fits') as fits:

469

table = fits[1]

470

471

# Query with WHERE clause

472

bright_stars = table.where("flux > 100.0")

473

northern = table.where("dec > 0")

474

complex_query = table.where("flux > 50 && dec > -30 && dec < 30")

475

476

# Use query results to read data

477

bright_data = table.read(rows=bright_stars)

478

479

# Combine with column selection

480

coords_north = table.read(columns=['ra', 'dec'], rows=northern)

481

482

# Multiple conditions

483

good_objects = table.where("flux > 10 && flag == 1")

484

print(f"Found {len(good_objects)} good objects")

485

```

486

487

### Working with Different Table Formats

488

489

```python

490

import fitsio

491

import numpy as np

492

493

# Create different data structures

494

# 1. List of arrays

495

x_data = np.random.random(100)

496

y_data = np.random.random(100)

497

names = [f'star_{i}' for i in range(100)]

498

499

# Write from list with names

500

fitsio.write('from_lists.fits', [x_data, y_data, names],

501

names=['x', 'y', 'name'])

502

503

# 2. Dictionary of arrays

504

data_dict = {

505

'x': x_data,

506

'y': y_data,

507

'name': names

508

}

509

fitsio.write('from_dict.fits', data_dict)

510

511

# 3. Record array (most flexible)

512

rec_data = np.rec.fromarrays([x_data, y_data, names],

513

names=['x', 'y', 'name'])

514

fitsio.write('from_recarray.fits', rec_data)

515

```

516

517

### Table Iteration and Large Tables

518

519

```python

520

import fitsio

521

522

# Efficient iteration over large tables

523

with fitsio.FITS('large_catalog.fits', iter_row_buffer=1000) as fits:

524

table = fits[1]

525

526

# Process table in chunks

527

for i, row in enumerate(table):

528

if i % 10000 == 0:

529

print(f"Processed {i} rows")

530

531

# Process individual row

532

if row['flux'] > 100:

533

# Do something with bright objects

534

pass

535

536

# Alternative: read in chunks manually

537

nrows = table.get_nrows()

538

chunk_size = 10000

539

540

for start in range(0, nrows, chunk_size):

541

end = min(start + chunk_size, nrows)

542

chunk = table.read_slice(start, end)

543

544

# Process chunk

545

bright = chunk[chunk['flux'] > 100]

546

print(f"Chunk {start}-{end}: found {len(bright)} bright objects")

547

```

548

549

### Advanced Table Operations

550

551

```python

552

import fitsio

553

import numpy as np

554

555

with fitsio.FITS('catalog.fits', 'rw') as fits:

556

table = fits[1]

557

558

# Get complete column information

559

dtype = table.get_rec_dtype()

560

column_desc = table.get_rec_column_descr()

561

562

print(f"Table dtype: {dtype}")

563

print(f"Column descriptions: {column_desc}")

564

565

# Case sensitivity control

566

table.case_sensitive = True

567

table.lower = False

568

table.upper = False

569

570

# Work with array columns (multi-dimensional)

571

# Add column with 2D array data

572

array_col = np.random.random((table.get_nrows(), 3, 3))

573

table.insert_column('covariance', array_col)

574

575

# Read array column

576

cov_matrices = table['covariance'][:]

577

print(f"Covariance matrices shape: {cov_matrices.shape}")

578

```