Codebase list ciftilib / 2e58203
Update upstream source from tag 'upstream/1.6.0' Update to upstream version '1.6.0' with Debian dir aef4d934e80556836ac264c7bc81cb9a79f8e848 Andreas Tille 3 years ago
12 changed file(s) with 71 addition(s) and 28 deletion(s). Raw diff Collapse all Expand all
0 os: linux
1 arch:
2 - amd64
3 - ppc64le
4
05 language: cpp
16 sudo: false
27
2934 - cd ../build
3035
3136 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
3338 - export LD_LIBRARY_PATH=$(if [[ $CXX == "clang++" ]]; then echo -n '/usr/local/clang/lib'; fi)
3439 - make -j 4
3540 - example/xmlinfo ../CiftiLib/example/data/ones.dscalar.nii
2020 SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/" "${CMAKE_SOURCE_DIR}/cmake/Modules/UseDoxygen/")
2121
2222 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")
2339
2440 #QT
2541 IF (NOT IGNORE_QT)
44 Description: C++ Library for reading and writing CIFTI-2 and CIFTI-1 files
55 Version: @CIFTILIB_VERSION@
66 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@
88 Libs: -L${libdir} -lCifti
99 @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.
23
34 The XML tells you things about the mappings, and lets you set new mappings or modify existing ones:
45
1516 See the rewrite example for how to read and write data to CiftiFile.
1617
1718 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.
2023
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.
1818 if (argc < 3)
1919 {
2020 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;
2222 return 1;
2323 }
2424 try
2525 {
2626 CiftiFile inputFile(argv[1]);//on-disk reading by default
2727 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
2929 //otherwise, it will read and write one row at a time, using very little memory
3030 //inputFile.setWritingDataTypeNoScaling(NIFTI_TYPE_FLOAT32);//this is how you would revert back to writing as float32 without rescaling
3131 } catch (CiftiException& e) {
2020 }
2121 try
2222 {
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
2424 const CiftiXML& myXML = inputFile.getCiftiXML();
2525 for (int whichDim = 0; whichDim < myXML.getNumberOfDimensions(); ++whichDim)
2626 {
6868
6969 void VolumeSpace::setSpace(const int64_t dims[3], const vector<vector<float> >& sform)
7070 {
71 if (sform.size() < 2 || sform.size() > 4)
71 if (sform.size() < 3 || sform.size() > 4)
7272 {
7373 CiftiAssert(false);
7474 throw CiftiException("VolumeSpace initialized with wrong size sform");
475475 int32_t intent_code = myXML.getIntentInfo(CiftiVersion(), junk);//use default writing version to check file extension, older version is missing some intent codes
476476 switch (intent_code)
477477 {
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
478482 case 3000://unknown
479483 if (!AString_endsWith(filename, ".nii"))
480484 {
495499 AString_endsWith(filename, ".pconnscalar.nii"))
496500 {
497501 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;
499503 }
500504 break;
501505 case 3001:
565569 cerr << "warning: parcels by parcels by scalar cifti file '" << AString_to_std_string(filename) << "' should be saved ending in .pconnscalar.nii" << endl;
566570 }
567571 break;
568 default:
569 CiftiAssert(0);
570 throw CiftiException("internal error, tell the developers what you just tried to do");
571572 }
572573 }
573574 }
4141 #include <QString>
4242 namespace cifti
4343 {
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 };
4561 #define ASTRING_TO_CSTR(mystr) ((mystr).toLocal8Bit().constData())
4662 #define ASTRING_UTF8_RAW(mystr) ((mystr).toUtf8().constData())
4763 inline std::string AString_to_std_string(const AString& mystr)
140140
141141 bool BinaryFile::getOpenForRead()
142142 {
143 return (m_curMode | READ) != 0;
143 return (m_curMode & READ) != 0;
144144 }
145145
146146 bool BinaryFile::getOpenForWrite()
147147 {
148 return (m_curMode | WRITE) != 0;
148 return (m_curMode & WRITE) != 0;
149149 }
150150
151151 void BinaryFile::open(const AString& filename, const OpenMode& opmode)
389389
390390 void QFileImpl::seek(const int64_t& position)
391391 {
392 if (m_file.pos() == position) return; //QFile::seek always does a flush in qt5, so try to avoid calling it
392393 if (!m_file.seek(position)) throw CiftiException("seek failed in file '" + m_fileName + "'");
393394 }
394395
778778 {
779779 Quirks ret;
780780 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
782782 for (int i = 0; i < 8; ++i)
783783 {
784784 if (header.magic[i] != magic[i]) throw CiftiException("incorrect magic in file '" + filename + "'");
304304 template<typename TO, typename FROM>
305305 TO NiftiIO::clamp(const FROM& in)
306306 {
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();
312313 } else {
313 if (-mylimits.max() > in) return -mylimits.max();
314 if (-mylimits::max() > in) return -mylimits::max();
314315 }
315316 return (TO)in;
316317 }