Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add vector type support #330

Merged
merged 6 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a

## [Unreleased]
### Added
* Support for vector data-types in reading and writing tables.
### Changed
### Removed

Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Before submitting a completed PR, make sure the following items have been addres
* **format the code** - make sure the code has been formatted by `rustfmt` before submitting. I have a [git `pre-push` hook](https://gist.github.com/zofrex/4a5084c49e4aadd0a3fa0edda14b1fa8) which handles this for me.
* **update the features tracking issue** - if relevant, update the [features tracking issue][features-tracking-issue]
* **update the full example** - if new features have been added, or changes made, update the `full_example.rs` example
* **satisfy clippy** - our Github CI will apply `cargo clippy` with warnings treated as errors.
fotonick marked this conversation as resolved.
Show resolved Hide resolved

[features-tracking-issue]: https://github.com/simonrw/rust-fitsio/issues/15

Expand Down
10 changes: 6 additions & 4 deletions fitsio/src/fitsfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,27 +368,29 @@ impl FitsFile {
for i in 0..num_cols {
let mut name_buffer: Vec<libc::c_char> = vec![0; 71];
let mut type_buffer: Vec<libc::c_char> = vec![0; 71];
let mut repeats: libc::c_long = 0;
unsafe {
fits_get_bcolparms(
self.fptr.as_mut() as *mut _,
i + 1,
name_buffer.as_mut_ptr(),
ptr::null_mut(),
type_buffer.as_mut_ptr(),
ptr::null_mut(),
&mut repeats as *mut libc::c_long,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
&mut status,
);
}

column_descriptions.push(ConcreteColumnDescription {
let mut col = ConcreteColumnDescription {
name: stringutils::buf_to_string(&name_buffer)?,
data_type: stringutils::buf_to_string(&type_buffer)?
.parse::<ColumnDataDescription>()?,
});
};
col.data_type.repeat = repeats as usize;
column_descriptions.push(col);
}

HduInfo::TableInfo {
Expand Down
47 changes: 40 additions & 7 deletions fitsio/src/longnam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
#![allow(unused_imports, dead_code)]

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

pub(crate) unsafe fn fits_close_file(fptr: *mut fitsfile, status: *mut libc::c_int) -> c_int {
Expand Down Expand Up @@ -148,6 +149,38 @@ pub(crate) unsafe fn fits_read_col_log(
)
}

pub(crate) unsafe fn fits_read_col_byt(
fptr: *mut fitsfile,
colnum: c_int,
firstrow: LONGLONG,
firstelem: LONGLONG,
nelem: LONGLONG,
nulval: c_uchar,
array: *mut c_uchar,
anynul: *mut c_int,
status: *mut c_int,
) -> c_int {
ffgcvb(
fptr, colnum, firstrow, firstelem, nelem, nulval, array, anynul, status,
)
}

pub(crate) unsafe fn fits_read_col_sbyt(
fptr: *mut fitsfile,
colnum: c_int,
firstrow: LONGLONG,
firstelem: LONGLONG,
nelem: LONGLONG,
nulval: c_schar,
array: *mut c_schar,
anynul: *mut c_int,
status: *mut c_int,
) -> c_int {
ffgcvsb(
fptr, colnum, firstrow, firstelem, nelem, nulval, array, anynul, status,
)
}

pub(crate) unsafe fn fits_read_col_sht(
fptr: *mut fitsfile,
colnum: c_int,
Expand Down
80 changes: 53 additions & 27 deletions fitsio/src/tables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::longnam::*;
use crate::stringutils::status_to_string;
use crate::types::DataType;
use std::ffi;
use std::mem::size_of;
use std::ops::Range;
use std::ptr;
use std::str::FromStr;
Expand Down Expand Up @@ -59,7 +60,6 @@ macro_rules! reads_col_impl {
..
}) => {
let num_output_rows = range.end - range.start;
let mut out = vec![$nullval; num_output_rows];
let test_name = name.into();
let column_number = column_descriptions
.iter()
Expand All @@ -68,14 +68,24 @@ macro_rules! reads_col_impl {
"Cannot find column {:?}",
test_name
)))?;
let col_desc = &column_descriptions[column_number];
#[allow(clippy::manual_bits)]
let repeat = if col_desc.data_type.typ == ColumnDataType::Bit {
// take the maximum of hte value with 1 for data types smaller than 8
// bites, e.g. u32
(col_desc.data_type.repeat / (size_of::<$t>() * 8)).max(1)
} else {
col_desc.data_type.repeat
};
let mut out = vec![$nullval; num_output_rows * repeat];
let mut status = 0;
unsafe {
$func(
fits_file.fptr.as_mut() as *mut _,
(column_number + 1) as i32,
(range.start + 1) as i64,
1,
num_output_rows as _,
(num_output_rows * repeat) as _,
$nullval,
out.as_mut_ptr(),
ptr::null_mut(),
Expand Down Expand Up @@ -121,6 +131,12 @@ macro_rules! reads_col_impl {
"Cannot find column {:?}",
test_name
)))?;
let repeat = column_descriptions[column_number].data_type.repeat;
if repeat > 1 {
unimplemented!(
"reading a single cell of a vector value (e.g., TFORM1 = 100E) is unimplemented. Call read_col() or read_col_range()."
)
}
let mut status = 0;

unsafe {
Expand Down Expand Up @@ -248,19 +264,15 @@ impl ReadsCol for bool {
}
}

reads_col_impl!(u8, fits_read_col_byt, 0);
reads_col_impl!(i8, fits_read_col_sbyt, 0);
reads_col_impl!(i16, fits_read_col_sht, 0);
reads_col_impl!(u16, fits_read_col_usht, 0);
reads_col_impl!(i32, fits_read_col_int, 0);
reads_col_impl!(u32, fits_read_col_uint, 0);
reads_col_impl!(f32, fits_read_col_flt, 0.0);
reads_col_impl!(f64, fits_read_col_dbl, 0.0);
#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))]
reads_col_impl!(i64, fits_read_col_lng, 0);
#[cfg(any(target_pointer_width = "32", target_os = "windows"))]
reads_col_impl!(i64, fits_read_col_lnglng, 0);
#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))]
reads_col_impl!(u64, fits_read_col_ulng, 0);
#[cfg(any(target_pointer_width = "32", target_os = "windows"))]
reads_col_impl!(u64, fits_read_col_ulnglng, 0);

impl ReadsCol for String {
Expand Down Expand Up @@ -387,7 +399,7 @@ macro_rules! writes_col_impl {
let colno = hdu.get_column_no(fits_file, col_name.into())?;
// TODO: check that the column exists in the file
let mut status = 0;
let n_elements = rows.end - rows.start;
let n_elements = (rows.end - rows.start);
unsafe {
fits_write_col(
fits_file.fptr.as_mut() as *mut _,
Expand Down Expand Up @@ -415,15 +427,13 @@ macro_rules! writes_col_impl {
};
}

writes_col_impl!(u8, DataType::TBYTE);
writes_col_impl!(i8, DataType::TSBYTE);
writes_col_impl!(u16, DataType::TUSHORT);
writes_col_impl!(i16, DataType::TSHORT);
writes_col_impl!(u32, DataType::TUINT);
#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))]
writes_col_impl!(u64, DataType::TULONG);
#[cfg(any(target_pointer_width = "32", target_os = "windows"))]
writes_col_impl!(u64, DataType::TLONGLONG);
writes_col_impl!(i32, DataType::TINT);
#[cfg(all(target_pointer_width = "64", not(target_os = "windows")))]
writes_col_impl!(i64, DataType::TLONG);
#[cfg(any(target_pointer_width = "32", target_os = "windows"))]
writes_col_impl!(u64, DataType::TULONGLONG);
writes_col_impl!(i64, DataType::TLONGLONG);
writes_col_impl!(f32, DataType::TFLOAT);
writes_col_impl!(f64, DataType::TDOUBLE);
Expand Down Expand Up @@ -639,14 +649,20 @@ impl From<ColumnDataDescription> for String {
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColumnDataType {
Logical,
Bit,
Bool,
Byte,
SignedByte,
Short,
UnsignedShort,
Int,
Long,
UnsignedLong,
Float,
Text,
Double,
Short,
Long,
LongLong,
UnsignedLongLong,
String,
}

Expand All @@ -655,14 +671,19 @@ impl From<ColumnDataType> for String {
use self::ColumnDataType::*;

match orig {
Logical => "L",
Bit => "X",
Bool => "B",
Int => "J",
Byte => "B",
SignedByte => "S",
Short => "I",
UnsignedShort => "U",
Int | Long => "J",
UnsignedLong => "V",
Float => "E",
Text | String => "A",
Double => "D",
Short => "I",
Long => "K",
LongLong => "K",
UnsignedLongLong => "W",
}
.to_string()
}
Expand Down Expand Up @@ -712,15 +733,19 @@ impl FromStr for ColumnDataDescription {
};

let data_type = match data_type_char {
'L' => ColumnDataType::Logical,
'X' => ColumnDataType::Bit,
'B' => ColumnDataType::Bool,
'B' => ColumnDataType::Byte,
'S' => ColumnDataType::SignedByte,
'E' => ColumnDataType::Float,
'J' => ColumnDataType::Int,
'D' => ColumnDataType::Double,
'I' => ColumnDataType::Short,
'K' => ColumnDataType::Long,
'K' => ColumnDataType::LongLong,
'A' => ColumnDataType::String,
'L' => ColumnDataType::Bool,
'U' => ColumnDataType::UnsignedShort,
'V' => ColumnDataType::UnsignedLong,
'W' => ColumnDataType::UnsignedLongLong,
_ => panic!(
"Have not implemented str -> ColumnDataType for {}",
data_type_char
Expand Down Expand Up @@ -772,8 +797,9 @@ macro_rules! datatype_into_impl {
DataType::TINT => 31,
DataType::TULONG => 40,
DataType::TLONG => 41,
DataType::TLONGLONG => 81,
DataType::TFLOAT => 42,
DataType::TULONGLONG => 80,
DataType::TLONGLONG => 81,
DataType::TDOUBLE => 82,
DataType::TCOMPLEX => 83,
DataType::TDBLCOMPLEX => 163,
Expand Down
3 changes: 2 additions & 1 deletion fitsio/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ pub enum DataType {
TINT,
TULONG,
TLONG,
TLONGLONG,
TFLOAT,
TULONGLONG,
TLONGLONG,
TDOUBLE,
TCOMPLEX,
TDBLCOMPLEX,
Expand Down
3 changes: 2 additions & 1 deletion fitsio/tests/test_bit_datatype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ fn test_writing_bit_data_type() {
let tmp_dir = Builder::new().prefix("fitsio-").tempdir().unwrap();
let file_path = tmp_dir.path().join("example.fits");

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

let data: Vec<u32> = (0..64).collect();
let col = ColumnDescription::new("BITMASK")
.with_type(ColumnDataType::Bit)
.create()
Expand All @@ -39,4 +39,5 @@ fn test_writing_bit_data_type() {
let table_hdu = f.hdu("DATA").unwrap();
let flags: Vec<u32> = dbg!(table_hdu.read_col(&mut f, "BITMASK").unwrap());
assert_eq!(flags.len(), 64);
assert!(data.iter().zip(&flags).all(|(a, b)| a == b));
simonrw marked this conversation as resolved.
Show resolved Hide resolved
}
Loading
Loading