Commit c5d94b6f authored by Floris Berendsen's avatar Floris Berendsen
Browse files

ENH EIP: deduce component selection from neighbor components

parent 70e48754
......@@ -54,43 +54,66 @@ Overlord::Configure()
<< " Components could not be uniquely selected" << std::endl << std::endl;
bool anySelectionNarrowed(true);
for (auto const & name : nonUniqueComponentNames)
{
// check all components that accept from component "name"
for (auto const & outgoingName : this->m_Blueprint->GetOutputNames(name))
while (anySelectionNarrowed){
anySelectionNarrowed = false;
for (auto const & name : nonUniqueComponentNames)
{
// if the accepting component is also not uniquely selected, we do not try to check all valid combinations, since this would make the handshake logic too complicated
if (std::find(nonUniqueComponentNames.begin(), nonUniqueComponentNames.end(), outgoingName) != nonUniqueComponentNames.end())
// check all components that accept from component "name"
for (auto const & outgoingName : this->m_Blueprint->GetOutputNames(name))
{
Blueprint::ParameterMapType connectionProperties = this->m_Blueprint->GetConnection(name, outgoingName);
ComponentBase::InterfaceCriteriaType interfaceCriteria;
//TODO:
//1: this lambda function converts the blueprint properties: map<string,vector<string>> to interfacecriteria: map<string,string>, consider redesign.
//2: connection blueprint->addConnection("myfirstnode","mysecondnode",{{}}) creates connectionProperties {"",[]} which is not an empty map.
std::for_each(connectionProperties.begin(), connectionProperties.end(), [interfaceCriteria](Blueprint::ParameterMapType::value_type kv) mutable { if (kv.second.size() > 0) interfaceCriteria[kv.first] = kv.second[0]; });
auto outgoingComponent = this->m_ComponentSelectorContainer[outgoingName]->GetComponent();
this->m_ComponentSelectorContainer[name]->RequireProvidingInterfaceTo(outgoingComponent, interfaceCriteria);
// if the accepting component is also not uniquely selected, we do not try to check all valid combinations, since this would make the handshake logic too complicated
if (std::find(nonUniqueComponentNames.begin(), nonUniqueComponentNames.end(), outgoingName) == nonUniqueComponentNames.end())
{
Blueprint::ParameterMapType connectionProperties = this->m_Blueprint->GetConnection(name, outgoingName);
ComponentBase::InterfaceCriteriaType interfaceCriteria;
//TODO:
//1: this lambda function converts the blueprint properties: map<string,vector<string>> to interfacecriteria: map<string,string>, consider redesign.
//2: connection blueprint->addConnection("myfirstnode","mysecondnode",{{}}) creates connectionProperties {"",[]} which is not an empty map.
std::for_each(connectionProperties.begin(), connectionProperties.end(), [interfaceCriteria](Blueprint::ParameterMapType::value_type kv) mutable { if (kv.second.size() > 0) interfaceCriteria[kv.first] = kv.second[0]; });
auto outgoingComponent = this->m_ComponentSelectorContainer[outgoingName]->GetComponent();
const unsigned int beforeCriteria = this->m_ComponentSelectorContainer[name]->NumberOfComponents();
this->m_ComponentSelectorContainer[name]->RequireProvidingInterfaceTo(outgoingComponent, interfaceCriteria);
const unsigned int afterCriteria = this->m_ComponentSelectorContainer[name]->NumberOfComponents();
std::cout << afterCriteria << " " << name << " components can Provide to " << outgoingName << std::endl;
if (beforeCriteria > afterCriteria)
{
anySelectionNarrowed = true;
}
}
}
}
// check all components that provide to component "name"
for (auto const & incomingName : this->m_Blueprint->GetInputNames(name))
{
// if the providing component is also not uniquely selected, we do not try to check all valid combinations, since this would make the handshake logic too complicated
if (std::find(nonUniqueComponentNames.begin(), nonUniqueComponentNames.end(), incomingName) != nonUniqueComponentNames.end())
// check all components that provide to component "name"
for (auto const & incomingName : this->m_Blueprint->GetInputNames(name))
{
Blueprint::ParameterMapType connectionProperties = this->m_Blueprint->GetConnection(incomingName, name);
ComponentBase::InterfaceCriteriaType interfaceCriteria;
//TODO:
//1: this lambda function converts the blueprint properties: map<string,vector<string>> to interfacecriteria: map<string,string>, consider redesign.
//2: connection blueprint->addConnection("myfirstnode","mysecondnode",{{}}) creates connectionProperties {"",[]} which is not an empty map.
std::for_each(connectionProperties.begin(), connectionProperties.end(), [interfaceCriteria](Blueprint::ParameterMapType::value_type kv) mutable { if (kv.second.size() > 0) interfaceCriteria[kv.first] = kv.second[0]; });
auto incomingComponent = this->m_ComponentSelectorContainer[incomingName]->GetComponent();
this->m_ComponentSelectorContainer[name]->RequireAcceptingInterfaceFrom(incomingComponent, interfaceCriteria);
// if the providing component is also not uniquely selected, we do not try to check all valid combinations, since this would make the handshake logic too complicated
if (std::find(nonUniqueComponentNames.begin(), nonUniqueComponentNames.end(), incomingName) == nonUniqueComponentNames.end())
{
//std::cout << "Check which " << name << " component can Accept from " << incomingName << std::endl;
Blueprint::ParameterMapType connectionProperties = this->m_Blueprint->GetConnection(incomingName, name);
ComponentBase::InterfaceCriteriaType interfaceCriteria;
//TODO:
//1: this lambda function converts the blueprint properties: map<string,vector<string>> to interfacecriteria: map<string,string>, consider redesign.
//2: connection blueprint->addConnection("myfirstnode","mysecondnode",{{}}) creates connectionProperties {"",[]} which is not an empty map.
std::for_each(connectionProperties.begin(), connectionProperties.end(), [interfaceCriteria](Blueprint::ParameterMapType::value_type kv) mutable { if (kv.second.size() > 0) interfaceCriteria[kv.first] = kv.second[0]; });
auto incomingComponent = this->m_ComponentSelectorContainer[incomingName]->GetComponent();
const unsigned int beforeCriteria = this->m_ComponentSelectorContainer[name]->NumberOfComponents();
this->m_ComponentSelectorContainer[name]->RequireAcceptingInterfaceFrom(incomingComponent, interfaceCriteria);
const unsigned int afterCriteria = this->m_ComponentSelectorContainer[name]->NumberOfComponents();
std::cout << afterCriteria << " " << name << " components can Accept from " << incomingName << std::endl;
if (beforeCriteria > afterCriteria)
{
anySelectionNarrowed = true;
}
}
}
}
}
this->m_isConfigured = true;
......@@ -101,7 +124,7 @@ Overlord::Configure()
std::cout << std::endl << "These Nodes need more criteria: " << std::endl;
for( const auto & nonUniqueComponentName : nonUniqueComponentNames )
{
std::cout << nonUniqueComponentName << std::endl;
std::cout << this->m_ComponentSelectorContainer[nonUniqueComponentName]->NumberOfComponents() << " " << nonUniqueComponentName << std::endl;
}
return false;
}
......
......@@ -27,6 +27,11 @@
#include "selxSSDMetric3rdPartyComponent.h"
#include "selxSSDMetric4thPartyComponent.h"
#include "selxRegisterComponentFactoriesByTypeList.h"
#include "selxDefaultComponents.h"
#include "gtest/gtest.h"
namespace selx
......@@ -51,6 +56,8 @@ public:
ComponentFactory< SSDMetric3rdPartyComponent >::RegisterOneFactory();
ComponentFactory< SSDMetric4thPartyComponent >::RegisterOneFactory();
/** make example blueprint configuration */
blueprint = Blueprint::New();
ParameterMapType metricComponentParameters;
......@@ -65,7 +72,6 @@ public:
ParameterMapType metric2TransformConnectionParameters;
metric2TransformConnectionParameters[ "NameOfInterface" ] = { "TransformedImageInterface" };
//TODO: check direction
blueprint->AddConnection( "Transform", "Metric", metric2TransformConnectionParameters );
}
......@@ -104,4 +110,128 @@ TEST_F( OverlordTest, Connect )
bool success;
EXPECT_NO_THROW( success = overlord->ConnectComponents() );
}
TEST_F(OverlordTest, DeduceComponentsFromConnections)
{
using CustomRegisterComponents = TypeList <
DisplacementFieldItkImageFilterSinkComponent< 3, double >,
DisplacementFieldItkImageFilterSinkComponent< 3, float >,
ItkImageSinkComponent< 3, double >,
ItkImageSinkComponent< 3, float >,
ItkImageSourceFixedComponent< 3, float >,
ItkImageSourceMovingComponent< 3, float >,
ItkImageSourceFixedComponent< 3, double >,
ItkImageSourceMovingComponent< 3, double >,
ItkImageRegistrationMethodv4Component< 3, double >,
ItkImageRegistrationMethodv4Component< 3, float >,
ItkANTSNeighborhoodCorrelationImageToImageMetricv4Component< 3, double >,
ItkMeanSquaresImageToImageMetricv4Component< 3, double >,
ItkANTSNeighborhoodCorrelationImageToImageMetricv4Component< 3, float >,
ItkMeanSquaresImageToImageMetricv4Component< 3, float >,
ItkGradientDescentOptimizerv4Component< double >,
ItkAffineTransformComponent< double, 3 >,
ItkGaussianExponentialDiffeomorphicTransformComponent< double, 3 >,
ItkGaussianExponentialDiffeomorphicTransformParametersAdaptorsContainerComponent< 3, double >,
ItkTransformDisplacementFilterComponent< 3, float, double >,
ItkTransformDisplacementFilterComponent< 3, double, double >,
ItkResampleFilterComponent< 3, float, double >,
ItkResampleFilterComponent< 3, double, double >> ;
using RegisterComponents = list_append< DefaultComponents, CustomRegisterComponents>::type;
RegisterFactoriesByTypeList<RegisterComponents>::Register();
blueprint = Blueprint::New(); // override old blueprint
blueprint->AddComponent("RegistrationMethod", { { "NameOfClass", { "ItkImageRegistrationMethodv4Component" } },
{ "Dimensionality", { "3" } },
{ "NumberOfLevels", { "2" } },
{ "ShrinkFactorsPerLevel", { "2", "1" } } });
blueprint->AddComponent("FixedImageSource", { { "NameOfClass", { "ItkImageSourceFixedComponent" } },
{ "Dimensionality", { "3" } },
{ "PixelType", { "float" } } });
ParameterMapType component2Parameters;
component2Parameters["NameOfClass"] = { "ItkImageSourceMovingComponent" };
component2Parameters["Dimensionality"] = { "3" }; // should be derived from the inputs
blueprint->AddComponent("MovingImageSource", component2Parameters);
ParameterMapType component3Parameters;
component3Parameters["NameOfClass"] = { "ItkImageSinkComponent" };
component3Parameters["Dimensionality"] = { "3" }; // should be derived from the outputs
blueprint->AddComponent("ResultImageSink", component3Parameters);
blueprint->AddComponent("ResultDisplacementFieldSink", { { "NameOfClass", { "DisplacementFieldItkImageFilterSinkComponent" } },
{ "Dimensionality", { "3" } },
{ "PixelType", { "float" } } });
ParameterMapType component5Parameters;
component5Parameters["NameOfClass"] = { "ItkANTSNeighborhoodCorrelationImageToImageMetricv4Component" };
component5Parameters["Dimensionality"] = { "3" }; // should be derived from the inputs
blueprint->AddComponent("Metric", component5Parameters);
ParameterMapType component6Parameters;
component6Parameters["NameOfClass"] = { "ItkTransformDisplacementFilterComponent" };
component6Parameters["Dimensionality"] = { "3" }; // should be derived from the outputs
blueprint->AddComponent("TransformDisplacementFilter", component6Parameters);
ParameterMapType component7Parameters;
component7Parameters["NameOfClass"] = { "ItkGradientDescentOptimizerv4Component" };
component7Parameters["NumberOfIterations"] = { "1" };
blueprint->AddComponent("Optimizer", component7Parameters);
blueprint->AddComponent("ResampleFilter", { { "NameOfClass", { "ItkResampleFilterComponent" } },
{ "Dimensionality", { "3" } } });
blueprint->AddComponent("Transform", { { "NameOfClass", { "ItkGaussianExponentialDiffeomorphicTransformComponent" } },
{ "Dimensionality", { "3" } } });
blueprint->AddComponent("TransformResolutionAdaptor", { { "NameOfClass", { "ItkGaussianExponentialDiffeomorphicTransformParametersAdaptorsContainerComponent" } },
{ "Dimensionality", { "3" } },
{ "ShrinkFactorsPerLevel", { "2", "1" } } });
blueprint->AddComponent("Controller", { { "NameOfClass", { "RegistrationControllerComponent" } } });
ParameterMapType connection1Parameters;
connection1Parameters["NameOfInterface"] = { "itkImageFixedInterface" };
blueprint->AddConnection("FixedImageSource", "RegistrationMethod", connection1Parameters);
ParameterMapType connection2Parameters;
connection2Parameters["NameOfInterface"] = { "itkImageMovingInterface" };
blueprint->AddConnection("MovingImageSource", "RegistrationMethod", connection2Parameters);
ParameterMapType connection3Parameters;
connection3Parameters["NameOfInterface"] = { "itkImageInterface" };
blueprint->AddConnection("ResampleFilter", "ResultImageSink", connection3Parameters);
ParameterMapType connection4Parameters;
connection4Parameters["NameOfInterface"] = { "DisplacementFieldItkImageSourceInterface" };
blueprint->AddConnection("TransformDisplacementFilter", "ResultDisplacementFieldSink", connection4Parameters);
ParameterMapType connection5Parameters;
connection5Parameters["NameOfInterface"] = { "itkMetricv4Interface" };
blueprint->AddConnection("Metric", "RegistrationMethod", connection5Parameters);
blueprint->AddConnection("FixedImageSource", "Transform", { {} });
blueprint->AddConnection("Transform", "RegistrationMethod", { {} });
blueprint->AddConnection("FixedImageSource", "TransformResolutionAdaptor", { {} });
blueprint->AddConnection("TransformResolutionAdaptor", "RegistrationMethod", { {} });
blueprint->AddConnection("Optimizer", "RegistrationMethod", { {} });
blueprint->AddConnection("RegistrationMethod", "TransformDisplacementFilter", { {} });
blueprint->AddConnection("FixedImageSource", "TransformDisplacementFilter", { {} });
blueprint->AddConnection("RegistrationMethod", "ResampleFilter", { {} });
blueprint->AddConnection("FixedImageSource", "ResampleFilter", { {} });
blueprint->AddConnection("MovingImageSource", "ResampleFilter", { {} });
blueprint->AddConnection("RegistrationMethod", "Controller", { {} }); //RunRegistrationInterface
blueprint->AddConnection("ResampleFilter", "Controller", { {} }); //ReconnectTransformInterface
blueprint->AddConnection("TransformDisplacementFilter", "Controller", { {} }); //ReconnectTransformInterface
std::unique_ptr< Overlord > overlord(new Overlord());
overlord->SetBlueprint(blueprint);
bool allUniqueComponents;
EXPECT_NO_THROW(allUniqueComponents = overlord->Configure());
EXPECT_TRUE(allUniqueComponents);
}
} // namespace selx
......@@ -31,6 +31,8 @@
#include "selxItkMeanSquaresImageToImageMetricv4.h"
#include "selxItkGradientDescentOptimizerv4.h"
#include "selxItkGaussianExponentialDiffeomorphicTransform.h"
#include "selxItkGaussianExponentialDiffeomorphicTransformParametersAdaptorsContainerComponent.h"
#include "selxItkAffineTransform.h"
#include "selxItkTransformDisplacementFilter.h"
#include "selxItkResampleFilter.h"
#include "selxRegistrationController.h"
......@@ -52,6 +54,8 @@ using DefaultComponents = selx::TypeList<
ItkMeanSquaresImageToImageMetricv4Component< 2, float >,
ItkGradientDescentOptimizerv4Component< double >,
ItkGaussianExponentialDiffeomorphicTransformComponent< double, 2 >,
ItkGaussianExponentialDiffeomorphicTransformParametersAdaptorsContainerComponent< 2, double >,
ItkAffineTransformComponent< double, 2 >,
ItkTransformDisplacementFilterComponent< 2, float, double >,
ItkResampleFilterComponent< 2, float, double >,
RegistrationControllerComponent< >,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment