Prince FAMD unable to transform data (shapes not aligned:(dim 1) != (dim 0)) - pca

I'm using prince to perform Factor Analysis of Mixed Data (FAMD). During training everything goes as planned, but when I try to transform new data, I get an error (shapes not aligned:(dim 1) != (dim 0)).
I've seen people claiming to have this problem before and they claim the problem is that they're trying to transform data from a test set, but I tried different approaches and I still get this error. Let me describe my situation:
My dataset has some 500k rows and some 20 columns.
Originally, I separated the dataset into a train(80%) and test(20%) and everything worked fine
The problem appears when I try to transform a small subset of the data
When I try transforming less than 100 rows, I get the aforementioned error
Between 100 and 2000 rows, there's no error, but the output is all nan
Over 2000 rows it works properly
Does anyone know how to fix this? I think it may be some issue with matrix rank, but right now I'm clueless
Here's the error message
ValueError Traceback (most recent call
last) in
----> 7 famd.transform(c)
\site-packages\prince\mfa.py in
transform(self, X)
135 def transform(self, X):
136 """Returns the row principal coordinates of a dataset."""
--> 137 return self.row_coordinates(X)
138
139 def _row_coordinates_from_global(self, X_global):
\site-packages\prince\mfa.py in
row_coordinates(self, X)
152 X = self._prepare_input(X)
153
--> 154 return self._row_coordinates_from_global(self._build_X_global(X))
155
156 def row_contributions(self, X):
\site-packages\prince\mfa.py in
_row_coordinates_from_global(self, X_global)
139 def _row_coordinates_from_global(self, X_global):
140 """Returns the row principal coordinates."""
--> 141 return len(X_global) ** 0.5 * super().row_coordinates(X_global)
142
143 def row_coordinates(self, X):
\site-packages\prince\pca.py in
row_coordinates(self, X)
136 X = self.scaler_.transform(X)
137
--> 138 return pd.DataFrame(data=X.dot(self.V_.T), index=index, dtype=np.float64)
139
140 def row_standard_coordinates(self, X):
ValueError: shapes (100,41) and (43,10) not aligned: 41 (dim 1) != 43
(dim 0)

Related

perft-function of chess engine is giving self-contradictory output

I am currently developing a chess engine in C++, and I am in the process of debugging my move generator. For this purpose, I wrote a simple perft() function:
int32_t Engine::perft(GameState game_state, int32_t depth)
{
int32_t last_move_nodes = 0;
int32_t all_nodes = 0;
Timer timer;
timer.start();
int32_t output_depth = depth;
if (depth == 0)
{
return 1;
}
std::vector<Move> legal_moves = generator.generate_legal_moves(game_state);
for (Move move : legal_moves)
{
game_state.make_move(move);
last_move_nodes = perft_no_print(game_state, depth - 1);
all_nodes += last_move_nodes;
std::cout << index_to_square_name(move.get_from_index()) << index_to_square_name(move.get_to_index()) << ": " << last_move_nodes << "\n";
game_state.unmake_move(move);
}
std::cout << "\nDepth: " << output_depth << "\nTotal nodes: " << all_nodes << "\nTotal time: " << timer.get_milliseconds() << "ms/" << timer.get_milliseconds()/1000.0f << "s\n\n";
return all_nodes;
}
int32_t Engine::perft_no_print(GameState game_state, int32_t depth)
{
int32_t nodes = 0;
if (depth == 0)
{
return 1;
}
std::vector<Move> legal_moves = generator.generate_legal_moves(game_state);
for (Move move : legal_moves)
{
game_state.make_move(move);
nodes += perft_no_print(game_state, depth - 1);
game_state.unmake_move(move);
}
return nodes;
}
It's results for the initial chess position (FEN: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1) for depths 1 and 2 match the results of stockfish's perft command, so I assume they are correct:
h2h3: 1
h2h4: 1
g2g3: 1
g2g4: 1
f2f3: 1
f2f4: 1
e2e3: 1
e2e4: 1
d2d3: 1
d2d4: 1
c2c3: 1
c2c4: 1
b2b3: 1
b2b4: 1
a2a3: 1
a2a4: 1
g1h3: 1
g1f3: 1
b1c3: 1
b1a3: 1
Depth: 1
Total nodes: 20
Total time: 1ms/0.001s
h2h3: 20
h2h4: 20
g2g3: 20
g2g4: 20
f2f3: 20
f2f4: 20
e2e3: 20
e2e4: 20
d2d3: 20
d2d4: 20
c2c3: 20
c2c4: 20
b2b3: 20
b2b4: 20
a2a3: 20
a2a4: 20
g1h3: 20
g1f3: 20
b1c3: 20
b1a3: 20
Depth: 2
Total nodes: 400
Total time: 1ms/0.001s
The results stop matching at depth 3, though:
Stockfish:
go perft 3
a2a3: 380
b2b3: 420
c2c3: 420
d2d3: 539
e2e3: 599
f2f3: 380
g2g3: 420
h2h3: 380
a2a4: 420
b2b4: 421
c2c4: 441
d2d4: 560
e2e4: 600
f2f4: 401
g2g4: 421
h2h4: 420
b1a3: 400
b1c3: 440
g1f3: 440
g1h3: 400
Nodes searched: 8902
My engine:
h2h3: 361
h2h4: 380
g2g3: 340
g2g4: 397
f2f3: 360
f2f4: 436
e2e3: 380
e2e4: 437
d2d3: 380
d2d4: 437
c2c3: 399
c2c4: 326
b2b3: 300
b2b4: 320
a2a3: 280
a2a4: 299
g1h3: 281
g1f3: 280
b1c3: 357
b1a3: 320
Depth: 3
Total nodes: 7070
Total time: 10ms/0.01s
I figured that my move generator was just buggy, and tried to track down the bugs by making a move the engine gives incorrect values for on the board and then calling perft() with depth = 2 on it to find out which moves are missing. But for all moves I tried this with, the engine suddenly starts to output the correct results I expected to get earlier!
Here is an example for the move a2a3:
When calling perft() on the initial position in stockfish, it calculates 380 subnodes for a2a3 at depth 3.
When calling perft() on the initial position in my engine, it calculates 280 subnodes for a2a3 at depth 3.
When calling perft() on the position you get after making the move a2a3 in the initial position in my engine, it calculates the correct number of total nodes at depth 2, 380:
h7h5: 19
h7h6: 19
g7g5: 19
g7g6: 19
f7f5: 19
f7f6: 19
e7e5: 19
e7e6: 19
d7d5: 19
d7d6: 19
c7c5: 19
c7c6: 19
b7b5: 19
b7b6: 19
a7a5: 19
a7a6: 19
g8h6: 19
g8f6: 19
b8c6: 19
b8a6: 19
Depth: 2
Total nodes: 380
Total time: 1ms/0.001s
If you have any idea what the problem could be here, please help me out. Thank you!
EDIT:
I discovered some interesting new facts that might help to solve the problem, but I don't know what to do with them:
For some reason, using std::sort() like this in perft():
std::sort(legal_moves.begin(), legal_moves.end(), [](auto first, auto second){ return first.get_from_index() % 8 > second.get_from_index() % 8; });
to sort the vector of legal moves causes the found number of total nodes for the initial position (for depth 3) to change from the wrong 7070 to the (also wrong) 7331.
When printing the game state after calling game_state.make_move() in perft(), it seems to have had no effect on the position bitboards (the other properties change like they are supposed to). This is very strange, because isolated, the make_move() method works just fine.
I'm unsure if you were able to pin down the issue but from the limited information available in the question, the best I can assume (and something I faced myself earlier) is that there is a problem in your unmake_move() function when it comes to captures since
Your perft fails only at level 3 - this is when the first legal capture is possible, move 1 and 2 can have no legal captures.
Your perft works fine when it's at depth 1 in the position after a2a3 rather than when it's searching at depth 3 from the start
This probably means that your unmake_move() fails at a depth greater than 1 where you need to restore some of the board's state that cannot be derived from just the move parameter you are passing in (e.g. enpassant, castling rights etc. before you made the move).
This is how you would like to debug your move generator using perft.
Given startpos as p1, generate perft(3) for your engine and sf. (you did that)
Now check any move that have different nodes, you pick a2a3. (you did that)
Given startpos + a2a3 as p2, generate perft(2) for your engine and sf. (you partially did this)
Now check any move that have different nodes in step 3. Let's say move x.
Given startpos + a2a3 + x as p3, generate perft(1) for your engine and sf.
Since that is only perft(1) by this time you will be able to figure out the wrong move or the missing move from your generator. Setup that last position or p3 on the board and see the wrong/missing moves from your engine compared to sf perft(1) result.

