Skip to content

Commit

Permalink
ENH: a different shot at refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
fedorov committed May 5, 2017
1 parent 97467eb commit 925b282
Show file tree
Hide file tree
Showing 16 changed files with 544 additions and 39 deletions.
4 changes: 3 additions & 1 deletion include/dcmqi/Helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

using namespace std;


namespace dcmqi {


Expand Down Expand Up @@ -50,6 +49,9 @@ namespace dcmqi {
static void checkValidityOfFirstSrcImage(DcmSegmentation *segdoc);

static CodeSequenceMacro* createNewCodeSequence(const string& code, const string& designator, const string& meaning);

static OFString generateUID();
static OFString getTagAsOFString(DcmDataset*, DcmTagKey);
};

}
Expand Down
12 changes: 10 additions & 2 deletions include/dcmqi/ImageVolume.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ namespace dcmqi {

// Maintain properties of the image volume
// Attributes ara parallel to those of itkImageData, but limited to what we need for the task of conversion,
// and the class is not templated over the pixel type
// and the class is not templated over the pixel type, since we may not know the pixel type
// at the time class is instantiated.
//
// Initially, limit implementation and support to just Float32 used by the original PM converter.

class ImageVolume {
public:
// pixel types that are relevant for the types of objects we want to support
Expand Down Expand Up @@ -47,7 +51,11 @@ namespace dcmqi {
protected:
int initializeDirections(FGInterface &);
int initializeExtent(FGInterface &);
bool getDeclaredSpacing(FGInterface&);
bool getDeclaredSliceSpacing(FGInterface&);
bool getCalculatedSliceSpacing();

int setDirections(vnl_vector<double> rowDirection, vnl_vector<double> columnDirection, vnl_vector<double> sliceDirection);
int setOrigin(vnl_vector<double>);

private:

Expand Down
47 changes: 47 additions & 0 deletions include/dcmqi/ImageVolumeGeometry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// Created by Andrey Fedorov on 3/11/17.
//

#ifndef DCMQI_IMAGEVOLUMEGEOMETRY_H
#define DCMQI_IMAGEVOLUMEGEOMETRY_H


#include <vnl/vnl_vector.h>
#include <itkVector.h>
#include <itkSize.h>
#include <itkImage.h>

class ImageVolumeGeometry {

friend class MultiframeObject;
friend class ParametricMapObject;

public:
typedef itk::Vector<double,3> DoubleVectorType;
typedef itk::Size<3> SizeType;

// implementation of the image volume geometry
// NB: duplicated from MultiframeObject!
typedef unsigned char DummyPixelType;
typedef itk::Image<DummyPixelType, 3> DummyImageType;
typedef DummyImageType::PointType PointType;
typedef DummyImageType::DirectionType DirectionType;

ImageVolumeGeometry();

int setSpacing(DoubleVectorType);
int setOrigin(PointType);
int setExtent(SizeType);
int setDirections(DirectionType);

protected:
// use vnl_vector to simplify support of vector calculations
vnl_vector<double> rowDirection, columnDirection, sliceDirection;
vnl_vector<double> origin;
vnl_vector<unsigned> extent;
vnl_vector<double> spacing;

};


#endif //DCMQI_IMAGEVOLUMEGEOMETRY_H
1 change: 1 addition & 0 deletions include/dcmqi/JSONSegmentationMetaInformationHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace dcmqi {
void readSegmentAttributes();

Json::Value createAndGetSegmentAttributes();

};

}
Expand Down
7 changes: 5 additions & 2 deletions include/dcmqi/MultiframeConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ namespace dcmqi {

class MultiframeConverter {
public:
virtual int convert();
//virtual int convert();
MultiframeConverter(){
};



protected:
static IODGeneralEquipmentModule::EquipmentInfo getEquipmentInfo();
static IODEnhGeneralEquipmentModule::EquipmentInfo getEnhEquipmentInfo();
static ContentIdentificationMacro createContentIdentificationInformation(JSONMetaInformationHandlerBase &metaInfo);
Expand Down
131 changes: 131 additions & 0 deletions include/dcmqi/MultiframeObject.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//
// Created by Andrey Fedorov on 3/11/17.
//

#ifndef DCMQI_MULTIFRAMEOBJECT_H
#define DCMQI_MULTIFRAMEOBJECT_H


#include <dcmtk/dcmfg/fgpixmsr.h>
#include <dcmtk/dcmfg/fgplanor.h>
#include <dcmtk/dcmfg/fgplanpo.h>
#include <dcmtk/dcmfg/fgfracon.h>
#include <dcmtk/dcmfg/fgderimg.h>
#include <dcmtk/dcmiod/modfloatingpointimagepixel.h>

#include <itkImage.h>
#include <json/json.h>

#include <vector>
#include <dcmtk/dcmiod/modequipment.h>
#include <dcmtk/dcmiod/modenhequipment.h>
#include <dcmtk/dcmiod/modmultiframedimension.h>

#include "dcmqi/Exceptions.h"
#include "dcmqi/ImageVolumeGeometry.h"

using namespace std;
/*
* Class to support conversion between DICOM and ITK representations
* of multiframe objects
*
*
*/
class MultiframeObject {

public:

// initialization from DICOM is always from the dataset(s)
// that encode DICOM representation, optionally augmented by the
// derivation datasets that potentially can be helpful in some
// situations.
int initializeFromDICOM(std::vector<DcmDataset*> sourceDataset);
int initializeFromDICOM(std::vector<DcmDataset*> sourceDatasets,
std::vector<DcmDataset*> derivationDatasets);

// initialization from ITK will be specific to the derived types,
// although there will be some common initialization of the metadata

// Output is always a single DcmDataset, since this is a multiframe
// object
DcmDataset* getDcmDataset() const;
Json::Value getMetaDataJson() const;

// get ITK representation will be specific to the derived classes,
// since the type of the ITK image and the number of ITK images is
// different between PM and SEG

protected:

// Helpers to convert to dummy image type to support common
// implementation of the image volume geometry
typedef unsigned char DummyPixelType;
typedef itk::Image<DummyPixelType, 3> DummyImageType;
typedef DummyImageType::PointType PointType;
typedef DummyImageType::DirectionType DirectionType;

int initializeMetaDataFromString(const std::string&);
// what this function does depends on whether we are coming from
// DICOM or from ITK. No parameters, since all it does is exchange
// between DICOM and MetaData
int initializeEquipmentInfo();
int initializeContentIdentification();

// from ITK
int initializeVolumeGeometryFromITK(DummyImageType::Pointer);

virtual int initializeCompositeContext();
virtual bool metaDataIsComplete();

// List of tags, and FGs they belong to, for initializing dimensions module
int initializeDimensions(IODMultiframeDimensionModule&, std::vector<std::pair<DcmTag, DcmTag> >);

// constants to describe original representation of the data being converted
enum {
DICOM_REPR = 0,
ITK_REPR
};
int sourceRepresentationType;

// TODO: abstract this into a different class, which would help with:
// - checking for presence of attributes
// - handling of defaults (in the future, initialized from the schema?)
// - simplifying common access patterns (access to the Code tuples)
Json::Value metaDataJson;

// Multiframe DICOM object representation
DcmDataset* dcmRepresentation;

ImageVolumeGeometry volumeGeometry;

// DcmDataset(s) that hold the original representation of the
// object, when the sourceRepresentationType == DICOM_REPR
OFVector<DcmDataset*> sourceDcmDatasets;

// Common components present in the derived classes
// TODO: check whether both PM and SEG use Enh module or not, refactor based on that
IODEnhGeneralEquipmentModule::EquipmentInfo equipmentInfoModule;
ContentIdentificationMacro contentIdentificationMacro;
IODMultiframeDimensionModule dimensionsModule;

// DcmDataset(s) that were used to derive the object
// Probably will only be populated when sourceRepresentationType == ITK_REPR
// Purpose of those:
// 1) initialize derivation derivationImageFG (ITK->)
// 2) initialize CommonInstanceReferenceModule (ITK->)
// 3) initialize common attributes (ITK->)
OFVector<DcmDataset*> derivationDcmDatasets;

// Functional groups common to all MF objects:
// - Shared
FGPixelMeasures pixelMeasuresFG;
FGPlaneOrientationPatient planeOrientationPatientFG;
// - Per-frame
OFVector<FGPlanePosPatient> planePosPatientFGList;
OFVector<FGFrameContent> frameContentFGList;
OFVector<FGDerivationImage> derivationImageFGList;

};


#endif //DCMQI_MULTIFRAMEOBJECT_H
3 changes: 2 additions & 1 deletion include/dcmqi/ParametricMapConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ namespace dcmqi {
const string &metaData);
static pair <FloatImageType::Pointer, string> paramap2itkimage(DcmDataset *pmapDataset);

// do the conversion
// given one representation, generate the parallel one
int convert();

// get the result
Expand All @@ -75,6 +75,7 @@ namespace dcmqi {
// these are the items we will need in the process of conversion
vector<DcmDataset*> referencedDatasets;
string metaData;

};

}
Expand Down
62 changes: 62 additions & 0 deletions include/dcmqi/ParametricMapObject.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// Created by Andrey Fedorov on 3/11/17.
//

#ifndef DCMQI_PARAMETRICMAPOBJECT_H
#define DCMQI_PARAMETRICMAPOBJECT_H


#include <dcmtk/dcmfg/fgframeanatomy.h>
#include <dcmtk/dcmfg/fgidentpixeltransform.h>
#include <dcmtk/dcmfg/fgparametricmapframetype.h>
#include <dcmtk/dcmfg/fgrealworldvaluemapping.h>
#include <dcmtk/dcmpmap/dpmparametricmapiod.h>
#include <itkCastImageFilter.h>

#include "MultiframeObject.h"

/*
*
*/
class ParametricMapObject : public MultiframeObject {
public:
typedef IODFloatingPointImagePixelModule::value_type Float32PixelType;
typedef itk::Image<Float32PixelType, 3> Float32ITKImageType;

// metadata is mandatory, since not all of the attributes can be present
// in the derivation DcmDataset(s)
int initializeFromITK(Float32ITKImageType::Pointer, const string&);
// metadata is mandatory, optionally, derivation DcmDataset(s) can
// help
int initializeFromITK(Float32ITKImageType::Pointer, const string&,
std::vector<DcmDataset*>);

int updateMetaDataFromDICOM(std::vector<DcmDataset*>);

protected:
typedef itk::CastImageFilter<Float32ITKImageType,DummyImageType>
Float32ToDummyCasterType;

int initializeVolumeGeometry();
int createParametricMap();
int initializeDimensionsModule();
int initializeCompositeContext();

// Functional groups initialization

// Functional groups specific to PM:
// - Shared
FGFrameAnatomy frameAnatomyFG;
FGIdentityPixelValueTransformation identityPixelValueTransformationFG;
FGParametricMapFrameType parametricMapFrameTypeFG;
FGRealWorldValueMapping rwvmFG;

// Data containers specific to this object
Float32ITKImageType::Pointer itkImage;

private:
DPMParametricMapIOD* parametricMap;
};


#endif //DCMQI_PARAMETRICMAPOBJECT_H
16 changes: 16 additions & 0 deletions include/dcmqi/SegmentationImageObject.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// Created by Andrey Fedorov on 3/11/17.
//

#ifndef DCMQI_SEGMENTATIONIMAGEOBJECT_H
#define DCMQI_SEGMENTATIONIMAGEOBJECT_H


#include "MultiframeObject.h"

class SegmentationImageObject : public MultiframeObject {

};


#endif //DCMQI_SEGMENTATIONIMAGEOBJECT_H
3 changes: 1 addition & 2 deletions libsrc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

#-----------------------------------------------------------------------------
set(ADDITIONAL_SRCS DICOMFrame.cpp ../include/dcmqi/DICOMFrame.h ImageVolume.cpp ../include/dcmqi/ImageVolume.h SegmentVolume.cpp ../include/dcmqi/SegmentVolume.h)
>>>>>>> WIP: refactoring of the multiframe conversion implementation
set(ADDITIONAL_SRCS DICOMFrame.cpp ../include/dcmqi/DICOMFrame.h ImageVolume.cpp ../include/dcmqi/ImageVolume.h SegmentVolume.cpp ../include/dcmqi/SegmentVolume.h MultiframeObject.cpp ../include/dcmqi/MultiframeObject.h ParametricMapObject.cpp ../include/dcmqi/ParametricMapObject.h SegmentationImageObject.cpp ../include/dcmqi/SegmentationImageObject.h ImageVolumeGeometry.cpp ../include/dcmqi/ImageVolumeGeometry.h)

if(DCMQI_BUILTIN_JSONCPP)
list(APPEND ADDITIONAL_SRCS
Expand Down
11 changes: 11 additions & 0 deletions libsrc/Helper.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

// DCMQI includes
#include <dcmqi/QIICRUIDs.h>
#include "dcmqi/Helper.h"

namespace dcmqi {
Expand Down Expand Up @@ -340,5 +341,15 @@ namespace dcmqi {
return new CodeSequenceMacro(code.c_str(), designator.c_str(), meaning.c_str());
}

OFString Helper::generateUID() {
char charUID[128];
dcmGenerateUniqueIdentifier(charUID, QIICR_UID_ROOT);
return OFString(charUID);
}

OFString Helper::getTagAsOFString(DcmDataset* dcm, DcmTagKey tag) {
OFString value;
CHECK_COND(dcm->findAndGetOFString(tag, value));
return value;
}
}
Loading

0 comments on commit 925b282

Please sign in to comment.