/* * * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by * * OFFIS e.V. * R&D Division Health * Escherweg 2 * D-26121 Oldenburg, Germany * * * Module: dcmfg * * Author: Michael Onken * * Purpose: Class for managing Real World Value Mapping Functional Group * */ #include "dcmtk/config/osconfig.h" #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmfg/fgrealworldvaluemapping.h" #include "dcmtk/dcmiod/iodutil.h" const OFString FGRealWorldValueMapping::RWVMItem::m_ModuleName = "RealWorldValueMappingItemMacro"; FGRealWorldValueMapping::FGRealWorldValueMapping() : FGBase(DcmFGTypes::EFG_REALWORLDVALUEMAPPING) , m_Items() { } FGRealWorldValueMapping::~FGRealWorldValueMapping() { clearData(); } FGBase* FGRealWorldValueMapping::clone() const { FGRealWorldValueMapping* copy = new FGRealWorldValueMapping(); if (copy) { for (OFVector::const_iterator it = m_Items.begin(); it < m_Items.end(); it++) { if (*it == NULL) return NULL; FGRealWorldValueMapping::RWVMItem* item = (*it)->clone(); if (item == NULL) return NULL; copy->m_Items.push_back(item); } } return copy; } void FGRealWorldValueMapping::clearData() { DcmIODUtil::freeContainer(m_Items); } OFCondition FGRealWorldValueMapping::check() const { // More checks checks for 1C conditions could be added return EC_Normal; } int FGRealWorldValueMapping::compare(const FGBase& rhs) const { int result = FGBase::compare(rhs); if (result != 0) return result; const FGRealWorldValueMapping* myRhs = OFstatic_cast(const FGRealWorldValueMapping*, &rhs); if (!myRhs) return -1; // Compare all items, start with VM if (m_Items.size() < myRhs->m_Items.size()) return 1; else if (m_Items.size() > myRhs->m_Items.size()) return -1; for (size_t n = 0; m_Items.size(); n++) { result = m_Items[n]->compare(*(myRhs->m_Items[n])); if (result != 0) return result; } return result; } /// Read from Frame Content Sequence OFCondition FGRealWorldValueMapping::read(DcmItem& item) { clearData(); DcmIODUtil::readSubSequence( item, DCM_RealWorldValueMappingSequence, m_Items, "1-n", "1", "RealWorldValueMappingMacro"); return EC_Normal; } OFCondition FGRealWorldValueMapping::write(DcmItem& item) { // OFCondition result = createNewFGSequence(item, DCM_RealWorldValueMappingSequence, 0, seqItem); OFCondition result; DcmIODUtil::writeSubSequence( result, DCM_RealWorldValueMappingSequence, m_Items, item, "1-n", "1", "RealWorldValueMappingMacro"); return result; } OFVector& FGRealWorldValueMapping::getRealWorldValueMapping() { return m_Items; } // ----------------------------------------------------------- FGRealWorldValueMapping::RWVMItem::RWVMItem(IODComponent* parent) : IODComponent(parent) , m_MeasurementUnitsCode() , m_QuantityDefinitionSequence() { resetRules(); } FGRealWorldValueMapping::RWVMItem::RWVMItem(OFshared_ptr item, OFshared_ptr rules, IODComponent* parent) : IODComponent(item, rules, parent) , m_MeasurementUnitsCode() , m_QuantityDefinitionSequence() { resetRules(); } FGRealWorldValueMapping::RWVMItem::RWVMItem(const FGRealWorldValueMapping::RWVMItem& rhs) : IODComponent(rhs) , m_MeasurementUnitsCode(rhs.m_MeasurementUnitsCode) , m_QuantityDefinitionSequence() { OFVector::const_iterator it = rhs.m_QuantityDefinitionSequence.begin(); while (it != rhs.m_QuantityDefinitionSequence.end()) { ContentItemMacro* macro = new ContentItemMacro(**it); if (macro == NULL) { DCMFG_ERROR("Out of memory in copy constructor of FGRealWorldValueMapping::RWVMItem::RWVMItem"); return; } m_QuantityDefinitionSequence.push_back(macro); it++; } } FGRealWorldValueMapping::RWVMItem* FGRealWorldValueMapping::RWVMItem::clone() { return new FGRealWorldValueMapping::RWVMItem(*this); } FGRealWorldValueMapping::RWVMItem::~RWVMItem() { DcmIODUtil::freeContainer(m_QuantityDefinitionSequence); } OFString FGRealWorldValueMapping::RWVMItem::getName() const { return m_ModuleName; } int FGRealWorldValueMapping::RWVMItem::compare(const IODComponent& rhs) const { int result = IODComponent::compare(rhs); const FGRealWorldValueMapping::RWVMItem* myRhs = OFstatic_cast(const FGRealWorldValueMapping::RWVMItem*, &rhs); if (!myRhs) return -1; if (result == 0) result = m_MeasurementUnitsCode.compare(*myRhs); if (result == 0) { size_t rhsSize = myRhs->m_QuantityDefinitionSequence.size(); size_t thisSize = m_QuantityDefinitionSequence.size(); if (thisSize < rhsSize) return -1; else if (thisSize > rhsSize) return 1; OFVector::const_iterator it = m_QuantityDefinitionSequence.begin(); OFVector::const_iterator rhsIt = myRhs->m_QuantityDefinitionSequence.begin(); while (it != m_QuantityDefinitionSequence.end() && (result == 0)) { result = (*it)->compare(*(*rhsIt)); it++; } } return result; } void FGRealWorldValueMapping::RWVMItem::resetRules() { // parameters are tag, VM, type. Overwrite old rules if any. m_Rules->addRule(new IODRule(DCM_RealWorldValueFirstValueMapped, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); m_Rules->addRule(new IODRule(DCM_RealWorldValueLastValueMapped, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); m_Rules->addRule( new IODRule(DCM_DoubleFloatRealWorldValueFirstValueMapped, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); m_Rules->addRule( new IODRule(DCM_DoubleFloatRealWorldValueLastValueMapped, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); m_Rules->addRule(new IODRule(DCM_RealWorldValueIntercept, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); m_Rules->addRule(new IODRule(DCM_RealWorldValueSlope, "1", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); m_Rules->addRule(new IODRule(DCM_RealWorldValueLUTData, "1-n", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); m_Rules->addRule(new IODRule(DCM_LUTExplanation, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); m_Rules->addRule(new IODRule(DCM_LUTLabel, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); m_Rules->addRule(new IODRule(DCM_MeasurementUnitsCodeSequence, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); m_Rules->addRule(new IODRule(DCM_QuantityDefinitionSequence, "1-n", "3", getName(), DcmIODTypes::IE_INSTANCE), OFTrue); } OFCondition FGRealWorldValueMapping::RWVMItem::read(DcmItem& source, const OFBool clearOldData) { DcmIODUtil::readSingleItem(source, DCM_MeasurementUnitsCodeSequence, m_MeasurementUnitsCode, "1", m_ModuleName); DcmIODUtil::readSubSequence(source, DCM_QuantityDefinitionSequence, m_QuantityDefinitionSequence, m_Rules->getByTag(DCM_QuantityDefinitionSequence)); return IODComponent::read(source, clearOldData); } OFCondition FGRealWorldValueMapping::RWVMItem::write(DcmItem& destination) { OFCondition result; DcmIODUtil::writeSingleItem( result, DCM_MeasurementUnitsCodeSequence, m_MeasurementUnitsCode, *m_Item, "1", m_ModuleName); DcmIODUtil::writeSubSequence(result, DCM_QuantityDefinitionSequence, m_QuantityDefinitionSequence, *m_Item, m_Rules->getByTag(DCM_QuantityDefinitionSequence)); if (result.good()) result = IODComponent::write(destination); return result; } OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueFirstValueMapped(Sint32& value, const unsigned long pos) const { return getUSorSS(*m_Item, DCM_RealWorldValueFirstValueMapped, pos, value); } OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueLastValueMapped(Sint32& value, const unsigned long pos) const { return getUSorSS(*m_Item, DCM_RealWorldValueLastValueMapped, pos, value); } OFCondition FGRealWorldValueMapping::RWVMItem::getDoubleFloatRealWorldValueFirstValueMapped(Float64& value, const unsigned long pos) const { return (*m_Item).findAndGetFloat64(DCM_DoubleFloatRealWorldValueFirstValueMapped, value, pos); } OFCondition FGRealWorldValueMapping::RWVMItem::getDoubleFloatRealWorldValueLastValueMapped(Float64& value, const unsigned long pos) const { return (*m_Item).findAndGetFloat64(DCM_DoubleFloatRealWorldValueFirstValueMapped, value, pos); } OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueLUTData(OFVector& values) const { DcmElement* elem = NULL; OFCondition result = m_Item->findAndGetElement(DCM_RealWorldValueLUTData, elem); if (result.good()) { size_t numValues = elem->getNumberOfValues(); for (size_t n = 0; n < numValues; n++) { Float64 value; result = elem->getFloat64(value, OFstatic_cast(unsigned long, n)); if (result.good()) values.push_back(value); } } return result; } OFCondition FGRealWorldValueMapping::RWVMItem::getRealWorldValueLUTData(Float64& value, const unsigned long pos) const { return m_Item->findAndGetFloat64(DCM_RealWorldValueLUTData, value, pos); } OFCondition FGRealWorldValueMapping::RWVMItem::getLUTExplanation(OFString& value, const signed long pos) const { return DcmIODUtil::getStringValueFromItem(DCM_LUTExplanation, *m_Item, value, pos); } OFCondition FGRealWorldValueMapping::RWVMItem::getLUTLabel(OFString& value, const signed long pos) const { return DcmIODUtil::getStringValueFromItem(DCM_LUTLabel, *m_Item, value, pos); } CodeSequenceMacro& FGRealWorldValueMapping::RWVMItem::getMeasurementUnitsCode() { return m_MeasurementUnitsCode; } OFVector& FGRealWorldValueMapping::RWVMItem::getEntireQuantityDefinitionSequence() { return m_QuantityDefinitionSequence; } OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueFirstValueMappedUnsigned(const Uint16 value, const OFBool checkValue) { (void)checkValue; DcmUnsignedShort* us = new DcmUnsignedShort(DCM_RealWorldValueFirstValueMapped); OFCondition result = us->putUint16(value); if (result.good()) result = m_Item->insert(us, OFTrue /* replace old */); if (result.bad()) delete us; return result; } OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueFirstValueMappedSigned(const Sint16& value, const OFBool checkValue) { (void)checkValue; DcmSignedShort* ss = new DcmSignedShort(DCM_RealWorldValueFirstValueMapped); OFCondition result = ss->putSint16(value); if (result.good()) result = m_Item->insert(ss, OFTrue /* replace old */); if (result.bad()) delete ss; return result; } OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueLastValueMappedSigned(const Sint16& value, const OFBool checkValue) { (void)checkValue; DcmSignedShort* ss = new DcmSignedShort(DCM_RealWorldValueLastValueMapped); OFCondition result = ss->putSint16(value); if (result.good()) result = m_Item->insert(ss, OFTrue /* replace old */); if (result.bad()) delete ss; return result; } OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueLastValueMappedUnsigned(const Uint16 value, const OFBool checkValue) { (void)checkValue; DcmUnsignedShort* us = new DcmUnsignedShort(DCM_RealWorldValueLastValueMapped); OFCondition result = us->putUint16(value); if (result.good()) result = m_Item->insert(us, OFTrue /* replace old */); if (result.bad()) delete us; return result; } OFCondition FGRealWorldValueMapping::RWVMItem::setDoubleFloatRealWorldValueFirstValueMapped(const Float64 value, const OFBool checkValue) { (void)checkValue; return (*m_Item).putAndInsertFloat64(DCM_DoubleFloatRealWorldValueFirstValueMapped, value); } OFCondition FGRealWorldValueMapping::RWVMItem::setDoubleFloatRealWorldValueLastValueMapped(const Float64 value, const OFBool checkValue) { (void)checkValue; return (*m_Item).putAndInsertFloat64(DCM_DoubleFloatRealWorldValueLastValueMapped, value); } OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueIntercept(const Float64 value, const OFBool checkValue) { (void)checkValue; return m_Item->putAndInsertFloat64(DCM_RealWorldValueIntercept, value); } OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueSlope(const Float64 value, const OFBool checkValue) { (void)checkValue; return m_Item->putAndInsertFloat64(DCM_RealWorldValueSlope, value); } OFCondition FGRealWorldValueMapping::RWVMItem::setRealWorldValueLUTData(const OFVector& value, const OFBool checkValue) { (void)checkValue; DcmElement* elem = NULL; OFCondition result = m_Item->findAndGetElement(DCM_RealWorldValueLUTData, elem); if (result.good()) { size_t count = value.size(); for (size_t n = 0; n < count; n++) { if (result.good()) result = elem->putFloat64(value[n], OFstatic_cast(unsigned long, n)); } } return result; } OFCondition FGRealWorldValueMapping::RWVMItem::setLUTExplanation(const OFString& value, const OFBool checkValue) { OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal; if (result.good()) result = m_Item->putAndInsertOFStringArray(DCM_LUTExplanation, value); return result; } OFCondition FGRealWorldValueMapping::RWVMItem::setLUTLabel(const OFString& value, const OFBool checkValue) { OFCondition result = (checkValue) ? DcmShortString::checkStringValue(value, "1") : EC_Normal; if (result.good()) result = m_Item->putAndInsertOFStringArray(DCM_LUTLabel, value); return result; } OFCondition FGRealWorldValueMapping::RWVMItem::getUSorSS(DcmItem& item, const DcmTagKey& key, const unsigned long pos, Sint32& value) { DcmElement* elem = NULL; OFCondition result = item.findAndGetElement(key, elem); if (result.good() && elem) { DcmEVR evr = elem->getVR(); if (evr == EVR_US) { Uint16 num; result = elem->getUint16(num, pos); if (result.good()) value = num; } else if (evr == EVR_SS) { Sint16 num; result = elem->getSint16(num, pos); if (result.good()) value = num; } else { DCMFG_ERROR("Illegal VR " << DcmVR(evr).getVRName() << " for tag " << DcmTag(key).getTagName()); result = EC_InvalidVR; } } return result; }