【gdb】【list】what does the second line of echo mean

when i use list *func+offset to view src in gdb, the second line of echo make me confused, what's the relationship between line 304 and *rte_ring_create_elem+0x1cc.
(gdb) l *rte_ring_create_elem+0x1cc
0x9f744 is in rte_ring_create_elem (src/lib/librte_ring/rte_ring.c:309).
304 src/lib/librte_ring/rte_ring.c: No such file or directory.
below is the dpdk src with line number.
294 mz = rte_memzone_reserve_aligned(mz_name, ring_size, socket_id,
295 mz_flags, __alignof__(*r));
296 if (mz != NULL) {
297 r = mz->addr;
298 /* no need to check return value here, we already checked the
299 * arguments above */
300 rte_ring_init(r, name, requested_count, flags);
301
302 te->data = (void *) r;
303 r->memzone = mz;
304
305 TAILQ_INSERT_TAIL(ring_list, te, next);
306 } else {
307 r = NULL;
308 RTE_LOG(ERR, RING, "Cannot reserve memory\n");
309 rte_free(te);
310 }
311 rte_mcfg_tailq_write_unlock();
I have tried to secarh the answer, but there are all the usage guide for list.
The list * command lists (by default) 10 lines of source code around the address in the binary you specified.
In your case, you specified the symbolic address rte_ring_create_elem+0x1cc, so gdb helpfully prints the actual address that is (0x9f744) and tells you that corresponds to line 309 in rte_ring.c. It then tries to show 10 lines around that (lines 304-313), but it can't find the source file, so gives the error you see.

How to print table of 12 using recursion, I want it upto 10 but on running it turns out to be upto 12

I was trying to create a program to print table of 12 using recursion as I wrote a simple program for this I did get table, but table was instead upto 144 (12times12=144) instead of 120(12times10=120) I am sharing my code and output with you guys I was writing code in C++
//we will print table of 12 using concept of recursion
//a table of 12 is like this
//12 24 36 48 60 72 84 96 108 120
#include<iostream>
using namespace std;
void table(int n)
{
if(n==1)
{
cout<<12<<"\n";
return;
}
table(n-1);
cout<<n*12<<"\n";
}
int main(void)
{
table(12);
}
and now here is out put of this program
12
24
36
48
60
72
84
96
108
120
132
144
please help me what I'm missing here I am positive that adding some condition will help I tried one adding if(n==12) { return;} but it prevents does nothing as in the end it is return n*12

Assertion triggered in CGAL when computing polygon union

