Skip to content

Commit

Permalink
Prep for 0.1.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
eta077 authored Jul 26, 2022
2 parents 98eddb0 + 5acdc9b commit 14b0432
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 71 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
files: results.xml
- name: Upload to CodeCov
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3
with:
files: ./lcov.info
fail_ci_if_error: true
9 changes: 8 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "astro-rs"
version = "0.0.4"
version = "0.1.0"
edition = "2021"
license = "MIT"
description = "Astronomy utils"
Expand All @@ -16,6 +16,10 @@ exclude = [

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
chrono = { version = "0.4", optional = true }
hyper = { version = "0.14", features = ["client", "http1", "tcp"], optional = true }
Expand All @@ -29,7 +33,10 @@ image = { version = "0.24", default-features = false, features = ["jpeg"] }
tokio-test = { version = "0.4" }

[features]
default = ["fits"]
coordinates = ["dep:chrono", "dep:hyper", "dep:measurements", "dep:urlencoding"]
cosmology = []
fits = []

[[bench]]
name = "fits_benchmark"
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
![GitHub Build Status (branch)](https://img.shields.io/github/workflow/status/eta077/astro-rs/Build/release) ![GitHub Test Status (branch)](https://img.shields.io/github/workflow/status/eta077/astro-rs/Test/release?label=test) [![codecov](https://codecov.io/gh/eta077/astro-rs/branch/release/graph/badge.svg)](https://codecov.io/gh/eta077/astro-rs) [![docs.rs](https://img.shields.io/docsrs/astro-rs)](https://docs.rs/astro-rs/latest/astro_rs/)

# astro-rs
Inspired by Astropy (http://astropy.org / https://github.com/astropy/astropy)
This library provides utilities to interact with astronomical data.

Inspired by Astropy (<http://astropy.org> / <https://github.com/astropy/astropy>)

# Goals
## General goals
Expand All @@ -10,9 +12,9 @@ Inspired by Astropy (http://astropy.org / https://github.com/astropy/astropy)

## Technical goals
* Deserialize as lazily as possible
* Balance 'tight' (https://www.ecorax.net/tightness) types and adherance to the FITS API with graceful handling of deviation
* Balance 'tight' (<https://www.ecorax.net/tightness>) types and adherance to the FITS API with graceful handling of deviation

# Testing
Test assets are from the following sources:
* https://esahubble.org/projects/fits_liberator/datasets_archives
* https://cxc.harvard.edu/cda/
* <https://esahubble.org/projects/fits_liberator/datasets_archives>
* <https://cxc.harvard.edu/cda/>
50 changes: 29 additions & 21 deletions benches/fits_benchmark.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,40 @@
use std::fs::File;
use std::io::BufReader;
#[cfg(feature = "fits")]
use {criterion::black_box, std::fs::File, std::io::BufReader};

use astro_rs::fits::*;

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use criterion::{criterion_group, criterion_main, Criterion};

#[allow(unused_variables)]
fn bench_get_header(c: &mut Criterion) {
c.bench_function("get header from fits file", |b| {
b.iter(|| {
let fits_file = black_box(File::open("assets/benchmarks/many_hdu.fits").unwrap());
let fits_file_reader = BufReader::new(fits_file);
#[cfg(feature = "fits")]
{
use astro_rs::fits::*;
c.bench_function("get header from fits file", |b| {
b.iter(|| {
let fits_file = black_box(File::open("assets/benchmarks/many_hdu.fits").unwrap());
let fits_file_reader = BufReader::new(fits_file);

let mut hdu_list = HduList::new(fits_file_reader);
hdu_list.first_mut().unwrap().header.clone()
})
});
let mut hdu_list = HduList::new(fits_file_reader);
hdu_list.first_mut().unwrap().header.clone()
})
});
}
}

#[allow(unused_variables)]
fn bench_get_header_20(c: &mut Criterion) {
c.bench_function("get 20th header from fits file", |b| {
b.iter(|| {
let fits_file = black_box(File::open("assets/benchmarks/many_hdu.fits").unwrap());
let fits_file_reader = BufReader::new(fits_file);
#[cfg(feature = "fits")]
{
use astro_rs::fits::*;
c.bench_function("get 20th header from fits file", |b| {
b.iter(|| {
let fits_file = black_box(File::open("assets/benchmarks/many_hdu.fits").unwrap());
let fits_file_reader = BufReader::new(fits_file);

let mut hdu_list = HduList::new(fits_file_reader);
hdu_list.get_by_index(20).unwrap().header.clone()
})
});
let mut hdu_list = HduList::new(fits_file_reader);
hdu_list.get_by_index(20).unwrap().header.clone()
})
});
}
}

criterion_group!(benches, bench_get_header, bench_get_header_20);
Expand Down
1 change: 1 addition & 0 deletions src/cosmology/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//! Represent and calculate data using cosmological models.
25 changes: 19 additions & 6 deletions src/fits/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,19 @@ impl FitsHeaderCard {
/// Gets the value of the header card.
/// If the value has not yet been deserialized, the deserialization process is attempted.
/// If the process succeeds, the deserialized value is cached.
///
/// ```
/// use astro_rs::fits::*;
///
/// let mut card = FitsHeaderCard::from(
/// *b"SIMPLE = T ",
/// );
/// assert!(card.get_value::<Bitpix>().is_err());
/// assert!(card.get_value::<bool>().map(|value| *value).unwrap_or_default());
/// // value is now cached, deserialization is not attempted, but types differ
/// assert!(card.get_value::<u32>().is_err());
/// assert!(card.get_value::<bool>().map(|value| *value).unwrap_or_default());
/// ```
pub fn get_value<T: FitsHeaderValue + 'static>(&mut self) -> Result<Rc<T>, FitsHeaderError> {
self.value.get_value()
}
Expand Down Expand Up @@ -508,14 +521,14 @@ impl FitsHeaderValueContainer {
/// ```
/// use astro_rs::fits::*;
///
/// let mut card = FitsHeaderCard::from(
/// *b"SIMPLE = T ",
/// let mut card_value = FitsHeaderValueContainer::from(
/// *b"= T ",
/// );
/// assert!(card.get_value::<Bitpix>().is_err());
/// assert!(card.get_value::<bool>().map(|value| *value).unwrap_or_default());
/// assert!(card_value.get_value::<Bitpix>().is_err());
/// assert!(card_value.get_value::<bool>().map(|value| *value).unwrap_or_default());
/// // value is now cached, deserialization is not attempted, but types differ
/// assert!(card.get_value::<u32>().is_err());
/// assert!(card.get_value::<bool>().map(|value| *value).unwrap_or_default());
/// assert!(card_value.get_value::<u32>().is_err());
/// assert!(card_value.get_value::<bool>().map(|value| *value).unwrap_or_default());
/// ```
pub fn get_value<T: FitsHeaderValue + 'static>(&mut self) -> Result<Rc<T>, FitsHeaderError> {
if let Some(data) = &self.value {
Expand Down
51 changes: 16 additions & 35 deletions src/fits/header_value/tform.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Defines the TFORM header value.
use crate::{deserialize_column, fits::FitsHeaderError, return_box};
use crate::fits::hdu_macros::return_box;
use crate::fits::FitsHeaderError;

use super::FitsHeaderValue;

Expand Down Expand Up @@ -110,7 +111,7 @@ impl TForm {
return_box!(result)
}
TFormType::I16 => {
deserialize_column!(
tform_macros::deserialize_column!(
i16,
num_rows,
row_len,
Expand All @@ -121,7 +122,7 @@ impl TForm {
)
}
TFormType::I32 => {
deserialize_column!(
tform_macros::deserialize_column!(
i32,
num_rows,
row_len,
Expand All @@ -135,7 +136,7 @@ impl TForm {
unsafe fn deserialize_char(value: [u8; 4]) -> char {
char::from_u32_unchecked(u32::from_be_bytes(value))
}
deserialize_column!(
tform_macros::deserialize_column!(
char,
num_rows,
row_len,
Expand All @@ -147,7 +148,7 @@ impl TForm {
)
}
TFormType::F32 => {
deserialize_column!(
tform_macros::deserialize_column!(
f32,
num_rows,
row_len,
Expand All @@ -158,7 +159,7 @@ impl TForm {
)
}
TFormType::F64 => {
deserialize_column!(
tform_macros::deserialize_column!(
f64,
num_rows,
row_len,
Expand All @@ -176,41 +177,27 @@ impl TForm {
}
}

#[macro_use]
mod tform_macros {
/// Creates a boxed vector deserialized with the given function, or a default function if one is not given.
#[macro_export]
macro_rules! deserialize_column {
($value_type: ty, $num_rows: expr, $row_len: expr, $column_start: expr, $column_len: expr, $repeats: expr, $data: expr, $deserialize_fn: tt,) => {{
$crate::do_deserialize_column!(
$value_type,
$num_rows,
$row_len,
$column_start,
$column_len,
$repeats,
$data,
$deserialize_fn
)
(@dfn $value_type: ty) => {{
<$value_type>::from_be_bytes
}};
($value_type: ty, $num_rows: expr, $row_len: expr, $column_start: expr, $column_len: expr, $repeats: expr, $data: expr,) => {{
let deserialize_fn = $crate::default_deserialize_fn!($value_type);
$crate::do_deserialize_column!(
let deserialize_fn = $crate::fits::header_value::tform::tform_macros::deserialize_column!(@dfn $value_type);
$crate::fits::header_value::tform::tform_macros::deserialize_column!(
$value_type,
$num_rows,
$row_len,
$column_start,
$column_len,
$repeats,
$data,
deserialize_fn
deserialize_fn,
)
}};
}

/// Creates a boxed vector deserialized with the given function.
#[macro_export]
macro_rules! do_deserialize_column {
($value_type: ty, $num_rows: expr, $row_len: expr, $column_start: expr, $column_len: expr, $repeats: expr, $data: expr, $deserialize_fn: tt) => {{
($value_type: ty, $num_rows: expr, $row_len: expr, $column_start: expr, $column_len: expr, $repeats: expr, $data: expr, $deserialize_fn: tt,) => {{
let mut result = Vec::with_capacity($num_rows * $repeats);
for i in 0..$num_rows {
let start = $row_len * i + $column_start;
Expand All @@ -225,17 +212,11 @@ mod tform_macros {
}
}

$crate::return_box!(result)
$crate::fits::hdu_macros::return_box!(result)
}};
}

/// Gets the default deserialization function for a type (assumes from_be_bytes).
#[macro_export]
macro_rules! default_deserialize_fn {
($value_type: ty) => {
<$value_type>::from_be_bytes
};
}
pub(crate) use deserialize_column;
}

/// ```
Expand Down
6 changes: 4 additions & 2 deletions src/fits/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Serialize and deserialize FITS data.
//! See https://archive.stsci.edu/fits/fits_standard/fits_standard.html for the FITS API.
//! See <https://archive.stsci.edu/fits/fits_standard/fits_standard.html> for the FITS API.
mod hdu_types;
mod header;
Expand Down Expand Up @@ -515,9 +515,9 @@ impl FitsDataCollection for Vec<f64> {
}
}

#[macro_use]
pub(crate) mod hdu_macros {
/// Creates a box of the given value and casts it to an implicit return type.
#[macro_export]
macro_rules! return_box {
($result: expr) => {{
let b = Box::new($result);
Expand All @@ -526,4 +526,6 @@ pub(crate) mod hdu_macros {
Box::from_raw(new_ptr)
}};
}

pub(crate) use return_box;
}
11 changes: 10 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
#![deny(missing_docs)]
#![deny(clippy::all)]
//! This library provides utilities to interact with astronomical data.
#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]

#[cfg(feature = "coordinates")]
#[cfg_attr(docsrs, doc(cfg(feature = "coordinates")))]
pub mod coordinates;

#[cfg(feature = "cosmology")]
#[cfg_attr(docsrs, doc(cfg(feature = "cosmology")))]
pub mod cosmology;

#[cfg(feature = "fits")]
#[cfg_attr(docsrs, doc(cfg(feature = "fits")))]
pub mod fits;
1 change: 1 addition & 0 deletions tests/fits.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[cfg(feature = "fits")]
mod fits_tests {
use std::error::Error;
use std::fs::File;
Expand Down

0 comments on commit 14b0432

Please sign in to comment.