• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

BlueBrain / MorphIO / 8813096586

24 Apr 2024 08:00AM UTC coverage: 77.356%. Remained the same
8813096586

push

github

web-flow
prepare release (#496)

0 of 1 new or added line in 1 file covered. (0.0%)

2060 of 2663 relevant lines covered (77.36%)

862.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.26
/src/shared_utils.cpp
1
/* Copyright (c) 2013-2023, EPFL/Blue Brain Project
2
 *
3
 * SPDX-License-Identifier: Apache-2.0
4
 */
5
#include <algorithm>  // std::max
6
#include <bitset>
7
#include <cmath>  // std::fabs
8
#include <limits>  // std::numeric_limits
9

10
#include "error_message_generation.h"
11
#include "morphio/vector_types.h"
12
#include "shared_utils.hpp"
13

14
#include <ghc/filesystem.hpp>
15

16
namespace morphio {
17

18
floatType _somaSurface(const SomaType type,
20✔
19
                       const range<const floatType>& diameters,
20
                       const range<const Point>& points) {
21
    size_t size = points.size();
20✔
22

23
    switch (type) {
20✔
24
    case SOMA_SINGLE_POINT: {
6✔
25
        if (diameters.size() != 1) {
6✔
26
            throw MorphioError(details::ErrorMessages().ERROR_SOMA_INVALID_SINGLE_POINT());
2✔
27
        }
28
        floatType radius = diameters[0] / 2;
4✔
29
        return 4 * morphio::PI * radius * radius;
4✔
30
    }
31
    case SOMA_NEUROMORPHO_THREE_POINT_CYLINDERS: {
6✔
32
        if (diameters.size() != 3) {
6✔
33
            throw MorphioError(details::ErrorMessages().ERROR_SOMA_INVALID_THREE_POINT_CYLINDER());
2✔
34
        }
35
        floatType radius = diameters[0] / 2;
4✔
36
        return 4 * morphio::PI * radius * radius;
4✔
37
    }
38
    case SOMA_CYLINDERS: {
2✔
39
        // Surface is approximated as the sum of areas of the conical frustums
40
        // defined by each segments. Does not include the endcaps areas
41
        floatType surface = 0;
2✔
42
        for (unsigned int i = 0; i < size - 1; ++i) {
6✔
43
            floatType r0 = static_cast<morphio::floatType>(diameters[i]) / 2;
4✔
44
            floatType r1 = static_cast<morphio::floatType>(diameters[i + 1]) / 2;
4✔
45
            floatType h2 = euclidean_distance(points[i], points[i + 1]);
4✔
46
            auto s = morphio::PI * (r0 + r1) * std::sqrt((r0 - r1) * (r0 - r1) + h2 * h2);
4✔
47
            surface += s;
4✔
48
        }
49
        return surface;
2✔
50
    }
51
    case SOMA_SIMPLE_CONTOUR: {
4✔
52
        throw NotImplementedError("Surface is not implemented for SOMA_SIMPLE_CONTOUR");
4✔
53
    }
54
    case SOMA_UNDEFINED:
2✔
55
    default: {
56
        morphio::details::ErrorMessages err;
4✔
57
        throw SomaError(err.ERROR_NOT_IMPLEMENTED_UNDEFINED_SOMA("Soma::surface"));
2✔
58
    }
59
    }
60
}
61

62

63
bool is_directory(const std::string& path) {
76✔
64
    return ghc::filesystem::exists(path) &&
220✔
65
           ghc::filesystem::is_directory(ghc::filesystem::canonical(path));
220✔
66
}
67

68
bool is_regular_file(const std::string& path) {
96✔
69
    return ghc::filesystem::exists(path) &&
272✔
70
           ghc::filesystem::is_regular_file(ghc::filesystem::canonical(path));
272✔
71
}
72

73
std::string join_path(const std::string& dirname, const std::string& filename) {
66✔
74
    return (ghc::filesystem::path(dirname) / filename).string();
132✔
75
}
76

77
namespace details {
78
ThreePointSomaStatus checkNeuroMorphoSoma(const std::array<Point, 3>& points, floatType radius) {
12✔
79
    //  NeuroMorpho is the main provider of morphologies, but they
80
    //  with SWC as their default file format: they convert all
81
    //  uploads to SWC.  In the process of conversion, they turn all
82
    //  somas into their custom 'Three-point soma representation':
83
    //  http://neuromorpho.org/SomaFormat.html
84
    //
85
    //  If the 2nd and the 3rd point have the same x,z,d values then the only valid soma is:
86
    //  1 1 x   y   z r -1
87
    //  2 1 x (y-r) z r  1
88
    //  3 1 x (y+r) z r  1
89
    //
90
    //  However, Prof Ascoli responded that they are relaxing the format:
91
    //  "I think that any 3 point soma would do as long as it represents
92
    //  a symmetric cylinder, and all trees stem from the central one of the 3 points."
93
    //  https://github.com/BlueBrain/morph-tool/issues/117#issuecomment-1772263991
94
    //
95
    //  Which I interpret to mean that as long as the `r` offset is applied along the same
96
    //  dimension, it's fine; and the +/- can either happen on point 2 or 3:
97
    //  EX, this is ok:
98
    //  1 1 x y  z      r -1
99
    //  2 1 x y (z + r) r  1 <- have `+` first
100
    //  3 1 x y (z - r) r  1
101

102
    auto withinTolerance = [](floatType a, floatType b) {
88✔
103
        floatType diff = std::fabs(a - b);
88✔
104
        // either we below the absolute epsilon...
105
        return diff < morphio::epsilon ||
112✔
106
               // or within a reasonable tolerance...
107
               // note: `(std::max)` is to work around `#define max` existing on some MSVC versions
108
               (diff <=
109
                (std::max)(std::fabs(a), std::fabs(b)) * std::numeric_limits<floatType>::epsilon());
112✔
110
    };
111

112
    std::bitset<3> column_mask = {};
12✔
113
    for (size_t i = 0; i < 3; ++i) {
48✔
114
        column_mask[i] = (withinTolerance(points[0][i], points[1][i]) &&
58✔
115
                          withinTolerance(points[0][i], points[2][i]));
58✔
116
    }
117

118
    if (column_mask.none()) {
12✔
119
        return ZeroColumnsAreTheSame;
×
120
    } else if (column_mask.count() == 1) {
12✔
121
        return OneColumnIsTheSame;
2✔
122
    } else if (column_mask.all()) {
10✔
123
        return ThreeColumnsAreTheSame;
×
124
    }
125

126
    const size_t col = !column_mask[0] ? 0 : !column_mask[1] ? 1 : 2;
10✔
127
    std::cout << "asdf\n";
10✔
128

129
    if (!(withinTolerance(points[0][col], points[1][col] - radius) &&
10✔
130
          withinTolerance(points[0][col], points[2][col] + radius)) &&
20✔
131
        !(withinTolerance(points[0][col], points[1][col] + radius) &&
10✔
132
          withinTolerance(points[0][col], points[2][col] - radius))) {
10✔
133
        return NotRadiusOffset;
×
134
    }
135

136
    return Conforms;
10✔
137
}
138

139
std::ostream& operator<<(std::ostream& os, ThreePointSomaStatus s) {
2✔
140
    switch (s) {
2✔
141
    case ZeroColumnsAreTheSame:
×
142
        os << "Three Point Soma: None of the columns (ie: all the X, Y or Z values) are the same.";
×
143
        break;
×
144
    case OneColumnIsTheSame:
2✔
145
        os << "Three Point Soma: Only one column has the same coordinates.";
2✔
146
        break;
2✔
147
    case ThreeColumnsAreTheSame:
×
148
        os << "Three Point Soma: All three columns have the same coordinates.";
×
149
        break;
×
150
    case NotRadiusOffset:
×
151
        os << "Three Point Soma: The non-constant columns is not offset by +/- the radius from the "
NEW
152
              "initial sample.";
×
153
        break;
×
154
    case Conforms:
×
155
        os << "Three Point Soma: conforms to specification";
×
156
        break;
×
157
    }
158
    return os;
2✔
159
}
160

161
}  // namespace details
162
}  // namespace morphio
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc