| 150 | } |
| 151 | |
| 152 | void mitk::TotalSegmentatorTool::DoUpdatePreview(const Image *inputAtTimeStep, |
| 153 | const Image * /*oldSegAtTimeStep*/, |
| 154 | MultiLabelSegmentation *previewImage, |
| 155 | TimeStepType timeStep) |
| 156 | { |
| 157 | m_LastErrorMessage.clear(); |
| 158 | |
| 159 | // The base UpdatePreview catches itk::ExceptionObject (what mitkThrow produces) |
| 160 | // and only forwards it to ErrorMessage, which no GUI here listens to. So catch |
| 161 | // every failure locally and record it in m_LastErrorMessage; the GUI shows that |
| 162 | // instead of the generic "cancelled or produced no result". |
| 163 | try |
| 164 | { |
| 165 | // Programmer-guarantee guards: the GUI always injects both before running. |
| 166 | if (m_ExecutablePath.empty()) |
| 167 | mitkThrow() << "TotalSegmentator executable path is not set."; |
| 168 | |
| 169 | if (!m_CommandRunner) |
| 170 | mitkThrow() << "No command runner is set for the TotalSegmentator tool."; |
| 171 | |
| 172 | if (m_MitkTempDir.empty()) |
| 173 | m_MitkTempDir = IOUtil::CreateTemporaryDirectory("mitk-XXXXXX"); |
| 174 | |
| 175 | const std::string inDir = IOUtil::CreateTemporaryDirectory("totalseg-in-XXXXXX", m_MitkTempDir); |
| 176 | const std::string outDir = IOUtil::CreateTemporaryDirectory("totalseg-out-XXXXXX", m_MitkTempDir); |
| 177 | |
| 178 | // Remove this run's scratch directories on every exit path; only the parent |
| 179 | // m_MitkTempDir persists (until the destructor), so repeated runs in one tool |
| 180 | // activation do not pile up input copies and outputs. |
| 181 | const ScopedDir inDirGuard{inDir}; |
| 182 | const ScopedDir outDirGuard{outDir}; |
| 183 | |
| 184 | std::ofstream tmpStream; |
| 185 | const std::string inputImagePath = IOUtil::CreateTemporaryFile(tmpStream, "XXXXXX.nii.gz", inDir); |
| 186 | tmpStream.close(); |
| 187 | |
| 188 | const std::string outputImagePath = outDir + IOUtil::GetDirectorySeparator() + "segmentation.nii.gz"; |
| 189 | |
| 190 | IOUtil::Save(inputAtTimeStep, inputImagePath); |
| 191 | |
| 192 | const auto args = this->BuildArguments(inputImagePath, outputImagePath); |
| 193 | const bool success = m_CommandRunner(m_ExecutablePath, args); |
| 194 | |
| 195 | if (!success) |
| 196 | return; // Cancelled by the user or the process failed: leave the preview empty. |
| 197 | |
| 198 | if (!fs::exists(outputImagePath)) |
| 199 | mitkThrow() << "TotalSegmentator finished but did not produce an output file."; |
| 200 | |
| 201 | Image::Pointer outputImage = IOUtil::Load<Image>(outputImagePath); |
| 202 | outputImage->SetGeometry(inputAtTimeStep->GetGeometry()); |
| 203 | |
| 204 | auto outputBuffer = mitk::MultiLabelSegmentation::New(); |
| 205 | outputBuffer->InitializeByLabeledImage(outputImage); |
| 206 | |
| 207 | this->MapLabelsToSegmentation(outputBuffer, previewImage); |
| 208 | previewImage->UpdateGroupImage( |
| 209 | previewImage->GetActiveLayer(), outputBuffer->GetGroupImage(outputBuffer->GetActiveLayer()), timeStep); |
nothing calls this directly
no test coverage detected