New upstream version 1.6.0
Andreas Tille
3 years ago
0 | os: linux | |
1 | arch: | |
2 | - amd64 | |
3 | - ppc64le | |
4 | ||
0 | 5 | language: cpp |
1 | 6 | sudo: false |
2 | 7 | |
29 | 34 | - cd ../build |
30 | 35 | |
31 | 36 | script: |
32 | - cmake -D BUILD_SHARED_LIBS:BOOL=$SHARED -D IGNORE_QT:BOOL=$IGNORE_QT ../CiftiLib | |
37 | - cmake -D CMAKE_CXX_FLAGS="-W -Wall -Wno-narrowing" -D BUILD_SHARED_LIBS:BOOL=$SHARED -D IGNORE_QT:BOOL=$IGNORE_QT ../CiftiLib | |
33 | 38 | - export LD_LIBRARY_PATH=$(if [[ $CXX == "clang++" ]]; then echo -n '/usr/local/clang/lib'; fi) |
34 | 39 | - make -j 4 |
35 | 40 | - example/xmlinfo ../CiftiLib/example/data/ones.dscalar.nii |
20 | 20 | SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/" "${CMAKE_SOURCE_DIR}/cmake/Modules/UseDoxygen/") |
21 | 21 | |
22 | 22 | INCLUDE(UseDoxygen) |
23 | ||
24 | #TSC: glibmm requires c++11, so it needs to be in the compile flags - in older cmake, this needs to be done manually | |
25 | IF (${CMAKE_VERSION} VERSION_LESS "3.1") | |
26 | IF (CMAKE_COMPILER_IS_GNUCC) | |
27 | include(CheckCXXCompilerFlag) | |
28 | CHECK_CXX_COMPILER_FLAG("-std=c++11" GCC_STD11) | |
29 | IF (${GCC_STD11}) | |
30 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | |
31 | ELSE (${GCC_STD11}) | |
32 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") | |
33 | ENDIF (${GCC_STD11}) | |
34 | ENDIF (CMAKE_COMPILER_IS_GNUCC) | |
35 | ELSE (${CMAKE_VERSION} VERSION_LESS "3.1") | |
36 | SET(CMAKE_CXX_STANDARD 11) | |
37 | SET(CMAKE_CXX_STANDARD_REQUIRED TRUE) | |
38 | ENDIF (${CMAKE_VERSION} VERSION_LESS "3.1") | |
23 | 39 | |
24 | 40 | #QT |
25 | 41 | IF (NOT IGNORE_QT) |
4 | 4 | Description: C++ Library for reading and writing CIFTI-2 and CIFTI-1 files |
5 | 5 | Version: @CIFTILIB_VERSION@ |
6 | 6 | URL: https://github.com/Washington-University/CiftiLib |
7 | Cflags: -I${includedir}/CiftiLib @CIFTILIB_PKGCONFIG_DEFINE@ | |
7 | Cflags: -I${includedir}/CiftiLib @CIFTILIB_PKGCONFIG_DEFINE@ @OpenMP_CXX_FLAGS@ | |
8 | 8 | Libs: -L${libdir} -lCifti |
9 | 9 | @CIFTILIB_PKGCONFIG_REQUIRES_LINE@ |
0 | The main object for dealing with Cifti is CiftiFile. To set up a new CiftiFile, | |
1 | make a CiftiXML object with the mappings you want, and call setCiftiXML on the CiftiFile object. | |
0 | The only header you need to include is CiftiFile.h, it will include the other needed headers. The main | |
1 | object for dealing with Cifti is CiftiFile. To set up a new CiftiFile, make a CiftiXML object with the | |
2 | mappings you want, and call setCiftiXML on the CiftiFile object. | |
2 | 3 | |
3 | 4 | The XML tells you things about the mappings, and lets you set new mappings or modify existing ones: |
4 | 5 | |
15 | 16 | See the rewrite example for how to read and write data to CiftiFile. |
16 | 17 | |
17 | 18 | CiftiFile internally uses NiftiIO, which is a NIfTI reader for both NIfTI-1 and NIfTI-2 single-file (.nii), |
18 | including reading .nii.gz files if zlib is found (NOTE: .nii.gz should not be used for CIFTI files, | |
19 | as seeking is slow, and seeking backwards is impossible). | |
19 | including reading .nii.gz files if zlib is found (NOTE: .nii.gz is not allowed in the CIFTI-2 standard, as | |
20 | seeking is slow, and seeking backwards is problematic). If you want to use our NIfTI implementation to | |
21 | read volume files, include NiftiIO.h. We do not provide a VolumeFile object, NiftiIO only handles the | |
22 | low-level file format details. | |
20 | 23 | |
21 | Our nifti1.h and nifti2.h are slightly modified, replacing the #defines of standard values for header fields | |
22 | with constant integers. We also declare CIFTI-specific intent codes and the extension code in nifti2.h, | |
23 | and have some macros for determining header version. | |
24 | ||
24 | Our nifti1.h and nifti2.h are slightly modified, replacing the #defines of standard values for header | |
25 | fields with constant integers, and placing almost everything in a namespace so that it shouldn't interfere | |
26 | with an existing nifti implementation in the same codebase. We also declare CIFTI-specific intent codes | |
27 | and the CIFTI extension code in nifti2.h, and have some macros for determining header version. |
18 | 18 | if (argc < 3) |
19 | 19 | { |
20 | 20 | cout << "usage: " << argv[0] << " <input cifti> <output cifti>" << endl; |
21 | cout << " rewrite the input cifti file to the output filename, using uint8 and data scaling." << endl; | |
21 | cout << " rewrite the input cifti file to the output filename, using uint8 and data scaling, little-endian." << endl; | |
22 | 22 | return 1; |
23 | 23 | } |
24 | 24 | try |
25 | 25 | { |
26 | 26 | CiftiFile inputFile(argv[1]);//on-disk reading by default |
27 | 27 | inputFile.setWritingDataTypeAndScaling(NIFTI_TYPE_UINT8, -1.0, 6.0);//tells it to use this datatype to best represent this specified range of values [-1.0, 6.0] whenever this instance is written |
28 | inputFile.writeFile(argv[2]);//if this is the same filename as the input, CiftiFile actually detects this and reads the input into memory first | |
28 | inputFile.writeFile(argv[2], CiftiVersion(), CiftiFile::LITTLE);//if this is the same filename as the input, CiftiFile actually detects this and reads the input into memory first | |
29 | 29 | //otherwise, it will read and write one row at a time, using very little memory |
30 | 30 | //inputFile.setWritingDataTypeNoScaling(NIFTI_TYPE_FLOAT32);//this is how you would revert back to writing as float32 without rescaling |
31 | 31 | } catch (CiftiException& e) { |
20 | 20 | } |
21 | 21 | try |
22 | 22 | { |
23 | CiftiFile inputFile(argv[1]);//on-disk reading by default, and we only need the XML header anyway | |
23 | CiftiFile inputFile((string(argv[1])));//on-disk reading by default, and we only need the XML header anyway | |
24 | 24 | const CiftiXML& myXML = inputFile.getCiftiXML(); |
25 | 25 | for (int whichDim = 0; whichDim < myXML.getNumberOfDimensions(); ++whichDim) |
26 | 26 | { |
68 | 68 | |
69 | 69 | void VolumeSpace::setSpace(const int64_t dims[3], const vector<vector<float> >& sform) |
70 | 70 | { |
71 | if (sform.size() < 2 || sform.size() > 4) | |
71 | if (sform.size() < 3 || sform.size() > 4) | |
72 | 72 | { |
73 | 73 | CiftiAssert(false); |
74 | 74 | throw CiftiException("VolumeSpace initialized with wrong size sform"); |
475 | 475 | int32_t intent_code = myXML.getIntentInfo(CiftiVersion(), junk);//use default writing version to check file extension, older version is missing some intent codes |
476 | 476 | switch (intent_code) |
477 | 477 | { |
478 | default: | |
479 | cerr << "warning: unhandled cifti type in extension warning check, tell the developers what you just tried to do" << endl; | |
480 | CiftiAssert(0);//yes, let it fall through to "unknown" in release so that it at least looks for .nii | |
481 | //-fallthrough | |
478 | 482 | case 3000://unknown |
479 | 483 | if (!AString_endsWith(filename, ".nii")) |
480 | 484 | { |
495 | 499 | AString_endsWith(filename, ".pconnscalar.nii")) |
496 | 500 | { |
497 | 501 | cerr << "warning: cifti file of nonstandard mapping combination '" << AString_to_std_string(filename) << "' should NOT be saved using an already-used cifti extension, " |
498 | << "please choose a different, reasonable cifti extension ending in .<something>.nii" << endl; | |
502 | << "please choose a different, reasonable cifti extension of the form .<something>.nii" << endl; | |
499 | 503 | } |
500 | 504 | break; |
501 | 505 | case 3001: |
565 | 569 | cerr << "warning: parcels by parcels by scalar cifti file '" << AString_to_std_string(filename) << "' should be saved ending in .pconnscalar.nii" << endl; |
566 | 570 | } |
567 | 571 | break; |
568 | default: | |
569 | CiftiAssert(0); | |
570 | throw CiftiException("internal error, tell the developers what you just tried to do"); | |
571 | 572 | } |
572 | 573 | } |
573 | 574 | } |
41 | 41 | #include <QString> |
42 | 42 | namespace cifti |
43 | 43 | { |
44 | typedef QString AString; | |
44 | struct AString : public QString | |
45 | {//QT doesn't convert from std::string, and conversions have to be member functions | |
46 | AString() : QString() {} | |
47 | ||
48 | //some QString constructors are explicit, so instead only make conversion constructors for whatever works with assignment to QString | |
49 | //the cast is required to avoid recursing through AString | |
50 | template <typename T> | |
51 | AString(const T& rhs) : QString() | |
52 | { | |
53 | *(static_cast<QString*>(this)) = rhs; | |
54 | } | |
55 | ||
56 | AString(const std::string& rhs) : QString() | |
57 | { | |
58 | (*this) = fromStdString(rhs); | |
59 | } | |
60 | }; | |
45 | 61 | #define ASTRING_TO_CSTR(mystr) ((mystr).toLocal8Bit().constData()) |
46 | 62 | #define ASTRING_UTF8_RAW(mystr) ((mystr).toUtf8().constData()) |
47 | 63 | inline std::string AString_to_std_string(const AString& mystr) |
140 | 140 | |
141 | 141 | bool BinaryFile::getOpenForRead() |
142 | 142 | { |
143 | return (m_curMode | READ) != 0; | |
143 | return (m_curMode & READ) != 0; | |
144 | 144 | } |
145 | 145 | |
146 | 146 | bool BinaryFile::getOpenForWrite() |
147 | 147 | { |
148 | return (m_curMode | WRITE) != 0; | |
148 | return (m_curMode & WRITE) != 0; | |
149 | 149 | } |
150 | 150 | |
151 | 151 | void BinaryFile::open(const AString& filename, const OpenMode& opmode) |
389 | 389 | |
390 | 390 | void QFileImpl::seek(const int64_t& position) |
391 | 391 | { |
392 | if (m_file.pos() == position) return; //QFile::seek always does a flush in qt5, so try to avoid calling it | |
392 | 393 | if (!m_file.seek(position)) throw CiftiException("seek failed in file '" + m_fileName + "'"); |
393 | 394 | } |
394 | 395 |
778 | 778 | { |
779 | 779 | Quirks ret; |
780 | 780 | if (header.sizeof_hdr != sizeof(nifti_2_header)) throw CiftiException("incorrect sizeof_hdr in file '" + filename + "'"); |
781 | const char magic[] = "n+2\0\r\n\032\n";//only support single-file nifti | |
781 | const char magic[] = "n+2\0\r\n\032\n";//only support single-file nifti, magic string detailed at https://www.nitrc.org/forum/forum.php?thread_id=2148&forum_id=1941 | |
782 | 782 | for (int i = 0; i < 8; ++i) |
783 | 783 | { |
784 | 784 | if (header.magic[i] != magic[i]) throw CiftiException("incorrect magic in file '" + filename + "'"); |
304 | 304 | template<typename TO, typename FROM> |
305 | 305 | TO NiftiIO::clamp(const FROM& in) |
306 | 306 | { |
307 | std::numeric_limits<TO> mylimits; | |
308 | if (mylimits.max() < in) return mylimits.max(); | |
309 | if (mylimits.is_integer)//c++11 can use lowest() instead of this mess | |
310 | { | |
311 | if (mylimits.min() > in) return mylimits.min(); | |
307 | typedef std::numeric_limits<TO> mylimits; | |
308 | if (mylimits::has_infinity && std::isinf(in)) return (TO)in;//in case we use this on float types at some point | |
309 | if (mylimits::max() < in) return mylimits::max(); | |
310 | if (mylimits::is_integer)//c++11 can use lowest() instead of this mess | |
311 | { | |
312 | if (mylimits::min() > in) return mylimits::min(); | |
312 | 313 | } else { |
313 | if (-mylimits.max() > in) return -mylimits.max(); | |
314 | if (-mylimits::max() > in) return -mylimits::max(); | |
314 | 315 | } |
315 | 316 | return (TO)in; |
316 | 317 | } |