Commit b8611ea42607f737686021ab27272c84eba7f838

Authored by Charles Otto
1 parent e465e02e

Restructure composite transform inheritance

Make ExpandTransform inherit from PipeTransform, move default implementations
of several things to PipeTransform.
This is cleaner since only ExpandTransform and PipeTransform actually share
code (since they have the same basic execution path).
Implement ExpandTransform using a decorator class.
sdk/openbr_plugin.h
@@ -1144,8 +1144,6 @@ public: @@ -1144,8 +1144,6 @@ public:
1144 Q_PROPERTY(QList<br::Transform*> transforms READ get_transforms WRITE set_transforms RESET reset_transforms) 1144 Q_PROPERTY(QList<br::Transform*> transforms READ get_transforms WRITE set_transforms RESET reset_transforms)
1145 BR_PROPERTY(QList<br::Transform*>, transforms, QList<br::Transform*>()) 1145 BR_PROPERTY(QList<br::Transform*>, transforms, QList<br::Transform*>())
1146 1146
1147 - virtual void train(const TemplateList &data);  
1148 -  
1149 virtual void project(const Template &src, Template &dst) const 1147 virtual void project(const Template &src, Template &dst) const
1150 { 1148 {
1151 if (timeVarying()) qFatal("No const project defined for time-varying transform"); 1149 if (timeVarying()) qFatal("No const project defined for time-varying transform");
@@ -1158,50 +1156,6 @@ public: @@ -1158,50 +1156,6 @@ public:
1158 _project(src, dst); 1156 _project(src, dst);
1159 } 1157 }
1160 1158
1161 - void backProject(const Template &dst, Template &src) const  
1162 - {  
1163 - // Backprojecting a time-varying transform is probably not going to work.  
1164 - if (timeVarying()) qFatal("No backProject defined for time-varying transform");  
1165 -  
1166 - src = dst;  
1167 - // Reverse order in which transforms are processed  
1168 - int length = transforms.length();  
1169 - for (int i=length-1; i>=0; i--) {  
1170 - Transform *f = transforms.at(i);  
1171 - try {  
1172 - src >> *f;  
1173 - } catch (...) {  
1174 - qWarning("Exception triggered when processing %s with transform %s", qPrintable(dst.file.flat()), qPrintable(f->objectName()));  
1175 - src = Template(src.file);  
1176 - src.file.setBool("FTE");  
1177 - }  
1178 - }  
1179 - }  
1180 -  
1181 - void projectUpdate(const Template &src, Template &dst)  
1182 - {  
1183 - dst = src;  
1184 - foreach (Transform *f, transforms) {  
1185 - try {  
1186 - f->projectUpdate(dst);  
1187 - } catch (...) {  
1188 - qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));  
1189 - dst = Template(src.file);  
1190 - dst.file.setBool("FTE");  
1191 - }  
1192 - }  
1193 - }  
1194 -  
1195 - // For time varying transforms, parallel execution over individual templates  
1196 - // won't work.  
1197 - void projectUpdate(const TemplateList & src, TemplateList & dst)  
1198 - {  
1199 - dst = src;  
1200 - foreach (Transform *f, transforms)  
1201 - {  
1202 - f->projectUpdate(dst);  
1203 - }  
1204 - }  
1205 1159
1206 bool timeVarying() const 1160 bool timeVarying() const
1207 { 1161 {
@@ -1220,45 +1174,11 @@ public: @@ -1220,45 +1174,11 @@ public:
1220 } 1174 }
1221 } 1175 }
1222 1176
1223 - virtual void finalize(TemplateList & output)  
1224 - {  
1225 - output.clear();  
1226 - // For each transform,  
1227 - for (int i = 0; i < transforms.size(); i++)  
1228 - {  
1229 -  
1230 - // Collect any final templates  
1231 - TemplateList last_set;  
1232 - transforms[i]->finalize(last_set);  
1233 - if (last_set.empty())  
1234 - continue;  
1235 - // Push any templates received through the remaining transforms in the sequence  
1236 - for (int j = (i+1); j < transforms.size();j++)  
1237 - {  
1238 - transforms[j]->projectUpdate(last_set);  
1239 - }  
1240 - // append the result to the output set  
1241 - output.append(last_set);  
1242 - }  
1243 - }  
1244 1177
1245 protected: 1178 protected:
1246 bool time_varying; 1179 bool time_varying;
1247 - // Single template const project, default implementation for aggregate transforms--pass the template through each  
1248 - // sub-transform, one after the other  
1249 - virtual void _project(const Template & src, Template & dst) const  
1250 - {  
1251 - dst = src;  
1252 - foreach (const Transform *f, transforms) {  
1253 - try {  
1254 - dst >> *f;  
1255 - } catch (...) {  
1256 - qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));  
1257 - dst = Template(src.file);  
1258 - dst.file.setBool("FTE");  
1259 - }  
1260 - }  
1261 - } 1180 +
  1181 + virtual void _project(const Template & src, Template & dst) const = 0;
1262 virtual void _project(const TemplateList & src, TemplateList & dst) const = 0; 1182 virtual void _project(const TemplateList & src, TemplateList & dst) const = 0;
1263 1183
1264 CompositeTransform() : TimeVaryingTransform(false) {} 1184 CompositeTransform() : TimeVaryingTransform(false) {}
sdk/plugins/meta.cpp
@@ -85,64 +85,78 @@ static void incrementStep() @@ -85,64 +85,78 @@ static void incrementStep()
85 Globals->currentStep += 1.0 / pow(10.0, double(depth)); 85 Globals->currentStep += 1.0 / pow(10.0, double(depth));
86 } 86 }
87 87
88 -// CompositeTransform::train placed here to pick up acquireStep and incrementStep  
89 -void CompositeTransform::train(const TemplateList &data) 88 +/*!
  89 + * \brief Use Expanded after basic calls that take a template list, used to implement ExpandTransform
  90 + */
  91 +class ExpandDecorator : public Transform
90 { 92 {
91 - acquireStep(); 93 + Q_OBJECT
  94 +
  95 + Q_PROPERTY(br::Transform* transform READ get_transform WRITE set_transform RESET reset_transform)
  96 + BR_PROPERTY(br::Transform*, transform, NULL)
92 97
93 - TemplateList copy(data);  
94 - for (int i=0; i<transforms.size(); i++) {  
95 - transforms[i]->train(copy);  
96 - copy >> *transforms[i];  
97 - incrementStep(); 98 +public:
  99 + ExpandDecorator(Transform * input)
  100 + {
  101 + transform = input;
  102 + transform->setParent(this);
  103 + file = transform->file;
  104 + setObjectName(transform->objectName());
98 } 105 }
99 106
100 - releaseStep();  
101 -} 107 + void train(const TemplateList &data)
  108 + {
  109 + transform->train(data);
  110 + }
102 111
103 -/*!  
104 - * \ingroup Transforms  
105 - * \brief Transforms in series.  
106 - * \author Josh Klontz \cite jklontz  
107 - *  
108 - * The source br::Template is given to the first transform and the resulting br::Template is passed to the next transform, etc.  
109 - *  
110 - * \see ExpandTransform  
111 - * \see ForkTransform  
112 - */  
113 -class PipeTransform : public CompositeTransform  
114 -{  
115 - Q_OBJECT 112 + void project(const Template &src, Template &dst) const
  113 + {
  114 + transform->project(src, dst);
  115 + }
116 116
  117 + void project(const TemplateList &src, TemplateList &dst) const
  118 + {
  119 + transform->project(src, dst);
  120 + dst = Expanded(dst);
  121 + }
117 122
118 -protected:  
119 - // Template list project -- process templates in parallel through Transform::project  
120 - // or if parallelism is disabled, handle them sequentially  
121 - void _project(const TemplateList &src, TemplateList &dst) const 123 +
  124 + void projectUpdate(const Template &src, Template &dst)
122 { 125 {
123 - if (Globals->parallelism < 0) {  
124 - dst = src;  
125 - foreach (const Transform *f, transforms)  
126 - dst >> *f;  
127 - } else {  
128 - Transform::project(src, dst);  
129 - } 126 + transform->projectUpdate(src, dst);
130 } 127 }
  128 +
  129 + void projectUpdate(const TemplateList & src, TemplateList & dst)
  130 + {
  131 + transform->projectUpdate(src, dst);
  132 + dst = Expanded(dst);
  133 + }
  134 +
  135 + bool timeVarying() const
  136 + {
  137 + return transform->timeVarying();
  138 + }
  139 +
  140 + void finalize(TemplateList & output)
  141 + {
  142 + transform->finalize(output);
  143 + output = Expanded(output);
  144 + }
  145 +
131 }; 146 };
132 147
133 -BR_REGISTER(Transform, PipeTransform)  
134 148
135 /*! 149 /*!
136 - * \ingroup transforms  
137 - * \brief Transforms in series with expansion step. 150 + * \ingroup Transforms
  151 + * \brief Transforms in series.
138 * \author Josh Klontz \cite jklontz 152 * \author Josh Klontz \cite jklontz
139 * 153 *
140 * The source br::Template is given to the first transform and the resulting br::Template is passed to the next transform, etc. 154 * The source br::Template is given to the first transform and the resulting br::Template is passed to the next transform, etc.
141 - * Each matrix is expanded into its own template between steps.  
142 * 155 *
143 - * \see PipeTransform 156 + * \see ExpandTransform
  157 + * \see ForkTransform
144 */ 158 */
145 -class ExpandTransform : public CompositeTransform 159 +class PipeTransform : public CompositeTransform
146 { 160 {
147 Q_OBJECT 161 Q_OBJECT
148 162
@@ -154,21 +168,54 @@ class ExpandTransform : public CompositeTransform @@ -154,21 +168,54 @@ class ExpandTransform : public CompositeTransform
154 for (int i=0; i<transforms.size(); i++) { 168 for (int i=0; i<transforms.size(); i++) {
155 transforms[i]->train(copy); 169 transforms[i]->train(copy);
156 copy >> *transforms[i]; 170 copy >> *transforms[i];
157 - copy = Expanded(copy);  
158 incrementStep(); 171 incrementStep();
159 } 172 }
160 173
161 releaseStep(); 174 releaseStep();
162 } 175 }
163 176
164 - // same as _project, but calling projectUpdate on sub-transforms instead of using  
165 - // operator>>  
166 - void projectUpdate(const TemplateList &src, TemplateList &dst) 177 + void backProject(const Template &dst, Template &src) const
  178 + {
  179 + // Backprojecting a time-varying transform is probably not going to work.
  180 + if (timeVarying()) qFatal("No backProject defined for time-varying transform");
  181 +
  182 + src = dst;
  183 + // Reverse order in which transforms are processed
  184 + int length = transforms.length();
  185 + for (int i=length-1; i>=0; i--) {
  186 + Transform *f = transforms.at(i);
  187 + try {
  188 + src >> *f;
  189 + } catch (...) {
  190 + qWarning("Exception triggered when processing %s with transform %s", qPrintable(dst.file.flat()), qPrintable(f->objectName()));
  191 + src = Template(src.file);
  192 + src.file.setBool("FTE");
  193 + }
  194 + }
  195 + }
  196 +
  197 + void projectUpdate(const Template &src, Template &dst)
167 { 198 {
168 dst = src; 199 dst = src;
169 - for (int i=0; i<transforms.size(); i++) {  
170 - transforms[i]->projectUpdate(dst);  
171 - dst = Expanded(dst); 200 + foreach (Transform *f, transforms) {
  201 + try {
  202 + f->projectUpdate(dst);
  203 + } catch (...) {
  204 + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
  205 + dst = Template(src.file);
  206 + dst.file.setBool("FTE");
  207 + }
  208 + }
  209 + }
  210 +
  211 + // For time varying transforms, parallel execution over individual templates
  212 + // won't work.
  213 + void projectUpdate(const TemplateList & src, TemplateList & dst)
  214 + {
  215 + dst = src;
  216 + foreach (Transform *f, transforms)
  217 + {
  218 + f->projectUpdate(dst);
172 } 219 }
173 } 220 }
174 221
@@ -182,31 +229,86 @@ class ExpandTransform : public CompositeTransform @@ -182,31 +229,86 @@ class ExpandTransform : public CompositeTransform
182 // Collect any final templates 229 // Collect any final templates
183 TemplateList last_set; 230 TemplateList last_set;
184 transforms[i]->finalize(last_set); 231 transforms[i]->finalize(last_set);
185 - last_set = Expanded(last_set);  
186 if (last_set.empty()) 232 if (last_set.empty())
187 continue; 233 continue;
188 // Push any templates received through the remaining transforms in the sequence 234 // Push any templates received through the remaining transforms in the sequence
189 for (int j = (i+1); j < transforms.size();j++) 235 for (int j = (i+1); j < transforms.size();j++)
190 { 236 {
191 transforms[j]->projectUpdate(last_set); 237 transforms[j]->projectUpdate(last_set);
192 - last_set = Expanded(last_set);  
193 } 238 }
194 // append the result to the output set 239 // append the result to the output set
195 output.append(last_set); 240 output.append(last_set);
196 } 241 }
197 } 242 }
198 243
  244 +
  245 +protected:
  246 + // Template list project -- process templates in parallel through Transform::project
  247 + // or if parallelism is disabled, handle them sequentially
  248 + void _project(const TemplateList &src, TemplateList &dst) const
  249 + {
  250 + if (Globals->parallelism < 0) {
  251 + dst = src;
  252 + foreach (const Transform *f, transforms)
  253 + dst >> *f;
  254 + } else {
  255 + Transform::project(src, dst);
  256 + }
  257 + }
  258 +
  259 + // Single template const project, pass the template through each sub-transform, one after the other
  260 + virtual void _project(const Template & src, Template & dst) const
  261 + {
  262 + dst = src;
  263 + foreach (const Transform *f, transforms) {
  264 + try {
  265 + dst >> *f;
  266 + } catch (...) {
  267 + qWarning("Exception triggered when processing %s with transform %s", qPrintable(src.file.flat()), qPrintable(f->objectName()));
  268 + dst = Template(src.file);
  269 + dst.file.setBool("FTE");
  270 + }
  271 + }
  272 + }
  273 +};
  274 +
  275 +BR_REGISTER(Transform, PipeTransform)
  276 +
  277 +/*!
  278 + * \ingroup transforms
  279 + * \brief Transforms in series with expansion step.
  280 + * \author Josh Klontz \cite jklontz
  281 + *
  282 + * The source br::Template is given to the first transform and the resulting br::Template is passed to the next transform, etc.
  283 + * Each matrix is expanded into its own template between steps.
  284 + *
  285 + * \see PipeTransform
  286 + */
  287 +class ExpandTransform : public PipeTransform
  288 +{
  289 + Q_OBJECT
  290 +
  291 + void init()
  292 + {
  293 + for (int i = 0; i < transforms.size(); i++)
  294 + {
  295 + transforms[i] = new ExpandDecorator(transforms[i]);
  296 + }
  297 + // Need to call this to set up timevariance correctly, and it won't
  298 + // be called automatically
  299 + CompositeTransform::init();
  300 + }
  301 +
199 protected: 302 protected:
200 303
201 // Template list project -- project through transforms sequentially, 304 // Template list project -- project through transforms sequentially,
202 // then expand the results, can't use Transform::Project(templateList) since 305 // then expand the results, can't use Transform::Project(templateList) since
203 - // we need to expand between tranforms 306 + // we need to expand between tranforms, so actually do need to overload this method
204 void _project(const TemplateList &src, TemplateList &dst) const 307 void _project(const TemplateList &src, TemplateList &dst) const
205 { 308 {
206 dst = src; 309 dst = src;
207 for (int i=0; i<transforms.size(); i++) { 310 for (int i=0; i<transforms.size(); i++) {
208 dst >> *transforms[i]; 311 dst >> *transforms[i];
209 - dst = Expanded(dst);  
210 } 312 }
211 } 313 }
212 }; 314 };
@@ -236,7 +338,7 @@ class ForkTransform : public CompositeTransform @@ -236,7 +338,7 @@ class ForkTransform : public CompositeTransform
236 } 338 }
237 if (threaded) Globals->trackFutures(futures); 339 if (threaded) Globals->trackFutures(futures);
238 } 340 }
239 - // The implementation of backProject in aggregate transform probably doesn't do anything useful here. 341 +
240 void backProject(const Template &dst, Template &src) const {Transform::backProject(dst, src);} 342 void backProject(const Template &dst, Template &src) const {Transform::backProject(dst, src);}
241 343
242 // same as _project, but calls projectUpdate on sub-transforms 344 // same as _project, but calls projectUpdate on sub-transforms
@@ -255,6 +357,18 @@ class ForkTransform : public CompositeTransform @@ -255,6 +357,18 @@ class ForkTransform : public CompositeTransform
255 } 357 }
256 } 358 }
257 359
  360 + void projectUpdate(const TemplateList & src, TemplateList & dst)
  361 + {
  362 + dst = src;
  363 + dst.reserve(src.size());
  364 + for (int i=0; i<src.size(); i++) dst.append(Template());
  365 + foreach (Transform *f, transforms) {
  366 + TemplateList m;
  367 + f->projectUpdate(src, m);
  368 + if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size.");
  369 + for (int i=0; i<src.size(); i++) dst[i].append(m[i]);
  370 + }
  371 + }
258 372
259 // this is probably going to go bad, fork transform probably won't work well in a variable 373 // this is probably going to go bad, fork transform probably won't work well in a variable
260 // input/output scenario 374 // input/output scenario
@@ -316,19 +430,6 @@ protected: @@ -316,19 +430,6 @@ protected:
316 } 430 }
317 } 431 }
318 432
319 - void projectUpdate(const TemplateList & src, TemplateList & dst)  
320 - {  
321 - dst = src;  
322 - dst.reserve(src.size());  
323 - for (int i=0; i<src.size(); i++) dst.append(Template());  
324 - foreach (Transform *f, transforms) {  
325 - TemplateList m;  
326 - f->projectUpdate(src, m);  
327 - if (m.size() != dst.size()) qFatal("TemplateList is of an unexpected size.");  
328 - for (int i=0; i<src.size(); i++) dst[i].append(m[i]);  
329 - }  
330 - }  
331 -  
332 }; 433 };
333 434
334 BR_REGISTER(Transform, ForkTransform) 435 BR_REGISTER(Transform, ForkTransform)