Skip to content

Commit

Permalink
Existing read methods now internally call the _into_buffer() read met…
Browse files Browse the repository at this point in the history
…hods. Updated FFI to do the same.
  • Loading branch information
gsleap committed May 10, 2021
1 parent 0b51770 commit 9a8ce8a
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 175 deletions.
123 changes: 11 additions & 112 deletions src/correlator_context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,57 +229,11 @@ impl CorrelatorContext {
timestep_index: usize,
coarse_chan_index: usize,
) -> Result<Vec<f32>, GpuboxError> {
// Validate the timestep
if timestep_index > self.num_timesteps - 1 {
return Err(GpuboxError::InvalidTimeStepIndex(self.num_timesteps - 1));
}

// Validate the coarse chan
if coarse_chan_index > self.num_coarse_chans - 1 {
return Err(GpuboxError::InvalidCoarseChanIndex(
self.num_coarse_chans - 1,
));
}

// Output buffer for read in data
let output_buffer: Vec<f32>;

// Lookup the coarse channel we need
let coarse_chan = self.coarse_chans[coarse_chan_index].gpubox_number;
let (batch_index, hdu_index) =
self.gpubox_time_map[&self.timesteps[timestep_index].unix_time_ms][&coarse_chan];

if self.gpubox_batches.is_empty() {
return Err(GpuboxError::NoGpuboxes);
}
let mut fptr =
fits_open!(&self.gpubox_batches[batch_index].gpubox_files[coarse_chan_index].filename)?;
let hdu = fits_open_hdu!(&mut fptr, hdu_index)?;
output_buffer = get_fits_image!(&mut fptr, &hdu)?;
// If legacy correlator, then convert the HDU into the correct output format
if self.corr_version == CorrelatorVersion::OldLegacy
|| self.corr_version == CorrelatorVersion::Legacy
{
// Prepare temporary buffer, if we are reading legacy correlator files
let mut temp_buffer = vec![
0.;
self.metafits_context.num_corr_fine_chans_per_coarse
* self.metafits_context.num_visibility_pols
* self.metafits_context.num_baselines
* 2
];
let mut return_buffer: Vec<f32> = vec![0.; self.num_timestep_coarse_chan_floats];

convert::convert_legacy_hdu_to_mwax_baseline_order(
&self.legacy_conversion_table,
&output_buffer,
&mut temp_buffer,
self.metafits_context.num_corr_fine_chans_per_coarse,
);
self.read_by_baseline_into_buffer(timestep_index, coarse_chan_index, &mut return_buffer)?;

Ok(temp_buffer)
} else {
Ok(output_buffer)
}
Ok(return_buffer)
}