I'm writing an application in Python that applies a watermark to a font file. The glyphs are non-convex polygons with holes and consist of bezier splines defined in PostScript. The watermark needs to merge with the glyphs, not overlap. I was unable to find a library to do this in Python so I'm using CGAL & C++. I have it working nicely on most glyphs, but it's mysteriously failing on others.
Initially, I was very impressed with CGAL. It looked very comprehensive and sophisticated and seemed to provide all the functionality I needed, but it suffers one fatal flaw - and I almost can't believe it - the library contains no error handling. No error codes, no exceptions, just assertions - but only in the debug build. In the release build you get a nice segmentation fault instead. Furthermore, the assertions reveal nothing about the nature of the problem.
The program fails only on certain glyphs. The letter 'e' works fine, but it crashes on 'a'. The crash occurs when I attempt to compute the union of the glyph with the watermark. There is nothing visibly wrong with the 'a' glyph. My application parses the PostScript correctly and renders it fine on a QGraphicsView.
This program needs to run on a server and its output sent directly to the customer so it must be reliable. I can't recover from an assertion failure or a segfault, so what can I do?
Even if I get it working reliably, how can I trust that it will never fail? If there was some kind of error handling in place, I could just skip the few glyphs that it fails on, leaving them unwatermarked - not ideal, but acceptable. I just don't understand what the authors of this library were thinking; they went to such tremendous effort to make the most comprehensive geometry library available only to ensure that it's completely unfit for purpose.
Currently, it's looking like I'm going to have to modify the code myself to handle the error in a sensible way, but this just seems so ridiculous.
I'm sorry if I come off as impatient, but I'm way past my deadline and my client isn't going to care about or understand these excuses.
The assertion failure is occurring on line 2141 of multiset.h:
CGAL_multiset_precondition (comp_f(object, nodeP->object) != LARGER);
It happens when I call join() on a BezierPolygonSet. My types are as follows:
typedef CGAL::CORE_algebraic_number_traits NtTraits;
typedef NtTraits::Rational Rational;
typedef NtTraits::Algebraic Algebraic;
typedef CGAL::Cartesian<Rational> RatKernel;
typedef CGAL::Cartesian<Algebraic> AlgKernel;
typedef RatKernel::Point_2 BezierRatPoint;
typedef CGAL::Arr_Bezier_curve_traits_2<RatKernel, AlgKernel, NtTraits> Traits;
typedef Traits::Point_2 BezierPoint;
typedef Traits::Curve_2 BezierCurve;
typedef CGAL::Gps_traits_2<Traits> BezierTraits;
typedef BezierTraits::X_monotone_curve_2 BezierXMonotoneCurve;
typedef BezierTraits::General_polygon_2 BezierPolygon;
typedef BezierTraits::General_polygon_with_holes_2 BezierPolygonWithHoles;
typedef CGAL::Gps_default_dcel<BezierTraits> BezierDcelTraits;
typedef CGAL::General_polygon_set_2<BezierTraits, BezierDcelTraits> BezierPolygonSet;
Any help would be much appreciated. Thanks.
EDIT:
I have a module called Geometry which wraps the CGAL code and exposes a bunch of geometric primitives (Point, Curve, LineSegment, CubicBezier, Path) and the functions:
PathList toPathList(const PolyList& polyList);
PolyList toPolyList(const PathList& paths);
The Path class has a method called computeUnion, which looks like this:
PathList Path::computeUnion(const PathList& paths1, const PathList& paths2) {
PolyList polyList1 = toPolyList(paths1);
PolyList polyList2 = toPolyList(paths2);
cgal_wrap::BezierPolygonSet polySet;
for (auto i : polyList1) {
polySet.join(i);
}
for (auto i : polyList2) {
polySet.join(i);
}
PolyList polyList;
polySet.polygons_with_holes(std::back_inserter(polyList));
return toPathList(polyList);
}
The error occurs when I call join(). The polygons are created from paths like so:
PolyList toPolyList(const PathList& paths) {
cgal_wrap::Traits traits;
cgal_wrap::Traits::Make_x_monotone_2 fnMakeXMonotone = traits.make_x_monotone_2_object();
cgal_wrap::RatKernel ratKernel;
cgal_wrap::RatKernel::Equal_2 fnEqual = ratKernel.equal_2_object();
PolyList polyList; // The final polygons with holes
cgal_wrap::BezierPolygon outerPoly;
std::list<cgal_wrap::BezierPolygon> holes;
std::list<cgal_wrap::BezierXMonotoneCurve> monoCurves;
bool first = true;
cgal_wrap::BezierRatPoint firstPoint;
// For each path in the list
for (auto i = paths.begin(); i != paths.end(); ++i) {
const Path& path = *i;
cgal_wrap::BezierRatPoint prevEndPoint;
// For each curve in the path
for (auto j = path.begin(); j != path.end(); ++j) {
const Curve& curve = **j;
std::list<cgal_wrap::BezierRatPoint> points;
if (curve.type() == LineSegment::type) {
const LineSegment& lseg = dynamic_cast<const LineSegment&>(curve);
cgal_wrap::BezierRatPoint A = lseg.A();
if (j != path.begin()) {
if (A != prevEndPoint) {
// TODO
assert(false);
}
A = prevEndPoint;
}
points.push_back(cgal_wrap::BezierRatPoint(A));
points.push_back(cgal_wrap::BezierRatPoint(lseg.B()));
}
else if (curve.type() == CubicBezier::type) {
const CubicBezier& bezier = dynamic_cast<const CubicBezier&>(curve);
cgal_wrap::BezierRatPoint A = bezier.A();
if (j != path.begin()) {
if (A != prevEndPoint) {
// TODO
assert(false);
}
A = prevEndPoint;
}
points.push_back(cgal_wrap::BezierRatPoint(A));
points.push_back(cgal_wrap::BezierRatPoint(bezier.B()));
points.push_back(cgal_wrap::BezierRatPoint(bezier.C()));
points.push_back(cgal_wrap::BezierRatPoint(bezier.D()));
}
bool bClosesCurve = false;
if (!first && Point(points.back()) == Point(firstPoint)) {
points.pop_back();
points.push_back(firstPoint);
bClosesCurve = true;
}
prevEndPoint = points.back();
cgal_wrap::BezierCurve cgalCurve(points.begin(), points.end());
std::list<CGAL::Object> monoObjs;
fnMakeXMonotone(cgalCurve, std::back_inserter(monoObjs));
// Append the x-monotone curves to the list
cgal_wrap::BezierXMonotoneCurve monoCurve;
for (auto o = monoObjs.begin(); o != monoObjs.end(); ++o) {
if (CGAL::assign(monoCurve, *o)) {
monoCurves.push_back(monoCurve);
}
}
if (!first) {
// If this curve closes the current chain, thereby creating a new polygon
if (bClosesCurve) {
// Add the new polygon to the list
cgal_wrap::BezierPolygon subPoly(monoCurves.begin(), monoCurves.end());
if (subPoly.orientation() == CGAL::COUNTERCLOCKWISE) {
if (!outerPoly.is_empty()) {
polyList.push_back(cgal_wrap::BezierPolygonWithHoles(outerPoly, holes.begin(), holes.end()));
holes.clear();
}
outerPoly = subPoly;
}
else {
holes.push_back(subPoly);
}
monoCurves.clear();
first = true;
}
}
else {
// This is the first curve in the chain - store its source point
firstPoint = cgalCurve.control_point(0);
first = false;
}
}
}
polyList.push_back(cgal_wrap::BezierPolygonWithHoles(outerPoly, holes.begin(), holes.end()));
return polyList;
}
Notice that I'm careful to ensure that the polygon boundaries have no gaps by setting the first point of curve n+1 to the last point of curve n in case they were slightly different. I was hoping this would solve the problem, but it didn't. I can't think of any other things that might make the shapes invalid.
Here is the successful merging of the 'e' glyph with the watermark (an X).
Here is what the 'a' glyph looks like. The merging fails on this glyph.
EDIT 2:
Here are the curves that make up the 'a' glyph after parsing it from PostScript. There doesn't appear to be anything wrong with it. As I said, it looks okay when rendered. The error probably occurs during the translation from this data into the CGAL types. The line segments get translated into BezierCurves with 2 control points. I will investigate further.
LineSegment[(344, 0), (409, 0)]
CubicBezier[(409, 0), (403, 24), (400, 68), (400, 161)]
LineSegment[(400, 161), (400, 324)]
CubicBezier[(400, 324), (400, 437), (330, 485), (232, 485)]
CubicBezier[(232, 485), (180, 485), (121, 472), (66, 437)]
LineSegment[(66, 437), (94, 385)]
CubicBezier[(94, 385), (127, 405), (167, 424), (224, 424)]
CubicBezier[(224, 424), (283, 424), (326, 392), (326, 320)]
LineSegment[(326, 320), (326, 290)]
LineSegment[(326, 290), (236, 287)]
CubicBezier[(236, 287), (188, 285), (150, 280), (118, 264)]
CubicBezier[(118, 264), (70, 242), (38, 199), (38, 136)]
CubicBezier[(38, 136), (38, 45), (102, -10), (188, -10)]
CubicBezier[(188, -10), (247, -10), (293, 18), (330, 53)]
LineSegment[(330, 53), (344, 0)]
LineSegment[(326, 234), (326, 114)]
CubicBezier[(326, 114), (304, 91), (260, 52), (201, 52)]
CubicBezier[(201, 52), (147, 52), (113, 88), (113, 140)]
CubicBezier[(113, 140), (113, 171), (127, 198), (154, 213)]
CubicBezier[(154, 213), (175, 224), (202, 230), (243, 231)]
LineSegment[(243, 231), (326, 234)]
EDIT 3:
Here are the 'a' glyph curves after translation into CGAL curves. Notice that they exactly match the curves before translation implying that none of them had to be split into X-monotone subcurves; they must have all been X-monotone already.
Outer boundary:
2 344 0 409 0 [1] | 344 0 --> 409 0
4 409 0 403 24 400 68 400 161 [1] | 409 0 --> 400 161
2 400 161 400 324 [1] | 400 161 --> 400 324
4 400 324 400 437 330 485 232 485 [1] | 400 324 --> 232 485
4 232 485 180 485 121 472 66 437 [1] | 232 485 --> 66 437
2 66 437 94 385 [1] | 66 437 --> 94 385
4 94 385 127 405 167 424 224 424 [1] | 94 385 --> 224 424
4 224 424 283 424 326 392 326 320 [1] | 224 424 --> 326 320
2 326 320 326 290 [1] | 326 320 --> 326 290
2 326 290 236 287 [1] | 326 290 --> 236 287
4 236 287 188 285 150 280 118 264 [1] | 236 287 --> 118 264
4 118 264 70 242 38 199 38 136 [1] | 118 264 --> 38 136
4 38 136 38 45 102 -10 188 -10 [1] | 38 136 --> 188 -10
4 188 -10 247 -10 293 18 330 53 [1] | 188 -10 --> 330 53
2 330 53 344 0 [1] | 330 53 --> 344 0
Holes:
Hole:
2 326 234 326 114 [1] | 326 234 --> 326 114
4 326 114 304 91 260 52 201 52 [1] | 326 114 --> 201 52
4 201 52 147 52 113 88 113 140 [1] | 201 52 --> 113 140
4 113 140 113 171 127 198 154 213 [1] | 113 140 --> 154 213
4 154 213 175 224 202 230 243 231 [1] | 154 213 --> 243 231
2 243 231 326 234 [1] | 243 231 --> 326 234
This polygon causes the assertion failure when added to a BezierPolygonSet. Any ideas?
You can customize error handling; see the manual.
Please attach a complete standalone program. Nothing looks wrong to me with statements you listed.
You can approximate the Bezier curves with polylines and process the whole things using polylines. If the problem is with the handling of Bezier curves, then this would solve it. If this is acceptable, it will also be more efficient.
We have fixed a bug in the CGAL component that handles Bezier curves, namely, Arr_Bezier_curve_traits_2.h.

