[ismrmrd] 98/281: fixed ismrmrd.h to compile with a C compiler.
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Wed Jan 14 20:01:01 UTC 2015
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to annotated tag ismrmrd0.5
in repository ismrmrd.
commit cbb1b2560ce1679eeb127feecfbfeb1887bf568a
Author: Joseph Naegele <joseph.naegele at gmail.com>
Date: Thu Mar 14 11:09:12 2013 -0400
fixed ismrmrd.h to compile with a C compiler.
also added a skeleton test for testing the usage of
both ISMRMRD header structs in code that is explicitly C,
as well as simple tests for quaternion to direction vectors
(and vice versa) functions.
---
CMakeLists.txt | 2 +-
ismrmrd.h | 252 ++++++++++++++++++++++++-----------------------
tests/CMakeLists.txt | 2 +
tests/c/CMakeLists.txt | 8 ++
tests/c/t_cquaternions.c | 45 +++++++++
tests/c/t_cstructs.c | 138 ++++++++++++++++++++++++++
6 files changed, 324 insertions(+), 123 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ea16ac0..516b3d9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -68,4 +68,4 @@ INSTALL(FILES ${MatlabMFiles} DESTINATION matlab/+ismrmrd)
add_subdirectory(doc)
add_subdirectory(examples/c++)
-add_subdirectory(tests/c++)
+add_subdirectory(tests)
diff --git a/ismrmrd.h b/ismrmrd.h
index dcaab01..a6de831 100644
--- a/ismrmrd.h
+++ b/ismrmrd.h
@@ -22,6 +22,7 @@ typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
+#include <math.h>
#endif
#endif
@@ -115,7 +116,7 @@ enum AcquisitionFlags {
Struct used for keeping track of typical loop counters in MR experiment.
*/
-struct EncodingCounters {
+typedef struct EncodingCounters {
uint16_t kspace_encode_step_1; /**< e.g. phase encoding line number */
uint16_t kspace_encode_step_2; /**< e.g. partition encodning number */
uint16_t average; /**< e.g. signal average number */
@@ -126,12 +127,12 @@ struct EncodingCounters {
uint16_t set; /**< e.g. flow encodning set */
uint16_t segment; /**< e.g. segment number for segmented acquisition */
uint16_t user[ISMRMRD_USER_INTS]; /**< Free user parameters */
-};
+} EncodingCounters;
/**
Header for each MR acquisition.
*/
-struct AcquisitionHeader
+typedef struct AcquisitionHeader
{
uint16_t version; /**< First unsigned int indicates the version */
uint64_t flags; /**< bit field with flags */
@@ -157,7 +158,7 @@ struct AcquisitionHeader
EncodingCounters idx; /**< Encoding loop counters, see above */
int32_t user_int[ISMRMRD_USER_INTS]; /**< Free user parameters */
float user_float[ISMRMRD_USER_FLOATS]; /**< Free user parameters */
-};
+} AcquisitionHeader;
enum ImageDataType
{
@@ -194,7 +195,7 @@ enum ImageFlags {
/**
* Definition of ISMRM Raw Data Image structure
*/
-struct ImageHeader
+typedef struct ImageHeader
{
uint16_t version; /**< First unsigned int indicates the version */
uint64_t flags; /**< bit field with flags */
@@ -221,7 +222,7 @@ struct ImageHeader
uint16_t image_series_index; /**< e.g. series number */
int32_t user_int[ISMRMRD_USER_INTS]; /**< Free user parameters */
float user_float[ISMRMRD_USER_FLOATS]; /**< Free user parameters */
-};
+} ImageHeader;
#ifdef __cplusplus
/**
@@ -1081,124 +1082,131 @@ protected:
#endif //__cplusplus
-/**
- * Calculates the determinant of the matrix and return the sign
- */
-inline int sign_of_directions(float read_dir[3], float phase_dir[3], float slice_dir[3])
-{
- float r11 = read_dir[0], r12 = phase_dir[0], r13 = slice_dir[0];
- float r21 = read_dir[1], r22 = phase_dir[1], r23 = slice_dir[1];
- float r31 = read_dir[2], r32 = phase_dir[2], r33 = slice_dir[2];
-
- /* Determinant should be 1 or -1 */
- float deti = (r11 * r22 * r33) + (r12 * r23 * r31) + (r21 * r32 * r13) -
- (r13 * r22 * r31) - (r12 * r21 * r33) - (r11 * r23 * r32);
-
- if (deti < 0) {
- return -1;
- } else {
- return 1;
- }
-}
-
-/**
- * Creates a normalized quaternion from a 3x3 rotation matrix
- */
-inline void directions_to_quaternion(float read_dir[3], float phase_dir[3],
- float slice_dir[3], float quat[4])
-{
- float r11 = read_dir[0], r12 = phase_dir[0], r13 = slice_dir[0];
- float r21 = read_dir[1], r22 = phase_dir[1], r23 = slice_dir[1];
- float r31 = read_dir[2], r32 = phase_dir[2], r33 = slice_dir[2];
-
- float a = 1, b = 0, c = 0, d = 0, s = 0;
- float trace = 0;
- float xd, yd, zd;
-
- /* verify the sign of the rotation*/
- if (sign_of_directions(read_dir, phase_dir, slice_dir) < 0) {
- /* flip 3rd column */
- r13 = -r13;
- r23 = -r23;
- r33 = -r33;
- }
-
- /* Compute quaternion parameters */
- /* http://www.cs.princeton.edu/~gewang/projects/darth/stuff/quat_faq.html#Q55 */
- trace = 1.0l + r11 + r22 + r33;
- if (trace > 0.00001l) { /* simplest case */
- s = sqrt(trace) * 2;
- a = (r32 - r23) / s;
- b = (r13 - r31) / s;
- c = (r21 - r12) / s;
- d = 0.25l * s;
- } else {
- /* trickier case...
- * determine which major diagonal element has
- * the greatest value... */
- xd = 1.0 + r11 - (r22 + r33); /* 4**b**b */
- yd = 1.0 + r22 - (r11 + r33); /* 4**c**c */
- zd = 1.0 + r33 - (r11 + r22); /* 4**d**d */
- /* if r11 is the greatest */
- if (xd > 1.0) {
- s = 2.0 * sqrt(xd);
- a = 0.25l * s;
- b = (r21 + r12) / s;
- c = (r31 + r13) / s;
- d = (r32 - r23) / s;
- }
- /* else if r22 is the greatest */
- else if (yd > 1.0) {
- s = 2.0 * sqrt(yd);
- a = (r21 + r12) / s;
- b = 0.25l * s;
- c = (r32 + r23) / s;
- d = (r13 - r31) / s;
- }
- /* else, r33 must be the greatest */
- else {
- s = 2.0 * sqrt(zd);
- a = (r13 + r31) / s;
- b = (r23 + r32) / s;
- c = 0.25l * s;
- d = (r21 - r12) / s;
- }
-
- if (a < 0.0l) {
- b = -b;
- c = -c;
- d = -d;
- a = -a;
- }
- }
-
- quat[0] = a; quat[1] = b; quat[2] = c; quat[3] = d;
-}
-
-/**
- * Converts a quaternion of the form | a b c d | to a
- * 3x3 rotation matrix
- *
- * http://www.cs.princeton.edu/~gewang/projects/darth/stuff/quat_faq.html#Q54
- */
-inline void quaternion_to_directions(float quat[4], float read_dir[3],
- float phase_dir[3], float slice_dir[3])
-{
- float a = quat[0], b = quat[1], c = quat[2], d = quat[3];
-
- read_dir[0] = 1.0 - 2.0 * ( b*b + c*c );
- phase_dir[0] = 2.0 * ( a*b - c*d );
- slice_dir[0] = 2.0 * ( a*c + b*d );
-
- read_dir[1] = 2.0 * ( a*b + c*d );
- phase_dir[1] = 1.0 - 2.0 * ( a*a + c*c );
- slice_dir[1] = 2.0 * ( b*c - a*d );
-
- read_dir[2] = 2.0 * ( a*c - b*d );
- phase_dir[2] = 2.0 * ( b*c + a*d );
- slice_dir[2] = 1.0 - 2.0 * ( a*a + b*b );
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * Calculates the determinant of the matrix and return the sign
+ */
+static inline int sign_of_directions(float read_dir[3], float phase_dir[3], float slice_dir[3])
+{
+ float r11 = read_dir[0], r12 = phase_dir[0], r13 = slice_dir[0];
+ float r21 = read_dir[1], r22 = phase_dir[1], r23 = slice_dir[1];
+ float r31 = read_dir[2], r32 = phase_dir[2], r33 = slice_dir[2];
+
+ /* Determinant should be 1 or -1 */
+ float deti = (r11 * r22 * r33) + (r12 * r23 * r31) + (r21 * r32 * r13) -
+ (r13 * r22 * r31) - (r12 * r21 * r33) - (r11 * r23 * r32);
+
+ if (deti < 0) {
+ return -1;
+ } else {
+ return 1;
+ }
}
+/**
+ * Creates a normalized quaternion from a 3x3 rotation matrix
+ */
+static inline void directions_to_quaternion(float read_dir[3], float phase_dir[3],
+ float slice_dir[3], float quat[4])
+{
+ float r11 = read_dir[0], r12 = phase_dir[0], r13 = slice_dir[0];
+ float r21 = read_dir[1], r22 = phase_dir[1], r23 = slice_dir[1];
+ float r31 = read_dir[2], r32 = phase_dir[2], r33 = slice_dir[2];
+
+ float a = 1, b = 0, c = 0, d = 0, s = 0;
+ float trace = 0;
+ float xd, yd, zd;
+
+ /* verify the sign of the rotation*/
+ if (sign_of_directions(read_dir, phase_dir, slice_dir) < 0) {
+ /* flip 3rd column */
+ r13 = -r13;
+ r23 = -r23;
+ r33 = -r33;
+ }
+
+ /* Compute quaternion parameters */
+ /* http://www.cs.princeton.edu/~gewang/projects/darth/stuff/quat_faq.html#Q55 */
+ trace = 1.0l + r11 + r22 + r33;
+ if (trace > 0.00001l) { /* simplest case */
+ s = sqrt(trace) * 2;
+ a = (r32 - r23) / s;
+ b = (r13 - r31) / s;
+ c = (r21 - r12) / s;
+ d = 0.25l * s;
+ } else {
+ /* trickier case...
+ * determine which major diagonal element has
+ * the greatest value... */
+ xd = 1.0 + r11 - (r22 + r33); /* 4**b**b */
+ yd = 1.0 + r22 - (r11 + r33); /* 4**c**c */
+ zd = 1.0 + r33 - (r11 + r22); /* 4**d**d */
+ /* if r11 is the greatest */
+ if (xd > 1.0) {
+ s = 2.0 * sqrt(xd);
+ a = 0.25l * s;
+ b = (r21 + r12) / s;
+ c = (r31 + r13) / s;
+ d = (r32 - r23) / s;
+ }
+ /* else if r22 is the greatest */
+ else if (yd > 1.0) {
+ s = 2.0 * sqrt(yd);
+ a = (r21 + r12) / s;
+ b = 0.25l * s;
+ c = (r32 + r23) / s;
+ d = (r13 - r31) / s;
+ }
+ /* else, r33 must be the greatest */
+ else {
+ s = 2.0 * sqrt(zd);
+ a = (r13 + r31) / s;
+ b = (r23 + r32) / s;
+ c = 0.25l * s;
+ d = (r21 - r12) / s;
+ }
+
+ if (a < 0.0l) {
+ b = -b;
+ c = -c;
+ d = -d;
+ a = -a;
+ }
+ }
+
+ quat[0] = a; quat[1] = b; quat[2] = c; quat[3] = d;
+}
+
+/**
+ * Converts a quaternion of the form | a b c d | to a
+ * 3x3 rotation matrix
+ *
+ * http://www.cs.princeton.edu/~gewang/projects/darth/stuff/quat_faq.html#Q54
+ */
+static inline void quaternion_to_directions(float quat[4], float read_dir[3],
+ float phase_dir[3], float slice_dir[3])
+{
+ float a = quat[0], b = quat[1], c = quat[2], d = quat[3];
+
+ read_dir[0] = 1.0 - 2.0 * ( b*b + c*c );
+ phase_dir[0] = 2.0 * ( a*b - c*d );
+ slice_dir[0] = 2.0 * ( a*c + b*d );
+
+ read_dir[1] = 2.0 * ( a*b + c*d );
+ phase_dir[1] = 1.0 - 2.0 * ( a*a + c*c );
+ slice_dir[1] = 2.0 * ( b*c - a*d );
+
+ read_dir[2] = 2.0 * ( a*c - b*d );
+ phase_dir[2] = 2.0 * ( b*c + a*d );
+ slice_dir[2] = 1.0 - 2.0 * ( a*a + b*b );
+}
+
+#ifdef __cplusplus
+}
+#endif
+
#ifdef __cplusplus
} //End of ISMRMRD namespace
#endif //__cplusplus
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..5f8644d
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(c++)
+add_subdirectory(c)
diff --git a/tests/c/CMakeLists.txt b/tests/c/CMakeLists.txt
new file mode 100644
index 0000000..f8dccaa
--- /dev/null
+++ b/tests/c/CMakeLists.txt
@@ -0,0 +1,8 @@
+enable_testing()
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..)
+
+add_executable(t_cstructs t_cstructs.c)
+add_test(t_cstructs ${CMAKE_CURRENT_BINARY_DIR}/t_cstructs)
+
+add_executable(t_cquaternions ../../ismrmrd.h t_cquaternions.c)
+add_test(t_cquaternions ${CMAKE_CURRENT_BINARY_DIR}/t_cquaternions)
diff --git a/tests/c/t_cquaternions.c b/tests/c/t_cquaternions.c
new file mode 100644
index 0000000..87e3126
--- /dev/null
+++ b/tests/c/t_cquaternions.c
@@ -0,0 +1,45 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "ismrmrd.h"
+
+
+int main(void)
+{
+ float read_dir[3] = {1.0, 0, 0};
+ float phase_dir[3] = {0, 1.0, 0};
+ float slice_dir[3] = {0, 0, 1.0};
+ float quaternion[4];
+
+ /* convert the direction vectors to a quaternion and verify */
+ directions_to_quaternion(read_dir, phase_dir, slice_dir, quaternion);
+
+ if (!((quaternion[0] == 0.0) && (quaternion[1] == 0.0) && (quaternion[2] == 0.0) && (quaternion[3] == 1.0))) {
+ return EXIT_FAILURE;
+ }
+
+ /* convert the quaternion back to direction cosines and verify */
+ quaternion_to_directions(quaternion, read_dir, phase_dir, slice_dir);
+ int rd = ((read_dir[0] == 1.0) && (read_dir[1] == 0.0) && (read_dir[2] == 0.0));
+ int pd = ((phase_dir[0] == 0.0) && (phase_dir[1] == 1.0) && (phase_dir[2] == 0.0));
+ int sd = ((slice_dir[0] == 0.0) && (slice_dir[1] == 0.0) && (slice_dir[2] == 1.0));
+
+ if (!(rd && pd && sd)) {
+ return EXIT_FAILURE;
+ }
+
+ /* check that determinant is > 0 */
+ if (sign_of_directions(read_dir, phase_dir, slice_dir) < 0) {
+ return EXIT_FAILURE;
+ }
+
+ /* flip sign of third column and check that determinant is < 0 */
+ slice_dir[0] = -slice_dir[0];
+ slice_dir[1] = -slice_dir[1];
+ slice_dir[2] = -slice_dir[2];
+ if (sign_of_directions(read_dir, phase_dir, slice_dir) > 0) {
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/c/t_cstructs.c b/tests/c/t_cstructs.c
new file mode 100644
index 0000000..c24aac9
--- /dev/null
+++ b/tests/c/t_cstructs.c
@@ -0,0 +1,138 @@
+#include "ismrmrd.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+int main(void)
+{
+ int i;
+
+ EncodingCounters idx;
+
+ idx.kspace_encode_step_1 = 1;
+ idx.kspace_encode_step_2 = 2;
+ idx.average = 50;
+ idx.slice = 14;
+ idx.contrast = 5000;
+ idx.phase = 42;
+ idx.repetition = 2;
+ idx.set = 1;
+ idx.segment = 1;
+ for (i = 0; i < ISMRMRD_USER_INTS; i++) {
+ idx.user[i] = i * 42;
+ }
+
+ AcquisitionHeader acq_head;
+ acq_head.version = 1;
+ acq_head.flags = -1;
+ acq_head.measurement_uid = 12345;
+ acq_head.scan_counter = 512;
+ acq_head.acquisition_time_stamp = 1363104441;
+ for (i = 0; i < ISMRMRD_PHYS_STAMPS; i++) {
+ acq_head.physiology_time_stamp[i] = 1363106388;
+ }
+ acq_head.number_of_samples = 24;
+ acq_head.available_channels = 32;
+ acq_head.active_channels = 32;
+ for (i = 0; i < ISMRMRD_CHANNEL_MASKS; i++) {
+ acq_head.channel_mask[i] = -1;
+ }
+ acq_head.discard_pre = 2;
+ acq_head.discard_post = 2;
+ acq_head.center_sample = 12;
+ acq_head.encoding_space_ref = 1;
+ acq_head.trajectory_dimensions = 2;
+ acq_head.sample_time_us = 123.321;
+
+ acq_head.position[0] = -12.80;
+ acq_head.position[1] = 0.23;
+ acq_head.position[2] = 12.45;
+
+ acq_head.read_dir[0] = 1;
+ acq_head.read_dir[1] = 0;
+ acq_head.read_dir[2] = 0;
+
+ acq_head.phase_dir[0] = 0;
+ acq_head.phase_dir[1] = 1;
+ acq_head.phase_dir[2] = 0;
+
+ acq_head.slice_dir[0] = 0;
+ acq_head.slice_dir[1] = 0;
+ acq_head.slice_dir[2] = 1;
+
+ acq_head.patient_table_position[0] = 0.0;
+ acq_head.patient_table_position[1] = 0.0;
+ acq_head.patient_table_position[2] = 2.13;
+
+ acq_head.idx = idx;
+ for (i = 0; i < ISMRMRD_USER_INTS; i++) {
+ acq_head.user_int[i] = i;
+ }
+ for (i = 0; i < ISMRMRD_USER_FLOATS; i++) {
+ acq_head.user_float[i] = (float)i;
+ }
+
+
+ ImageHeader img_head;
+ img_head.version = 1;
+ img_head.flags = -1;
+ img_head.measurement_uid = 12345;
+
+ img_head.matrix_size[0] = 128;
+ img_head.matrix_size[1] = 128;
+ img_head.matrix_size[2] = 0;
+
+ img_head.field_of_view[0] = 256.0;
+ img_head.field_of_view[1] = 256.0;
+ img_head.field_of_view[2] = 12.0;
+
+ img_head.channels = 32;
+
+ img_head.position[0] = -12.80;
+ img_head.position[1] = 0.23;
+ img_head.position[2] = 12.45;
+
+ img_head.read_dir[0] = 1;
+ img_head.read_dir[1] = 0;
+ img_head.read_dir[2] = 0;
+
+ img_head.phase_dir[0] = 0;
+ img_head.phase_dir[1] = 1;
+ img_head.phase_dir[2] = 0;
+
+ img_head.slice_dir[0] = 0;
+ img_head.slice_dir[1] = 0;
+ img_head.slice_dir[2] = 1;
+
+ img_head.patient_table_position[0] = 0.0;
+ img_head.patient_table_position[1] = 0.0;
+ img_head.patient_table_position[2] = 2.13;
+
+ img_head.average = 50;
+ img_head.slice = 14;
+ img_head.contrast = 5000;
+ img_head.phase = 42;
+ img_head.repetition = 2;
+ img_head.set = 1;
+
+ img_head.acquisition_time_stamp = 1363104441;
+
+ for (i = 0; i < ISMRMRD_PHYS_STAMPS; i++) {
+ img_head.physiology_time_stamp[i] = 1363106388;
+ }
+
+ img_head.image_data_type = DATA_FLOAT;
+ img_head.image_type = TYPE_MAGNITUDE;
+ img_head.image_index = 42;
+ img_head.image_series_index = 3;
+
+ for (i = 0; i < ISMRMRD_USER_INTS; i++) {
+ img_head.user_int[i] = i;
+ }
+ for (i = 0; i < ISMRMRD_USER_FLOATS; i++) {
+ img_head.user_float[i] = (float)i;
+ }
+
+ return EXIT_SUCCESS;
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/ismrmrd.git
More information about the debian-science-commits
mailing list