diff --git a/.github/workflows/modules.yml b/.github/workflows/modules.yml index c50798507..79e426d95 100644 --- a/.github/workflows/modules.yml +++ b/.github/workflows/modules.yml @@ -63,7 +63,7 @@ jobs: artifact: 'build/inviwo-v*.dmg' - system: linux - os: 'ubuntu-24.04' + os: 'ubuntu-26.04' targets: 'all' installer: 'inviwo-installer-linux' artifact: 'build/inviwo-v*.AppImage' @@ -446,7 +446,7 @@ jobs: pull-requests: write env: LLVM_VERSION: 19 - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 320 steps: @@ -627,7 +627,7 @@ jobs: name: "Test Installer Linux" needs: build - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: "Download artifact" uses: actions/download-artifact@v7 @@ -668,7 +668,7 @@ jobs: create-changelog: name: "Create Changelog" - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: "Generate Changelog" id: changelog @@ -696,7 +696,7 @@ jobs: if: github.ref == 'refs/heads/master' needs: [build, test-installer-windows, test-installer-macos, test-installer-linux, regression] - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: "Clone Inviwo" uses: actions/checkout@v6 @@ -739,7 +739,7 @@ jobs: name: "Update latest release" if: github.ref == 'refs/heads/master' needs: [build, test-installer-windows, test-installer-macos, test-installer-linux, regression, create-changelog] - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: "Download installer" diff --git a/medvis/dicom/CMakeLists.txt b/medvis/dicom/CMakeLists.txt index baa64f01d..0d44a13d1 100644 --- a/medvis/dicom/CMakeLists.txt +++ b/medvis/dicom/CMakeLists.txt @@ -31,7 +31,7 @@ ivw_group("Source Files" ${SOURCE_FILES}) ivw_create_module(${SOURCE_FILES} ${HEADER_FILES}) find_package(TIFF REQUIRED) -find_package(gdcm CONFIG REQUIRED) +find_package(GDCM CONFIG REQUIRED) target_link_libraries(inviwo-module-dicom PUBLIC @@ -48,8 +48,8 @@ target_link_libraries(inviwo-module-dicom PRIVATE TIFF::TIFF ) -target_include_directories(inviwo-module-dicom PUBLIC gdcm) -ivw_vcpkg_install(gdcm MODULE DICOM) +target_include_directories(inviwo-module-dicom PUBLIC GDCM) +ivw_vcpkg_install(GDCM MODULE DICOM) #-------------------------------------------------------------------- ivw_make_package(InviwoDICOMModule inviwo-module-dicom) diff --git a/medvis/dicom/src/datastructures/dicomdirtypes.cpp b/medvis/dicom/src/datastructures/dicomdirtypes.cpp index 082f52945..7399e090e 100644 --- a/medvis/dicom/src/datastructures/dicomdirtypes.cpp +++ b/medvis/dicom/src/datastructures/dicomdirtypes.cpp @@ -83,7 +83,7 @@ void Image::updateInfo(const gdcm::DataSet& dataset) { // Pixel Spacing https://dicom.innolitics.com/ciods/ct-image/image-plane/00280030 gdcm::Attribute<0x0028, 0x0030> pixelSpacingAttr{{1.0, 1.0}}; pixelSpacingAttr.Set(dataset); - pixelSpacing = gdcmutil::toGlmVec<3>(pixelSpacingAttr.GetValues()); + pixelSpacing = dvec3{gdcmutil::toGlmVec<2>(pixelSpacingAttr.GetValues()), 0.0}; updateZpos(); } @@ -185,20 +185,19 @@ void Series::updateImageInformation(const std::filesystem::path& dicompath) { auto sanityCheck = [&](const ImageMetaData& ref, const ImageMetaData& img) { if (ref.dims != img.dims) { throw DataReaderException( - fmt::format( - "image sizes differ in DICOM series '{}', expected {} but found {} ('{}')", - desc, toString(ref.dims), toString(img.dims), dicompath), - IVW_CONTEXT); + SourceContext{}, + "image sizes differ in DICOM series '{}', expected {} but found {} ('{}')", desc, + toString(ref.dims), toString(img.dims), dicompath); } if (ref.pixelformat != img.pixelformat) { - throw DataReaderException( - fmt::format("pixel formats differ in DICOM series '{}' ('{}')", desc, dicompath), - IVW_CONTEXT); + throw DataReaderException(SourceContext{}, + "pixel formats differ in DICOM series '{}' ('{}')", desc, + dicompath); } if (!ref.photometric.IsSameColorSpace(img.photometric)) { - throw DataReaderException( - fmt::format("photometric info differ in DICOM series '{}' ('{}')", desc, dicompath), - IVW_CONTEXT); + throw DataReaderException(SourceContext{}, + "photometric info differ in DICOM series '{}' ('{}')", desc, + dicompath); } const double dicomDelta = 1.0e-4; if (std::abs(ref.slope - img.slope) > dicomDelta || @@ -232,10 +231,9 @@ void Series::updateImageInformation(const std::filesystem::path& dicompath) { continue; } if (!imageReader.Read()) { - throw DataReaderException( - fmt::format("could not read image '{}' in DICOM series '{}' ('{}')", imgInfo.path, - desc, dicompath), - IVW_CONTEXT); + throw DataReaderException(SourceContext{}, + "could not read image '{}' in DICOM series '{}' ('{}')", + imgInfo.path, desc, dicompath); } imgInfo.updateInfo(imageReader); @@ -249,19 +247,17 @@ void Series::updateImageInformation(const std::filesystem::path& dicompath) { } if (warnSlopeIntercept) { - LogWarn( - fmt::format("varying slopes/intercepts in DICOM series '{}' ('{}')", desc, dicompath)); + log::warn("varying slopes/intercepts in DICOM series '{}' ('{}')", desc, dicompath); } if (warnPixelSpacing) { - LogWarn(fmt::format("pixel spacings differ in DICOM series '{}', expected {} ('{}')", desc, - toString(refImage.pixelSpacing), dicompath)); + log::warn("pixel spacings differ in DICOM series '{}', expected {} ('{}')", desc, + toString(refImage.pixelSpacing), dicompath); } if (warnOrientation) { - LogWarn( - fmt::format("image orientations differ in DICOM series '{}' ('{}')", desc, dicompath)); + log::warn("image orientations differ in DICOM series '{}' ('{}')", desc, dicompath); } if (warnOrigin) { - LogWarn(fmt::format("origins differ in DICOM series '{}' ('{}')", desc, dicompath)); + log::warn("origins differ in DICOM series '{}' ('{}')", desc, dicompath); } util::erase_remove_if(images, [](dicomdir::Image& image) { return image.empty(); }); diff --git a/medvis/dicom/src/errorlogging.cpp b/medvis/dicom/src/errorlogging.cpp index e5c5db1d9..be2db938f 100644 --- a/medvis/dicom/src/errorlogging.cpp +++ b/medvis/dicom/src/errorlogging.cpp @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -78,21 +77,20 @@ class StreambufLineout : public std::streambuf { if (ch == '\n') { if (!buffer.empty()) { // at the end of a line we want to pass the message to Inviwo's logging system - inviwo::LogCentral::getPtr()->log("Gdcm Volume Importer", loglevel, - LogAudience::User, "", "", 0, - buffer); + LogCentral::getPtr()->log("Gdcm Volume Importer", loglevel, LogAudience::User, + "", "", 0, buffer); } buffer.clear(); } else if (!Traits::eq_int_type(ch, Traits::eof())) { buffer.push_back(static_cast(ch)); } - } catch (std::exception& ex) { + } catch (const std::exception& ex) { // error while logging, print what we've got so far - inviwo::LogCentral::getPtr()->log("Gdcm Volume Importer", loglevel, LogAudience::User, - "", "", 0, buffer); + LogCentral::getPtr()->log("Gdcm Volume Importer", loglevel, LogAudience::User, + "", "", 0, buffer); buffer.clear(); - // and tell the user what hargspened - LogError("Exception while logging Gdcm: " << ex.what()); + // and tell the user what happened + log::error("Exception while logging Gdcm: {}", ex.what()); // return traits::eof on failure return Traits::eof(); } diff --git a/medvis/dicom/src/io/gdcmvolumereader.cpp b/medvis/dicom/src/io/gdcmvolumereader.cpp index 086f95ac5..6610583b6 100644 --- a/medvis/dicom/src/io/gdcmvolumereader.cpp +++ b/medvis/dicom/src/io/gdcmvolumereader.cpp @@ -74,7 +74,7 @@ GdcmVolumeReader::GdcmVolumeReader() , format_{DataUInt8::get()} , dimension_{0, 0, 0} { - addExtension(FileExtension("dcm", "DICOM Volume file format")); + addExtension({.extension = LCString{"dcm"}, .description = "DICOM Volume file format"}); enableGdcmLogging(LogVerbosity::Error); } @@ -90,9 +90,9 @@ std::shared_ptr GdcmVolumeReader::getVolumeDescription(dicomdir::Series& series.updateImageInformation(path); if (series.empty()) { - throw DataReaderException( - fmt::format("DICOM series '{}' does not contain any images ({})", series.desc, path), - IVW_CONTEXT_CUSTOM("GdcmVolumeReader::getVolumeDescription")); + throw DataReaderException(SourceContext{}, + "DICOM series '{}' does not contain any images ({})", series.desc, + path); } // sort images by slice position (z) in patient coords @@ -104,10 +104,9 @@ std::shared_ptr GdcmVolumeReader::getVolumeDescription(dicomdir::Series& // create an Inviwo Volume const DataFormatBase* format = gdcmutil::getDataFormatBase(series.pixelformat); if (!format) { - throw DataReaderException( - fmt::format("unsupported image format in DICOM series '{}': {} ({})", series.desc, - series.pixelformat.GetScalarTypeAsString(), path), - IVW_CONTEXT_CUSTOM("GdcmVolumeReader::getVolumeDescription")); + throw DataReaderException(SourceContext{}, + "unsupported image format in DICOM series '{}': {} ({})", + series.desc, series.pixelformat.GetScalarTypeAsString(), path); } auto volume = std::make_shared(series.dims, format); @@ -139,10 +138,10 @@ std::shared_ptr GdcmVolumeReader::getVolumeDescription(dicomdir::Series& dvec3 spacing{series.pixelSpacing}; if (series.pixelSpacing.z == 0.0) { if (dicomImg.sliceThickness == 0.0) { - LogWarnCustom("GdcmVolumeReader::getVolumeDescription", - fmt::format("DICOM series '{}' does not define pixel spacing in z or " - "slice thickness, using 1.0 for z ({})", - series.desc, path)); + log::warn( + "DICOM series '{}' does not define pixel spacing in z or " + "slice thickness, using 1.0 for z ({})", + series.desc, path); spacing.z = 1.0; } else { spacing.z = dicomImg.sliceThickness; @@ -189,7 +188,7 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMsequenceRecursive( std::shared_ptr GdcmVolumeReader::tryReadDICOMsequence( const std::filesystem::path& sequenceDirectory) { const auto files = filesystem::getDirectoryContents(sequenceDirectory); - std::shared_ptr outputVolumes = std::make_shared(); + auto outputVolumes = std::make_shared(); std::map seriesByUID; for (const auto& f : files) { @@ -199,15 +198,13 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMsequence( // add sequences to "outputVolumes" std::filesystem::path file = sequenceDirectory / f; if (!std::filesystem::is_regular_file(file)) { - throw DataReaderException(fmt::format("file does not exist ({})", file), - IVW_CONTEXT_CUSTOM("GdcmVolumeReader::tryReadDICOMsequence")); + throw DataReaderException(SourceContext{}, "file does not exist ({})", file); } gdcm::ImageReader imageReader; std::ifstream imageInputStream(file, std::ios::binary); if (!imageInputStream.is_open()) { - throw DataReaderException(fmt::format("file cannot be opened ({})", file), - IVW_CONTEXT_CUSTOM("GdcmVolumeReader::tryReadDICOMsequence")); + throw DataReaderException(SourceContext{}, "file cannot be opened ({})", file); } /*if (!imageReader.CanRead()) { // call this on file BrainSample 11.7T\4\pdata\1\2dseq @@ -231,17 +228,15 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMsequence( } seriesByUID[suid].images.push_back(dicomdir::Image{file.string()}); } else { - throw DataReaderException( - fmt::format("could not find DICOM series UID ({})", file), - IVW_CONTEXT_CUSTOM("GdcmVolumeReader::tryReadDICOMsequence")); + throw DataReaderException(SourceContext{}, "could not find DICOM series UID ({})", + file); } } else { continue; // skip non-dicom files } } - for (const auto& pair : seriesByUID) { - dicomdir::Series series = pair.second; + for (auto&& [uid, series] : seriesByUID) { if (series.images.empty()) { continue; } @@ -266,8 +261,7 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMDIR( std::ifstream dicomdirInputStream(dicomdirPath, std::ios::binary); if (!dicomdirInputStream.is_open()) { - throw DataReaderException(fmt::format("could not open DICOM file ({})", dicomdirPath), - IVW_CONTEXT_CUSTOM("GdcmVolumeReader::tryReadDICOMDIR")); + throw DataReaderException(SourceContext{}, "could not open DICOM file ({})", dicomdirPath); } // Analog to gdcm example "ReadAndDumpdicomdir::" @@ -275,7 +269,7 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMDIR( reader.SetStream(dicomdirInputStream); if (!reader.Read()) { // LogInfo(dicomdirPath + " is no DICOM file"); - return 0; + return nullptr; } gdcm::File& file = reader.GetFile(); @@ -285,7 +279,7 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMDIR( gdcm::MediaStorage dicomMediaStorage; dicomMediaStorage.SetFromFile(file); if (dicomMediaStorage != gdcm::MediaStorage::MediaStorageDirectoryStorage) { - return 0; + return nullptr; } std::stringstream storageUID; @@ -294,7 +288,7 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMDIR( metainfo.GetDataElement(gdcm::Tag(0x0002, 0x0002)).GetValue().Print(storageUID); } else { // Media Storage Sop Class UID not present - return 0; + return nullptr; } // Trim string because DICOM allows padding with spaces @@ -302,7 +296,7 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMDIR( if ("1.2.840.10008.1.3.10" != storageUIDstr) { // This file is not a dicomdir:: - return 0; + return nullptr; } // Now read actual dataset @@ -346,7 +340,8 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMDIR( auto recordSequence = dataElement.GetValueAsSQ(); // This loop also iterates all the nested records sequences (like depth-first tree // traversal) - for (int recIndex = 1; recIndex <= recordSequence->GetNumberOfItems(); recIndex++) { + for (gdcm::SequenceOfItems::SizeType recIndex = 1; + recIndex <= recordSequence->GetNumberOfItems(); recIndex++) { // Records contain data about either a patient, study, series or image // image records reference image files gdcm::Item& record = recordSequence->GetItem(recIndex); @@ -390,7 +385,7 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMDIR( auto& study = dataPerPatient.back().studies.back(); auto& series = study.series.back(); - series.images.push_back(dicomdir::Image{imagePath.string()}); + series.images.emplace_back(imagePath.string()); } imageCount++; @@ -398,19 +393,20 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMDIR( } } - LogInfoCustom("GdcmVolumeReader", "Scanned dicomdir:: ('" - << dicomdirPath << "'):\n PatientCount = " - << patientCount << "\n StudyCount = " << studyCount - << "\n ImageCount = " << imageCount); + log::info( + "Scanned dicomdir:: ('{}'):\n" + " PatientCount = {}\n" + " StudyCount = {}\n" + " ImageCount = {}", + dicomdirPath, patientCount, studyCount, imageCount); if (patientCount == 0 || studyCount == 0 || seriesCount == 0 || imageCount == 0) { - LogWarnCustom("GdcmVolumeReader", - "No volumes found in dicomdir:: ('" << dicomdirPath << "')"); - return 0; + log::warn("No volumes found in dicomdir:: ('{}')", dicomdirPath); + return nullptr; } // Build volumes from images - std::shared_ptr outputVolumes = std::make_shared(); + auto outputVolumes = std::make_shared(); for (dicomdir::Patient& patient : dataPerPatient) { // push everything in one sequence for (dicomdir::Study& study : patient.studies) { for (dicomdir::Series& series : study.series) { @@ -440,67 +436,55 @@ std::shared_ptr GdcmVolumeReader::tryReadDICOMDIR( } // print a summary of all collected volumes - auto createLine = [](const std::string& tag, auto text, int indent) { + auto createLine = [](std::string_view tag, auto text, int indent) { return fmt::format("{0:<{1}}{2:<12}{3}\n", "", indent, tag, text); }; size_t volindex = 0; auto printSeries = [createLine, &volindex](const dicomdir::Series& series, int indent) { - std::ostringstream ss; - - ss << createLine("[ DICOM Series", "", indent); + StrBuffer buf; if (glm::compMul(series.dims) > 0) { ++volindex; - ss << createLine("Volume Idx:", volindex, indent + 2) - << createLine("Dimensions:", toString(series.dims), indent + 2); + buf.append("{}", createLine("Volume Idx:", volindex, indent + 2)); + buf.append("{}", createLine("Dimensions:", toString(series.dims), indent + 2)); } if (!series.desc.empty()) { - ss << createLine("Desc.:", series.desc, indent + 2); + buf.append("{}", createLine("Desc.:", series.desc, indent + 2)); } if (!series.modality.empty()) { - ss << createLine("Modality:", series.modality, indent + 2); + buf.append("{}", createLine("Modality:", series.modality, indent + 2)); } - ss << createLine("No. Images:", series.images.size(), indent + 2) - << createLine("]", "", indent); + buf.append("{}", createLine("No. Images:", series.images.size(), indent + 2)); - return ss.str(); + return fmt::format("{0:<{1}}[ DICOM Series\n{2}{0:<{1}}]", "", indent, buf.view()); }; auto printStudy = [createLine, printSeries](const dicomdir::Study& study, int indent) { - std::ostringstream ss; - - ss << createLine("[ DICOM Study", "", indent); + StrBuffer buf; if (!study.desc.empty()) { - ss << createLine("Desc.:", study.desc, indent + 2); + buf.append("{}", createLine("Desc.:", study.desc, indent + 2)); } if (!study.date.empty()) { - ss << createLine("Date:", study.date, indent + 2); + buf.append("{}", createLine("Date:", study.date, indent + 2)); } - ss << createLine("No. Series:", study.series.size(), indent + 2); + buf.append("{}", createLine("No. Series:", study.series.size(), indent + 2)); for (const auto& s : study.series) { - ss << printSeries(s, indent + 2); + buf.append("{}", printSeries(s, indent + 2)); } - ss << createLine("]", "", indent); - return ss.str(); + return fmt::format("{0:<{1}}[ DICOM Study\n{2}{0:<{1}}]", "", indent, buf.view()); }; - auto printPatient = [createLine, printStudy](const dicomdir::Patient& p) { - std::ostringstream ss; - - ss << "[ DICOM Patient\n" - << createLine("Name:", p.patientName, 2) << createLine("ID", p.patientId, 2) - << createLine("No. Studies:", p.studies.size(), 2); + for (const auto& p : dataPerPatient) { + StrBuffer buf; + buf.append("{}{}{}", createLine("Name:", p.patientName, 2), + createLine("ID", p.patientId, 2), + createLine("No. Studies:", p.studies.size(), 2)); for (const auto& s : p.studies) { - ss << printStudy(s, 2); + buf.append("{}", printStudy(s, 2)); } - ss << "]"; - - return ss.str(); - }; - for (const auto& p : dataPerPatient) { - LogInfoCustom("GdcmVolumeReader", printPatient(p)); + log::info("[ DICOM Patient\n{}]", buf.view()); } return outputVolumes; @@ -516,8 +500,7 @@ std::shared_ptr GdcmVolumeReader::readData(const std::filesystem if (std::filesystem::is_regular_file(newPath)) { path = newPath; } else { - throw DataReaderException(fmt::format("could not read input file ({})", path), - IVW_CONTEXT); + throw DataReaderException(SourceContext{}, "could not read input file ({})", path); } } @@ -543,19 +526,21 @@ std::shared_ptr GdcmVolumeReader::readData(const std::filesystem // Otherwise keep trying file_ = path; - std::shared_ptr outputVolumes = std::make_shared(); + auto outputVolumes = std::make_shared(); gdcm::ImageReader reader; reader.SetFileName(file_.string().c_str()); if (!reader.Read()) { MevisVolumeReader mvreader; if (mvreader.setFilenames(file_)) { - LogInfo("This seems to be a MevisLab dcm/tif file - calling the appropriate reader..."); + log::info( + "This seems to be a MevisLab dcm/tif file - calling the appropriate reader..."); + gdcm::Trace::WarningOff(); std::shared_ptr v = mvreader.readData(file_); + gdcm::Trace::WarningOn(); outputVolumes->push_back(v); return outputVolumes; } else { - throw DataReaderException(fmt::format("could not read input file ({})", path), - IVW_CONTEXT); + throw DataReaderException(SourceContext{}, "could not read input file ({})", path); } } @@ -563,7 +548,7 @@ std::shared_ptr GdcmVolumeReader::readData(const std::filesystem const gdcm::File& file = reader.GetFile(); std::shared_ptr v = generateVolume(image, file); if (!v) { - throw DataReaderException(fmt::format("could not read input file ({})", path), IVW_CONTEXT); + throw DataReaderException(SourceContext{}, "could not read input file ({})", path); } outputVolumes->push_back(v); @@ -616,67 +601,51 @@ std::shared_ptr GdcmVolumeReader::generateVolume(const gdcm::Image& imag // create an Inviwo Volume const DataFormatBase* format = gdcmutil::getDataFormatBase(image); if (!format) { - throw DataReaderException(fmt::format("unsupported image format in DICOM image: {} ({})", - image.GetPixelFormat().GetScalarTypeAsString(), - file.GetHeader().GetMediaStorageAsString()), - IVW_CONTEXT); + throw DataReaderException(SourceContext{}, + "unsupported image format in DICOM image: {} ({})", + image.GetPixelFormat().GetScalarTypeAsString(), + file.GetHeader().GetMediaStorageAsString()); } std::size_t voxelsz = (format->getSizeInBytes()) * (format->getComponents()); std::size_t size = glm::compMul(dimension) * voxelsz; // sanity check - std::size_t len = image.GetBufferLength(); - // if gdcm says the volume size is LARGER than we compute - inviwo may crash because // the allocated buffer can be too small for image.GetBuffer(destination) - if (size != len) { + if (std::size_t len = image.GetBufferLength(); size != len) { throw DataReaderException( - fmt::format( - "inconsistent format size information: {} byte (Inviwo), {} byte (gdcm) ({})", size, - len, file.GetHeader().GetMediaStorageAsString()), - IVW_CONTEXT); + SourceContext{}, + "inconsistent format size information: {} byte (Inviwo), {} byte (gdcm) ({})", size, + len, file.GetHeader().GetMediaStorageAsString()); } - gdcm::MediaStorage ms = gdcm::MediaStorage(); - // add some info in debug mode + gdcm::MediaStorage ms{}; + ms.SetFromFile(file); #if defined(IVW_DEBUG) - LogInfo("========================================================================"); - LogInfo(file_ << " - Volume Information:"); - std::string dimstr = std::to_string(dims[0]); - std::string oristr = std::to_string(origin[0]); - std::string spacestr = std::to_string(spacings[0]); - for (std::size_t i = 1; i < dims.size(); ++i) { - dimstr += "x" + std::to_string(dims[i]); - oristr += "x" + std::to_string(origin[i]); - spacestr += "x" + std::to_string(spacings[i]); - } - - ms.SetFromFile(file); - gdcm::MediaStorage::MSType typ = ms.GetMSType(ms.GetString()); - - LogInfo("media storage type: " << ms.GetMSString(typ)); - LogInfo("volume is " << dims.size() << "D"); - LogInfo("size: " << dimstr); - LogInfo("offset: " << oristr); - LogInfo("spacing: " << spacestr); - LogInfo("volume size: " << size); - LogInfo("voxel size: " << voxelsz << "(components: " << (format->getComponents()) - << ", component size: " << (format->getSizeInBytes()) << ")"); - LogInfo("sample value range is [" << pixelformat.GetMin() << ", " << pixelformat.GetMax() - << "]."); + StrBuffer buf; + const char* msStorageType = + gdcm::MediaStorage::GetMSString(gdcm::MediaStorage::GetMSType(ms.GetString())); + log::warn("{0:=<80}", ""); + log::warn("{} - Volume Information:", file_); + log::warn("{}", msStorageType); + log::warn("volume is {}D\nsize: {}\noffset: {}\nspacing: {}\nvolume size (byte): {}", + dims.size(), fmt::join(dims, "x"), fmt::join(origin, "x"), fmt::join(spacings, "x"), + size); + log::warn("voxel size: {} (components: {}, component size: {})", voxelsz, + format->getComponents(), format->getSizeInBytes()); + + log::warn("sample value range is [{}, {}]", pixelformat.GetMin(), pixelformat.GetMax()); pixelformat.Print(gdcm::Trace::GetDebugStream()); - LogInfo("corresponding inviwo format: " << format->getString()); - LogInfo("format: " << format->getString() << "[" << format->getMin() << ", " << format->getMax() - << "]"); - LogInfo("========================================================================"); + log::warn("corresponding inviwo format: ", format->getString()); + log::warn("{0:=<80}", ""); #endif dimension_ = dimension; format_ = format; - std::shared_ptr volume = std::make_shared(dimension, format); + auto volume = std::make_shared(dimension, format); volume->setBasis(basis); volume->setOffset(offset); volume->setWorldMatrix(wtm); @@ -687,10 +656,9 @@ std::shared_ptr GdcmVolumeReader::generateVolume(const gdcm::Image& imag std::vector is = gdcm::ImageHelper::GetRescaleInterceptSlopeValue(file); auto intercept = is[0]; auto slope = is[1]; - const std::string modality(ms.GetModality()); - // TODO: check this heuristics!!! - if (modality == "CT") { + // TODO: check this heuristic!!! + if (std::string{ms.GetModality()} == "CT") { // Computed Tomography volume->dataMap.valueAxis = Axis{"Hounsfield", units::unit_from_string("HU")}; if (format->getPrecision() == 16) { @@ -729,7 +697,7 @@ std::shared_ptr GCDMVolumeRAMLoader::createRepresentation( gdcm::ImageReader reader; reader.SetFileName(file_.string().c_str()); if (!reader.Read()) { - throw DataReaderException(fmt::format("could not read file ({})", file_), IVW_CONTEXT); + throw DataReaderException(SourceContext{}, "could not read file ({})", file_); } const gdcm::Image& image = reader.GetImage(); image.GetBuffer(data.get()); @@ -755,8 +723,7 @@ void GCDMVolumeRAMLoader::getVolumeData(const dicomdir::Series& series, void* ou std::ifstream imageInputStream(imgInfo.path, std::ios::binary); if (!imageInputStream.is_open()) { - throw DataReaderException(fmt::format("file cannot be opened ({})", imgInfo.path), - IVW_CONTEXT); + throw DataReaderException(SourceContext{}, "file cannot be opened ({})", imgInfo.path); } imageReader.SetStream(imageInputStream); @@ -769,8 +736,8 @@ void GCDMVolumeRAMLoader::getVolumeData(const dicomdir::Series& series, void* ou gdcm::Image image = imageReader.GetImage(); // Get RAW image (gdcm does the decoding for us) if (!image.GetBuffer(reinterpret_cast(outData) + totalByteCount)) { - throw DataReaderException( - fmt::format("could not read image data ({})", imgInfo.path), IVW_CONTEXT); + throw DataReaderException(SourceContext{}, "could not read image data ({})", + imgInfo.path); } totalByteCount += image.GetBufferLength(); @@ -784,7 +751,7 @@ void GCDMVolumeRAMLoader::updateRepresentation(std::shared_ptr MevisVolumeReader::readData(const std::filesystem::path& gdcm::ImageReader reader; reader.SetFileName(dcm_file_.string().c_str()); if (reader.Read()) { - LogWarn("dcm file " << dcm_file_ << " contains an image/volume - maybe the data in " - << tif_file_ << " does not belong to this dcm file?") + log::warn( + "dcm file '{}' contains an image/volume - maybe the data in '{}' does not belong to " + "this dcm file?", + dcm_file_, tif_file_); } else { - LogInfo("You can savely ignore the last \"no pixel data found!\" warning from gdcm."); + log::info("You can savely ignore the last \"no pixel data found!\" warning from gdcm."); // as a alternative call gdcm::Trace::WarningOff(); before reader.Read() } @@ -215,8 +217,9 @@ std::shared_ptr MevisVolumeRAMLoader::createRepresentation auto data = std::make_unique(size); if (!data) { throw DataReaderException( - IVW_CONTEXT, - "Error: Could not allocate memory for loading mevis volume data: ", tif_file_); + SourceContext{}, + "Error: Could not allocate memory for loading mevis volume data: {}", + tif_file_); } readDataInto(reinterpret_cast(data.get())); @@ -292,9 +295,9 @@ void MevisVolumeRAMLoader::readDataInto(void* destination) const { #if defined(IVW_DEBUG) unsigned int number_of_tiles = TIFFNumberOfTiles(tiffimage); - LogInfo("number of tiles: " << number_of_tiles); - LogInfo(fmt::format("tilesize: {} ({}x{}x{})", tilesz, tilesize.x, tilesize.y, tilesize.z)); - LogInfo(fmt::format("rowbyte: {}, bytespersample: {}", tilerowbytes, bytespersample)); + log::info("number of tiles: {}", number_of_tiles); + log::info("tilesize: {} ({}x{}x{})", tilesz, tilesize.x, tilesize.y, tilesize.z); + log::info("rowbyte: {}, bytespersample: {}", tilerowbytes, bytespersample); #endif IVW_ASSERT(tilerowbytes == tilesize.x * bytespersample, diff --git a/misc/c3d/src/processors/c3daveragedpositions.cpp b/misc/c3d/src/processors/c3daveragedpositions.cpp index 5ddca3f57..0b160bc78 100644 --- a/misc/c3d/src/processors/c3daveragedpositions.cpp +++ b/misc/c3d/src/processors/c3daveragedpositions.cpp @@ -172,7 +172,7 @@ void C3DAveragedPositions::process() { radii.emplace_back(markerRadius_.get()); index.emplace_back(static_cast(pointIdx)); - pickIds.emplace_back(picking_.getPickingId(pointIdx)); + pickIds.emplace_back(static_cast(picking_.getPickingId(pointIdx))); } for (size_t frameIdx = startFrame; frameIdx <= endFrame; ++frameIdx) { diff --git a/misc/c3d/src/processors/c3dtomesh.cpp b/misc/c3d/src/processors/c3dtomesh.cpp index f4276abbc..1ce04691b 100644 --- a/misc/c3d/src/processors/c3dtomesh.cpp +++ b/misc/c3d/src/processors/c3dtomesh.cpp @@ -146,7 +146,8 @@ void C3DToMesh::process() { radii.emplace_back(markerRadius_.get()); // Unique ID for each point - pickIds.emplace_back(picking_.getPickingId(frameIdx * nbPoints + pointIdx)); + pickIds.emplace_back( + static_cast(picking_.getPickingId(frameIdx * nbPoints + pointIdx))); index.emplace_back(static_cast(frameIdx)); } diff --git a/misc/c3d/src/processors/c3dtransformpoints.cpp b/misc/c3d/src/processors/c3dtransformpoints.cpp index e4baa8066..800460e09 100644 --- a/misc/c3d/src/processors/c3dtransformpoints.cpp +++ b/misc/c3d/src/processors/c3dtransformpoints.cpp @@ -56,10 +56,10 @@ C3DTransformPoints::C3DTransformPoints() : Processor{} , inport_{"inport", ""_help} , outport_{"outport", ""_help} - , refs_{{{"ref1", "Referece 1", "phantom:skull1"}, - {"ref2", "Referece 2", "phantom:skull3"}, - {"ref3", "Referece 3", "phantom:skull2"}, - {"ref4", "Referece 4", "phantom:skull4"}}} + , refs_{{{"ref1", "Reference 1", "phantom:skull1"}, + {"ref2", "Reference 2", "phantom:skull3"}, + {"ref3", "Reference 3", "phantom:skull2"}, + {"ref4", "Reference 4", "phantom:skull4"}}} , refGroup_{"refGroup", "Reference Markers"} , transforms_("transformations", "Transformation Stack") { diff --git a/misc/computeshaderexamples/src/processors/computeshaderminmax.cpp b/misc/computeshaderexamples/src/processors/computeshaderminmax.cpp index a2e8b177a..b200934ad 100644 --- a/misc/computeshaderexamples/src/processors/computeshaderminmax.cpp +++ b/misc/computeshaderexamples/src/processors/computeshaderminmax.cpp @@ -242,12 +242,10 @@ void ComputeShaderMinMax::process() { const auto loglevel = diffDetected ? inviwo::LogLevel::Warn : inviwo::LogLevel::Info; if (!logErrorOnly_ || diffDetected) { - LogSpecial(inviwo::LogCentral::getPtr(), loglevel, - fmt::format("{} min/max: {:.8} / {:.8}", name, minTest.x, maxTest.x)); - LogSpecial(inviwo::LogCentral::getPtr(), loglevel, - fmt::format("ref min/max: {:.8} / {:.8}", refMin.x, refMax.x)); + log::message(loglevel, "{} min/max: {:.8} / {:.8}", name, minTest.x, maxTest.x); + log::message(loglevel, "ref min/max: {:.8} / {:.8}", refMin.x, refMax.x); if (diffDetected) { - LogInfo(fmt::format("delta min/max: {:.8} / {:.8}", deltaMin, deltaMax)); + log::info("delta min/max: {:.8} / {:.8}", deltaMin, deltaMax); } } }; diff --git a/misc/dataframeclustering/src/processors/dataframeclustering.cpp b/misc/dataframeclustering/src/processors/dataframeclustering.cpp index ff921a19a..87cd9ae2c 100644 --- a/misc/dataframeclustering/src/processors/dataframeclustering.cpp +++ b/misc/dataframeclustering/src/processors/dataframeclustering.cpp @@ -32,7 +32,7 @@ #include #include -#include +#include namespace inviwo { @@ -159,7 +159,7 @@ void DataFrameClustering::onDataFrameChange() { if (auto pp = dynamic_cast(p)) { return pp; } - throw inviwo::Exception("Property not a BoolProperty", IVW_CONTEXT); + throw inviwo::Exception("Property not a BoolProperty"); } else { auto cp = std::make_unique(id, header, columns_.size() < 2); cp->setSerializationMode(PropertySerializationMode::All); diff --git a/misc/graphviz/src/graphvizsettings.cpp b/misc/graphviz/src/graphvizsettings.cpp index 4ae773baf..4d5e2ebe1 100644 --- a/misc/graphviz/src/graphvizsettings.cpp +++ b/misc/graphviz/src/graphvizsettings.cpp @@ -158,7 +158,8 @@ void calculateLayout(StrBuffer& buff, ProcessorNetwork* net, const Func& func) { ivec2 center{0}; int count = 0; net->forEachProcessor([&](Processor* p) { - if (auto* n = agnode(G, const_cast(p->getIdentifier().c_str()), 0)) { + const std::string identifier{p->getIdentifier()}; + if (auto* n = agnode(G, const_cast(identifier.c_str()), 0)) { const auto& coord = ND_coord(n); center += ivec2{coord.x, -coord.y}; ++count; @@ -173,7 +174,8 @@ void calculateLayout(StrBuffer& buff, ProcessorNetwork* net, const Func& func) { const dvec2 offset = oldCenter - newCenter; net->forEachProcessor([&](Processor* p) { - if (auto* n = agnode(G, const_cast(p->getIdentifier().c_str()), 0)) { + const std::string identifier{p->getIdentifier()}; + if (auto* n = agnode(G, const_cast(identifier.c_str()), 0)) { const auto& coord = ND_coord(n); func(p, dvec2{coord.x, -coord.y} + offset); } diff --git a/misc/graphviz/src/processors/layoutmergetree.cpp b/misc/graphviz/src/processors/layoutmergetree.cpp index caf306595..b3a33e68b 100644 --- a/misc/graphviz/src/processors/layoutmergetree.cpp +++ b/misc/graphviz/src/processors/layoutmergetree.cpp @@ -128,12 +128,12 @@ void LayoutMergeTree::process() { mesh->reserveSizeInVertexBuffer(downsTyped->getSize()); pm_.resize(downsTyped->getSize()); - size_t startPickId = pm_.getPickingId(0); + const auto startPickId = static_cast(pm_.getPickingId(0)); const auto colorRange = colors->getRange(); std::unordered_map nodeToVertex; - for (auto&& [index, node] : util::enumerate(*downsTyped)) { + for (auto&& [index, node] : util::enumerate(*downsTyped)) { Agnode_t* n = agnode(G, const_cast(buff.replace("{}", node).c_str()), 0); if (n != nullptr) { auto& coord = ND_coord(n); diff --git a/misc/openmesh/include/inviwo/openmesh/utils/openmeshconverters.h b/misc/openmesh/include/inviwo/openmesh/utils/openmeshconverters.h index 640598c93..41e49a4c9 100644 --- a/misc/openmesh/include/inviwo/openmesh/utils/openmeshconverters.h +++ b/misc/openmesh/include/inviwo/openmesh/utils/openmeshconverters.h @@ -154,8 +154,7 @@ std::shared_ptr toInviwo(const OM_Mesh& mesh) { } } if (skipped) { - LogWarnCustom("openmeshutil::toInviwo", - "Skipped " << skipped << " faces since they weren't triangles"); + log::warn("Skipped {} faces since they weren't triangles", skipped); } return newmesh; } diff --git a/misc/openmesh/src/openmeshmodule.cpp b/misc/openmesh/src/openmeshmodule.cpp index 98937dce8..247a6ac52 100644 --- a/misc/openmesh/src/openmeshmodule.cpp +++ b/misc/openmesh/src/openmeshmodule.cpp @@ -61,7 +61,7 @@ OpenMeshModule::OpenMeshModule(InviwoApplication* app) : InviwoModule(app, "Open registerDataReader(std::make_unique()); registerDataWriter(std::make_unique()); - LogInfo("OpenMesh version: " << OM_GET_VER << "." << OM_GET_MAJ << "." << OM_GET_MIN); + log::info("OpenMesh version: {}.{}.{}", OM_GET_VER, OM_GET_MAJ, OM_GET_MIN); } } // namespace inviwo diff --git a/misc/openmesh/src/openmeshreader.cpp b/misc/openmesh/src/openmeshreader.cpp index 7ccef915f..552a42346 100644 --- a/misc/openmesh/src/openmeshreader.cpp +++ b/misc/openmesh/src/openmeshreader.cpp @@ -67,7 +67,7 @@ std::shared_ptr OpenMeshReader::readData(const std::filesystem::path& file TriMesh mesh; if (!OpenMesh::IO::read_mesh(mesh, filePath.string())) { - throw Exception(IVW_CONTEXT, "Failed reading mesh from disk {}", filePath); + throw Exception(SourceContext{}, "Failed reading mesh from disk {}", filePath); } mesh.request_vertex_normals(); mesh.request_face_normals(); diff --git a/misc/pythontools/depends.cmake b/misc/pythontools/depends.cmake index 343c242bb..2e137fc52 100644 --- a/misc/pythontools/depends.cmake +++ b/misc/pythontools/depends.cmake @@ -10,4 +10,4 @@ set(dependencies # By calling set(EnableByDefault ON) the module will be set to enabled # when initially being added to CMake. Default OFF. -set(EnableByDefault ON) \ No newline at end of file +set(EnableByDefault OFF) \ No newline at end of file diff --git a/misc/pythontools/tests/regression/camera_trajectory/Canvas.png b/misc/pythontools/tests/regression/camera_trajectory/Canvas.png index ebd2f7860..f94ed7a82 100644 Binary files a/misc/pythontools/tests/regression/camera_trajectory/Canvas.png and b/misc/pythontools/tests/regression/camera_trajectory/Canvas.png differ diff --git a/misc/vtk/src/processors/volumetovtk.cpp b/misc/vtk/src/processors/volumetovtk.cpp index 28ce8ef5f..34006b692 100644 --- a/misc/vtk/src/processors/volumetovtk.cpp +++ b/misc/vtk/src/processors/volumetovtk.cpp @@ -212,7 +212,8 @@ void VolumeToVTK::process() { auto scalars = vtkSmartPointer( vtkDataArray::CreateDataArray(vtkType(dataFormat->getId()))); scalars->SetNumberOfComponents(static_cast(dataFormat->getComponents())); - scalars->SetName(outport->getProcessor()->getIdentifier().c_str()); + const std::string identifier{outport->getProcessor()->getIdentifier()}; + scalars->SetName(identifier.c_str()); scalars->SetNumberOfTuples(glm::compMul(dim)); void* dstData = scalars->GetVoidPointer(0); diff --git a/tensorvis/tensorvisbase/include/inviwo/tensorvisbase/datastructures/invariantspace.h b/tensorvis/tensorvisbase/include/inviwo/tensorvisbase/datastructures/invariantspace.h index 1d4ab0558..c3e854cb7 100644 --- a/tensorvis/tensorvisbase/include/inviwo/tensorvisbase/datastructures/invariantspace.h +++ b/tensorvis/tensorvisbase/include/inviwo/tensorvisbase/datastructures/invariantspace.h @@ -63,8 +63,8 @@ struct IVW_MODULE_TENSORVISBASE_API InvariantSpace { } template - void addAxis(const tensor::MetaDataType* metaData, const std::string& name = "") { - identifiers_.push_back(name.empty() ? metaData->getDisplayName() : name); + void addAxis(const tensor::MetaDataType* metaData, std::string_view name = "") { + identifiers_.push_back(name.empty() ? metaData->getDisplayName() : std::string{name}); metaDataTypes_.push_back(metaData->type_); minmax_.push_back({{metaData->getMinMax().first, metaData->getMinMax().second}}); diff --git a/vectorvis/integrallinefiltering/include/inviwo/integrallinefiltering/algorithm/uniformspherepartitioning.h b/vectorvis/integrallinefiltering/include/inviwo/integrallinefiltering/algorithm/uniformspherepartitioning.h index bf70e4715..22443774d 100644 --- a/vectorvis/integrallinefiltering/include/inviwo/integrallinefiltering/algorithm/uniformspherepartitioning.h +++ b/vectorvis/integrallinefiltering/include/inviwo/integrallinefiltering/algorithm/uniformspherepartitioning.h @@ -103,7 +103,7 @@ class UniformSpherePartitioning { */ UniformSpherePartitioning(const size_t segments = 20) { if (segments == 0) { - throw Exception("Zero segments not allowed", IVW_CONTEXT); + throw Exception("Zero segments not allowed"); } else if (segments == 1) { collars_.emplace_back(glm::pi(), 1); return; diff --git a/vectorvis/integrallinefiltering/include/inviwo/integrallinefiltering/processors/integrallinestodataframe.h b/vectorvis/integrallinefiltering/include/inviwo/integrallinefiltering/processors/integrallinestodataframe.h index d58cfbcad..833b19e1f 100644 --- a/vectorvis/integrallinefiltering/include/inviwo/integrallinefiltering/processors/integrallinestodataframe.h +++ b/vectorvis/integrallinefiltering/include/inviwo/integrallinefiltering/processors/integrallinestodataframe.h @@ -111,17 +111,17 @@ class IVW_MODULE_INTEGRALLINEFILTERING_API IntegralLinesToDataFrame : public Pro template void createFunction(std::vector& funcs, DataFrame& dataFrame, - std::vector percentiles, std::string name, C toFloat) { + std::vector percentiles, std::string_view name, C toFloat) { std::vector* avg = nullptr; std::vector* sds = nullptr; if (avg_.get()) { - avg = &dataFrame.addColumn(name + " μ") + avg = &dataFrame.addColumn(fmt::format("{} μ", name)) ->getTypedBuffer() ->getEditableRAMRepresentation() ->getDataContainer(); } if (sd_.get()) { - sds = &dataFrame.addColumn(name + " σ") + sds = &dataFrame.addColumn(fmt::format("{} σ", name)) ->getTypedBuffer() ->getEditableRAMRepresentation() ->getDataContainer(); @@ -129,13 +129,13 @@ class IVW_MODULE_INTEGRALLINEFILTERING_API IntegralLinesToDataFrame : public Pro std::vector*> percentilesColumns; for (auto p : percentiles) { percentilesColumns.push_back( - &dataFrame.addColumn(name + " (p:" + std::to_string(p) + ")") + &dataFrame.addColumn(fmt::format("{} (p:{})", name, p)) ->getTypedBuffer() ->getEditableRAMRepresentation() ->getDataContainer()); } funcs.push_back([&](const IntegralLine& line) { - auto& vec = line.getMetaData(Property::getDisplayName()); + auto& vec = line.getMetaData(std::string{Property::getDisplayName()}); std::vector values; std::transform(vec.begin() + 1, vec.end() - 1, std::back_inserter(values), [&](const auto& v) { diff --git a/vectorvis/integrallinefiltering/src/processors/integrallinestodataframe.cpp b/vectorvis/integrallinefiltering/src/processors/integrallinestodataframe.cpp index d552552b2..31bcab949 100644 --- a/vectorvis/integrallinefiltering/src/processors/integrallinestodataframe.cpp +++ b/vectorvis/integrallinefiltering/src/processors/integrallinestodataframe.cpp @@ -108,12 +108,12 @@ void IntegralLinesToDataFrame::MetaDataSettings::initFunctions( double d; while (iss >> d) { if (d < 0) { - throw Exception(fmt::format("Percentile cant be negative (got: {})", d), IVW_CONTEXT); + throw Exception(SourceContext{}, "Percentile cant be negative (got: {})", d); } if (d > 100) { - throw Exception(fmt::format("Percentile cant needs to be less than 100 (got: {})", d), - IVW_CONTEXT); + throw Exception(SourceContext{}, "Percentile cant needs to be less than 100 (got: {})", + d); } if (d > 1) d /= 100; // from percent to ratio percentiles.push_back(d); @@ -136,7 +136,7 @@ void IntegralLinesToDataFrame::MetaDataSettings::initFunctions( df = &dataFrame](auto ramT) { using T = typename util::PrecisionValueType; if (useMagnitude_.get()) { - createFunction(funcs, *df, percentiles, name + "", [c](const T& v) -> float { + createFunction(funcs, *df, percentiles, name, [c](const T& v) -> float { float l = 0; for (size_t i = 0; i < c; i++) { l += static_cast(util::glmcomp(v, i) * util::glmcomp(v, i)); @@ -145,24 +145,24 @@ void IntegralLinesToDataFrame::MetaDataSettings::initFunctions( }); } if (x_.get()) { - createFunction(funcs, *df, percentiles, name + "-x", [](const T& v) -> float { - return static_cast(util::glmcomp(v, 0)); - }); + createFunction( + funcs, *df, percentiles, fmt::format("{}-x", name), + [](const T& v) -> float { return static_cast(util::glmcomp(v, 0)); }); } if (y_.get()) { - createFunction(funcs, *df, percentiles, name + "-y", [](const T& v) -> float { - return static_cast(util::glmcomp(v, 1)); - }); + createFunction( + funcs, *df, percentiles, fmt::format("{}-y", name), + [](const T& v) -> float { return static_cast(util::glmcomp(v, 1)); }); } if (z_.get()) { - createFunction(funcs, *df, percentiles, name + "-w", [](const T& v) -> float { - return static_cast(util::glmcomp(v, 2)); - }); + createFunction( + funcs, *df, percentiles, fmt::format("{}-w", name), + [](const T& v) -> float { return static_cast(util::glmcomp(v, 2)); }); } if (w_.get()) { - createFunction(funcs, *df, percentiles, name + "-z", [](const T& v) -> float { - return static_cast(util::glmcomp(v, 3)); - }); + createFunction( + funcs, *df, percentiles, fmt::format("{}-z", name), + [](const T& v) -> float { return static_cast(util::glmcomp(v, 3)); }); } }); }