Skip to content

Commit d599ff5

Browse files
committed
Add vector type support (ex: '100E')
1 parent e2a79db commit d599ff5

File tree

7 files changed

+199
-29
lines changed

7 files changed

+199
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
66

77
## [Unreleased]
88
### Added
9+
* Support for vector data-types in reading and writing tables.
910
### Changed
1011
### Removed
1112

fitsio/src/fitsfile.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -368,27 +368,29 @@ impl FitsFile {
368368
for i in 0..num_cols {
369369
let mut name_buffer: Vec<libc::c_char> = vec![0; 71];
370370
let mut type_buffer: Vec<libc::c_char> = vec![0; 71];
371+
let mut repeats: libc::c_long = 0;
371372
unsafe {
372373
fits_get_bcolparms(
373374
self.fptr.as_mut() as *mut _,
374375
i + 1,
375376
name_buffer.as_mut_ptr(),
376377
ptr::null_mut(),
377378
type_buffer.as_mut_ptr(),
378-
ptr::null_mut(),
379+
&mut repeats as *mut libc::c_long,
379380
ptr::null_mut(),
380381
ptr::null_mut(),
381382
ptr::null_mut(),
382383
ptr::null_mut(),
383384
&mut status,
384385
);
385386
}
386-
387-
column_descriptions.push(ConcreteColumnDescription {
387+
let mut col = ConcreteColumnDescription {
388388
name: stringutils::buf_to_string(&name_buffer)?,
389389
data_type: stringutils::buf_to_string(&type_buffer)?
390390
.parse::<ColumnDataDescription>()?,
391-
});
391+
};
392+
col.data_type.repeat = repeats as usize;
393+
column_descriptions.push(col);
392394
}
393395

394396
HduInfo::TableInfo {

fitsio/src/longnam.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
#![allow(unused_imports, dead_code)]
66

77
pub(crate) use crate::sys::{
8-
ffclos, ffcopy, ffcrim, ffcrtb, ffdcol, ffdhdu, ffflmd, ffgbcl, ffgcdw, ffgcno, ffgcvd, ffgcve,
9-
ffgcvi, ffgcvj, ffgcvjj, ffgcvk, ffgcvl, ffgcvs, ffgcvui, ffgcvuj, ffgcvujj, ffgcvuk, ffghdn,
10-
ffghdt, ffgidm, ffgiet, ffgisz, ffgkyd, ffgkye, ffgkyj, ffgkyjj, ffgkyl, ffgkys, ffgncl,
11-
ffgnrw, ffgpv, ffgsv, fficol, ffinit, ffmahd, ffmnhd, ffopen, ffpcl, ffpcls, ffphps, ffpky,
12-
ffpkyd, ffpkye, ffpkys, ffppr, ffpss, ffrsim, ffthdu, fitsfile, LONGLONG,
8+
ffclos, ffcopy, ffcrim, ffcrtb, ffdcol, ffdhdu, ffflmd, ffgbcl, ffgcdw, ffgcno, ffgcvb, ffgcvd,
9+
ffgcve, ffgcvi, ffgcvj, ffgcvjj, ffgcvk, ffgcvl, ffgcvs, ffgcvsb, ffgcvui, ffgcvuj, ffgcvujj,
10+
ffgcvuk, ffgcx, ffghdn, ffghdt, ffgidm, ffgiet, ffgisz, ffgkyd, ffgkye, ffgkyj, ffgkyjj,
11+
ffgkyl, ffgkys, ffgncl, ffgnrw, ffgpv, ffgsv, fficol, ffinit, ffmahd, ffmnhd, ffopen, ffpcl,
12+
ffpcls, ffpclx, ffphps, ffpky, ffpkyd, ffpkye, ffpkys, ffppr, ffpss, ffrsim, ffthdu, fitsfile,
13+
LONGLONG,
1314
};
1415
pub use libc::{
15-
c_char, c_double, c_float, c_int, c_long, c_short, c_uint, c_ulong, c_ulonglong, c_ushort,
16-
c_void,
16+
c_char, c_double, c_float, c_int, c_long, c_schar, c_short, c_uchar, c_uint, c_ulong,
17+
c_ulonglong, c_ushort, c_void,
1718
};
1819

1920
pub(crate) unsafe fn fits_close_file(fptr: *mut fitsfile, status: *mut libc::c_int) -> c_int {
@@ -148,6 +149,38 @@ pub(crate) unsafe fn fits_read_col_log(
148149
)
149150
}
150151

152+
pub(crate) unsafe fn fits_read_col_byt(
153+
fptr: *mut fitsfile,
154+
colnum: c_int,
155+
firstrow: LONGLONG,
156+
firstelem: LONGLONG,
157+
nelem: LONGLONG,
158+
nulval: c_uchar,
159+
array: *mut c_uchar,
160+
anynul: *mut c_int,
161+
status: *mut c_int,
162+
) -> c_int {
163+
ffgcvb(
164+
fptr, colnum, firstrow, firstelem, nelem, nulval, array, anynul, status,
165+
)
166+
}
167+
168+
pub(crate) unsafe fn fits_read_col_sbyt(
169+
fptr: *mut fitsfile,
170+
colnum: c_int,
171+
firstrow: LONGLONG,
172+
firstelem: LONGLONG,
173+
nelem: LONGLONG,
174+
nulval: c_schar,
175+
array: *mut c_schar,
176+
anynul: *mut c_int,
177+
status: *mut c_int,
178+
) -> c_int {
179+
ffgcvsb(
180+
fptr, colnum, firstrow, firstelem, nelem, nulval, array, anynul, status,
181+
)
182+
}
183+
151184
pub(crate) unsafe fn fits_read_col_sht(
152185
fptr: *mut fitsfile,
153186
colnum: c_int,

fitsio/src/tables.rs

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::longnam::*;
66
use crate::stringutils::status_to_string;
77
use crate::types::DataType;
88
use std::ffi;
9+
use std::mem::size_of;
910
use std::ops::Range;
1011
use std::ptr;
1112
use std::str::FromStr;
@@ -59,7 +60,6 @@ macro_rules! reads_col_impl {
5960
..
6061
}) => {
6162
let num_output_rows = range.end - range.start;
62-
let mut out = vec![$nullval; num_output_rows];
6363
let test_name = name.into();
6464
let column_number = column_descriptions
6565
.iter()
@@ -68,14 +68,22 @@ macro_rules! reads_col_impl {
6868
"Cannot find column {:?}",
6969
test_name
7070
)))?;
71+
let col_desc = &column_descriptions[column_number];
72+
#[allow(clippy::manual_bits)]
73+
let repeat = if col_desc.data_type.typ == ColumnDataType::Bit {
74+
col_desc.data_type.repeat / (size_of::<$t>() * 8)
75+
} else {
76+
col_desc.data_type.repeat
77+
};
78+
let mut out = vec![$nullval; num_output_rows * repeat];
7179
let mut status = 0;
7280
unsafe {
7381
$func(
7482
fits_file.fptr.as_mut() as *mut _,
7583
(column_number + 1) as i32,
7684
(range.start + 1) as i64,
7785
1,
78-
num_output_rows as _,
86+
(num_output_rows * repeat) as _,
7987
$nullval,
8088
out.as_mut_ptr(),
8189
ptr::null_mut(),
@@ -121,6 +129,12 @@ macro_rules! reads_col_impl {
121129
"Cannot find column {:?}",
122130
test_name
123131
)))?;
132+
let repeat = column_descriptions[column_number].data_type.repeat;
133+
if repeat > 1 {
134+
unimplemented!(
135+
"reading a single cell of a vector value (e.g., TFORM1 = 100E) is unimplemented. Call read_col() or read_col_range()."
136+
)
137+
}
124138
let mut status = 0;
125139

126140
unsafe {
@@ -248,6 +262,8 @@ impl ReadsCol for bool {
248262
}
249263
}
250264

265+
reads_col_impl!(u8, fits_read_col_byt, 0);
266+
reads_col_impl!(i8, fits_read_col_sbyt, 0);
251267
reads_col_impl!(i16, fits_read_col_sht, 0);
252268
reads_col_impl!(u16, fits_read_col_usht, 0);
253269
reads_col_impl!(i32, fits_read_col_int, 0);
@@ -387,15 +403,15 @@ macro_rules! writes_col_impl {
387403
let colno = hdu.get_column_no(fits_file, col_name.into())?;
388404
// TODO: check that the column exists in the file
389405
let mut status = 0;
390-
let n_elements = rows.end - rows.start;
406+
let n_rows = rows.end - rows.start;
391407
unsafe {
392408
fits_write_col(
393409
fits_file.fptr.as_mut() as *mut _,
394410
$data_type.into(),
395411
(colno + 1) as _,
396412
(rows.start + 1) as _,
397413
1,
398-
n_elements as _,
414+
n_rows as _,
399415
col_data.as_ptr() as *mut _,
400416
&mut status,
401417
);
@@ -415,6 +431,8 @@ macro_rules! writes_col_impl {
415431
};
416432
}
417433

434+
writes_col_impl!(u8, DataType::TBYTE);
435+
writes_col_impl!(i8, DataType::TSBYTE);
418436
writes_col_impl!(u32, DataType::TUINT);
419437
#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))]
420438
writes_col_impl!(u64, DataType::TULONG);
@@ -639,14 +657,20 @@ impl From<ColumnDataDescription> for String {
639657
#[allow(missing_docs)]
640658
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
641659
pub enum ColumnDataType {
660+
Logical,
642661
Bit,
643-
Bool,
662+
Byte,
663+
SignedByte,
664+
Short,
665+
UnsignedShort,
644666
Int,
667+
Long,
668+
UnsignedLong,
645669
Float,
646670
Text,
647671
Double,
648-
Short,
649-
Long,
672+
LongLong,
673+
UnsignedLongLong,
650674
String,
651675
}
652676

@@ -655,14 +679,19 @@ impl From<ColumnDataType> for String {
655679
use self::ColumnDataType::*;
656680

657681
match orig {
682+
Logical => "L",
658683
Bit => "X",
659-
Bool => "B",
660-
Int => "J",
684+
Byte => "B",
685+
SignedByte => "S",
686+
Short => "I",
687+
UnsignedShort => "U",
688+
Int | Long => "J",
689+
UnsignedLong => "U",
661690
Float => "E",
662691
Text | String => "A",
663692
Double => "D",
664-
Short => "I",
665-
Long => "K",
693+
LongLong => "K",
694+
UnsignedLongLong => "W",
666695
}
667696
.to_string()
668697
}
@@ -712,15 +741,19 @@ impl FromStr for ColumnDataDescription {
712741
};
713742

714743
let data_type = match data_type_char {
744+
'L' => ColumnDataType::Logical,
715745
'X' => ColumnDataType::Bit,
716-
'B' => ColumnDataType::Bool,
746+
'B' => ColumnDataType::Byte,
747+
'S' => ColumnDataType::SignedByte,
717748
'E' => ColumnDataType::Float,
718749
'J' => ColumnDataType::Int,
719750
'D' => ColumnDataType::Double,
720751
'I' => ColumnDataType::Short,
721-
'K' => ColumnDataType::Long,
752+
'K' => ColumnDataType::LongLong,
722753
'A' => ColumnDataType::String,
723-
'L' => ColumnDataType::Bool,
754+
'U' => ColumnDataType::UnsignedShort,
755+
'V' => ColumnDataType::UnsignedLong,
756+
'W' => ColumnDataType::UnsignedLongLong,
724757
_ => panic!(
725758
"Have not implemented str -> ColumnDataType for {}",
726759
data_type_char
@@ -772,8 +805,9 @@ macro_rules! datatype_into_impl {
772805
DataType::TINT => 31,
773806
DataType::TULONG => 40,
774807
DataType::TLONG => 41,
775-
DataType::TLONGLONG => 81,
776808
DataType::TFLOAT => 42,
809+
DataType::TULONGLONG => 80,
810+
DataType::TLONGLONG => 81,
777811
DataType::TDOUBLE => 82,
778812
DataType::TCOMPLEX => 83,
779813
DataType::TDBLCOMPLEX => 163,

fitsio/src/types.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ pub enum DataType {
1616
TINT,
1717
TULONG,
1818
TLONG,
19-
TLONGLONG,
2019
TFLOAT,
20+
TULONGLONG,
21+
TLONGLONG,
2122
TDOUBLE,
2223
TCOMPLEX,
2324
TDBLCOMPLEX,

fitsio/tests/test_bit_datatype.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ fn test_writing_bit_data_type() {
1919
let tmp_dir = Builder::new().prefix("fitsio-").tempdir().unwrap();
2020
let file_path = tmp_dir.path().join("example.fits");
2121

22+
let data: Vec<u32> = (0..64).collect();
2223
{
2324
let mut fitsfile = FitsFile::create(&file_path).open().unwrap();
2425

25-
let data: Vec<u32> = (0..64).collect();
2626
let col = ColumnDescription::new("BITMASK")
2727
.with_type(ColumnDataType::Bit)
2828
.create()
@@ -38,5 +38,5 @@ fn test_writing_bit_data_type() {
3838

3939
let table_hdu = f.hdu("DATA").unwrap();
4040
let flags: Vec<u32> = dbg!(table_hdu.read_col(&mut f, "BITMASK").unwrap());
41-
assert_eq!(flags.len(), 64);
41+
assert!(data.iter().zip(&flags).all(|(a, b)| a == b));
4242
}

0 commit comments

Comments
 (0)