Skip to content

Commit 797769e

Browse files
committed
Merge branch 'rel_4.0'
2 parents 476b643 + 525a333 commit 797769e

File tree

13 files changed

+261
-57
lines changed

13 files changed

+261
-57
lines changed

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#.git

CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ ENDIF()
9090
# These four fields should be modified when versions change
9191
SET(SNAP_VERSION_MAJOR 4)
9292
SET(SNAP_VERSION_MINOR 0)
93-
SET(SNAP_VERSION_PATCH 0)
93+
SET(SNAP_VERSION_PATCH 1)
9494
SET(SNAP_VERSION_QUALIFIER "")
9595

9696
# These fields should also be modified each time
97-
SET(SNAP_VERSION_RELEASE_DATE "20230220")
98-
SET(SNAP_VERSION_RELEASE_DATE_FORMATTED "February 20, 2023")
97+
SET(SNAP_VERSION_RELEASE_DATE "20230320")
98+
SET(SNAP_VERSION_RELEASE_DATE_FORMATTED "March 20, 2023")
9999

100100
# This field should only change when the format of the settings files changes
101101
# in a non backwards-compatible way

GUI/Model/RegistrationModel.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,7 @@ ::ResliceMovingImage(InterpolationMethod method)
934934
roi.SetInterpolationMethod(method);
935935
roi.SetROI(m_Driver->GetCurrentImageData()->GetMain()->GetBufferedRegion());
936936
SmartPtr<ImageWrapperBase> reslice =
937-
moving->ExtractROI(roi, m_Parent->GetProgressCommand());
937+
moving->ExtractROI4D(roi, m_Parent->GetProgressCommand());
938938

939939
// Give it a nickname
940940
reslice->SetCustomNickname(std::string("resliced ") + moving->GetNickname());

GUI/Qt/Windows/InterpolateLabelsDialog.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ color: gray;</string>
163163
<item>
164164
<widget class="QStackedWidget" name="stackedWidget">
165165
<property name="currentIndex">
166-
<number>1</number>
166+
<number>0</number>
167167
</property>
168168
<widget class="QWidget" name="morphoptions">
169169
<layout class="QVBoxLayout" name="verticalLayout_2">

GUI/Renderer/OrientationWidget/Reorient/AxesWidget.cxx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,14 @@ AxesWidget::AxesWidget()
2121
m_pvtkAxesActor->SetYAxisLabelText( "y" );
2222
m_pvtkAxesActor->SetZAxisLabelText( "z" );
2323

24+
// Turn off lighting to prevent normal flipping effect
25+
m_pvtkAxesActor->GetXAxisShaftProperty()->SetLighting(false);
26+
m_pvtkAxesActor->GetYAxisShaftProperty()->SetLighting(false);
27+
m_pvtkAxesActor->GetZAxisShaftProperty()->SetLighting(false);
28+
2429
m_pvtkAxesActor->SetTotalLength( 1.5, 1.5, 1.5 );
25-
m_pvtkAxesActor->SetCylinderRadius( 0.500 * m_pvtkAxesActor->GetCylinderRadius() );
26-
m_pvtkAxesActor->SetConeRadius ( 1.025 * m_pvtkAxesActor->GetConeRadius() );
30+
m_pvtkAxesActor->SetCylinderRadius( 0.250 * m_pvtkAxesActor->GetCylinderRadius() );
31+
m_pvtkAxesActor->SetConeRadius ( 0.750 * m_pvtkAxesActor->GetConeRadius() );
2732
m_pvtkAxesActor->SetSphereRadius ( 1.500 * m_pvtkAxesActor->GetSphereRadius() );
2833

2934
m_pvtkAxesActor->SetConeResolution(100);

GUI/Renderer/OrientationWidget/Reorient/PolyDataAlgorithm2ActorPipe.cxx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <vtkObjectFactory.h>
33
#include <vtkActor.h>
44
#include <vtkPolyDataMapper.h>
5+
#include <vtkProperty.h>
56