/// Read a single timestep for a single coarse channel
Expand All @@ -297,74 +251,19 @@ impl CorrelatorContext {
///
/// # Returns
///
/// * A Result containing vector of 32 bit floats containing the data in [frequency][baseline][pol][r][i] order, if Ok.
/// * A Result containing vector of 32 bit floats containing the data in frequency,baseline,pol,r,i order, if Ok.
///
///
pub fn read_by_frequency(
&self,
timestep_index: usize,
coarse_chan_index: usize,
) -> Result<Vec<f32>, GpuboxError> {
// Validate the timestep
if timestep_index > self.num_timesteps - 1 {
return Err(GpuboxError::InvalidTimeStepIndex(self.num_timesteps - 1));
}
let mut return_buffer: Vec<f32> = vec![0.; self.num_timestep_coarse_chan_floats];

// Validate the coarse chan
if coarse_chan_index > self.num_coarse_chans - 1 {
return Err(GpuboxError::InvalidCoarseChanIndex(
self.num_coarse_chans - 1,
));
}
self.read_by_frequency_into_buffer(timestep_index, coarse_chan_index, &mut return_buffer)?;

// Output buffer for read in data
let output_buffer: Vec<f32>;

// Prepare temporary buffer
let mut temp_buffer = vec![
0.;
self.metafits_context.num_corr_fine_chans_per_coarse
* self.metafits_context.num_visibility_pols
* self.metafits_context.num_baselines
* 2
];

// Lookup the coarse channel we need
let coarse_chan = self.coarse_chans[coarse_chan_index].gpubox_number;
let (batch_index, hdu_index) =
self.gpubox_time_map[&self.timesteps[timestep_index].unix_time_ms][&coarse_chan];

if self.gpubox_batches.is_empty() {
return Err(GpuboxError::NoGpuboxes);
}
let mut fptr =
fits_open!(&self.gpubox_batches[batch_index].gpubox_files[coarse_chan_index].filename)?;
let hdu = fits_open_hdu!(&mut fptr, hdu_index)?;
output_buffer = get_fits_image!(&mut fptr, &hdu)?;
// If legacy correlator, then convert the HDU into the correct output format
if self.corr_version == CorrelatorVersion::OldLegacy
|| self.corr_version == CorrelatorVersion::Legacy
{
convert::convert_legacy_hdu_to_mwax_frequency_order(
&self.legacy_conversion_table,
&output_buffer,
&mut temp_buffer,
self.metafits_context.num_corr_fine_chans_per_coarse,
);

Ok(temp_buffer)
} else {
// Do conversion for mwax (it is in baseline order, we want it in freq order)
convert::convert_mwax_hdu_to_frequency_order(
&output_buffer,
&mut temp_buffer,
self.metafits_context.num_baselines,
self.metafits_context.num_corr_fine_chans_per_coarse,
self.metafits_context.num_visibility_pols,
);

Ok(temp_buffer)
}
Ok(return_buffer)
}

/// Read a single timestep for a single coarse channel
Expand Down Expand Up @@ -429,7 +328,7 @@ impl CorrelatorContext {
];

// Read into temp buffer
let result = get_fits_float_image_into_buffer!(&mut fptr, &hdu, &mut temp_buffer);
get_fits_float_image_into_buffer!(&mut fptr, &hdu, &mut temp_buffer)?;

convert::convert_legacy_hdu_to_mwax_baseline_order(
&self.legacy_conversion_table,
Expand All @@ -441,7 +340,7 @@ impl CorrelatorContext {
Ok(())
} else {
// Read into caller's buffer
let result = get_fits_float_image_into_buffer!(&mut fptr, &hdu, buffer);
get_fits_float_image_into_buffer!(&mut fptr, &hdu, buffer)?;

Ok(())
}
Expand Down Expand Up @@ -504,8 +403,8 @@ impl CorrelatorContext {
fits_open!(&self.gpubox_batches[batch_index].gpubox_files[coarse_chan_index].filename)?;
let hdu = fits_open_hdu!(&mut fptr, hdu_index)?;

// Read the hud into our temp buffer
let result = get_fits_float_image_into_buffer!(&mut fptr, &hdu, &mut temp_buffer);
// Read the hdu into our temp buffer
get_fits_float_image_into_buffer!(&mut fptr, &hdu, &mut temp_buffer)?;

// If legacy correlator, then convert the HDU into the correct output format
if self.corr_version == CorrelatorVersion::OldLegacy
Expand Down
88 changes: 82 additions & 6 deletions src/correlator_context/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ fn test_context_new_invalid_metafits() {

#[test]
fn test_context_legacy_v1() {
// Open the test mwax file
// Open the test legacy file
let metafits_filename = "test_files/1101503312_1_timestep/1101503312.metafits";
let filename = "test_files/1101503312_1_timestep/1101503312_20141201210818_gpubox01_00.fits";

Expand Down Expand Up @@ -74,16 +74,92 @@ fn test_context_legacy_v1() {
assert_eq!(context.num_coarse_chans, 1);

// coarse channels: [gpu=1 corr=0 rec=109 @ 139.520 MHz],
assert_eq!(context.coarse_chans[0].corr_chan_number, 0);
assert_eq!(context.coarse_chans[0].gpubox_number, 1);
assert_eq!(context.coarse_chans[0].rec_chan_number, 109);
assert_eq!(context.coarse_chans[0].chan_centre_hz, 139_520_000);

// gpubox HDU size: 32.25 MiB,
// Memory usage per scan: 32.25 MiB,
// Check that antenna[0].tile and antenna[1].tile equal rf_input[0] & [1].tile and rf_input[2] & [3].tile respectively
assert_eq!(
context.metafits_context.antennas[0].tile_id,
context.metafits_context.rf_inputs[0].tile_id
);
assert_eq!(
context.metafits_context.antennas[0].tile_id,
context.metafits_context.rf_inputs[1].tile_id
);
assert_eq!(
context.metafits_context.antennas[1].tile_id,
context.metafits_context.rf_inputs[2].tile_id
);
assert_eq!(
context.metafits_context.antennas[1].tile_id,
context.metafits_context.rf_inputs[3].tile_id
);
}

#[test]
fn test_context_mwax() {
// Open the test mwax file
let metafits_filename = "test_files/1244973688_1_timestep/1244973688.metafits";
let filename = "test_files/1244973688_1_timestep/1244973688_20190619100110_ch114_000.fits";

//
// Read the observation using mwalib
//
// Open a context and load in a test metafits and gpubox file
let gpuboxfiles = vec![filename];
let context = CorrelatorContext::new(&metafits_filename, &gpuboxfiles)
.expect("Failed to create mwalibContext");

// Test the properties of the context object match what we expect
// Correlator version: v2,
assert_eq!(context.corr_version, CorrelatorVersion::V2);

// metafits filename: ../test_files/1101503312_1_timestep/1101503312.metafits,
// gpubox batches: [
// batch_number=0 gpubox_files=[filename=../test_files/1101503312_1_timestep/1101503312_20141201210818_gpubox01_00.fits channelidentifier=1]
// Actual UNIX start time: 1560938470,
assert_eq!(context.start_unix_time_ms, 1_560_938_470_000);

// Actual UNIX end time: 1560938471,
assert_eq!(context.end_unix_time_ms, 1_560_938_471_000);

// Actual duration: 1 s,
assert_eq!(context.duration_ms, 1000);

// num timesteps: 1,
assert_eq!(context.num_timesteps, 1);

// timesteps: [unix=1560938470.000],
assert_eq!(context.timesteps[0].unix_time_ms, 1_560_938_470_000);

// observation bandwidth: 1.28 MHz,
assert_eq!(context.bandwidth_hz, 1_280_000);

// num coarse channels, 1,
assert_eq!(context.num_coarse_chans, 1);

// coarse channels: [gpu=114 corr=10 rec=114 @ MHz],
assert_eq!(context.coarse_chans[0].corr_chan_number, 10);
assert_eq!(context.coarse_chans[0].gpubox_number, 114);
assert_eq!(context.coarse_chans[0].rec_chan_number, 114);
assert_eq!(context.coarse_chans[0].chan_centre_hz, 145_920_000);

// Check that antenna[0].tile and antenna[1].tile equal rf_input[0] & [1].tile and rf_input[2] & [3].tile respectively
assert_eq!(
context.metafits_context.antennas[0].tile_id,
context.metafits_context.rf_inputs[0].tile_id
);
assert_eq!(
context.metafits_context.antennas[0].tile_id,
context.metafits_context.rf_inputs[1].tile_id
);
assert_eq!(
context.metafits_context.antennas[1].tile_id,
context.metafits_context.rf_inputs[2].tile_id
);
assert_eq!(
context.metafits_context.antennas[1].tile_id,
context.metafits_context.rf_inputs[3].tile_id
);
}

#[test]
Expand Down
51 changes: 13 additions & 38 deletions src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,33 +415,19 @@ pub unsafe extern "C" fn mwalib_correlator_context_read_by_baseline(

let output_slice = slice::from_raw_parts_mut(buffer_ptr, buffer_len);

// Read data in.
let data = match corr_context.read_by_baseline(timestep_index, coarse_chan_index) {
Ok(data) => data,
// Read data into provided buffer
match corr_context.read_by_baseline_into_buffer(timestep_index, coarse_chan_index, output_slice)
{
Ok(_) => 0,
Err(e) => {
set_error_message(
&format!("{}", e),
error_message as *mut u8,
error_message_length,
);
return 1;
1
}
};

// If the data buffer is empty, then just return a null pointer.
if data.is_empty() {
set_error_message(
"mwalib_correlator_context_read_by_baseline() ERROR: no data was returned.",
error_message as *mut u8,
error_message_length,
);
return 1;
}

// Populate the buffer which was provided to us by caller
output_slice[..data.len()].copy_from_slice(data.as_slice());
// Return Success
0
}

/// Read a single timestep / coarse channel of MWA data.
Expand Down Expand Up @@ -506,33 +492,22 @@ pub unsafe extern "C" fn mwalib_correlator_context_read_by_frequency(

let output_slice = slice::from_raw_parts_mut(buffer_ptr, buffer_len);

// Read data in.
let data = match corr_context.read_by_frequency(timestep_index, coarse_chan_index) {
Ok(data) => data,
// Read data into provided buffer
match corr_context.read_by_frequency_into_buffer(
timestep_index,
coarse_chan_index,
output_slice,
) {
Ok(_) => 0,
Err(e) => {
set_error_message(
&format!("{}", e),
error_message as *mut u8,
error_message_length,
);
return 1;
1
}
};

// If the data buffer is empty, then just return a null pointer.
if data.is_empty() {
set_error_message(
"mwalib_correlator_context_read_by_frequency() ERROR: no data was returned.",
error_message as *mut u8,
error_message_length,
);
return 1;
}

// Populate the buffer which was provided to us by caller
output_slice[..data.len()].copy_from_slice(data.as_slice());
// Return Success
0
}

/// Free a previously-allocated `CorrelatorContext` struct (and it's members).
Expand Down
4 changes: 2 additions & 2 deletions src/ffi/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1430,15 +1430,15 @@ fn test_mwalib_antennas_get_from_correlator_context_valid() {
}

#[test]
fn test_mwalib_antennas_get_from_voltage_context_valid() {
fn test_mwalib_antennas_get_from_voltage_context_valid_mwax() {
// This test populates antennas given a voltage context
let index = 2; // valid should be Tile013
let error_len: size_t = 128;
let error_message = CString::new(" ".repeat(error_len)).unwrap();
let error_message_ptr = error_message.as_ptr() as *const c_char;

unsafe {
let context = get_test_ffi_voltage_context(CorrelatorVersion::Legacy);
let context = get_test_ffi_voltage_context(CorrelatorVersion::V2);

// Check we got a context object
let context_ptr = context.as_mut();
Expand Down
Loading

0 comments on commit 9a8ce8a

Please sign in to comment.