Understanding some C++ coding practice [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am currently trying to understand how the following code (http://pastebin.com/zTHUrmyx) works, my approach is currently compiling the software in debug and using gdb to step through the code.
However, I'm running into the problem that 'step' does not always tell me what is going on. Particularly unclear to me is the EXECUTE {...} which I cannot step into.
How do I go about learning what the code is doing?
1 /*
2 Copyright 2008 Brain Research Institute, Melbourne, Australia
3
4 Written by J-Donald Tournier, 27/06/08.
5
6 This file is part of MRtrix.
7
8 MRtrix is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 MRtrix is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with MRtrix. If not, see <http://www.gnu.org/licenses/>.
20
21
22 15-10-2008 J-Donald Tournier <d.tournier#brain.org.au>
23 * fix -prs option handling
24 * remove MR::DICOM_DW_gradients_PRS flag
25
26 15-10-2008 J-Donald Tournier <d.tournier#brain.org.au>
27 * add -layout option to manipulate data ordering within the image file
28
29 14-02-2010 J-Donald Tournier <d.tournier#brain.org.au>
30 * fix -coord option so that the "end" keyword can be used
31
32
33 */
34
35 #include "app.h"
36 #include "image/position.h"
37 #include "image/axis.h"
38 #include "math/linalg.h"
39
40 using namespace std;
41 using namespace MR;
42
43 SET_VERSION_DEFAULT;
44
45 DESCRIPTION = {
46 "perform conversion between different file types and optionally extract a subset of the input image.",
47 "If used correctly, this program can be a very useful workhorse. In addition to converting images between different formats, it can be used to extract specific studies from a data set, extract a specific region of interest, flip the images, or to scale the intensity of the images.",
48 NULL
49 };
50
51 ARGUMENTS = {
52 Argument ("input", "input image", "the input image.").type_image_in (),
53 Argument ("ouput", "output image", "the output image.").type_image_out (),
54 Argument::End
55 };
56
57
58 const gchar* type_choices[] = { "REAL", "IMAG", "MAG", "PHASE", "COMPLEX", NULL };
59 const gchar* data_type_choices[] = { "FLOAT32", "FLOAT32LE", "FLOAT32BE", "FLOAT64", "FLOAT64LE", "FLOAT64BE",
60 "INT32", "UINT32", "INT32LE", "UINT32LE", "INT32BE", "UINT32BE",
61 "INT16", "UINT16", "INT16LE", "UINT16LE", "INT16BE", "UINT16BE",
62 "CFLOAT32", "CFLOAT32LE", "CFLOAT32BE", "CFLOAT64", "CFLOAT64LE", "CFLOAT64BE",
63 "INT8", "UINT8", "BIT", NULL };
64
65 OPTIONS = {
66 Option ("coord", "select coordinates", "extract data only at the coordinates specified.", false, true)
67 .append (Argument ("axis", "axis", "the axis of interest").type_integer (0, INT_MAX, 0))
68 .append (Argument ("coord", "coordinates", "the coordinates of interest").type_sequence_int()),
69
70 Option ("vox", "voxel size", "change the voxel dimensions.")
71 .append (Argument ("sizes", "new dimensions", "A comma-separated list of values. Only those values specified will be changed. For example: 1,,3.5 will change the voxel size along the x & z axes, and leave the y-axis voxel size unchanged.")
72 .type_sequence_float ()),
73
74 Option ("datatype", "data type", "specify output image data type.")
75 .append (Argument ("spec", "specifier", "the data type specifier.").type_choice (data_type_choices)),
76
77 Option ("scale", "scaling factor", "apply scaling to the intensity values.")
78 .append (Argument ("factor", "factor", "the factor by which to multiply the intensities.").type_float (NAN, NAN, 1.0)),
79
80 Option ("offset", "offset", "apply offset to the intensity values.")
81 .append (Argument ("bias", "bias", "the value of the offset.").type_float (NAN, NAN, 0.0)),
82
83 Option ("zero", "replace NaN by zero", "replace all NaN values with zero."),
84
85 Option ("output", "output type", "specify type of output")
86 .append (Argument ("type", "type", "type of output.")
87 .type_choice (type_choices)),
88
89 Option ("layout", "data layout", "specify the layout of the data in memory. The actual layout produced will depend on whether the output image format can support it.")
90 .append (Argument ("spec", "specifier", "the data layout specifier.").type_string ()),
91
92 Option ("prs", "DW gradient specified as PRS", "assume that the DW gradients are specified in the PRS frame (Siemens DICOM only)."),
93
94 Option::End
95 };
96
97
98
99 inline bool next (Image::Position& ref, Image::Position& other, const std::vector<int>* pos)
100 {
101 int axis = 0;
102 do {
103 ref.inc (axis);
104 if (ref[axis] < ref.dim(axis)) {
105 other.set (axis, pos[axis][ref[axis]]);
106 return (true);
107 }
108 ref.set (axis, 0);
109 other.set (axis, pos[axis][0]);
110 axis++;
111 } while (axis < ref.ndim());
112 return (false);
113 }
114
115
116
117
118
119 EXECUTE {
120 std::vector<OptBase> opt = get_options (1); // vox
121 std::vector<float> vox;
122 if (opt.size())
123 vox = parse_floats (opt[0][0].get_string());
124
125
126 opt = get_options (3); // scale
127 float scale = 1.0;
128 if (opt.size()) scale = opt[0][0].get_float();
129
130 opt = get_options (4); // offset
131 float offset = 0.0;
132 if (opt.size()) offset = opt[0][0].get_float();
133
134 opt = get_options (5); // zero
135 bool replace_NaN = opt.size();
136
137 opt = get_options (6); // output
138 Image::OutputType output_type = Image::Default;
139 if (opt.size()) {
140 switch (opt[0][0].get_int()) {
141 case 0: output_type = Image::Real; break;
142 case 1: output_type = Image::Imaginary; break;
143 case 2: output_type = Image::Magnitude; break;
144 case 3: output_type = Image::Phase; break;
145 case 4: output_type = Image::RealImag; break;
146 }
147 }
148
149
150
151
152 Image::Object &in_obj (*argument[0].get_image());
153
154 Image::Header header (in_obj);
155
156 if (output_type == 0) {
157 if (in_obj.is_complex()) output_type = Image::RealImag;
158 else output_type = Image::Default;
159 }
160
161 if (output_type == Image::RealImag) header.data_type = DataType::CFloat32;
162 else if (output_type == Image::Phase) header.data_type = DataType::Float32;
163 else header.data_type.unset_flag (DataType::ComplexNumber);
164
165
166 opt = get_options (2); // datatype
167 if (opt.size()) header.data_type.parse (data_type_choices[opt[0][0].get_int()]);
168
169 for (guint n = 0; n < vox.size(); n++)
170 if (isfinite (vox[n])) header.axes.vox[n] = vox[n];
171
172 opt = get_options (7); // layout
173 if (opt.size()) {
174 std::vector<Image::Axis> ax = parse_axes_specifier (header.axes, opt[0][0].get_string());
175 if (ax.size() != (guint) header.axes.ndim())
176 throw Exception (String("specified layout \"") + opt[0][0].get_string() + "\" does not match image dimensions");
177
178 for (guint i = 0; i < ax.size(); i++) {
179 header.axes.axis[i] = ax[i].axis;
180 header.axes.forward[i] = ax[i].forward;
181 }
182 }
183
184
185 opt = get_options (8); // prs
186 if (opt.size() && header.DW_scheme.rows() && header.DW_scheme.columns()) {
187 for (guint row = 0; row < header.DW_scheme.rows(); row++) {
188 double tmp = header.DW_scheme(row, 0);
189 header.DW_scheme(row, 0) = header.DW_scheme(row, 1);
190 header.DW_scheme(row, 1) = tmp;
191 header.DW_scheme(row, 2) = -header.DW_scheme(row, 2);
192 }
193 }
194
195 std::vector<int> pos[in_obj.ndim()];
196
197 opt = get_options (0); // coord
198 for (guint n = 0; n < opt.size(); n++) {
199 int axis = opt[n][0].get_int();
200 if (pos[axis].size()) throw Exception ("\"coord\" option specified twice for axis " + str (axis));
201 pos[axis] = parse_ints (opt[n][1].get_string(), header.dim(axis)-1);
202 header.axes.dim[axis] = pos[axis].size();
203 }
204
205 for (int n = 0; n < in_obj.ndim(); n++) {
206 if (pos[n].empty()) {
207 pos[n].resize (in_obj.dim(n));
208 for (guint i = 0; i < pos[n].size(); i++) pos[n][i] = i;
209 }
210 }
211
212
213 in_obj.apply_scaling (scale, offset);
214
215
216
217
218
219
220 Image::Position in (in_obj);
221 Image::Position out (*argument[1].get_image (header));
222
223 for (int n = 0; n < in.ndim(); n++) in.set (n, pos[n][0]);
224
225 ProgressBar::init (out.voxel_count(), "copying data...");
226
227 do {
228
229 float re, im = 0.0;
230 in.get (output_type, re, im);
231 if (replace_NaN) if (gsl_isnan (re)) re = 0.0;
232 out.re (re);
233
234 if (output_type == Image::RealImag) {
235 if (replace_NaN) if (gsl_isnan (im)) im = 0.0;
236 out.im (im);
237 }
238
239 ProgressBar::inc();
240 } while (next (out, in, pos));
241
242 ProgressBar::done();
243 }
As was noted in the comments, EXECUTE seems to be a macro, apparent from the context a function header (and maybe a bit more, e.g. some global variables and functions), so the part in curly braces is the function body.
To get to the definition of EXECUTE, you will have to examine the headers.
However, if you can reach some part of the code during debugging, you could insert a string or char[] at that point, giving it the stringified version of EXECUTE, so you get whatever the preprocessor will emit for EXECUTE at that position in the code.
#define STR(x) #x
#define STRINGIFY(x) STR(x)
char c[] = STRINGIFY(EXECUTE);
the two macros are a known little macro trick to get the content of any macro as a string literal. Try it out and inspect the char array in your debugger to get the content of execute.
My wild guess here: EXECUTE is the main function or a replacement for it, the OPTIONS and ARGUMENTS describe what arguments the program expects and what command line options you can pass to it. Those macros and some of the used functions and variables (get_options, argument) are part of a little framework that should facilitate the usage, evaluation and user information about command line options.