LCOV - code coverage report
Current view: top level - ml - Layer.cpp (source / functions) Hit Total Coverage
Test: test_coverage.info.cleaned Lines: 54 83 65.1 %
Date: 2022-07-06 02:47:47 Functions: 13 18 72.2 %

          Line data    Source code
       1             : #include <sstream>
       2             : #include <algorithm>
       3             : #include "TypeCasts.hpp"
       4             : 
       5             : #include "Layer.h"
       6             : 
       7             : namespace elsa::ml
       8             : {
       9             :     template <typename data_t>
      10           9 :     Layer<data_t>::Layer(LayerType layerType, const std::string& name,
      11             :                          int requiredNumberOfDimensions, int allowedNumberOfInputs,
      12             :                          bool isTrainable)
      13             :         : requiredNumberOfDimensions_(requiredNumberOfDimensions),
      14             :           allowedNumberOfInputs_(allowedNumberOfInputs),
      15             :           layerType_(layerType),
      16             :           numberOfTrainableParameters_(0),
      17           9 :           isTrainable_(isTrainable)
      18             :     {
      19           9 :         globalIndex_ = staticGlobalIndex_++;
      20             : 
      21             :         // If no name is set we use a (lowercase) string representation of the
      22             :         // layer-type together with the layer's global index
      23           9 :         if (name == "") {
      24          10 :             std::stringstream ss;
      25           5 :             std::string typeString = detail::getEnumMemberAsString(layerType);
      26           5 :             std::transform(std::begin(typeString), std::end(typeString), std::begin(typeString),
      27          27 :                            [](unsigned char c) { return std::tolower(c); });
      28           5 :             ss << typeString << "_" << globalIndex_;
      29           5 :             name_ = ss.str();
      30             :         } else {
      31           4 :             name_ = name;
      32             :         }
      33             : 
      34           9 :         if (this->isTrainable())
      35           3 :             staticGlobalIndex_++;
      36           9 :     }
      37             : 
      38             :     template <typename data_t>
      39           0 :     Layer<data_t>::Layer(const Layer& other)
      40           0 :         : globalIndex_(other.globalIndex_),
      41           0 :           layerType_(other.layerType_),
      42           0 :           name_(other.name_),
      43           0 :           outputDescriptor_(other.outputDescriptor_->clone())
      44             :     {
      45           0 :         for (std::size_t i = 0; i < other.inputDescriptors_.size(); ++i)
      46           0 :             inputDescriptors_.push_back(other.inputDescriptors_[i]->clone());
      47           0 :     }
      48             : 
      49             :     template <typename data_t>
      50           0 :     Layer<data_t>& Layer<data_t>::operator=(const Layer<data_t>& other)
      51             :     {
      52           0 :         if (this != &other) {
      53           0 :             globalIndex_ = other.globalIndex_;
      54           0 :             layerType_ = other.layerType_;
      55           0 :             name_ = other.name_;
      56           0 :             outputDescriptor_ = other.outputDescriptor_->clone();
      57           0 :             for (std::size_t i = 0; i < other.inputDescriptors_.size(); ++i)
      58           0 :                 inputDescriptors_.push_back(other.inputDescriptors_[i]->clone());
      59             :         }
      60           0 :         return *this;
      61             :     }
      62             : 
      63             :     template <typename data_t>
      64           1 :     LayerType Layer<data_t>::getLayerType() const
      65             :     {
      66           1 :         return layerType_;
      67             :     }
      68             : 
      69             :     template <typename data_t>
      70           4 :     std::string Layer<data_t>::getName() const
      71             :     {
      72           4 :         return name_;
      73             :     }
      74             : 
      75             :     template <typename data_t>
      76           9 :     void Layer<data_t>::setInputDescriptor(const VolumeDescriptor& inputDescriptor)
      77             :     {
      78           9 :         Layer<data_t>::checkNumberOfInputDimensions(inputDescriptor);
      79           8 :         inputDescriptors_.push_back(inputDescriptor.clone());
      80           8 :     }
      81             : 
      82             :     template <typename data_t>
      83           2 :     void Layer<data_t>::setInput(Layer<data_t>* layer)
      84             :     {
      85             :         // Get graph from global state
      86           2 :         auto& graph = detail::State<data_t>::getGraph();
      87             :         // Add edge from layer to this and fill the graph nodes
      88           2 :         graph.addEdge(layer->getGlobalIndex(), globalIndex_);
      89           2 :         graph.setData(layer->getGlobalIndex(), layer);
      90           2 :         graph.setData(globalIndex_, this);
      91             : 
      92             :         // Note that we don't set input descriptors here since we want to allow delaying the
      93             :         // input specifications. We'll set all input descriptors later when building the model
      94             :         // by traversing the graph
      95           2 :     }
      96             : 
      97             :     template <typename data_t>
      98           0 :     void Layer<data_t>::setInput(std::initializer_list<Layer*> layers)
      99             :     {
     100           0 :         for (auto&& l : layers)
     101           0 :             setInput(l);
     102           0 :     }
     103             : 
     104             :     template <typename data_t>
     105           7 :     VolumeDescriptor Layer<data_t>::getInputDescriptor(index_t index) const
     106             :     {
     107           7 :         if (inputDescriptors_.size() <= static_cast<std::size_t>(index))
     108           0 :             throw std::logic_error("No input descriptor at given index");
     109             : 
     110           7 :         if (!inputDescriptors_[asUnsigned(index)])
     111           0 :             throw std::logic_error("Input descriptor not set");
     112             : 
     113           7 :         return downcast_safe<VolumeDescriptor>(*inputDescriptors_[asUnsigned(index)]);
     114             :     }
     115             : 
     116             :     template <typename data_t>
     117           0 :     index_t Layer<data_t>::getNumberOfInputs() const
     118             :     {
     119           0 :         return static_cast<index_t>(inputDescriptors_.size());
     120             :     }
     121             : 
     122             :     template <typename data_t>
     123           7 :     VolumeDescriptor Layer<data_t>::getOutputDescriptor() const
     124             :     {
     125           7 :         if (!outputDescriptor_)
     126           0 :             throw std::logic_error("Output descriptor not set");
     127             : 
     128           7 :         return downcast_safe<VolumeDescriptor>(*outputDescriptor_);
     129             :     }
     130             : 
     131             :     template <typename data_t>
     132           4 :     index_t Layer<data_t>::getGlobalIndex() const
     133             :     {
     134           4 :         return globalIndex_;
     135             :     }
     136             : 
     137             :     template <typename data_t>
     138           2 :     void Layer<data_t>::computeOutputDescriptor()
     139             :     {
     140             :         // This default implementation requires a single input descriptor
     141           2 :         if (inputDescriptors_.size() != 1 || !inputDescriptors_.front())
     142             :             throw std::logic_error("Cannot compute output descriptor since it depends on an input "
     143           0 :                                    "descriptor that has not been set");
     144           2 :         outputDescriptor_ = inputDescriptors_.front()->clone();
     145           2 :     }
     146             : 
     147             :     template <typename data_t>
     148           9 :     void Layer<data_t>::checkNumberOfInputDimensions(const VolumeDescriptor& inputDescriptor) const
     149             :     {
     150          18 :         if (requiredNumberOfDimensions_ != Layer<data_t>::AnyNumberOfInputDimensions
     151           9 :             && requiredNumberOfDimensions_ != inputDescriptor.getNumberOfDimensions()) {
     152           2 :             std::stringstream what;
     153           1 :             what << "Expected an input descriptor with " << requiredNumberOfDimensions_
     154           1 :                  << " dimension but got one with " << inputDescriptor.getNumberOfDimensions()
     155           1 :                  << ".";
     156           1 :             throw std::invalid_argument(what.str());
     157             :         }
     158           8 :     }
     159             : 
     160             :     template <typename data_t>
     161           9 :     bool Layer<data_t>::isTrainable() const
     162             :     {
     163           9 :         return isTrainable_;
     164             :     }
     165             : 
     166             :     template <typename data_t>
     167           0 :     bool Layer<data_t>::canMerge() const
     168             :     {
     169           0 :         return false;
     170             :     }
     171             : 
     172             :     template <typename data_t>
     173           2 :     index_t Layer<data_t>::getNumberOfTrainableParameters() const
     174             :     {
     175           2 :         return numberOfTrainableParameters_;
     176             :     }
     177             : 
     178             :     template class Layer<float>;
     179             : } // namespace elsa::ml

Generated by: LCOV version 1.15