1 /**
2 * \file RMF/Category.h
3 * \brief Handle read/write of Model data from/to files.
4 *
5 * Copyright 2007-2021 IMP Inventors. All rights reserved.
6 *
7 */
8
9 #include "RMF/decorator/alternatives.h"
10 #include "RMF/decorator/physics.h"
11 #include "RMF/decorator/sequence.h"
12 #include <numeric>
13
14 RMF_ENABLE_WARNINGS
15
16 namespace RMF {
17 namespace decorator {
18
19 namespace {
get_resolution_metric(double a,double b)20 double get_resolution_metric(double a, double b) {
21 if (a < b) std::swap(a, b);
22 return a / b - 1;
23 }
24
get_resolution_impl(NodeConstHandle root,IntermediateParticleFactory ipcf,GaussianParticleFactory gpf)25 std::pair<double, bool> get_resolution_impl(NodeConstHandle root,
26 IntermediateParticleFactory ipcf,
27 GaussianParticleFactory gpf) {
28 std::pair<double, bool> ret(std::numeric_limits<double>::max(), false);
29 RMF_FOREACH(NodeConstHandle ch, root.get_children()) {
30 std::pair<double, bool> cur = get_resolution_impl(ch, ipcf, gpf);
31 ret.first = std::min(ret.first, cur.first);
32 ret.second = ret.second || cur.second;
33 }
34 if (!ret.second) {
35 if (ipcf.get_is(root)) {
36 ret.first = ipcf.get(root).get_radius();
37 ret.second = true;
38 } else if (gpf.get_is(root)) {
39 Vector3 sdfs = gpf.get(root).get_variances();
40 ret.first = std::accumulate(sdfs.begin(), sdfs.end(), 0.0) / 3.0;
41 ret.second = true;
42 }
43 }
44 return ret;
45 }
46 }
47
AlternativesFactory(FileHandle fh)48 AlternativesFactory::AlternativesFactory(FileHandle fh)
49 : cat_(fh.get_category("alternatives")),
50 types_key_(fh.get_key<IntsTag>(cat_, "types")),
51 roots_key_(fh.get_key<IntsTag>(cat_, "roots")) {}
52
AlternativesFactory(FileConstHandle fh)53 AlternativesFactory::AlternativesFactory(FileConstHandle fh)
54 : cat_(fh.get_category("alternatives")),
55 types_key_(fh.get_key<IntsTag>(cat_, "types")),
56 roots_key_(fh.get_key<IntsTag>(cat_, "roots")) {}
57
get_alternative_impl(RepresentationType type,float resolution) const58 NodeID AlternativesConst::get_alternative_impl(RepresentationType type,
59 float resolution) const {
60 if (!get_node().get_has_value(types_key_)) return get_node().get_id();
61
62 double closest_resolution = get_resolution(get_node());
63 int closest_index = -1;
64 Nullable<Ints> types = get_node().get_value(types_key_);
65 if (!types.get_is_null()) {
66 Ints roots = get_node().get_value(roots_key_);
67 for (unsigned int i = 0; i < types.get().size(); ++i) {
68 if (types.get()[i] != type) continue;
69 double cur_resolution =
70 get_resolution(get_node().get_file().get_node(NodeID(roots[i])));
71 if (get_resolution_metric(resolution, cur_resolution) <
72 get_resolution_metric(resolution, closest_resolution)) {
73 closest_index = i;
74 closest_resolution = cur_resolution;
75 }
76 }
77 }
78 if (closest_index == -1) {
79 return get_node().get_id();
80 } else {
81 return NodeID(get_node().get_value(roots_key_).get()[closest_index]);
82 }
83 }
84
get_alternatives_impl(RepresentationType type) const85 NodeIDs AlternativesConst::get_alternatives_impl(RepresentationType type)
86 const {
87 NodeIDs ret;
88 if (type == PARTICLE) ret.push_back(get_node().get_id());
89
90 if (get_node().get_has_value(roots_key_)) {
91 Ints roots = get_node().get_value(roots_key_).get();
92 Ints types = get_node().get_value(types_key_).get();
93
94 for (unsigned int i = 0; i < roots.size(); ++i) {
95 RMF_INTERNAL_CHECK(roots[i] != 0, "The root can't be an alternative rep");
96 if (RepresentationType(types[i]) == type) ret.push_back(NodeID(roots[i]));
97 }
98 }
99 return ret;
100 }
101
get_resolution(NodeConstHandle root)102 double get_resolution(NodeConstHandle root) {
103 ExplicitResolutionFactory erf(root.get_file());
104 if (erf.get_is(root)) {
105 return erf.get(root).get_static_explicit_resolution();
106 } else {
107 IntermediateParticleFactory ipcf(root.get_file());
108 GaussianParticleFactory gpf(root.get_file());
109 std::pair<double, bool> total = get_resolution_impl(root, ipcf, gpf);
110 RMF_USAGE_CHECK(total.second,
111 std::string("No particles were found at ") + root.get_name());
112 return 1.0 / total.first;
113 }
114 }
115
Alternatives(NodeHandle nh,IntsKey types_key,IntsKey roots_key)116 Alternatives::Alternatives(NodeHandle nh, IntsKey types_key, IntsKey roots_key)
117 : AlternativesConst(nh, types_key, roots_key) {}
118
add_alternative(NodeHandle root,RepresentationType type)119 void Alternatives::add_alternative(NodeHandle root, RepresentationType type) {
120 RMF_USAGE_CHECK(root.get_id() != NodeID(0),
121 "The root can't be an alternative");
122 get_node()
123 .get_shared_data()
124 ->access_static_value(get_node().get_id(), types_key_)
125 .push_back(type);
126 get_node()
127 .get_shared_data()
128 ->access_static_value(get_node().get_id(), roots_key_)
129 .push_back(root.get_id().get_index());
130
131 RMF_INTERNAL_CHECK(get_alternatives(type).size() >= 1, "None found");
132 }
133
get_alternative(RepresentationType type,double resolution) const134 NodeConstHandle AlternativesConst::get_alternative(RepresentationType type,
135 double resolution) const {
136 return get_node().get_file().get_node(get_alternative_impl(type, resolution));
137 }
138
get_alternatives(RepresentationType type) const139 NodeConstHandles AlternativesConst::get_alternatives(RepresentationType type)
140 const {
141 NodeConstHandles ret;
142 RMF_FOREACH(NodeID nid, get_alternatives_impl(type)) {
143 ret.push_back(get_node().get_file().get_node(nid));
144 }
145 return ret;
146 }
147
get_representation_type(NodeID id) const148 RepresentationType AlternativesConst::get_representation_type(NodeID id) const {
149 if (id == get_node().get_id()) return PARTICLE;
150
151 Ints roots = get_node().get_value(roots_key_);
152 for (unsigned int i = 0; i < roots.size(); ++i) {
153 if (roots[i] == static_cast<int>(id.get_index())) {
154 return RepresentationType(get_node().get_value(types_key_).get()[i]);
155 }
156 }
157 RMF_THROW(Message("No such alternative representation"), UsageException);
158 }
159
160 namespace {
get_resolutions_impl(NodeConstHandle root,AlternativesFactory af,RepresentationType type)161 Floats get_resolutions_impl(NodeConstHandle root, AlternativesFactory af,
162 RepresentationType type) {
163 Floats ret;
164 if (af.get_is(root)) {
165 RMF_FOREACH(NodeConstHandle a, af.get(root).get_alternatives(type)) {
166 ret.push_back(get_resolution(a));
167 }
168 } else {
169 RMF_FOREACH(NodeConstHandle ch, root.get_children()) {
170 Floats cur = get_resolutions_impl(ch, af, type);
171 ret.insert(ret.end(), cur.begin(), cur.end());
172 }
173 }
174 return ret;
175 }
176 }
177
get_resolutions(NodeConstHandle root,RepresentationType type,double accuracy)178 Floats get_resolutions(NodeConstHandle root, RepresentationType type,
179 double accuracy) {
180 AlternativesFactory af(root.get_file());
181 Floats unclustered = get_resolutions_impl(root, af, type);
182 if (unclustered.empty()) unclustered.push_back(1.0);
183 std::sort(unclustered.begin(), unclustered.end());
184 double lb = unclustered[0];
185 double ub = lb;
186 Floats ret;
187 RMF_FOREACH(double r, unclustered) {
188 if (r > lb + accuracy) {
189 ret.push_back(.5 * (lb + ub));
190 lb = r;
191 }
192 ub = r;
193 }
194 ret.push_back(.5 * (lb + ub));
195 return ret;
196 }
197
198 } /* namespace decorator */
199 } /* namespace RMF */
200
201 RMF_DISABLE_WARNINGS
202