67
#include "PolyDataAlgorithm2ActorPipe.h"
78

@@ -13,6 +14,7 @@ PolyDataAlgorithm2ActorPipe::PolyDataAlgorithm2ActorPipe()
1314
m_pvtkPolyDataMapper = vtkSmartPointer < vtkPolyDataMapper >::New();
1415
m_pvtkActor = vtkSmartPointer < vtkActor >::New();
1516
m_pvtkActor->SetMapper(m_pvtkPolyDataMapper);
17+
m_pvtkActor->GetProperty()->SetLighting(false);
1618

1719
}
1820

GUI/Renderer/OrientationWidget/Reorient/ScanningROI.cxx

Lines changed: 15 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -159,71 +159,36 @@ void ScanningROI::setSpacing(double aarrdbXYZ[3])
159159

160160
void ScanningROI::Update()
161161
{
162+
m_pAxesWidget->GetAxesActor()->SetPosition(- m_dbGraphicScale / 2.0, -m_dbGraphicScale / 2.0, -m_dbGraphicScale / 2.0);
163+
m_pAxesWidget->SetLabels("i", "j", "k");
164+
m_pAxesWidget->SetColors(AxesWidget::m_arrdbColRed, AxesWidget::m_arrdbColGreen, AxesWidget::m_arrdbColBlue);
165+
m_pAxesWidget->SetLengths(2.0 * m_dbGraphicScale);
162166

163-
vtkSmartPointer < vtkMatrix4x4 > pMatrix4x4DirectionsAccompanying =
164-
vtkSmartPointer < vtkMatrix4x4 >::New();
165-
pMatrix4x4DirectionsAccompanying->Identity();
166-
167-
if(m_pMatrix4x4Directions->Determinant() > 0.0)
168-
{
169-
m_pAxesWidget->GetAxesActor()->SetPosition(- m_dbGraphicScale / 2.0, -m_dbGraphicScale / 2.0, -m_dbGraphicScale / 2.0);
170-
m_pAxesWidget->SetLabels("i", "j", "k");
171-
m_pAxesWidget->SetColors(AxesWidget::m_arrdbColRed, AxesWidget::m_arrdbColGreen, AxesWidget::m_arrdbColBlue);
172-
}
173-
else
174-
{
175-
//m_pAxesWidget->GetAxesActor()->SetPosition(m_dbGraphicScale / 2.0, m_dbGraphicScale / 2.0, m_dbGraphicScale / 2.0);
176-
177-
pMatrix4x4DirectionsAccompanying->SetElement(0, 0, -1.0);
178-
pMatrix4x4DirectionsAccompanying->SetElement(1, 1, 0.0);
179-
pMatrix4x4DirectionsAccompanying->SetElement(1, 2, -1.0);
180-
pMatrix4x4DirectionsAccompanying->SetElement(2, 1, -1.0);
181-
pMatrix4x4DirectionsAccompanying->SetElement(2, 2, 0.0);
182-
183-
changeOrientation3x3(m_pMatrix4x4Directions);
184-
m_pAxesWidget->SetLabels("i", "k", "j");
185-
m_pAxesWidget->SetColors(AxesWidget::m_arrdbColRed, AxesWidget::m_arrdbColBlue, AxesWidget::m_arrdbColGreen);
186-
}
187-
188-
m_pAxesWidget->GetAxesActor()->SetUserMatrix(pMatrix4x4DirectionsAccompanying);
189-
190-
//m_pMatrix4x4Directions->DeepCopy(apMatrix4x4);
191-
//widget->GetProp3D()->SetUserTransform(t);
192167
vtkSmartPointer < vtkTransform > pTransform = vtkSmartPointer < vtkTransform >::New();
193168
pTransform->SetMatrix(m_pMatrix4x4Directions);
194-
vtkLinearTransform *pLinearTransform = m_pvtkAssembly->GetUserTransform();
195-
if(pLinearTransform == 0)
196-
m_pvtkAssembly->SetUserTransform(pTransform);
197-
else
198-
pLinearTransform->DeepCopy(pTransform);
199-
200-
m_pAxesWidget->SetLengths(2.0 * m_dbGraphicScale);
169+
m_pvtkAssembly->SetUserTransform(pTransform);
201170

202171
int nI;
203172
int nPlanesNr = getPlanesNr();
204173
double dbDelta = m_dbGraphicScale / ((double)(nPlanesNr - 1));
205174
for(nI = 0; nI < nPlanesNr; nI++)
206175
{
207176
//First, create the transparent planes
208-
double arrdbOrigin[4] = {0.0, 0.0, 0.0, 1.0},
209-
arrdbP1[4] = {0.0, 0.0, 0.0, 1.0},
210-
arrdbP2[4] = {0.0, 0.0, 0.0, 1.0};
177+
double arrdbOrigin[4] = {0.0, 0.0, 0.0, 1.0};
178+
double arrdbP1[4] = {0.0, 0.0, 0.0, 1.0};
179+
double arrdbP2[4] = {0.0, 0.0, 0.0, 1.0};
211180

212181
arrdbOrigin[0] = - m_dbGraphicScale / 2.0;
213-
arrdbOrigin[1] = - m_dbGraphicScale / 2.0;
182+
arrdbOrigin[1] = - m_dbGraphicScale / 2.0;
214183
arrdbOrigin[2] = dbDelta * nI - ((int)(((double)nPlanesNr) / 2.0)) * dbDelta;
215184

216-
arrdbP1[0] = m_dbGraphicScale / 2.0;
217-
arrdbP1[1] = - m_dbGraphicScale / 2.0;
218-
arrdbP1[2] = arrdbOrigin[2];
219-
220-
arrdbP2[0] = - m_dbGraphicScale / 2.0;
221-
arrdbP2[1] = m_dbGraphicScale / 2.0;
222-
arrdbP2[2] = arrdbOrigin[2];
185+
arrdbP1[0] = m_dbGraphicScale / 2.0;
186+
arrdbP1[1] = - m_dbGraphicScale / 2.0;
187+
arrdbP1[2] = arrdbOrigin[2];
223188

224-
//pMatrix4x4DirectionsAccompanying->MultiplyDoublePoint(arrdbOrigin);
225-
//pMatrix4x4DirectionsAccompanying->MultiplyDoublePoint(arrdbP2);
226-
//pMatrix4x4DirectionsAccompanying->MultiplyDoublePoint(arrdbP2);
189+
arrdbP2[0] = - m_dbGraphicScale / 2.0;
190+
arrdbP2[1] = m_dbGraphicScale / 2.0;
191+
arrdbP2[2] = arrdbOrigin[2];
227192

228193
Pairs_Plane_Pipe & ppp = m_arrpPairsPP_Axial[nI];
229194
vtkSmartPointer < vtkPlaneSource > pPlaneSource = ppp.m_p_PlaneSource;

GUI/Renderer/OrientationWidget/Reorient/ScanningROI.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class vtkAssembly;
88
class vtkPlaneSource;
99
class vtkCaptionActor2D;
1010
class vtkTubeFilter;
11+
class vtkMatrix4x4;
1112

1213
class AxesWidget;
1314
class PolyDataAlgorithm2ActorPipe;

Logic/ImageWrapper/ImageWrapper.cxx

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#include "AffineTransformHelper.h"
7575
#include "InputSelectionImageFilter.h"
7676
#include "MetaDataAccess.h"
77+
#include "AllPurposeProgressAccumulator.h"
7778

7879
#include <vnl/vnl_inverse.h>
7980
#include <iostream>
@@ -2371,6 +2372,39 @@ ::ExtractROI(const SNAPSegmentationROISettings &roi,
23712372
return retptr;
23722373
}
23732374

2375+
template<class TTraits, class TBase>
2376+
SmartPtr<ImageWrapperBase>
2377+
ImageWrapper<TTraits,TBase>
2378+
::ExtractROI4D(const SNAPSegmentationROISettings &roi,
2379+
itk::Command *progressCommand) const
2380+
{
2381+
Image4DPointer newImage = this->DeepCopyRegion4D(roi, progressCommand);
2382+
2383+
// Initialize the new wrapper
2384+
typedef typename TTraits::WrapperType WrapperType;
2385+
SmartPtr<WrapperType> newWrapper = WrapperType::New();
2386+
2387+
// Copy the display to anatomy geometry to the new wrapper
2388+
IRISDisplayGeometry temp = m_DisplayGeometry;
2389+
newWrapper->SetDisplayGeometry(temp);
2390+
2391+
// Assign the new image to the new wrapper
2392+
newWrapper->SetImage4D(newImage);
2393+
newWrapper->SetNativeMapping(this->GetNativeMapping());
2394+
2395+
// Appropriate the default nickname?
2396+
newWrapper->SetDefaultNickname(this->GetDefaultNickname());
2397+
newWrapper->SetAlpha(this->GetAlpha());
2398+
newWrapper->SetSticky(this->IsSticky());
2399+
2400+
// We should not copy the user-assigned metadata. It's up to the
2401+
// user what should propagate to the ROI
2402+
2403+
// Cast to base class
2404+
SmartPtr<ImageWrapperBase> retptr = newWrapper.GetPointer();
2405+
return retptr;
2406+
}
2407+
23742408

23752409
template<class TTraits, class TBase>
23762410
typename ImageWrapper<TTraits,TBase>::ImagePointer
@@ -2391,6 +2425,85 @@ ::DeepCopyRegion(const SNAPSegmentationROISettings &roi,
23912425
force_resampling, progressCommand);
23922426
}
23932427

2428+
template<class TTraits, class TBase>
2429+
typename ImageWrapper<TTraits,TBase>::Image4DPointer
2430+
ImageWrapper<TTraits,TBase>
2431+
::DeepCopyRegion4D(const SNAPSegmentationROISettings &roi,
2432+
itk::Command *progressCommand) const
2433+
{
2434+
// If the image in this wrapper is not the same as the reference space,
2435+
// we must force resampling to occur
2436+
bool force_resampling = !this->IsSlicingOrthogonal();
2437+
2438+
Image4DPointer outImg = Image4DType::New();
2439+
const unsigned int nT = this->GetNumberOfTimePoints();
2440+
2441+
// Set the spacing, origin, direction for the last coordinate
2442+
auto spacing_4d = m_Image4D->GetSpacing();
2443+
auto origin_4d = m_Image4D->GetOrigin();
2444+
auto dir_4d = m_Image4D->GetDirection();
2445+
auto region_4d = m_Image4D->GetBufferedRegion();
2446+
2447+
// Create a 4d buffer
2448+
typedef typename Image4DType::PixelContainer::Element ElementType;
2449+
typedef typename Image4DType::PixelContainer::ElementIdentifier ElementIdType;
2450+
auto size_3d = roi.GetROI().GetSize();
2451+
auto nC = m_Image4D->GetNumberOfComponentsPerPixel();
2452+
ElementIdType buffer3dSize = size_3d[0] * size_3d[1] * size_3d[2] * nC;
2453+
ElementIdType buffer3dSizeInBytes = buffer3dSize * sizeof(ElementType);
2454+
ElementIdType buffer4dSize = buffer3dSize * nT;
2455+
ElementType *buffer4d = new ElementType[buffer4dSize];
2456+
ElementType *pCrntTPStart = buffer4d; // starting mem location of the current tp
2457+
2458+
typedef ImageWrapperPartialSpecializationTraits<ImageType, Image4DType> Specialization;
2459+
2460+
// Prepare progress accumulation
2461+
SmartPtr<AllPurposeProgressAccumulator> progress = AllPurposeProgressAccumulator::New();
2462+
progress->AddObserver(itk::ProgressEvent(), progressCommand);
2463+
typedef AllPurposeProgressAccumulator::CommandPointer CmdPtr;
2464+
std::vector<CmdPtr> TPCommand;
2465+
2466+
for (unsigned int t = 0u; t < nT; ++t)
2467+
{
2468+
TPCommand.push_back(progress->RegisterITKSourceViaCommand(1));
2469+
}
2470+
2471+
typename ImageType::Pointer tpResliced, tpImg;
2472+
2473+
for (unsigned int t = 0u; t < nT; ++t)
2474+
{
2475+
tpImg = this->GetImageByTimePoint(t);
2476+
tpResliced = Specialization::CopyRegion(tpImg, m_ReferenceSpace, this->GetITKTransform(),
2477+
roi, force_resampling, TPCommand[t]);
2478+
2479+
auto buffer3d = tpResliced->GetPixelContainer()->GetBufferPointer();
2480+
memcpy(pCrntTPStart, buffer3d, buffer3dSizeInBytes);
2481+
pCrntTPStart += buffer3dSize; // Increment pointer to next tp start
2482+
}
2483+
2484+
// use the last resliced tp image to configure the output origin/spacing/direction/region
2485+
// -- this only configures the first three dimensions
2486+
for (int j = 0; j < 3; ++j)
2487+
{
2488+
region_4d.SetIndex(j, tpResliced->GetBufferedRegion().GetIndex(j));
2489+
region_4d.SetSize(j, tpResliced->GetBufferedRegion().GetSize(j));
2490+
spacing_4d[j] = tpResliced->GetSpacing()[j];
2491+
origin_4d[j] = tpResliced->GetOrigin()[j];
2492+
for(unsigned int k = 0; k < 3; k++)
2493+
dir_4d(j,k) = tpResliced->GetDirection() (j,k);
2494+
}
2495+
2496+
outImg->SetRegions(region_4d);
2497+
outImg->SetSpacing(spacing_4d);
2498+
outImg->SetOrigin(origin_4d);
2499+
outImg->SetDirection(dir_4d);
2500+
outImg->SetNumberOfComponentsPerPixel(tpResliced->GetNumberOfComponentsPerPixel());
2501+
2502+
// set the constructed 4d buffer to output's pixel container
2503+
outImg->GetPixelContainer()->SetImportPointer(buffer4d, buffer4dSize, true);
2504+
return outImg;
2505+
}
2506+
23942507

23952508

23962509

Logic/ImageWrapper/ImageWrapper.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,13 @@ class ImageWrapper : public TBase
487487
virtual SmartPtr<ImageWrapperBase> ExtractROI(
488488
const SNAPSegmentationROISettings &roi, itk::Command *progressCommand) const ITK_OVERRIDE;
489489

490+
/**
491+
* Extract a 3d region of interest from all time points in the image wrapper,
492+
* as a new wrapper of the same type
493+
*/
494+
virtual SmartPtr<ImageWrapperBase> ExtractROI4D(
495+
const SNAPSegmentationROISettings &roi, itk::Command *progressCommand) const ITK_OVERRIDE;
496+
490497

491498
/**
492499
* This method is used to perform a deep copy of a region of this image
@@ -496,6 +503,14 @@ class ImageWrapper : public TBase
496503
virtual ImagePointer DeepCopyRegion(const SNAPSegmentationROISettings &roi,
497504
itk::Command *progressCommand = NULL) const;
498505

506+
/**
507+
* This method is used to perform a deep copy of a 3D region of each time points
508+
* of this image into another 4D image, potentially resampling the region to use a
509+
* different voxel size
510+
*/
511+
virtual Image4DPointer DeepCopyRegion4D(const SNAPSegmentationROISettings &roi,
512+
itk::Command *progressCommand = NULL) const;
513+
499514

500515
/**
501516
* Get an iterator for traversing the image. The iterator is initialized

0 commit comments

Comments
 (0)