├── .gitignore
├── LICENSE
├── README.md
├── SynthRAD_banner.png
├── analysis_paper.py
├── configs
├── param_def_cbct_AB.txt
├── param_def_cbct_AB_2ABD.txt
├── param_def_cbct_HN.txt
├── param_def_cbct_TH.txt
├── param_def_mr_AB.txt
├── param_def_mr_HN.txt
├── param_def_mr_TH.txt
├── param_inverse_def.txt
├── param_rigid.txt
├── param_rigid_general.txt
├── param_rigid_large_1024.txt
├── param_rigid_large_4096.txt
├── param_rigid_large_512.txt
├── param_rigid_simple.txt
├── param_rigid_small_4096.txt
├── param_rigid_small_512.txt
├── param_trans_simple.txt
├── tags_CBCT.txt
├── tags_CT.txt
└── tags_MR.txt
├── docker
├── Dockerfile
├── docker-compose.yml
└── requirements.txt
├── preprocessing_utils.py
├── stage1.py
├── stage1_config.csv
├── stage2.py
├── stage2_config.csv
└── utilities
├── clip_data.py
├── create_final_csvs.py
├── create_final_release.py
└── extract_dicom_tags.py
/.gitignore:
--------------------------------------------------------------------------------
1 | utils_stage1.ipynb
2 | /__pycache__/
3 | *.log
4 | stage1.ipynb
5 | stage2.ipynb
6 | stage2_details.txt
7 | stage2_config_AB.csv
8 | test_deformable.ipynb
9 | stage2_config_HN.csv
10 | stage2_config_TH.csv
11 | stage2_config_TH copy.csv
12 | stage2_config_TH_single.csv
13 | 2ABA002_planning.png
14 | create_release.py
15 | .~lock.stage1_config_full.csv#
16 | .~lock.stage1_config.csv#
17 | stage1_config_full.csv
18 | .~lock.stage2_config_AB.csv#
19 | .~lock.stage2_config.csv#
20 | stage2_config_TH_A.csv
21 | fix_structure_stitching.py
22 | utilities/download_data_split.py
23 | utilities/client_secrets.json
24 | local/
25 |
26 | utilities/download_parameters.py
27 | analysis_paper.ipynb
28 | .gitignore
29 | asd.csv
30 | utilities/apply_renaming.ipynb
31 | utilities/create_preliminary.py
32 | utilities/find_biggest_array.py
33 | utilities/padd_preliminary.ipynb
34 | utilities/qa_clip.py
35 | utilities/zip_dirs.sh
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [![Contributors][contributors-shield]][contributors-url]
2 | [![Forks][forks-shield]][forks-url]
3 | [![Stargazers][stars-shield]][stars-url]
4 | [![Issues][issues-shield]][issues-url]
5 | [![GNU GPL-v3.0][license-shield]][license-url]
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Data preprocessing step for the
16 | SynthRAD2025 Grand Challenge
17 |
18 | Explore the docs »
19 |
20 |
21 | View Demo
22 | ·
23 | Report Bug
24 | ·
25 | Request Feature
26 |
27 |
28 |
29 | # SynthRAD2025 pre-processing
30 | This repository contains the code for pre-processing the data for the [SynthRAD2025 challenge](https://synthrad2025.grand-challenge.org/). The data preprocessing is performed in two stages:
31 | 1. **Stage 1** contains all pre-processing steps carried out locally in each data providing center. This includes the following steps:
32 | - **Data conversion**: All image data is converted to .nii.gz and .nrrd format.
33 | - **Rigid registration**: CBCT and MR images are registered to the corresponding CT images.
34 | - **Defacing**: Datasets with visible faces in the images are defaced.
35 | - **Resampling**: Images are resampled to a common voxel size.
36 |
37 | 2. **Stage 2** contains all steps that are carried out for the entire dataset at once and includes the following steps:
38 | - **Deformable image registration**: MR/CBCT images are deformably registered to the CT
39 | - **Cropping**: CBCT/CT/MR and structures are cropped to the same size.
40 | - **Validation**: The preprocessed data is validated to ensure that the preprocessing steps have been carried out correctly.
41 | - **Dataset creation**: The preprocessed data is seperated into training/validation and test datasets. Furthermore separate datasets for centers and tasks are created.
42 |
43 | # Requirements
44 |
45 | The code is written/tested in Python 3.12.3 The following packages are required to run the code:
46 |
47 | - SimpleITK-SimpleElastix
48 | - numpy
49 | - nibabel
50 | - scipy
51 | - totalsegmentator
52 | - matplotlib
53 | - csv
54 |
55 | For Dicom tag extraction the following packages are required:
56 | - pydicom
57 | - openpyxl
58 |
59 | To convert RT structs to .nrrd files plastimatch is required. Plastimatch can be downloaded from [here](https://plastimatch.org/). The path to plastimatch should be added to the system path.
60 |
61 | # Usage
62 |
63 | The code is organized in two main files: [stage1.py](./stage1.py) and [stage2.py](./stage2.py). The code for stage 1 can be run by executing the following command:
64 |
65 | ```python stage1.py config.csv```
66 |
67 | ## Stage 1
68 |
69 | ### Inputs
70 |
71 | [stage1_config.csv](./stage1_config.csv) is a configuration file that contains the paths to the input data and the parameters for the preprocessing steps. The configuration file contains a header in the first row each further row contains configuration for a single patient. The configuration file should contain the following columns:
72 |
73 | | column | description | parsed as|
74 | | ------------- |-------------| -------|
75 | | **ID** | A unique patient ID in the synhtRAD2025 format: [Task][Region][Center][001-999].| str |
76 | | **task** | *1* for Task 1 (MR-to-CT) and *2* for Task 2 (CBCT-to-CT) |int|
77 | | **region** | *HN* for head and neck, *AB* for abdomen, *TH* for thorax | string |
78 | | **ct_path** | path to CT image, can be a dicom directory or a single file compatible with SimpleITK (e.g .mha, .nrrd, .nii.gz, ...) | string |
79 | | **input_path**| path to MR/CBCT image, can be a dicom directory or a single file compatible with SimpleITK (e.g .mha, .nrrd, .nii.gz, ...) | string |
80 | | **struct_path**| path to RTstruct file, can be left empty if no structure file is available| string |
81 | | **output_dir**| path to output directory, if directory does not exist it will be generated| string |
82 | | **defacing**| *True* if defacing is required, *False* otherwise| bool |
83 | | **registration**| path to registration parameter file, registration files are provided in [configs](./configs/)| bool |
84 | | **reg_fovmask**| *True* if a FOV mask should be used for registration, *False* otherwise| bool |
85 | | **background**| intensity of background, usually 0 for MR and -1024 for CBCT, but can vary between centers/regions and can influence FOV masking| float |
86 | | **order**| order of axis, usually should be [Sagittal, Coronal, Axial], if reordering is required indicate order using following notation: e.g. [2,1,0] reverses the order | array |
87 | | **flip**| flip an axis, usually should be [False, False, False], if flipping is required indicate flip using following notation: e.g. [True, False, False] flips the first axis | array |
88 | | **resample**| resamples to a uniform voxel size, indicate the target voxel size with array, e.g. [1,1,3] results in in-plane voxel size of 1mm x 1mm and slice thickness of 3 mm | array |
89 | | **mr_overlap_correction**| *True* if MR overlap correction (some centers have artificial override to match multiple scans) is required, *False* otherwise| bool |
90 | | **intensity_shift**| shifts the intensity of an image, usually 0, but can be required for CBCTs| float |
91 |
92 | ### Outputs
93 |
94 | stage1.py generates the following outputs for each patient:
95 |
96 | - **ct_s1.nii.gz**: defaced (if HN) and resampled CT image
97 | - **mr_s1.nii.gz**: defaced (if HN), resampled and registered MR image (only for task 1 cases)
98 | - **cbct_s1.nii.gz**: defaced (if HN), resampled and registered CBCT image (only for task 2 cases)
99 | - **fov_s1.nii.gz**: FOV mask of input image (CBCT/MR) in CT frame of reference
100 | - **defacing_mask.nii.gz**: mask of defaced region
101 | - **transform.tfm**: transformation file from input image to CT frame of reference
102 | - **overview.png**: overview image of the CT and input images (CBCT/MR)
103 |
104 | ### Troubleshooting
105 |
106 | #### Registration
107 | In case the registration fails, the following steps can be taken:
108 | - If the script crashes during registration, try changing the registration parameter file and use a parameter file with more or less sampling points (indicated by the number in the filename).
109 | - If the script does not crash, but images are not registered correctly, try changing the registration parameter file. If you are currently using `param_rigid_small_*.txt`, try using a `param_rigid_large_*.txt` parameter file (or the other way around).
110 |
111 |
112 | ## Stage 2
113 |
114 | ### Inputs
115 | [stage2_config.csv](./stage2_config.csv) is a configuration file that contains all input parameters for the second stage. The configuration file contains a header in the first row and each further row contains configuration parameters for a single patient. The configuration file must contain the following columns:
116 |
117 | | column | description | parsed as|
118 | | ------------- |-----------------------| ---------|
119 | | **ID** | A unique patient ID in the synhtRAD2025 format: [Task][Region][Center][001-999].| str |
120 | | **task** | *1* for Task 1 (MR-to-CT) and *2* for Task 2 (CBCT-to-CT) |int|
121 | | **region** | *HN* for head and neck, *AB* for abdomen, *TH* for thorax | string |
122 | | **output_dir** | directory containing outputs from stage1 and where all generated data from stage 1 will be stored | string |
123 | | **mask_thresh**| threshold for masking patient outline, value between 0 and 1, see stage2_config.csv for examples| float |
124 | |**defacing_correction**| *True* if defacing correction is required, *False* otherwis, ensures that all masks and images are defaced correctly| bool |
125 | |**cone_correction**| *True* if cone correction is required, *False* otherwise, ensures that all masks and images are corrected for cone beam artifacts at FOV edge, used only in Task2 | bool |
126 | |**IS_correction**| *True* if inferior-superuior FOV corrections are required, *False* otherwise, used mainly for 1B data | bool |
127 | |**parameter_def**| path to parameter file for deformable registration, example registration files are provided in [configs](./configs/)| string |
128 | |**invert_structures**| if structures are delineated on the MR frame of reference instead of CT set to true| bool |
129 |
130 | ### Outputs
131 | stage2.py generates the following outputs for each patient:
132 | - **ct_s2.nii.gz**: resampled and cropped CT image
133 | - **mr_s2.nii.gz**: resampled, registered and cropped MR image (only for task 1 cases)
134 | - **cbct_s2.nii.gz**: resampled, registered and cropped CBCT image (only for task 2 cases)
135 | - **fov_s2.nii.gz**: FOV mask of input image (CBCT/MR) in CT frame of reference
136 | - **transform_def.txt**: transformation file from input image to CT frame of reference
137 | - **ID_s2.png**: overview image of the CT, input images (CBCT/MR), mask and and overlay
138 | - **ID_planning_s2.nrrd**: overview image showing also the deformed CT, planning structures and overlays for the deformed image
139 |
140 | ## Dicom tag extraction
141 |
142 | Following functions are available to extract relevant image acqusition parameters and some patient characteristics. Tags that are extracte are defined in the [tags_CBCT.txt](./configs/tags_CBCT.txt), [tags_MR.txt](./configs/tags_MR.txt) and [tags_CT.txt](./configs/tags_CT.txt) files.
143 |
144 | **read_tags(input_txt)**
145 |
146 | description:
147 | read dicom tag strings from a txt file
148 |
149 | arguments:
150 | input_txt: file path to text file containg dicom tags (see example in param_files)
151 |
152 | returns:
153 | python list containing dicom tags
154 |
155 | **extract_tags(dcm_folder_path,tag_list,pre_processed=None)**
156 |
157 | description:
158 | extracts tags from a folder containg dicom files (only from the first element) and from pre-processed nifti images
159 |
160 | arguments:
161 | dcm_folder_path: path to folder containing dicom image slices
162 | tag_list: list defining which tags to extract
163 | pre_processed: path to pre-processed nifti file (can be left out if tags should be only extracted from dicom files)
164 |
165 | returns:
166 | python dict with dicom tags as key:value pairs
167 |
168 | **write_dict_to_csv(input_dict,output_csv,tag_list)**
169 |
170 | description:
171 | takes a dict containing dicom tags and writes it to a csv file
172 |
173 | arguments:
174 | input_dict: dict containing extracted tags
175 | output_csv: filename of output csv file
176 | tag_list: list of dicom tags, necessary to create header in csv file
177 |
178 | **write_csv_to_xlsx(input_csv,output_xlsx)**
179 |
180 | description:
181 | takes a csv and creates an xlsx file
182 |
183 | arguments:
184 | input_csv: path to csv file
185 | output_xlsx: filepath of output xlsx file
186 |
187 |
188 |
190 | [contributors-shield]: https://img.shields.io/github/contributors/SynthRAD2025/preprocessing.svg?style=flat-square
191 | [contributors-url]: https://github.com/SynthRAD2025/preprocessing/graphs/contributors
192 | [forks-shield]: https://img.shields.io/github/forks/SynthRAD2025/preprocessing.svg?style=flat-square
193 | [forks-url]: https://github.com/SynthRAD2025/preprocessing/network/members
194 | [stars-shield]: https://img.shields.io/github/stars/SynthRAD2025/preprocessing.svg?style=flat-square
195 | [stars-url]: https://github.com/SynthRAD2025/preprocessing/stargazers
196 | [issues-shield]: https://img.shields.io/github/issues/SynthRAD2025/preprocessing.svg?style=flat-square
197 | [issues-url]: https://github.com/SynthRAD2025/preprocessing/issues
198 | [license-shield]: https://img.shields.io/github/license/SynthRAD2025/preprocessing.svg?style=flat-square
199 | [license-url]: https://github.com/SynthRAD2025/preprocessing/blob/master/LICENSE.txt
200 |
--------------------------------------------------------------------------------
/SynthRAD_banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SynthRAD2025/preprocessing/8a5b125e3a2a3e92287ed381519f5416bbb358b4/SynthRAD_banner.png
--------------------------------------------------------------------------------
/analysis_paper.py:
--------------------------------------------------------------------------------
1 | import preprocessing_utils as utils
2 | import os
3 | import pandas as pd
4 | import matplotlib.pyplot as plt
5 | import SimpleITK as sitk
6 |
7 | ROOT = "/workspace/data/full"
8 |
9 | CENTERS = ['A','B','C','D','E']
10 | TASKS = ['1','2']
11 | REGIONS = ['HN','AB','TH']
12 | SETS = ['train','val','test']
13 |
14 | def outline_no_dilation(image,threshold):
15 | mask = utils.segment_outline(image, threshold=threshold)
16 | return mask
17 |
18 | df = pd.DataFrame(columns=['Patient ID', 'Volume_mask', 'Volume_img', 'Task', 'Center', 'Region'])
19 |
20 | for center in CENTERS:
21 | for task in TASKS:
22 | for region in REGIONS:
23 | for set in SETS:
24 | # Read patient IDs from Set file
25 | source = os.path.join(ROOT, center, f'Task{task}', region)
26 | set_file = os.path.join(source, f'{task}{region}{center}_Set.csv')
27 | pre_process_settings = os.path.join(source, f'stage2_config_{task}{region}{center}.csv')
28 | if not os.path.exists(pre_process_settings):
29 | continue
30 | # Read pre-process settings
31 | pre_params = pd.read_csv(pre_process_settings)
32 |
33 | if os.path.exists(set_file):
34 | with open(set_file) as f:
35 | lines = f.readlines()
36 | for i,line in enumerate(lines):
37 | if i > 0:
38 | line = line.strip()
39 | line = line.strip("'")
40 | if line == "":
41 | continue
42 | patient_id = line.split(",")[0].strip('"').strip("'")
43 | patient_set = line.split(",")[1].strip('"')
44 | if patient_set.lower() == set:
45 | # Read mask
46 | if task == '1':
47 | img_file = os.path.join(source,patient_id,'output','mr_s2.nii.gz')
48 | else:
49 | img_file = os.path.join(source,patient_id,'output','cbct_s2.nii.gz')
50 | if os.path.exists(img_file):
51 | print(patient_id)
52 | if not os.path.exists(os.path.join(source,patient_id,'output','mask_no_dilation.nii.gz')):
53 | print(f'{patient_id} segmenting...')
54 | img = utils.read_image(img_file)
55 | row = pre_params[pre_params['ID'] == patient_id]
56 | mask = outline_no_dilation(img, row['mask_thresh'].values[0])
57 | utils.save_image(mask, os.path.join(source,patient_id,'output','mask_no_dilation.nii.gz'))
58 | # new_row = pd.DataFrame({'Patient ID': [patient_id], 'Volume_mask': [volume], 'Volume_img': [volume_img], 'Task': [task], 'Center': [center], 'Region': [region]})
59 | # df = pd.concat([df, new_row], ignore_index=True)
60 | else:
61 | print(f"Mask file not found for patient ID: {patient_id}")
--------------------------------------------------------------------------------
/configs/param_def_cbct_AB.txt:
--------------------------------------------------------------------------------
1 | (FixedInternalImagePixelType "float")
2 | (MovingInternalImagePixelType "float")
3 | (FixedImageDimension 3)
4 | (MovingImageDimension 3)
5 | (UseDirectionCosines "true")
6 | (ErodeMask "true")
7 |
8 | // ******************* Main Components ************************
9 |
10 | (Registration "MultiMetricMultiResolutionRegistration")
11 | (Interpolator "BSplineInterpolator" "BSplineInterpolator" "BSplineInterpolator")
12 | (ResampleInterpolator "FinalBSplineInterpolator")
13 | (Resampler "DefaultResampler")
14 |
15 | (FixedImagePyramid "FixedRecursiveImagePyramid")
16 | (MovingImagePyramid "MovingRecursiveImagePyramid")
17 |
18 | (Optimizer "AdaptiveStochasticGradientDescent")
19 | (Transform "BSplineTransform")
20 | (Metric "AdvancedMattesMutualInformation" "TransformBendingEnergyPenalty" "TransformRigidityPenalty")
21 | (Metric0Weight 1 1 1)
22 | (Metric1Weight 10 10 10)
23 | (Metric2Weight 0.5 0.5 0.5)
24 |
25 | // ******************* Transformation **************************
26 |
27 | (GridSpacingSchedule 4 2 1)
28 | (FinalGridSpacingInPhysicalUnits 10)
29 | (HowToCombineTransforms "Compose")
30 |
31 | // ******************* Similarity measure *********************
32 |
33 | (NumberOfHistogramBins 100)
34 |
35 | // ******************** Multiresolution **********************
36 |
37 | (NumberOfResolutions 3)
38 | (ImagePyramidSchedule 4 4 4 2 2 2 1 1 1)
39 |
40 | // ******************* Optimizer ****************************
41 |
42 | (MaximumNumberOfIterations 500 200 100)
43 |
44 | // **************** Image sampling **********************
45 | (Sampler "RandomSampler")
46 | (NumberOfSpatialSamples 4096)
47 | (NewSamplesEveryIteration "true")
48 | (ImageSampler "Grid" "Grid" "Grid")
49 | (SampleGridSpacing 4 2 2)
50 | (SampleRegionSize 100)
51 | (UseRandomSampleRegion "true")
52 | (MaximumNumberOfSamplingAttempts 5)
53 | (RequiredRatioOfValidSamples 0.05)
54 |
55 | // ************* Interpolation and Resampling ****************
56 |
57 | (BSplineInterpolationOrder 3)
58 | (FinalBSplineInterpolationOrder 3)
59 |
60 | (ShowExactMetricValue "false")
61 | (WriteTransformParametersEachResolution "true")
62 | //(WriteResultImageAfterEachResolution "true")
63 | //(WritePyramidImagesAfterEachResolution "true")
64 |
65 | (DefaultPixelValue -1000)
66 | (WriteResultImage "true")
67 | (ResultImagePixelType "short")
68 | (ResultImageFormat "nii.gz")
--------------------------------------------------------------------------------
/configs/param_def_cbct_AB_2ABD.txt:
--------------------------------------------------------------------------------
1 | (FixedInternalImagePixelType "float")
2 | (MovingInternalImagePixelType "float")
3 | (FixedImageDimension 3)
4 | (MovingImageDimension 3)
5 | (UseDirectionCosines "true")
6 | (ErodeMask "true")
7 |
8 | // ******************* Main Components ************************
9 |
10 | (Registration "MultiMetricMultiResolutionRegistration")
11 | (Interpolator "BSplineInterpolator" "BSplineInterpolator" "BSplineInterpolator")
12 | (ResampleInterpolator "FinalBSplineInterpolator")
13 | (Resampler "DefaultResampler")
14 |
15 | (FixedImagePyramid "FixedRecursiveImagePyramid")
16 | (MovingImagePyramid "MovingRecursiveImagePyramid")
17 |
18 | (Optimizer "AdaptiveStochasticGradientDescent")
19 | (Transform "BSplineTransform")
20 | (Metric "AdvancedMattesMutualInformation" "TransformBendingEnergyPenalty" "TransformRigidityPenalty")
21 | (Metric0Weight 1 1 1)
22 | (Metric1Weight 10 10 10)
23 | (Metric2Weight 10 10 10)
24 |
25 | // ******************* Transformation **************************
26 |
27 | (GridSpacingSchedule 4 2 1)
28 | (FinalGridSpacingInPhysicalUnits 10)
29 | (HowToCombineTransforms "Compose")
30 |
31 | // ******************* Similarity measure *********************
32 |
33 | (NumberOfHistogramBins 100)
34 |
35 | // ******************** Multiresolution **********************
36 |
37 | (NumberOfResolutions 3)
38 | (ImagePyramidSchedule 4 4 4 2 2 2 1 1 1)
39 |
40 | // ******************* Optimizer ****************************
41 |
42 | (MaximumNumberOfIterations 500 200 100)
43 |
44 | // **************** Image sampling **********************
45 | (Sampler "RandomSampler")
46 | (NumberOfSpatialSamples 4096)
47 | (NewSamplesEveryIteration "true")
48 | (ImageSampler "Grid" "Grid" "Grid")
49 | (SampleGridSpacing 4 2 1)
50 | (SampleRegionSize 100)
51 | (UseRandomSampleRegion "true")
52 | (MaximumNumberOfSamplingAttempts 5)
53 | (RequiredRatioOfValidSamples 0.05)
54 |
55 | // ************* Interpolation and Resampling ****************
56 |
57 | (BSplineInterpolationOrder 3)
58 | (FinalBSplineInterpolationOrder 3)
59 |
60 | (ShowExactMetricValue "false")
61 | (WriteTransformParametersEachResolution "true")
62 | //(WriteResultImageAfterEachResolution "true")
63 | //(WritePyramidImagesAfterEachResolution "true")
64 |
65 | (DefaultPixelValue -1000)
66 | (WriteResultImage "true")
67 | (ResultImagePixelType "short")
68 | (ResultImageFormat "nii.gz")
--------------------------------------------------------------------------------
/configs/param_def_cbct_HN.txt:
--------------------------------------------------------------------------------
1 | (FixedInternalImagePixelType "float")
2 | (MovingInternalImagePixelType "float")
3 | (FixedImageDimension 3)
4 | (MovingImageDimension 3)
5 | (UseDirectionCosines "true")
6 | (ErodeMask "true")
7 |
8 | // ******************* Main Components ************************
9 |
10 | (Registration "MultiMetricMultiResolutionRegistration")
11 | (Interpolator "BSplineInterpolator" "BSplineInterpolator" "BSplineInterpolator")
12 | (ResampleInterpolator "FinalBSplineInterpolator")
13 | (Resampler "DefaultResampler")
14 |
15 | (FixedImagePyramid "FixedRecursiveImagePyramid")
16 | (MovingImagePyramid "MovingRecursiveImagePyramid")
17 |
18 | (Optimizer "AdaptiveStochasticGradientDescent")
19 | (Transform "BSplineTransform")
20 | (Metric "AdvancedMattesMutualInformation" "TransformBendingEnergyPenalty" "TransformRigidityPenalty")
21 | (Metric0Weight 1 1 1)
22 | (Metric1Weight 10 10 10)
23 | (Metric2Weight 0.5 0.5 0.5)
24 |
25 | // ******************* Transformation **************************
26 |
27 | (GridSpacingSchedule 4 2 1)
28 | (FinalGridSpacingInPhysicalUnits 10)
29 | (HowToCombineTransforms "Compose")
30 |
31 | // ******************* Similarity measure *********************
32 |
33 | (NumberOfHistogramBins 100)
34 |
35 | // ******************** Multiresolution **********************
36 |
37 | (NumberOfResolutions 3)
38 | (ImagePyramidSchedule 4 4 4 2 2 2 1 1 1)
39 |
40 | // ******************* Optimizer ****************************
41 |
42 | (MaximumNumberOfIterations 500 200 100)
43 |
44 | // **************** Image sampling **********************
45 | (Sampler "RandomSampler")
46 | (NumberOfSpatialSamples 4096)
47 | (NewSamplesEveryIteration "true")
48 | (ImageSampler "Grid" "Grid" "Grid")
49 | (SampleGridSpacing 4 2 2)
50 | (SampleRegionSize 100)
51 | (UseRandomSampleRegion "true")
52 | (MaximumNumberOfSamplingAttempts 5)
53 | (RequiredRatioOfValidSamples 0.05)
54 |
55 | // ************* Interpolation and Resampling ****************
56 |
57 | (BSplineInterpolationOrder 3)
58 | (FinalBSplineInterpolationOrder 3)
59 |
60 | (ShowExactMetricValue "false")
61 | (WriteTransformParametersEachResolution "true")
62 | //(WriteResultImageAfterEachResolution "true")
63 | //(WritePyramidImagesAfterEachResolution "true")
64 |
65 | (DefaultPixelValue -1000)
66 | (WriteResultImage "false")
67 | (ResultImagePixelType "short")
68 | (ResultImageFormat "nii.gz")
--------------------------------------------------------------------------------
/configs/param_def_cbct_TH.txt:
--------------------------------------------------------------------------------
1 | (FixedInternalImagePixelType "float")
2 | (MovingInternalImagePixelType "float")
3 | (FixedImageDimension 3)
4 | (MovingImageDimension 3)
5 | (UseDirectionCosines "true")
6 | (ErodeMask "true")
7 |
8 | // ******************* Main Components ************************
9 |
10 | (Registration "MultiMetricMultiResolutionRegistration")
11 | (Interpolator "BSplineInterpolator" "BSplineInterpolator" "BSplineInterpolator")
12 | (ResampleInterpolator "FinalBSplineInterpolator")
13 | (Resampler "DefaultResampler")
14 |
15 | (FixedImagePyramid "FixedRecursiveImagePyramid")
16 | (MovingImagePyramid "MovingRecursiveImagePyramid")
17 |
18 | (Optimizer "AdaptiveStochasticGradientDescent")
19 | (Transform "BSplineTransform")
20 | (Metric "AdvancedMattesMutualInformation" "TransformBendingEnergyPenalty" "TransformRigidityPenalty")
21 | (Metric0Weight 1 1 1)
22 | (Metric1Weight 10 10 10)
23 | (Metric2Weight 0.5 0.5 0.5)
24 |
25 | // ******************* Transformation **************************
26 |
27 | (GridSpacingSchedule 4 2 1)
28 | (FinalGridSpacingInPhysicalUnits 10)
29 | (HowToCombineTransforms "Compose")
30 |
31 | // ******************* Similarity measure *********************
32 |
33 | (NumberOfHistogramBins 100)
34 |
35 | // ******************** Multiresolution **********************
36 |
37 | (NumberOfResolutions 3)
38 | (ImagePyramidSchedule 4 4 4 2 2 2 1 1 1)
39 |
40 | // ******************* Optimizer ****************************
41 |
42 | (MaximumNumberOfIterations 500 200 100)
43 |
44 | // **************** Image sampling **********************
45 | (Sampler "RandomSampler")
46 | (NumberOfSpatialSamples 4096)
47 | (NewSamplesEveryIteration "true")
48 | (ImageSampler "Grid" "Grid" "Grid")
49 | (SampleGridSpacing 4 2 2)
50 | (SampleRegionSize 100)
51 | (UseRandomSampleRegion "true")
52 | (MaximumNumberOfSamplingAttempts 5)
53 | (RequiredRatioOfValidSamples 0.05)
54 |
55 | // ************* Interpolation and Resampling ****************
56 |
57 | (BSplineInterpolationOrder 3)
58 | (FinalBSplineInterpolationOrder 3)
59 |
60 | (ShowExactMetricValue "false")
61 | (WriteTransformParametersEachResolution "true")
62 | //(WriteResultImageAfterEachResolution "true")
63 | //(WritePyramidImagesAfterEachResolution "true")
64 |
65 | (DefaultPixelValue -1000)
66 | (WriteResultImage "true")
67 | (ResultImagePixelType "short")
68 | (ResultImageFormat "nii.gz")
--------------------------------------------------------------------------------
/configs/param_def_mr_AB.txt:
--------------------------------------------------------------------------------
1 | (FixedInternalImagePixelType "float")
2 | (MovingInternalImagePixelType "float")
3 | (FixedImageDimension 3)
4 | (MovingImageDimension 3)
5 | (UseDirectionCosines "true")
6 |
7 | // **************** Main Components **************************
8 |
9 | (Registration "MultiMetricMultiResolutionRegistration")
10 | (Interpolator "BSplineInterpolator")
11 | (ResampleInterpolator "FinalBSplineInterpolator")
12 | (Resampler "DefaultResampler")
13 |
14 | (FixedImagePyramid "FixedSmoothingImagePyramid")
15 | (MovingImagePyramid "MovingSmoothingImagePyramid")
16 |
17 | (Optimizer "AdaptiveStochasticGradientDescent")
18 | (Transform "BSplineTransform")
19 | (Metric "AdvancedMattesMutualInformation" "TransformBendingEnergyPenalty")
20 | (Metric0Weight 1)
21 | (Metric1Weight 50) // OPTIMIZED BY QUANTITATIVE MEASURES
22 |
23 | // ***************** Transformation **************************
24 |
25 | (GridSpacingSchedule 4 2 1)
26 | (FinalGridSpacingInPhysicalUnits 15)
27 | (HowToCombineTransforms "Compose")
28 |
29 | // ******************* Similarity measure *********************
30 |
31 | (NumberOfHistogramBins 60) // OPTIMIZED BY QUANTITATIVE MEASURES
32 |
33 | // ******************** Multiresolution **********************
34 |
35 | (NumberOfResolutions 3)
36 | (ImagePyramidSchedule 8 8 8 4 4 4 1 1 1)
37 |
38 | // ******************* Optimizer ****************************
39 |
40 | (MaximumNumberOfIterations 2000 2000 1000) // COULD PROBABLY BE LOWERED, ESPECIALLY FOR THE FIRST LEVELS OF THE IMAGE PYRAMID
41 |
42 | // **************** Image sampling **********************
43 | (Sampler "GridSampler")
44 | (NumberOfSpatialSamples 4096)
45 | (NewSamplesEveryIteration "true")
46 | (ImageSampler "RandomCoordinate")
47 | (SampleRegionSize 100)
48 | (UseRandomSampleRegion "true")
49 | (MaximumNumberOfSamplingAttempts 5)
50 | (RequiredRatioOfValidSamples 0.05)
51 |
52 | // ************* Interpolation and Resampling ****************
53 |
54 | (BSplineInterpolationOrder 3)
55 | (FinalBSplineInterpolationOrder 3)
56 |
57 | (ShowExactMetricValue "false")
58 | (WriteTransformParametersEachResolution "true")
59 | //(WriteResultImageAfterEachResolution "true")
60 | //(WritePyramidImagesAfterEachResolution "true")
61 |
62 | (DefaultPixelValue -1000)
63 | (WriteResultImage "true")
64 | (ResultImagePixelType "short")
65 | (ResultImageFormat "nii.gz")
--------------------------------------------------------------------------------
/configs/param_def_mr_HN.txt:
--------------------------------------------------------------------------------
1 | (FixedInternalImagePixelType "float")
2 | (MovingInternalImagePixelType "float")
3 | (FixedImageDimension 3)
4 | (MovingImageDimension 3)
5 | (UseDirectionCosines "true")
6 |
7 | // ******************* Main Components ************************
8 |
9 | (Registration "MultiMetricMultiResolutionRegistration")
10 | (Interpolator "BSplineInterpolator")
11 | (ResampleInterpolator "FinalBSplineInterpolator")
12 | (Resampler "DefaultResampler")
13 |
14 | (FixedImagePyramid "FixedRecursiveImagePyramid")
15 | (MovingImagePyramid "MovingRecursiveImagePyramid")
16 |
17 | (Optimizer "AdaptiveStochasticGradientDescent")
18 | (Transform "BSplineTransform")
19 | (Metric "AdvancedMattesMutualInformation" "TransformBendingEnergyPenalty" "TransformRigidityPenalty")
20 | (Metric0Weight 1)
21 | (Metric1Weight 50)
22 | (Metric2Weight 2)
23 |
24 | // ******************* Transformation **************************
25 |
26 | (GridSpacingSchedule 4 2 1)
27 | (FinalGridSpacingInPhysicalUnits 15)
28 | (HowToCombineTransforms "Compose")
29 |
30 | // ******************* Similarity measure *********************
31 |
32 | (NumberOfHistogramBins 100)
33 |
34 | // ******************** Multiresolution **********************
35 |
36 | (NumberOfResolutions 3)
37 | (ImagePyramidSchedule 4 4 4 2 2 2 1 1 1)
38 |
39 | // ******************* Optimizer ****************************
40 |
41 | (MaximumNumberOfIterations 500 300 200)
42 |
43 | // **************** Image sampling **********************
44 | (Sampler "RandomSampler")
45 | (NumberOfSpatialSamples 4096)
46 | (NewSamplesEveryIteration "true")
47 | (ImageSampler "Grid")
48 | (SampleGridSpacing 4 2 1)
49 | (SampleRegionSize 100)
50 | (UseRandomSampleRegion "true")
51 | (MaximumNumberOfSamplingAttempts 5)
52 | (RequiredRatioOfValidSamples 0.05)
53 |
54 | // ************* Interpolation and Resampling ****************
55 |
56 | (BSplineInterpolationOrder 3)
57 | (FinalBSplineInterpolationOrder 3)
58 |
59 | (ShowExactMetricValue "false")
60 | (WriteTransformParametersEachResolution "true")
61 | //(WriteResultImageAfterEachResolution "true")
62 | //(WritePyramidImagesAfterEachResolution "true")
63 |
64 | (DefaultPixelValue -1000)
65 | (WriteResultImage "true")
66 | (ResultImagePixelType "short")
67 | (ResultImageFormat "nii.gz")
--------------------------------------------------------------------------------
/configs/param_def_mr_TH.txt:
--------------------------------------------------------------------------------
1 | (FixedInternalImagePixelType "float")
2 | (MovingInternalImagePixelType "float")
3 | (FixedImageDimension 3)
4 | (MovingImageDimension 3)
5 | (UseDirectionCosines "true")
6 |
7 | // ******************* Main Components ************************
8 |
9 | (Registration "MultiMetricMultiResolutionRegistration")
10 | (Interpolator "BSplineInterpolator")
11 | (ResampleInterpolator "FinalBSplineInterpolator")
12 | (Resampler "DefaultResampler")
13 |
14 | (FixedImagePyramid "FixedRecursiveImagePyramid")
15 | (MovingImagePyramid "MovingRecursiveImagePyramid")
16 |
17 | (Optimizer "AdaptiveStochasticGradientDescent")
18 | (Transform "BSplineTransform")
19 | (Metric "AdvancedMattesMutualInformation" "TransformBendingEnergyPenalty" "TransformRigidityPenalty")
20 | (Metric0Weight 1)
21 | (Metric1Weight 50)
22 | (Metric2Weight 2)
23 |
24 | // ******************* Transformation **************************
25 |
26 | (GridSpacingSchedule 4 2 1)
27 | (FinalGridSpacingInPhysicalUnits 10)
28 | (HowToCombineTransforms "Compose")
29 |
30 | // ******************* Similarity measure *********************
31 |
32 | (NumberOfHistogramBins 100)
33 |
34 | // ******************** Multiresolution **********************
35 |
36 | (NumberOfResolutions 3)
37 | (ImagePyramidSchedule 4 4 4 2 2 2 1 1 1)
38 |
39 | // ******************* Optimizer ****************************
40 |
41 | (MaximumNumberOfIterations 500 300 200)
42 |
43 | // **************** Image sampling **********************
44 | (Sampler "RandomSampler")
45 | (NumberOfSpatialSamples 4096)
46 | (NewSamplesEveryIteration "true")
47 | (ImageSampler "Grid")
48 | (SampleGridSpacing 4 2 1)
49 | (SampleRegionSize 100)
50 | (UseRandomSampleRegion "true")
51 | (MaximumNumberOfSamplingAttempts 5)
52 | (RequiredRatioOfValidSamples 0.05)
53 |
54 | // ************* Interpolation and Resampling ****************
55 |
56 | (BSplineInterpolationOrder 3)
57 | (FinalBSplineInterpolationOrder 3)
58 |
59 | (ShowExactMetricValue "false")
60 | (WriteTransformParametersEachResolution "true")
61 | //(WriteResultImageAfterEachResolution "true")
62 | //(WritePyramidImagesAfterEachResolution "true")
63 |
64 | (DefaultPixelValue -1000)
65 | (WriteResultImage "true")
66 | (ResultImagePixelType "short")
67 | (ResultImageFormat "nii.gz")
--------------------------------------------------------------------------------
/configs/param_inverse_def.txt:
--------------------------------------------------------------------------------
1 | (FixedInternalImagePixelType "float")
2 | (MovingInternalImagePixelType "float")
3 | (FixedImageDimension 3)
4 | (MovingImageDimension 3)
5 | (UseDirectionCosines "true")
6 |
7 | // **************** Main Components **************************
8 |
9 | (Registration "MultiResolutionRegistration")
10 | (Interpolator "BSplineInterpolator")
11 | (ResampleInterpolator "FinalBSplineInterpolator")
12 | (Resampler "DefaultResampler")
13 |
14 | (FixedImagePyramid "FixedSmoothingImagePyramid")
15 | (MovingImagePyramid "MovingSmoothingImagePyramid")
16 |
17 | (Optimizer "AdaptiveStochasticGradientDescent")
18 | (Transform "BSplineTransform")
19 | (Metric "DisplacementMagnitudePenalty")
20 |
21 | // ***************** Transformation **************************
22 | (HowToCombineTransforms "Compose")
23 | (FinalGridSpacingInPhysicalUnits 15)
24 |
25 | // ******************* Similarity measure *********************
26 | (NumberOfHistogramBins 128) // OPTIMIZED BY QUANTITATIVE MEASURES
27 |
28 | // ******************** Multiresolution **********************
29 | (NumberOfResolutions 3)
30 | (ImagePyramidSchedule 8 8 8 4 4 4 1 1 1)
31 |
32 | // ******************* Optimizer ****************************
33 | (MaximumNumberOfIterations 1000 1000 1000) // COULD PROBABLY BE LOWERED, ESPECIALLY FOR THE FIRST LEVELS OF THE IMAGE PYRAMID
34 |
35 | // **************** Image sampling **********************
36 | (Sampler "RandomSampler")
37 | (NumberOfSpatialSamples 4096)
38 | (NewSamplesEveryIteration "true")
39 | (ImageSampler "Random")
40 | (SampleRegionSize 140)
41 | (UseRandomSampleRegion "true")
42 | (MaximumNumberOfSamplingAttempts 5)
43 | (RequiredRatioOfValidSamples 0.05)
44 |
45 | // ************* Interpolation and Resampling ****************
46 |
47 | (BSplineInterpolationOrder 3)
48 | (FinalBSplineInterpolationOrder 3)
49 |
50 | (ShowExactMetricValue "false")
51 | (WriteTransformParametersEachResolution "true")
52 | //(WriteResultImageAfterEachResolution "true")
53 | //(WritePyramidImagesAfterEachResolution "true")
54 |
55 | (DefaultPixelValue 0)
56 | (WriteResultImage "false")
57 |
--------------------------------------------------------------------------------
/configs/param_rigid.txt:
--------------------------------------------------------------------------------
1 | //Parameter file
2 |
3 | //********adaptions***********
4 | //(RequiredRatioOfValidSamples 0.05) -> extra parameter
5 | //(MaximumNumberOfSamplingAttempts 50) -> was 15 attempts -> back to 20 attempts
6 | //(NumberOfSpatialSamples 3000) -> was 2048 samples
7 | //(UseRandomSampleRegion "false") -> was 'true'
8 | // center of gravity instead of geometricalCenter (edit:25022019)
9 | // image sampler on grid (4 4 4 4) instead of (random)coordinateSampler (edit:25022019)
10 | // (MaximumNumberOfIterations 1000 1000 300 300) -> was (1000 1000 1500 1500)(edit:25022019)
11 |
12 | //**********ImageTypes**********
13 |
14 | // The internal pixel type, used for internal computations
15 | // Leave to float in general.
16 | // NB: this is not the type of the input images! The pixel
17 | // type of the input images is automatically read from the
18 | // images themselves.
19 | // This setting can be changed to "short" to save some memory
20 | // in case of very large 3D images.
21 | (FixedInternalImagePixelType "float")
22 | (MovingInternalImagePixelType "float")
23 | (FixedImageDimension 3)
24 | (MovingImageDimension 3)
25 |
26 |
27 | // Specify whether you want to take into account the so-called
28 | // direction cosines of the images. Recommended: true.
29 | // In some cases, the direction cosines of the image are corrupt,
30 | // due to image format conversions for example. In that case, you
31 | // may want to set this option to "false".
32 | (UseDirectionCosines "true")
33 |
34 |
35 | //*********Components**********
36 |
37 | (Registration "MultiResolutionRegistration")
38 |
39 | //***Interpolator
40 | //(Interpolator "BSplineInterpolator")
41 | (Interpolator "LinearInterpolator")
42 | //***Resampler
43 | (Resampler "DefaultResampler")
44 | (ResampleInterpolator "FinalBSplineInterpolator")
45 | //(ResampleInterpolator "LinearInterpolator")
46 |
47 | (FixedImagePyramid "FixedRecursiveImagePyramid")
48 | (MovingImagePyramid "MovingRecursiveImagePyramid")
49 | //(FixedImagePyramid "FixedSmoothingImagePyramid")
50 | //(MovingImagePyramid "MovingSmoothingImagePyramid")
51 | //(FixedImagePyramid "FixedShrinkingImagePyramid")
52 | //(MovingImagePyramid "MovingShrinkingImagePyramid")
53 |
54 | // The following components are most important:
55 | // The optimizer AdaptiveStochasticGradientDescent (ASGD) works
56 | // quite ok in general. The Transform and Metric are important
57 | // and need to be chosen careful for each application. See manual.
58 | (Transform "EulerTransform")
59 | (Sampler "Random")
60 | (Optimizer "AdaptiveStochasticGradientDescent")
61 | (Metric "AdvancedMattesMutualInformation")
62 |
63 | //************Transform************
64 |
65 | // Scales the rotations compared to the translations, to make
66 | // sure they are in the same range. In general, it's best to
67 | // use automatic scales estimation:
68 | //(AutomaticScalesEstimation "true")
69 | (Scales 10000)
70 |
71 | // Automatically guess an initial translation by aligning the
72 | // geometric centers of the fixed and moving.
73 | (AutomaticTransformInitialization "true")
74 |
75 | // Whether transforms are combined by composition or by addition.
76 | // In generally, Compose is the best option in most cases.
77 | // It does not influence the results very much.
78 | (HowToCombineTransforms "Compose")
79 | //(AutomaticTransformInitializationMethod "GeometricalCenter")
80 | (AutomaticTransformInitializationMethod "CenterOfGravity")
81 |
82 |
83 | //************Similarity Measure************
84 |
85 | // Number of grey level bins in each resolution level,
86 | // for the mutual information. 16 or 32 usually works fine.
87 | // You could also employ a hierarchical strategy:
88 | (NumberOfHistogramBins 32 32 32 32)
89 | //(NumberOfHistogramBins 32)
90 |
91 |
92 | //**************Multiresolution **********************
93 |
94 | // The number of resolutions. 1 Is only enough if the expected
95 | // deformations are small. 3 or 4 mostly works fine. For large
96 | // images and large deformations, 5 or 6 may even be useful.
97 | (NumberOfResolutions 4)
98 | (ImagePyramidSchedule 8 8 8 4 4 4 2 2 2 1 1 1 )
99 | //(FinalGridSpacingInVoxels 1.0 1.0 1.0)
100 | //(FinalGridSpacingInPhysicalUnits 1.0 1.0 1.0)
101 | //(GridSpacingSchedule 6.0 6.0 6.0 3.0 3.0 3.0 1.0 1.0 1.0)
102 | // Make sure that the number of elements equals the number
103 | // of resolutions times the image dimension
104 |
105 |
106 | // ******************* Optimizer ****************************
107 |
108 | // Maximum number of iterations in each resolution level:
109 | // 200-500 works usually fine for rigid registration.
110 | // For more robustness, you may increase this to 1000-2000.
111 | (MaximumNumberOfIterations 1000 1000 500 500)
112 | //(MaximumNumberOfIterations 100 100 30 30)
113 |
114 |
115 | // The step size of the optimizer, in mm. By default the voxel size is used.
116 | // which usually works well. In case of unusual high-resolution images
117 | // (eg histology) it is necessary to increase this value a bit, to the size
118 | // of the "smallest visible structure" in the image:
119 | //(MaximumStepLength 1.0)
120 |
121 |
122 | //************Image Sampling************
123 |
124 | // Number of spatial samples used to compute the mutual
125 | // information (and its derivative) in each iteration.
126 | // With an AdaptiveStochasticGradientDescent optimizer,
127 | // in combination with the two options below, around 2000
128 | // samples may already suffice.
129 | (NumberOfSpatialSamples 3000)
130 | //(NumberOfSpatialSamples 2048)
131 |
132 | // Refresh these spatial samples in every iteration, and select
133 | // them randomly. See the manual for information on other sampling
134 | // strategies.
135 | //(NewSamplesEveryIteration "true")
136 | //(ImageSampler "RandomCoordinate")
137 | //(ImageSampler "Random")
138 | //(ImageSampler "Full")
139 | (ImageSampler "Grid")
140 | (SampleGridSpacing 4 4 4 2)
141 | (MaximumNumberOfSamplingAttempts 20)
142 | (RequiredRatioOfValidSamples 0.045)
143 |
144 |
145 | (FixedImageBSplineInterpolationOrder 1)
146 | //(UseRandomSampleRegion "true")
147 | //(SampleRegionSize 50 50 50)
148 |
149 | // ************* Interpolation and Resampling ****************
150 |
151 | // Order of B-Spline interpolation used during registration/optimisation.
152 | // It may improveie accuracy if you set this to 3. Never use 0.
153 | // An order of 1 gives linear interpolation. This is in most
154 | // applications a good choice.
155 | (BSplineInterpolationOrder 1)
156 |
157 | // Order of B-Spline interpolation used for applying the final
158 | // deformation.
159 | // 3 gives good accuracy; recommended in most cases.
160 | // 1 gives worse accuracy (linear interpolation)
161 | // 0 gives worst accuracy, but is appropriate for binary images
162 | // (masks, segmentations); equivalent to nearest neighbor interpolation.
163 | (FinalBSplineInterpolationOrder 1)
164 |
165 | //Default pixel value for pixels that come from outside the picture:
166 | (DefaultPixelValue -1000)
167 |
168 | //************Output***************
169 |
170 | // Write resulting images. You can save some time by setting this to false, if you are only interested in the final deformed moving image for example.
171 | (WriteResultImage "true")
172 |
173 | //***********MiscVisulaization
174 | (WriteTransformParametersEachIteration "false" "false" "false" "false")
175 | (WriteTransformParametersEachResolution "true" "true" "true" "true")
176 |
177 | // Define output format
178 | //(ResultImagePixelType "double")
179 | (ResultImageFormat "nrrd")
--------------------------------------------------------------------------------
/configs/param_rigid_general.txt:
--------------------------------------------------------------------------------
1 | //Parameter file
2 |
3 | //********adaptions***********
4 | //Original -> /nfs/bsc01/researchData/PROJECT/PEDIATRIC/Script/RegistrationPar/ParameterFileRigid_MRreg2CT.txt
5 | //(RequiredRatioOfValidSamples 0.05) -> extra parameter
6 | //(MaximumNumberOfSamplingAttempts 50) -> was 15 attempts -> back to 20 attempts
7 | //(NumberOfSpatialSamples 3000) -> was 2048 samples
8 | //(UseRandomSampleRegion "false") -> was 'true'
9 | // center of gravity instead of geometricalCenter (edit:25022019)
10 | // image sampler on grid (4 4 4 4) instead of (random)coordinateSampler (edit:25022019)
11 | // (MaximumNumberOfIterations 1000 1000 300 300) -> was (1000 1000 1500 1500)(edit:25022019)
12 |
13 | //**********ImageTypes**********
14 |
15 | // The internal pixel type, used for internal computations
16 | // Leave to float in general.
17 | // NB: this is not the type of the input images! The pixel
18 | // type of the input images is automatically read from the
19 | // images themselves.
20 | // This setting can be changed to "short" to save some memory
21 | // in case of very large 3D images.
22 | (FixedInternalImagePixelType "float")
23 | (MovingInternalImagePixelType "float")
24 | (FixedImageDimension 3)
25 | (MovingImageDimension 3)
26 | (ErodeMask "true")
27 |
28 |
29 | // Specify whether you want to take into account the so-called
30 | // direction cosines of the images. Recommended: true.
31 | // In some cases, the direction cosines of the image are corrupt,
32 | // due to image format conversions for example. In that case, you
33 | // may want to set this option to "false".
34 | (UseDirectionCosines "true")
35 |
36 |
37 | //*********Components**********
38 |
39 | //(Registration "MultiResolutionRegistration")
40 | (Registration "MultiMetricMultiResolutionRegistration")
41 |
42 | //***Interpolator
43 | //(Interpolator "BSplineInterpolator")
44 | (Interpolator "LinearInterpolator")
45 | //***Resampler
46 | (Resampler "DefaultResampler")
47 | (ResampleInterpolator "FinalBSplineInterpolator")
48 | //(ResampleInterpolator "LinearInterpolator")
49 |
50 | (FixedImagePyramid "FixedRecursiveImagePyramid")
51 | (MovingImagePyramid "MovingRecursiveImagePyramid")
52 | //(FixedImagePyramid "FixedSmoothingImagePyramid")
53 | //(MovingImagePyramid "MovingSmoothingImagePyramid")
54 | //(FixedImagePyramid "FixedShrinkingImagePyramid")
55 | //(MovingImagePyramid "MovingShrinkingImagePyramid")
56 |
57 | // The following components are most important:
58 | // The optimizer AdaptiveStochasticGradientDescent (ASGD) works
59 | // quite ok in general. The Transform and Metric are important
60 | // and need to be chosen careful for each application. See manual.
61 | (Transform "EulerTransform")
62 | (Sampler "RandomCoordinate")
63 | (Optimizer "AdaptiveStochasticGradientDescent")
64 | (Metric "AdvancedNormalizedCorrelation" "AdvancedMattesMutualInformation")
65 | //(Metric "AdvancedMattesMutualInformation")
66 |
67 | //************Transform************
68 |
69 | // Scales the rotations compared to the translations, to make
70 | // sure they are in the same range. In general, it's best to
71 | // use automatic scales estimation:
72 | (AutomaticScalesEstimation "false")
73 |
74 | // Automatically guess an initial translation by aligning the
75 | // geometric centers of the fixed and moving.
76 | (AutomaticTransformInitialization "true")
77 |
78 | // Whether transforms are combined by composition or by addition.
79 | // In generally, Compose is the best option in most cases.
80 | // It does not influence the results very much.
81 | (HowToCombineTransforms "Compose")
82 | //(AutomaticTransformInitializationMethod "GeometricalCenter")
83 | (AutomaticTransformInitializationMethod "CenterOfGravity")
84 |
85 |
86 | //************Similarity Measure************
87 |
88 | // Number of grey level bins in each resolution level,
89 | // for the mutual information. 16 or 32 usually works fine.
90 | // You could also employ a hierarchical strategy:
91 | (NumberOfHistogramBins 16 32 32 64)
92 | //(NumberOfHistogramBins 32)
93 |
94 |
95 | //**************Multiresolution **********************
96 |
97 | // The number of resolutions. 1 Is only enough if the expected
98 | // deformations are small. 3 or 4 mostly works fine. For large
99 | // images and large deformations, 5 or 6 may even be useful.
100 | (NumberOfResolutions 4)
101 | (ImagePyramidSchedule 8 8 8 4 4 4 2 2 2 1 1 1 )
102 | //(FinalGridSpacingInVoxels 1.0 1.0 1.0)
103 | //(FinalGridSpacingInPhysicalUnits 1.0 1.0 1.0)
104 | //(GridSpacingSchedule 6.0 6.0 6.0 3.0 3.0 3.0 1.0 1.0 1.0)
105 | // Make sure that the number of elements equals the number
106 | // of resolutions times the image dimension
107 |
108 |
109 | // ******************* Optimizer ****************************
110 |
111 | // Maximum number of iterations in each resolution level:
112 | // 200-500 works usually fine for rigid registration.
113 | // For more robustness, you may increase this to 1000-2000.
114 | (MaximumNumberOfIterations 1000 1000 300 150)
115 | //(MaximumNumberOfIterations 100 100 30 30)
116 |
117 |
118 | // The step size of the optimizer, in mm. By default the voxel size is used.
119 | // which usually works well. In case of unusual high-resolution images
120 | // (eg histology) it is necessary to increase this value a bit, to the size
121 | // of the "smallest visible structure" in the image:
122 | (MaximumStepLength 2.0)
123 |
124 |
125 | //************Image Sampling************
126 |
127 | // Number of spatial samples used to compute the mutual
128 | // information (and its derivative) in each iteration.
129 | // With an AdaptiveStochasticGradientDescent optimizer,
130 | // in combination with the two options below, around 2000
131 | // samples may already suffice.
132 | (NumberOfSpatialSamples 3000)
133 | //(NumberOfSpatialSamples 2048)
134 |
135 | // Refresh these spatial samples in every iteration, and select
136 | // them randomly. See the manual for information on other sampling
137 | // strategies.
138 | //(NewSamplesEveryIteration "true")
139 | //(ImageSampler "RandomCoordinate")
140 | //(ImageSampler "Random")
141 | //(ImageSampler "Full")
142 | (ImageSampler "Grid")
143 | (SampleGridSpacing 4 4 4 2)
144 | (MaximumNumberOfSamplingAttempts 20)
145 | (RequiredRatioOfValidSamples 0.045)
146 |
147 |
148 | (FixedImageBSplineInterpolationOrder 1)
149 | //(UseRandomSampleRegion "true")
150 | //(SampleRegionSize 50 50 50)
151 |
152 | // ************* Interpolation and Resampling ****************
153 |
154 | // Order of B-Spline interpolation used during registration/optimisation.
155 | // It may improveie accuracy if you set this to 3. Never use 0.
156 | // An order of 1 gives linear interpolation. This is in most
157 | // applications a good choice.
158 | (BSplineInterpolationOrder 1)
159 |
160 | // Order of B-Spline interpolation used for applying the final
161 | // deformation.
162 | // 3 gives good accuracy; recommended in most cases.
163 | // 1 gives worse accuracy (linear interpolation)
164 | // 0 gives worst accuracy, but is appropriate for binary images
165 | // (masks, segmentations); equivalent to nearest neighbor interpolation.
166 | (FinalBSplineInterpolationOrder 1)
167 |
168 | //Default pixel value for pixels that come from outside the picture:
169 | (DefaultPixelValue 0)
170 |
171 | //************Output***************
172 |
173 | // Write resulting images. You can save some time by setting this to false, if you are only interested in the final deformed moving image for example.
174 | (WriteResultImage "true")
175 |
176 | //***********MiscVisulaization
177 | (WriteTransformParametersEachIteration "false" "false" "false" "false")
178 | (WriteTransformParametersEachResolution "false" "false" "false" "true")
179 |
180 | // Define output format
181 | //(ResultImagePixelType "double")
182 | (ResultImageFormat "nrrd")
--------------------------------------------------------------------------------
/configs/param_rigid_large_1024.txt:
--------------------------------------------------------------------------------
1 | //Parameter file
2 |
3 | //**********ImageTypes**********
4 | // The internal pixel type, used for internal computations
5 | // Leave to float in general.
6 | // NB: this is not the type of the input images! The pixel
7 | // type of the input images is automatically read from the
8 | // images themselves.
9 | // This setting can be changed to "short" to save some memory
10 | // in case of very large 3D images.
11 | (FixedInternalImagePixelType "float")
12 | (MovingInternalImagePixelType "float")
13 | (FixedImageDimension 3)
14 | (MovingImageDimension 3)
15 | (ErodeMask "true")
16 |
17 |
18 | // Specify whether you want to take into account the so-called
19 | // direction cosines of the images. Recommended: true.
20 | // In some cases, the direction cosines of the image are corrupt,
21 | // due to image format conversions for example. In that case, you
22 | // may want to set this option to "false".
23 | (UseDirectionCosines "true")
24 |
25 |
26 | //*********Components**********
27 |
28 | //(Registration "MultiResolutionRegistration")
29 | (Registration "MultiMetricMultiResolutionRegistration")
30 |
31 | //***Interpolator
32 | //(Interpolator "BSplineInterpolator")
33 | (Interpolator "LinearInterpolator")
34 | //***Resampler
35 | (Resampler "DefaultResampler")
36 | (ResampleInterpolator "FinalBSplineInterpolator")
37 | //(ResampleInterpolator "LinearInterpolator")
38 |
39 | (FixedImagePyramid "FixedRecursiveImagePyramid")
40 | (MovingImagePyramid "MovingRecursiveImagePyramid")
41 | //(FixedImagePyramid "FixedSmoothingImagePyramid")
42 | //(MovingImagePyramid "MovingSmoothingImagePyramid")
43 | //(FixedImagePyramid "FixedShrinkingImagePyramid")
44 | //(MovingImagePyramid "MovingShrinkingImagePyramid")
45 |
46 | // The following components are most important:
47 | // The optimizer AdaptiveStochasticGradientDescent (ASGD) works
48 | // quite ok in general. The Transform and Metric are important
49 | // and need to be chosen careful for each application. See manual.
50 | //(Transform "TranslationTransform")
51 | (Transform "EulerTransform")
52 | (Sampler "RandomCoordinate")
53 | (Optimizer "AdaptiveStochasticGradientDescent")
54 | //(Metric "AdvancedMattesMutualInformation" "AdvancedNormalizedCorrelation")
55 | (Metric "AdvancedMattesMutualInformation")
56 |
57 | //************Transform************
58 |
59 | // Scales the rotations compared to the translations, to make
60 | // sure they are in the same range. In general, it's best to
61 | // use automatic scales estimation:
62 | //(AutomaticScalesEstimation "true")
63 | (Scales 1000000)
64 |
65 | // Automatically guess an initial translation by aligning the
66 | // geometric centers of the fixed and moving.
67 | (AutomaticTransformInitialization "true")
68 | //(AutomaticTransformInitializationMethod "GeometricalCenter")
69 | (AutomaticTransformInitializationMethod "CenterOfGravity")
70 |
71 | // Whether transforms are combined by composition or by addition.
72 | // In generally, Compose is the best option in most cases.
73 | // It does not influence the results very much.
74 | (HowToCombineTransforms "Compose")
75 |
76 |
77 |
78 | //************Similarity Measure************
79 |
80 | // Number of grey level bins in each resolution level,
81 | // for the mutual information. 16 or 32 usually works fine.
82 | // You could also employ a hierarchical strategy:
83 | (NumberOfHistogramBins 64 64 64 64)
84 | //(NumberOfHistogramBins 32)
85 |
86 |
87 | //**************Multiresolution **********************
88 |
89 | // The number of resolutions. 1 Is only enough if the expected
90 | // deformations are small. 3 or 4 mostly works fine. For large
91 | // images and large deformations, 5 or 6 may even be useful.
92 | (NumberOfResolutions 4)
93 | (ImagePyramidSchedule 8 8 8 4 4 4 2 2 2 1 1 1 )
94 |
95 |
96 |
97 | // ******************* Optimizer ****************************
98 |
99 | // Maximum number of iterations in each resolution level:
100 | // 200-500 works usually fine for rigid registration.
101 | // For more robustness, you may increase this to 1000-2000.
102 | //(MaximumNumberOfIterations 1500 1500 1000 1000)
103 | (MaximumNumberOfIterations 2500 2500 1000 500)
104 |
105 |
106 | // The step size of the optimizer, in mm. By default the voxel size is used.
107 | // which usually works well. In case of unusual high-resolution images
108 | // (eg histology) it is necessary to increase this value a bit, to the size
109 | // of the "smallest visible structure" in the image:
110 | (MaximumStepLength 60.0 20.0 5.0 2.0)
111 | //(MaximumStepLengthRatio 0.2 0.5 1 1)
112 | (SP_A 10000.000000 1000.000000 100.000000 1.000000 )
113 | //(Sp_a 1000 500 500 200)
114 |
115 |
116 | //************Image Sampling************
117 |
118 | // Number of spatial samples used to compute the mutual
119 | // information (and its derivative) in each iteration.
120 | // With an AdaptiveStochasticGradientDescent optimizer,
121 | // in combination with the two options below, around 2000
122 | // samples may already suffice.
123 | (NumberOfSpatialSamples 1024)
124 | (CheckNumberOfSamples "true")
125 | //(NumberOfSpatialSamples 2048)
126 |
127 | // Refresh these spatial samples in every iteration, and select
128 | // them randomly. See the manual for information on other sampling
129 | // strategies.
130 | (NewSamplesEveryIteration "true")
131 | //(ImageSampler "RandomCoordinate")
132 | (ImageSampler "Random")
133 | //(ImageSampler "Full")
134 | //(ImageSampler "Grid")
135 | (SampleGridSpacing 4 4 4 2)
136 | (MaximumNumberOfSamplingAttempts 2000)
137 | (RequiredRatioOfValidSamples 0.045)
138 |
139 |
140 | (FixedImageBSplineInterpolationOrder 1)
141 | //(UseRandomSampleRegion "true")
142 | //(SampleRegionSize 50 50 50)
143 |
144 | // ************* Interpolation and Resampling ****************
145 |
146 | // Order of B-Spline interpolation used during registration/optimisation.
147 | // It may improveie accuracy if you set this to 3. Never use 0.
148 | // An order of 1 gives linear interpolation. This is in most
149 | // applications a good choice.
150 | (BSplineInterpolationOrder 1)
151 |
152 | // Order of B-Spline interpolation used for applying the final
153 | // deformation.
154 | // 3 gives good accuracy; recommended in most cases.
155 | // 1 gives worse accuracy (linear interpolation)
156 | // 0 gives worst accuracy, but is appropriate for binary images
157 | // (masks, segmentations); equivalent to nearest neighbor interpolation.
158 | (FinalBSplineInterpolationOrder 1)
159 |
160 | //Default pixel value for pixels that come from outside the picture:
161 | (DefaultPixelValue -1000)
162 |
163 | //************Output***************
164 |
165 | // Write resulting images. You can save some time by setting this to false, if you are only interested in the final deformed moving image for example.
166 | (WriteResultImage "true")
167 |
168 | //***********MiscVisulaization
169 | (WriteTransformParametersEachIteration "false" "false" "false" "false")
170 | (WriteTransformParametersEachResolution "false" "false" "false" "true")
171 |
172 | // Define output format
173 | //(ResultImagePixelType "double")
174 | (ResultImageFormat "nrrd")
--------------------------------------------------------------------------------
/configs/param_rigid_large_4096.txt:
--------------------------------------------------------------------------------
1 | //Parameter file
2 |
3 | //**********ImageTypes**********
4 | // The internal pixel type, used for internal computations
5 | // Leave to float in general.
6 | // NB: this is not the type of the input images! The pixel
7 | // type of the input images is automatically read from the
8 | // images themselves.
9 | // This setting can be changed to "short" to save some memory
10 | // in case of very large 3D images.
11 | (FixedInternalImagePixelType "float")
12 | (MovingInternalImagePixelType "float")
13 | (FixedImageDimension 3)
14 | (MovingImageDimension 3)
15 | (ErodeMask "true")
16 |
17 |
18 | // Specify whether you want to take into account the so-called
19 | // direction cosines of the images. Recommended: true.
20 | // In some cases, the direction cosines of the image are corrupt,
21 | // due to image format conversions for example. In that case, you
22 | // may want to set this option to "false".
23 | (UseDirectionCosines "true")
24 |
25 |
26 | //*********Components**********
27 |
28 | //(Registration "MultiResolutionRegistration")
29 | (Registration "MultiMetricMultiResolutionRegistration")
30 |
31 | //***Interpolator
32 | //(Interpolator "BSplineInterpolator")
33 | (Interpolator "LinearInterpolator")
34 | //***Resampler
35 | (Resampler "DefaultResampler")
36 | (ResampleInterpolator "FinalBSplineInterpolator")
37 | //(ResampleInterpolator "LinearInterpolator")
38 |
39 | (FixedImagePyramid "FixedRecursiveImagePyramid")
40 | (MovingImagePyramid "MovingRecursiveImagePyramid")
41 | //(FixedImagePyramid "FixedSmoothingImagePyramid")
42 | //(MovingImagePyramid "MovingSmoothingImagePyramid")
43 | //(FixedImagePyramid "FixedShrinkingImagePyramid")
44 | //(MovingImagePyramid "MovingShrinkingImagePyramid")
45 |
46 | // The following components are most important:
47 | // The optimizer AdaptiveStochasticGradientDescent (ASGD) works
48 | // quite ok in general. The Transform and Metric are important
49 | // and need to be chosen careful for each application. See manual.
50 | //(Transform "TranslationTransform")
51 | (Transform "EulerTransform")
52 | (Sampler "RandomCoordinate")
53 | (Optimizer "AdaptiveStochasticGradientDescent")
54 | //(Metric "AdvancedMattesMutualInformation" "AdvancedNormalizedCorrelation")
55 | (Metric "AdvancedMattesMutualInformation")
56 |
57 | //************Transform************
58 |
59 | // Scales the rotations compared to the translations, to make
60 | // sure they are in the same range. In general, it's best to
61 | // use automatic scales estimation:
62 | //(AutomaticScalesEstimation "true")
63 | (Scales 1000000)
64 |
65 | // Automatically guess an initial translation by aligning the
66 | // geometric centers of the fixed and moving.
67 | (AutomaticTransformInitialization "true")
68 | //(AutomaticTransformInitializationMethod "GeometricalCenter")
69 | (AutomaticTransformInitializationMethod "CenterOfGravity")
70 |
71 | // Whether transforms are combined by composition or by addition.
72 | // In generally, Compose is the best option in most cases.
73 | // It does not influence the results very much.
74 | (HowToCombineTransforms "Compose")
75 |
76 |
77 |
78 | //************Similarity Measure************
79 |
80 | // Number of grey level bins in each resolution level,
81 | // for the mutual information. 16 or 32 usually works fine.
82 | // You could also employ a hierarchical strategy:
83 | (NumberOfHistogramBins 64 64 64 64)
84 | //(NumberOfHistogramBins 32)
85 |
86 |
87 | //**************Multiresolution **********************
88 |
89 | // The number of resolutions. 1 Is only enough if the expected
90 | // deformations are small. 3 or 4 mostly works fine. For large
91 | // images and large deformations, 5 or 6 may even be useful.
92 | (NumberOfResolutions 4)
93 | (ImagePyramidSchedule 8 8 8 4 4 4 2 2 2 1 1 1 )
94 |
95 |
96 |
97 | // ******************* Optimizer ****************************
98 |
99 | // Maximum number of iterations in each resolution level:
100 | // 200-500 works usually fine for rigid registration.
101 | // For more robustness, you may increase this to 1000-2000.
102 | //(MaximumNumberOfIterations 1500 1500 1000 1000)
103 | (MaximumNumberOfIterations 2500 2500 1000 500)
104 |
105 |
106 | // The step size of the optimizer, in mm. By default the voxel size is used.
107 | // which usually works well. In case of unusual high-resolution images
108 | // (eg histology) it is necessary to increase this value a bit, to the size
109 | // of the "smallest visible structure" in the image:
110 | (MaximumStepLength 60.0 20.0 5.0 2.0)
111 | //(MaximumStepLengthRatio 0.2 0.5 1 1)
112 | (SP_A 10000.000000 1000.000000 100.000000 1.000000 )
113 | //(Sp_a 1000 500 500 200)
114 |
115 |
116 | //************Image Sampling************
117 |
118 | // Number of spatial samples used to compute the mutual
119 | // information (and its derivative) in each iteration.
120 | // With an AdaptiveStochasticGradientDescent optimizer,
121 | // in combination with the two options below, around 2000
122 | // samples may already suffice.
123 | (NumberOfSpatialSamples 4096)
124 | (CheckNumberOfSamples "true")
125 | //(NumberOfSpatialSamples 2048)
126 |
127 | // Refresh these spatial samples in every iteration, and select
128 | // them randomly. See the manual for information on other sampling
129 | // strategies.
130 | (NewSamplesEveryIteration "true")
131 | //(ImageSampler "RandomCoordinate")
132 | (ImageSampler "Random")
133 | //(ImageSampler "Full")
134 | //(ImageSampler "Grid")
135 | (SampleGridSpacing 4 4 4 2)
136 | (MaximumNumberOfSamplingAttempts 2000)
137 | (RequiredRatioOfValidSamples 0.045)
138 |
139 |
140 | (FixedImageBSplineInterpolationOrder 1)
141 | //(UseRandomSampleRegion "true")
142 | //(SampleRegionSize 50 50 50)
143 |
144 | // ************* Interpolation and Resampling ****************
145 |
146 | // Order of B-Spline interpolation used during registration/optimisation.
147 | // It may improveie accuracy if you set this to 3. Never use 0.
148 | // An order of 1 gives linear interpolation. This is in most
149 | // applications a good choice.
150 | (BSplineInterpolationOrder 1)
151 |
152 | // Order of B-Spline interpolation used for applying the final
153 | // deformation.
154 | // 3 gives good accuracy; recommended in most cases.
155 | // 1 gives worse accuracy (linear interpolation)
156 | // 0 gives worst accuracy, but is appropriate for binary images
157 | // (masks, segmentations); equivalent to nearest neighbor interpolation.
158 | (FinalBSplineInterpolationOrder 1)
159 |
160 | //Default pixel value for pixels that come from outside the picture:
161 | (DefaultPixelValue -1000)
162 |
163 | //************Output***************
164 |
165 | // Write resulting images. You can save some time by setting this to false, if you are only interested in the final deformed moving image for example.
166 | (WriteResultImage "true")
167 |
168 | //***********MiscVisulaization
169 | (WriteTransformParametersEachIteration "false" "false" "false" "false")
170 | (WriteTransformParametersEachResolution "false" "false" "false" "true")
171 |
172 | // Define output format
173 | //(ResultImagePixelType "double")
174 | (ResultImageFormat "nrrd")
--------------------------------------------------------------------------------
/configs/param_rigid_large_512.txt:
--------------------------------------------------------------------------------
1 | //Parameter file
2 |
3 | //**********ImageTypes**********
4 | // The internal pixel type, used for internal computations
5 | // Leave to float in general.
6 | // NB: this is not the type of the input images! The pixel
7 | // type of the input images is automatically read from the
8 | // images themselves.
9 | // This setting can be changed to "short" to save some memory
10 | // in case of very large 3D images.
11 | (FixedInternalImagePixelType "float")
12 | (MovingInternalImagePixelType "float")
13 | (FixedImageDimension 3)
14 | (MovingImageDimension 3)
15 | (ErodeMask "true")
16 |
17 |
18 | // Specify whether you want to take into account the so-called
19 | // direction cosines of the images. Recommended: true.
20 | // In some cases, the direction cosines of the image are corrupt,
21 | // due to image format conversions for example. In that case, you
22 | // may want to set this option to "false".
23 | (UseDirectionCosines "true")
24 |
25 |
26 | //*********Components**********
27 |
28 | //(Registration "MultiResolutionRegistration")
29 | (Registration "MultiMetricMultiResolutionRegistration")
30 |
31 | //***Interpolator
32 | //(Interpolator "BSplineInterpolator")
33 | (Interpolator "LinearInterpolator")
34 | //***Resampler
35 | (Resampler "DefaultResampler")
36 | (ResampleInterpolator "FinalBSplineInterpolator")
37 | //(ResampleInterpolator "LinearInterpolator")
38 |
39 | (FixedImagePyramid "FixedRecursiveImagePyramid")
40 | (MovingImagePyramid "MovingRecursiveImagePyramid")
41 | //(FixedImagePyramid "FixedSmoothingImagePyramid")
42 | //(MovingImagePyramid "MovingSmoothingImagePyramid")
43 | //(FixedImagePyramid "FixedShrinkingImagePyramid")
44 | //(MovingImagePyramid "MovingShrinkingImagePyramid")
45 |
46 | // The following components are most important:
47 | // The optimizer AdaptiveStochasticGradientDescent (ASGD) works
48 | // quite ok in general. The Transform and Metric are important
49 | // and need to be chosen careful for each application. See manual.
50 | //(Transform "TranslationTransform")
51 | (Transform "EulerTransform")
52 | (Sampler "RandomCoordinate")
53 | (Optimizer "AdaptiveStochasticGradientDescent")
54 | //(Metric "AdvancedMattesMutualInformation" "AdvancedNormalizedCorrelation")
55 | (Metric "AdvancedMattesMutualInformation")
56 |
57 | //************Transform************
58 |
59 | // Scales the rotations compared to the translations, to make
60 | // sure they are in the same range. In general, it's best to
61 | // use automatic scales estimation:
62 | //(AutomaticScalesEstimation "true")
63 | (Scales 1000000)
64 |
65 | // Automatically guess an initial translation by aligning the
66 | // geometric centers of the fixed and moving.
67 | (AutomaticTransformInitialization "true")
68 | //(AutomaticTransformInitializationMethod "GeometricalCenter")
69 | (AutomaticTransformInitializationMethod "CenterOfGravity")
70 |
71 | // Whether transforms are combined by composition or by addition.
72 | // In generally, Compose is the best option in most cases.
73 | // It does not influence the results very much.
74 | (HowToCombineTransforms "Compose")
75 |
76 |
77 |
78 | //************Similarity Measure************
79 |
80 | // Number of grey level bins in each resolution level,
81 | // for the mutual information. 16 or 32 usually works fine.
82 | // You could also employ a hierarchical strategy:
83 | (NumberOfHistogramBins 64 64 64 64)
84 | //(NumberOfHistogramBins 32)
85 |
86 |
87 | //**************Multiresolution **********************
88 |
89 | // The number of resolutions. 1 Is only enough if the expected
90 | // deformations are small. 3 or 4 mostly works fine. For large
91 | // images and large deformations, 5 or 6 may even be useful.
92 | (NumberOfResolutions 4)
93 | (ImagePyramidSchedule 8 8 8 4 4 4 2 2 2 1 1 1 )
94 |
95 |
96 |
97 | // ******************* Optimizer ****************************
98 |
99 | // Maximum number of iterations in each resolution level:
100 | // 200-500 works usually fine for rigid registration.
101 | // For more robustness, you may increase this to 1000-2000.
102 | //(MaximumNumberOfIterations 1500 1500 1000 1000)
103 | (MaximumNumberOfIterations 2500 2500 1000 500)
104 |
105 |
106 | // The step size of the optimizer, in mm. By default the voxel size is used.
107 | // which usually works well. In case of unusual high-resolution images
108 | // (eg histology) it is necessary to increase this value a bit, to the size
109 | // of the "smallest visible structure" in the image:
110 | (MaximumStepLength 60.0 20.0 5.0 2.0)
111 | //(MaximumStepLengthRatio 0.2 0.5 1 1)
112 | (SP_A 10000.000000 1000.000000 100.000000 1.000000 )
113 | //(Sp_a 1000 500 500 200)
114 |
115 |
116 | //************Image Sampling************
117 |
118 | // Number of spatial samples used to compute the mutual
119 | // information (and its derivative) in each iteration.
120 | // With an AdaptiveStochasticGradientDescent optimizer,
121 | // in combination with the two options below, around 2000
122 | // samples may already suffice.
123 | (NumberOfSpatialSamples 512)
124 | (CheckNumberOfSamples "true")
125 | //(NumberOfSpatialSamples 2048)
126 |
127 | // Refresh these spatial samples in every iteration, and select
128 | // them randomly. See the manual for information on other sampling
129 | // strategies.
130 | (NewSamplesEveryIteration "true")
131 | //(ImageSampler "RandomCoordinate")
132 | (ImageSampler "Random")
133 | //(ImageSampler "Full")
134 | //(ImageSampler "Grid")
135 | (SampleGridSpacing 4 4 4 2)
136 | (MaximumNumberOfSamplingAttempts 2000)
137 | (RequiredRatioOfValidSamples 0.045)
138 |
139 |
140 | (FixedImageBSplineInterpolationOrder 1)
141 | //(UseRandomSampleRegion "true")
142 | //(SampleRegionSize 50 50 50)
143 |
144 | // ************* Interpolation and Resampling ****************
145 |
146 | // Order of B-Spline interpolation used during registration/optimisation.
147 | // It may improveie accuracy if you set this to 3. Never use 0.
148 | // An order of 1 gives linear interpolation. This is in most
149 | // applications a good choice.
150 | (BSplineInterpolationOrder 1)
151 |
152 | // Order of B-Spline interpolation used for applying the final
153 | // deformation.
154 | // 3 gives good accuracy; recommended in most cases.
155 | // 1 gives worse accuracy (linear interpolation)
156 | // 0 gives worst accuracy, but is appropriate for binary images
157 | // (masks, segmentations); equivalent to nearest neighbor interpolation.
158 | (FinalBSplineInterpolationOrder 1)
159 |
160 | //Default pixel value for pixels that come from outside the picture:
161 | (DefaultPixelValue -1000)
162 |
163 | //************Output***************
164 |
165 | // Write resulting images. You can save some time by setting this to false, if you are only interested in the final deformed moving image for example.
166 | (WriteResultImage "true")
167 |
168 | //***********MiscVisulaization
169 | (WriteTransformParametersEachIteration "false" "false" "false" "false")
170 | (WriteTransformParametersEachResolution "false" "false" "false" "true")
171 |
172 | // Define output format
173 | //(ResultImagePixelType "double")
174 | (ResultImageFormat "nrrd")
--------------------------------------------------------------------------------
/configs/param_rigid_simple.txt:
--------------------------------------------------------------------------------
1 | (AutomaticParameterEstimation "true")
2 | (AutomaticScalesEstimation "true")
3 | (AutomaticTransformInitialization "true")
4 | (AutomaticTransformInitializationMethod "CenterOfGravity")
5 | (CheckNumberOfSamples "true")
6 | (DefaultPixelValue -1024.000000)
7 | (FinalBSplineInterpolationOrder 3.000000)
8 | (FixedImagePyramid "FixedSmoothingImagePyramid")
9 | (ImageSampler "RandomCoordinate")
10 | (Interpolator "LinearInterpolator")
11 | (MaximumNumberOfIterations 256.000000)
12 | (MaximumNumberOfSamplingAttempts 8.000000)
13 | (Metric "AdvancedMeanSquares")
14 | (MovingImagePyramid "MovingSmoothingImagePyramid")
15 | (NewSamplesEveryIteration "true")
16 | (NumberOfResolutions 4.000000)
17 | (NumberOfSamplesForExactGradient 4096.000000)
18 | (NumberOfSpatialSamples 2048.000000)
19 | (Optimizer "AdaptiveStochasticGradientDescent")
20 | (Registration "MultiResolutionRegistration")
21 | (ResampleInterpolator "FinalBSplineInterpolator")
22 | (Resampler "DefaultResampler")
23 | (ResultImageFormat "nii")
24 | (Transform "EulerTransform")
25 | (WriteIterationInfo "false")
26 | (WriteResultImage "true")
--------------------------------------------------------------------------------
/configs/param_rigid_small_4096.txt:
--------------------------------------------------------------------------------
1 | //Parameter file
2 |
3 | //**********ImageTypes**********
4 | // The internal pixel type, used for internal computations
5 | // Leave to float in general.
6 | // NB: this is not the type of the input images! The pixel
7 | // type of the input images is automatically read from the
8 | // images themselves.
9 | // This setting can be changed to "short" to save some memory
10 | // in case of very large 3D images.
11 | (FixedInternalImagePixelType "float")
12 | (MovingInternalImagePixelType "float")
13 | (FixedImageDimension 3)
14 | (MovingImageDimension 3)
15 | (ErodeMask "true")
16 |
17 |
18 | // Specify whether you want to take into account the so-called
19 | // direction cosines of the images. Recommended: true.
20 | // In some cases, the direction cosines of the image are corrupt,
21 | // due to image format conversions for example. In that case, you
22 | // may want to set this option to "false".
23 | (UseDirectionCosines "true")
24 |
25 |
26 | //*********Components**********
27 |
28 | //(Registration "MultiResolutionRegistration")
29 | (Registration "MultiMetricMultiResolutionRegistration")
30 |
31 | //***Interpolator
32 | //(Interpolator "BSplineInterpolator")
33 | (Interpolator "LinearInterpolator")
34 | //***Resampler
35 | (Resampler "DefaultResampler")
36 | (ResampleInterpolator "FinalBSplineInterpolator")
37 | //(ResampleInterpolator "LinearInterpolator")
38 |
39 | (FixedImagePyramid "FixedRecursiveImagePyramid")
40 | (MovingImagePyramid "MovingRecursiveImagePyramid")
41 | //(FixedImagePyramid "FixedSmoothingImagePyramid")
42 | //(MovingImagePyramid "MovingSmoothingImagePyramid")
43 | //(FixedImagePyramid "FixedShrinkingImagePyramid")
44 | //(MovingImagePyramid "MovingShrinkingImagePyramid")
45 |
46 | // The following components are most important:
47 | // The optimizer AdaptiveStochasticGradientDescent (ASGD) works
48 | // quite ok in general. The Transform and Metric are important
49 | // and need to be chosen careful for each application. See manual.
50 | //(Transform "TranslationTransform")
51 | (Transform "EulerTransform")
52 | (Sampler "RandomCoordinate")
53 | (Optimizer "AdaptiveStochasticGradientDescent")
54 | //(Metric "AdvancedMattesMutualInformation" "AdvancedNormalizedCorrelation")
55 | (Metric "AdvancedMattesMutualInformation")
56 |
57 | //************Transform************
58 |
59 | // Scales the rotations compared to the translations, to make
60 | // sure they are in the same range. In general, it's best to
61 | // use automatic scales estimation:
62 | //(AutomaticScalesEstimation "true")
63 | (Scales 1000000)
64 |
65 | // Automatically guess an initial translation by aligning the
66 | // geometric centers of the fixed and moving.
67 | (AutomaticTransformInitialization "true")
68 | //(AutomaticTransformInitializationMethod "GeometricalCenter")
69 | (AutomaticTransformInitializationMethod "CenterOfGravity")
70 |
71 | // Whether transforms are combined by composition or by addition.
72 | // In generally, Compose is the best option in most cases.
73 | // It does not influence the results very much.
74 | (HowToCombineTransforms "Compose")
75 |
76 |
77 |
78 | //************Similarity Measure************
79 |
80 | // Number of grey level bins in each resolution level,
81 | // for the mutual information. 16 or 32 usually works fine.
82 | // You could also employ a hierarchical strategy:
83 | (NumberOfHistogramBins 64 64 64 64)
84 | //(NumberOfHistogramBins 32)
85 |
86 |
87 | //**************Multiresolution **********************
88 |
89 | // The number of resolutions. 1 Is only enough if the expected
90 | // deformations are small. 3 or 4 mostly works fine. For large
91 | // images and large deformations, 5 or 6 may even be useful.
92 | (NumberOfResolutions 4)
93 | (ImagePyramidSchedule 8 8 8 4 4 4 2 2 2 1 1 1 )
94 |
95 |
96 |
97 | // ******************* Optimizer ****************************
98 |
99 | // Maximum number of iterations in each resolution level:
100 | // 200-500 works usually fine for rigid registration.
101 | // For more robustness, you may increase this to 1000-2000.
102 | //(MaximumNumberOfIterations 1500 1500 1000 1000)
103 | (MaximumNumberOfIterations 5000 5000 1000 1000)
104 |
105 |
106 | // The step size of the optimizer, in mm. By default the voxel size is used.
107 | // which usually works well. In case of unusual high-resolution images
108 | // (eg histology) it is necessary to increase this value a bit, to the size
109 | // of the "smallest visible structure" in the image:
110 | (MaximumStepLength 20.0 10.0 2.0 2.0)
111 | //(MaximumStepLengthRatio 0.2 0.5 1 1)
112 | (SP_A 10000.000000 1000.000000 100.000000 1.000000 )
113 | //(Sp_a 1000 500 500 200)
114 |
115 |
116 | //************Image Sampling************
117 |
118 | // Number of spatial samples used to compute the mutual
119 | // information (and its derivative) in each iteration.
120 | // With an AdaptiveStochasticGradientDescent optimizer,
121 | // in combination with the two options below, around 2000
122 | // samples may already suffice.
123 | (NumberOfSpatialSamples 4096)
124 | (CheckNumberOfSamples "true")
125 | //(NumberOfSpatialSamples 2048)
126 |
127 | // Refresh these spatial samples in every iteration, and select
128 | // them randomly. See the manual for information on other sampling
129 | // strategies.
130 | (NewSamplesEveryIteration "true")
131 | //(ImageSampler "RandomCoordinate")
132 | (ImageSampler "Random")
133 | //(ImageSampler "Full")
134 | //(ImageSampler "Grid")
135 | (SampleGridSpacing 2 2 2 2)
136 | (MaximumNumberOfSamplingAttempts 2000)
137 | (RequiredRatioOfValidSamples 0.045)
138 |
139 |
140 | (FixedImageBSplineInterpolationOrder 1)
141 | //(UseRandomSampleRegion "true")
142 | //(SampleRegionSize 50 50 50)
143 |
144 | // ************* Interpolation and Resampling ****************
145 |
146 | // Order of B-Spline interpolation used during registration/optimisation.
147 | // It may improveie accuracy if you set this to 3. Never use 0.
148 | // An order of 1 gives linear interpolation. This is in most
149 | // applications a good choice.
150 | (BSplineInterpolationOrder 1)
151 |
152 | // Order of B-Spline interpolation used for applying the final
153 | // deformation.
154 | // 3 gives good accuracy; recommended in most cases.
155 | // 1 gives worse accuracy (linear interpolation)
156 | // 0 gives worst accuracy, but is appropriate for binary images
157 | // (masks, segmentations); equivalent to nearest neighbor interpolation.
158 | (FinalBSplineInterpolationOrder 1)
159 |
160 | //Default pixel value for pixels that come from outside the picture:
161 | (DefaultPixelValue -1000)
162 |
163 | //************Output***************
164 |
165 | // Write resulting images. You can save some time by setting this to false, if you are only interested in the final deformed moving image for example.
166 | (WriteResultImage "true")
167 |
168 | //***********MiscVisulaization
169 | (WriteTransformParametersEachIteration "false" "false" "false" "false")
170 | (WriteTransformParametersEachResolution "false" "false" "false" "true")
171 |
172 | // Define output format
173 | //(ResultImagePixelType "double")
174 | (ResultImageFormat "nrrd")
--------------------------------------------------------------------------------
/configs/param_rigid_small_512.txt:
--------------------------------------------------------------------------------
1 | //Parameter file
2 |
3 | //**********ImageTypes**********
4 | // The internal pixel type, used for internal computations
5 | // Leave to float in general.
6 | // NB: this is not the type of the input images! The pixel
7 | // type of the input images is automatically read from the
8 | // images themselves.
9 | // This setting can be changed to "short" to save some memory
10 | // in case of very large 3D images.
11 | (FixedInternalImagePixelType "float")
12 | (MovingInternalImagePixelType "float")
13 | (FixedImageDimension 3)
14 | (MovingImageDimension 3)
15 | (ErodeMask "true")
16 |
17 |
18 | // Specify whether you want to take into account the so-called
19 | // direction cosines of the images. Recommended: true.
20 | // In some cases, the direction cosines of the image are corrupt,
21 | // due to image format conversions for example. In that case, you
22 | // may want to set this option to "false".
23 | (UseDirectionCosines "true")
24 |
25 |
26 | //*********Components**********
27 |
28 | //(Registration "MultiResolutionRegistration")
29 | (Registration "MultiMetricMultiResolutionRegistration")
30 |
31 | //***Interpolator
32 | //(Interpolator "BSplineInterpolator")
33 | (Interpolator "LinearInterpolator")
34 | //***Resampler
35 | (Resampler "DefaultResampler")
36 | (ResampleInterpolator "FinalBSplineInterpolator")
37 | //(ResampleInterpolator "LinearInterpolator")
38 |
39 | (FixedImagePyramid "FixedRecursiveImagePyramid")
40 | (MovingImagePyramid "MovingRecursiveImagePyramid")
41 | //(FixedImagePyramid "FixedSmoothingImagePyramid")
42 | //(MovingImagePyramid "MovingSmoothingImagePyramid")
43 | //(FixedImagePyramid "FixedShrinkingImagePyramid")
44 | //(MovingImagePyramid "MovingShrinkingImagePyramid")
45 |
46 | // The following components are most important:
47 | // The optimizer AdaptiveStochasticGradientDescent (ASGD) works
48 | // quite ok in general. The Transform and Metric are important
49 | // and need to be chosen careful for each application. See manual.
50 | //(Transform "TranslationTransform")
51 | (Transform "EulerTransform")
52 | (Sampler "RandomCoordinate")
53 | (Optimizer "AdaptiveStochasticGradientDescent")
54 | //(Metric "AdvancedMattesMutualInformation" "AdvancedNormalizedCorrelation")
55 | (Metric "AdvancedMattesMutualInformation")
56 |
57 | //************Transform************
58 |
59 | // Scales the rotations compared to the translations, to make
60 | // sure they are in the same range. In general, it's best to
61 | // use automatic scales estimation:
62 | //(AutomaticScalesEstimation "true")
63 | (Scales 1000000)
64 |
65 | // Automatically guess an initial translation by aligning the
66 | // geometric centers of the fixed and moving.
67 | (AutomaticTransformInitialization "true")
68 | //(AutomaticTransformInitializationMethod "GeometricalCenter")
69 | (AutomaticTransformInitializationMethod "CenterOfGravity")
70 |
71 | // Whether transforms are combined by composition or by addition.
72 | // In generally, Compose is the best option in most cases.
73 | // It does not influence the results very much.
74 | (HowToCombineTransforms "Compose")
75 |
76 |
77 |
78 | //************Similarity Measure************
79 |
80 | // Number of grey level bins in each resolution level,
81 | // for the mutual information. 16 or 32 usually works fine.
82 | // You could also employ a hierarchical strategy:
83 | (NumberOfHistogramBins 64 64 64 64)
84 | //(NumberOfHistogramBins 32)
85 |
86 |
87 | //**************Multiresolution **********************
88 |
89 | // The number of resolutions. 1 Is only enough if the expected
90 | // deformations are small. 3 or 4 mostly works fine. For large
91 | // images and large deformations, 5 or 6 may even be useful.
92 | (NumberOfResolutions 4)
93 | (ImagePyramidSchedule 8 8 8 4 4 4 2 2 2 1 1 1 )
94 |
95 |
96 |
97 | // ******************* Optimizer ****************************
98 |
99 | // Maximum number of iterations in each resolution level:
100 | // 200-500 works usually fine for rigid registration.
101 | // For more robustness, you may increase this to 1000-2000.
102 | //(MaximumNumberOfIterations 1500 1500 1000 1000)
103 | (MaximumNumberOfIterations 5000 5000 1000 1000)
104 |
105 |
106 | // The step size of the optimizer, in mm. By default the voxel size is used.
107 | // which usually works well. In case of unusual high-resolution images
108 | // (eg histology) it is necessary to increase this value a bit, to the size
109 | // of the "smallest visible structure" in the image:
110 | (MaximumStepLength 20.0 10.0 2.0 2.0)
111 | //(MaximumStepLengthRatio 0.2 0.5 1 1)
112 | (SP_A 10000.000000 1000.000000 100.000000 1.000000 )
113 | //(Sp_a 1000 500 500 200)
114 |
115 |
116 | //************Image Sampling************
117 |
118 | // Number of spatial samples used to compute the mutual
119 | // information (and its derivative) in each iteration.
120 | // With an AdaptiveStochasticGradientDescent optimizer,
121 | // in combination with the two options below, around 2000
122 | // samples may already suffice.
123 | (NumberOfSpatialSamples 512)
124 | (CheckNumberOfSamples "true")
125 | //(NumberOfSpatialSamples 2048)
126 |
127 | // Refresh these spatial samples in every iteration, and select
128 | // them randomly. See the manual for information on other sampling
129 | // strategies.
130 | (NewSamplesEveryIteration "true")
131 | //(ImageSampler "RandomCoordinate")
132 | (ImageSampler "Random")
133 | //(ImageSampler "Full")
134 | //(ImageSampler "Grid")
135 | (SampleGridSpacing 2 2 2 2)
136 | (MaximumNumberOfSamplingAttempts 2000)
137 | (RequiredRatioOfValidSamples 0.045)
138 |
139 |
140 | (FixedImageBSplineInterpolationOrder 1)
141 | //(UseRandomSampleRegion "true")
142 | //(SampleRegionSize 50 50 50)
143 |
144 | // ************* Interpolation and Resampling ****************
145 |
146 | // Order of B-Spline interpolation used during registration/optimisation.
147 | // It may improveie accuracy if you set this to 3. Never use 0.
148 | // An order of 1 gives linear interpolation. This is in most
149 | // applications a good choice.
150 | (BSplineInterpolationOrder 1)
151 |
152 | // Order of B-Spline interpolation used for applying the final
153 | // deformation.
154 | // 3 gives good accuracy; recommended in most cases.
155 | // 1 gives worse accuracy (linear interpolation)
156 | // 0 gives worst accuracy, but is appropriate for binary images
157 | // (masks, segmentations); equivalent to nearest neighbor interpolation.
158 | (FinalBSplineInterpolationOrder 1)
159 |
160 | //Default pixel value for pixels that come from outside the picture:
161 | (DefaultPixelValue -1000)
162 |
163 | //************Output***************
164 |
165 | // Write resulting images. You can save some time by setting this to false, if you are only interested in the final deformed moving image for example.
166 | (WriteResultImage "true")
167 |
168 | //***********MiscVisulaization
169 | (WriteTransformParametersEachIteration "false" "false" "false" "false")
170 | (WriteTransformParametersEachResolution "false" "false" "false" "true")
171 |
172 | // Define output format
173 | //(ResultImagePixelType "double")
174 | (ResultImageFormat "nrrd")
--------------------------------------------------------------------------------
/configs/param_trans_simple.txt:
--------------------------------------------------------------------------------
1 | // Initialization
2 | (AutomaticTransformInitialization "true")
3 | (AutomaticTransformInitializationMethod "CenterOfGravity")
4 |
5 |
6 | (CheckNumberOfSamples "true")
7 | (DefaultPixelValue -1024.000000)
8 | (FinalBSplineInterpolationOrder 3.000000)
9 |
10 | (FixedImagePyramid "FixedSmoothingImagePyramid")
11 |
12 | (ImageSampler "RandomCoordinate")
13 |
14 | (Interpolator "LinearInterpolator")
15 |
16 | (MaximumNumberOfIterations 1024.000000)
17 | (MaximumNumberOfSamplingAttempts 8.000000)
18 |
19 | (Metric "AdvancedMattesMutualInformation")
20 |
21 | (MovingImagePyramid "MovingSmoothingImagePyramid")
22 |
23 | (NewSamplesEveryIteration "true")
24 | (NumberOfResolutions 4.000000)
25 | (NumberOfSamplesForExactGradient 4096.000000)
26 | (NumberOfSpatialSamples 2048.000000)
27 | (Optimizer "AdaptiveStochasticGradientDescent")
28 | (AutomaticParameterEstimation "true")
29 | (Registration "MultiResolutionRegistration")
30 | (ResampleInterpolator "FinalBSplineInterpolator")
31 |
32 | (Resampler "DefaultResampler")
33 | (ResultImageFormat "nii")
34 | (Transform "TranslationTransform")
35 | (WriteIterationInfo "false")
36 | (WriteResultImage "true")
--------------------------------------------------------------------------------
/configs/tags_CBCT.txt:
--------------------------------------------------------------------------------
1 | PatientSex
2 | PatientAge
3 | Modality
4 | StudyDate
5 | StudyDescription
6 | SeriesDescription
7 | KVP
8 | ExposureTime
9 | XRayTubeCurrent
10 | Exposure
11 | Rows
12 | Columns
13 | PixelSpacing
14 | SliceThickness
15 | DataCollectionDiameter
16 | ReconstructionDiameter
17 | Manufacturer
18 | ManufacturerModelName
19 | StationName
20 |
--------------------------------------------------------------------------------
/configs/tags_CT.txt:
--------------------------------------------------------------------------------
1 | PatientSex
2 | PatientAge
3 | Modality
4 | StudyDate
5 | StudyDescription
6 | SeriesDescription
7 | KVP
8 | ExposureTime
9 | XRayTubeCurrent
10 | Exposure
11 | FilterType
12 | CTDIvol
13 | Rows
14 | Columns
15 | PixelSpacing
16 | SliceThickness
17 | DataCollectionDiameter
18 | ReconstructionDiameter
19 | Manufacturer
20 | ManufacturerModelName
21 |
--------------------------------------------------------------------------------
/configs/tags_MR.txt:
--------------------------------------------------------------------------------
1 | PatientSex
2 | PatientAge
3 | PatientWeight
4 | PatientSize
5 | Modality
6 | MagneticFieldStrength
7 | StudyDate
8 | StudyDescription
9 | SeriesDescription
10 | ScanningSequence
11 | SequenceVariant
12 | ScanOptions
13 | MRAcquisitionType
14 | SequenceName
15 | FlipAngle
16 | EchoNumbers
17 | InversionTime
18 | EchoTime
19 | RepetitionTime
20 | NumberOfAverages
21 | NumberOfPhaseEncodingSteps
22 | EchoTrainLength
23 | PixelBandwidth
24 | AcquisitionDuration
25 | Rows
26 | Columns
27 | PixelSpacing
28 | SliceThickness
29 | AcquisitionMatrix
30 | Manufacturer
31 | ManufacturerModelName
32 | SoftwareVersions
33 |
--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.12
2 |
3 | COPY requirements.txt ./
4 | RUN pip install --no-cache-dir -r requirements.txt
5 | RUN apt-get update && apt-get install -y plastimatch
6 | RUN apt-get install -y git
7 | RUN pip uninstall -y SimpleITK
8 | RUN pip uninstall SimpleITK-SimpleElastix
9 | RUN pip install SimpleITK-SimpleElastix
--------------------------------------------------------------------------------
/docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | synthrad:
3 | build:
4 | context: .
5 | volumes:
6 | # path to data directory
7 | - /path/to/data/:/data
8 | # path to pre-processing code
9 | - ../:/code
10 | command: tail -F anything
11 | shm_size: '2gb'
12 | deploy:
13 | resources:
14 | reservations:
15 | devices:
16 | - driver: nvidia
17 | count: 'all'
18 | capabilities: [gpu]
19 |
--------------------------------------------------------------------------------
/docker/requirements.txt:
--------------------------------------------------------------------------------
1 | numpy
2 | matplotlib
3 | scipy
4 | scikit-build
5 | itk
6 | SimpleITK-SimpleElastix
7 | TotalSegmentator
8 | ipykernel
9 |
--------------------------------------------------------------------------------
/stage1.py:
--------------------------------------------------------------------------------
1 | import preprocessing_utils as utils
2 | import os
3 | import SimpleITK as sitk
4 | import logging
5 | import sys
6 |
7 | # Set this to true if you want to skip already pre-processsed patients (checks if output files already exists)
8 | skip_existing = True
9 |
10 | if __name__ == "__main__":
11 |
12 | ## set up logging to console and file
13 | log_file = 'stage1.log'
14 |
15 | logger = logging.getLogger()
16 | logger.setLevel(logging.INFO)
17 |
18 | file_handler = logging.FileHandler('stage1.log',mode = 'a')
19 | file_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
20 |
21 | console_handler = logging.StreamHandler()
22 | console_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
23 |
24 | logger.addHandler(file_handler)
25 | logger.addHandler(console_handler)
26 |
27 | logger.info('Starting stage 1 preprocessing')
28 |
29 | ## load pre-processing configuration from .csv file (sys.argv[1])
30 | file = sys.argv[1]
31 | if file.endswith('.csv'):
32 | patient_dict = utils.csv_to_dict(file)
33 | else:
34 | logger.error('Input file must be a csv file')
35 | sys.exit(1)
36 |
37 | for pat in patient_dict:
38 | patient = patient_dict[pat]
39 | # check if output files already exist and skip if flag is set
40 | if skip_existing:
41 | if patient['task'] == 1:
42 | if (os.path.isfile(os.path.join(patient['output_dir'],'mr_s1.nii.gz')) and
43 | os.path.isfile(os.path.join(patient['output_dir'],'ct_s1.nii.gz')) and
44 | os.path.isfile(os.path.join(patient['output_dir'],'fov_s1.nii.gz'))):
45 | logger.info(f'Patient {pat} already pre-processed. Skipping...')
46 | continue
47 | elif patient['task'] == 2:
48 | if (os.path.isfile(os.path.join(patient['output_dir'],'cbct_s1.nii.gz')) and
49 | os.path.isfile(os.path.join(patient['output_dir'],'ct_s1.nii.gz')) and
50 | os.path.isfile(os.path.join(patient['output_dir'],'fov_s1.nii.gz'))):
51 | logger.info(f'Patient {pat} already pre-processed. Skipping...')
52 | continue
53 |
54 | # log patient details
55 | logger.info(f'''Processing case {pat}:
56 | Input: {patient['input_path']}
57 | CT: {patient['ct_path']}
58 | Output: {patient['output_dir']}''')
59 |
60 | # Load input (CBCT or MRI) and CT as sitk images, if dicom provide path to directory, if other file type provide path to file
61 | input = utils.read_image(patient['input_path'],log=logger)
62 | ct = utils.read_image(patient['ct_path'],log=logger)
63 |
64 | # if necessary correct orientation of input/MRI (swap or flip axes)
65 | input = utils.correct_image_properties(input_image = input,
66 | order = patient['order'],
67 | flip = patient['flip'],
68 | mr_overlap_correction = patient['mr_overlap_correction'],
69 | intensity_shift = patient['intensity_shift'],
70 | log = logger)
71 |
72 | # calculate CBCT/MRI FOV mask
73 | if patient['task'] == 1:
74 | fov_mask = utils.get_mr_fov(input)
75 | if patient['task'] == 2:
76 | fov_mask = utils.get_cbct_fov(input,background=patient['background'],log=logger)
77 |
78 | # Register CBCT/MRI to CT
79 | parameter_file = patient['registration']
80 | if patient['reg_fovmask']:
81 | logger.info('Registering input to CT using FOV mask...')
82 | input, transform = utils.rigid_registration(ct, input, parameter_file, default_value=patient['background'], log=logger, mask=fov_mask)
83 | else:
84 | logger.info('Registering input to CT without FOV mask...')
85 | input, transform = utils.rigid_registration(ct, input, parameter_file, default_value=patient['background'], log=logger)
86 |
87 | # Apply transformation to CBCT/MRI FOV mask
88 | fov_mask_reg = utils.apply_transform(fov_mask,transform,ct)
89 |
90 | # Deface CBCT/MRI and CT
91 | if patient['defacing']:
92 | # Get structures for defacing
93 | brain,skull = utils.segment_defacing(ct,log=logger)
94 | defacing_mask = utils.defacing(brain,skull,log=logger)
95 | ct = sitk.Mask(ct,defacing_mask,outsideValue=-1024,maskingValue=1)
96 | input = sitk.Mask(input,defacing_mask,outsideValue=patient['background'],maskingValue=1)
97 |
98 | # Resample everything
99 | input = utils.resample_image(input,new_spacing=patient['resample'],log=logger)
100 | ct = utils.resample_image(ct,new_spacing=patient['resample'],log=logger)
101 | fov_mask_reg = utils.resample_image(fov_mask_reg,new_spacing=patient['resample'],log=logger)
102 | if patient['defacing']:
103 | defacing_mask = utils.resample_image(defacing_mask,new_spacing=patient['resample'],log=logger)
104 |
105 | # Save registered,defaced CBCT/MRI and CT, input/MRI FOV mask and transform
106 | if not os.path.isdir(patient['output_dir']):
107 | os.mkdir(patient['output_dir'])
108 | logger.info('Creating output directory...')
109 | else:
110 | logger.warning('Output directory already exists. Overwriting existing files...')
111 | if patient['task'] == 1:
112 | utils.save_image(input,os.path.join(patient['output_dir'],'mr_s1.nii.gz'))
113 | if patient['task'] == 2:
114 | utils.save_image(input,os.path.join(patient['output_dir'],'cbct_s1.nii.gz'))
115 | utils.save_image(fov_mask_reg,os.path.join(patient['output_dir'],'fov_s1.nii.gz'))
116 | utils.save_image(ct,os.path.join(patient['output_dir'],'ct_s1.nii.gz'))
117 | if patient['defacing']:
118 | utils.save_image(defacing_mask,os.path.join(patient['output_dir'],'defacing_mask.nii.gz'))
119 | sitk.WriteTransform(transform,os.path.join(patient['output_dir'],'transform.tfm'))
120 |
121 | # convert rtstruct to nrrd
122 | if not patient['struct_path']=='':
123 | utils.convert_rtstruct_to_nrrd(patient['struct_path'],patient['output_dir'],log=logger)
124 |
125 | # generate overview png
126 | utils.generate_overview_stage1(ct,input,patient['output_dir'])
127 |
--------------------------------------------------------------------------------
/stage1_config.csv:
--------------------------------------------------------------------------------
1 | ID,task,region,ct_path,input_path,struct_path,output_dir,defacing,registration,reg_fovmask,background,order,flip,resample,mr_overlap_correction,intensity_shift
2 | 1ABA001,1,AB,/workspace/data/1%/Task1/Abdomen/1ABA001/ct_or.nii.gz,/workspace/data/1%/Task1/Abdomen/1ABA001/mr_or.nii.gz,,/workspace/data/1%/Task1/Abdomen/1ABA001/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
3 | 1ABA002,1,AB,/workspace/data/1%/Task1/Abdomen/1ABA002/ct_or.nii.gz,/workspace/data/1%/Task1/Abdomen/1ABA002/mr_or.nii.gz,,/workspace/data/1%/Task1/Abdomen/1ABA002/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
4 | 1ABA006,1,AB,/workspace/data/1%/Task1/Abdomen/1ABA006/ct_or.nii.gz,/workspace/data/1%/Task1/Abdomen/1ABA006/mr_or.nii.gz,,/workspace/data/1%/Task1/Abdomen/1ABA006/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
5 | 1ABB001,1,AB,/workspace/data/1%/Task1/Abdomen/1ABB001/ct.nrrd,/workspace/data/1%/Task1/Abdomen/1ABB001/mr.nrrd,,/workspace/data/1%/Task1/Abdomen/1ABB001/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
6 | 1ABB002,1,AB,/workspace/data/1%/Task1/Abdomen/1ABB002/ct.nrrd,/workspace/data/1%/Task1/Abdomen/1ABB002/mr.nrrd,,/workspace/data/1%/Task1/Abdomen/1ABB002/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
7 | 1ABB003,1,AB,/workspace/data/1%/Task1/Abdomen/1ABB003/ct.nrrd,/workspace/data/1%/Task1/Abdomen/1ABB003/mr.nrrd,,/workspace/data/1%/Task1/Abdomen/1ABB003/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
8 | 1ABC001,1,AB,/workspace/data/1%/Task1/Abdomen/1ABC001/CT.nii.gz,/workspace/data/1%/Task1/Abdomen/1ABC001/MRI.nii.gz,,/workspace/data/1%/Task1/Abdomen/1ABC001/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
9 | 1ABC002,1,AB,/workspace/data/1%/Task1/Abdomen/1ABC002/CT.nii.gz,/workspace/data/1%/Task1/Abdomen/1ABC002/MRI.nii.gz,,/workspace/data/1%/Task1/Abdomen/1ABC002/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_large_1024.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
10 | 1ABC003,1,AB,/workspace/data/1%/Task1/Abdomen/1ABC003/CT.nii.gz,/workspace/data/1%/Task1/Abdomen/1ABC003/MRI.nii.gz,,/workspace/data/1%/Task1/Abdomen/1ABC003/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
11 | 1HNA901,1,HN,/workspace/data/1%/Task1/HN/1HNA901/ct_or.nii.gz,/workspace/data/1%/Task1/HN/1HNA901/mr_or.nii.gz,,/workspace/data/1%/Task1/HN/1HNA901/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_large_1024.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
12 | 1HNA902,1,HN,/workspace/data/1%/Task1/HN/1HNA902/ct_or.nii.gz,/workspace/data/1%/Task1/HN/1HNA902/mr_or.nii.gz,,/workspace/data/1%/Task1/HN/1HNA902/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_large_1024.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
13 | 1HNA903,1,HN,/workspace/data/1%/Task1/HN/1HNA903/ct_or.nii.gz,/workspace/data/1%/Task1/HN/1HNA903/mr_or.nii.gz,,/workspace/data/1%/Task1/HN/1HNA903/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_large_1024.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
14 | 1HNA904,1,HN,/workspace/data/1%/Task1/HN/1HNA904/ct_or.nii.gz,/workspace/data/1%/Task1/HN/1HNA904/mr_or.nii.gz,,/workspace/data/1%/Task1/HN/1HNA904/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_large_1024.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
15 | 1HNA905,1,HN,/workspace/data/1%/Task1/HN/1HNA905/ct_or.nii.gz,/workspace/data/1%/Task1/HN/1HNA905/mr_or.nii.gz,,/workspace/data/1%/Task1/HN/1HNA905/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_large_1024.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
16 | 1HNA906,1,HN,/workspace/data/1%/Task1/HN/1HNA906/ct_or.nii.gz,/workspace/data/1%/Task1/HN/1HNA906/mr_or.nii.gz,,/workspace/data/1%/Task1/HN/1HNA906/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_large_1024.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
17 | 1HNC001,1,HN,/workspace/data/1%/Task1/HN/1HNC001/CT.nii.gz,/workspace/data/1%/Task1/HN/1HNC001/MRI.nii.gz,,/workspace/data/1%/Task1/HN/1HNC001/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,TRUE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
18 | 1HNC002,1,HN,/workspace/data/1%/Task1/HN/1HNC002/CT.nii.gz,/workspace/data/1%/Task1/HN/1HNC002/MRI.nii.gz,,/workspace/data/1%/Task1/HN/1HNC002/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,TRUE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
19 | 1HNC004,1,HN,/workspace/data/1%/Task1/HN/1HNC004/CT.nii.gz,/workspace/data/1%/Task1/HN/1HNC004/MRI.nii.gz,,/workspace/data/1%/Task1/HN/1HNC004/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,TRUE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
20 | 1THA901,1,TH,/workspace/data/1%/Task1/Thorax/1THA901/ct_or.nii.gz,/workspace/data/1%/Task1/Thorax/1THA901/mr_or.nii.gz,,/workspace/data/1%/Task1/Thorax/1THA901/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
21 | 1THA936,1,TH,/workspace/data/1%/Task1/Thorax/1THA936/ct_or.nii.gz,/workspace/data/1%/Task1/Thorax/1THA936/mr_or.nii.gz,,/workspace/data/1%/Task1/Thorax/1THA936/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
22 | 1THA9201,1,TH,/workspace/data/1%/Task1/Thorax/1THA9201/ct_or.nii.gz,/workspace/data/1%/Task1/Thorax/1THA9201/mr_or.nii.gz,,/workspace/data/1%/Task1/Thorax/1THA9201/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",TRUE,0
23 | 1THB001,1,TH,/workspace/data/1%/Task1/Thorax/1THB001/ct.nrrd,/workspace/data/1%/Task1/Thorax/1THB001/mr.nrrd,,/workspace/data/1%/Task1/Thorax/1THB001/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
24 | 1THB002,1,TH,/workspace/data/1%/Task1/Thorax/1THB002/ct.nrrd,/workspace/data/1%/Task1/Thorax/1THB002/mr.nrrd,,/workspace/data/1%/Task1/Thorax/1THB002/output,FALSE,/workspace/code/preprocessing/configs/xparam_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
25 | 1THB004,1,TH,/workspace/data/1%/Task1/Thorax/1THB004/ct.nrrd,/workspace/data/1%/Task1/Thorax/1THB004/mr.nrrd,,/workspace/data/1%/Task1/Thorax/1THB004/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
26 | 1THC001,1,TH,/workspace/data/1%/Task1/Thorax/1THC001/CT.nii.gz,/workspace/data/1%/Task1/Thorax/1THC001/MRI.nii.gz,,/workspace/data/1%/Task1/Thorax/1THC001/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
27 | 1THC002,1,TH,/workspace/data/1%/Task1/Thorax/1THC002/CT.nii.gz,/workspace/data/1%/Task1/Thorax/1THC002/MRI.nii.gz,,/workspace/data/1%/Task1/Thorax/1THC002/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
28 | 1THC004,1,TH,/workspace/data/1%/Task1/Thorax/1THC004/CT.nii.gz,/workspace/data/1%/Task1/Thorax/1THC004/MRI.nii.gz,,/workspace/data/1%/Task1/Thorax/1THC004/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,0,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
29 | #2ABA001,2,AB,/workspace/data/1%/Task2/Abdomen/2ABA001/ct_or.nii.gz,/workspace/data/1%/Task2/Abdomen/2ABA001/cbct_or.nii.gz,,/workspace/data/1%/Task2/Abdomen/2ABA001/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_4096.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
30 | 2ABA002,2,AB,/workspace/data/1%/Task2/Abdomen/2ABA902/ct_or.nii.gz,/workspace/data/1%/Task2/Abdomen/2ABA902/cbct_or.nii.gz,,/workspace/data/1%/Task2/Abdomen/2ABA902/output,FALSE,/workspace/code/preprocessing/configs/param_rigid.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
31 | 2ABA903,2,AB,/workspace/data/1%/Task2/Abdomen/2ABA903/ct_or.nii.gz,/workspace/data/1%/Task2/Abdomen/2ABA903/cbct_or.nii.gz,,/workspace/data/1%/Task2/Abdomen/2ABA903/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_4096.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
32 | 2ABA904,2,AB,/workspace/data/1%/Task2/Abdomen/2ABA904/ct_or.nii.gz,/workspace/data/1%/Task2/Abdomen/2ABA904/cbct_or.nii.gz,,/workspace/data/1%/Task2/Abdomen/2ABA904/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_large_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
33 | 2ABB001,2,AB,/workspace/data/1%/Task2/Abdomen/2ABB001/ct.nrrd,/workspace/data/1%/Task2/Abdomen/2ABB001/scan.mha,,/workspace/data/1%/Task2/Abdomen/2ABB001/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_large_4096.txt,FALSE,-1000,"[2,1,0]","[False,False,True]","[1,1,3]",FALSE,-1000
34 | 2ABB002,2,AB,/workspace/data/1%/Task2/Abdomen/2ABB002/ct.nrrd,/workspace/data/1%/Task2/Abdomen/2ABB002/scan.mha,,/workspace/data/1%/Task2/Abdomen/2ABB002/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_large_512.txt,FALSE,-1000,"[2,1,0]","[False,False,True]","[1,1,3]",FALSE,-1000
35 | 2ABB003,2,AB,/workspace/data/1%/Task2/Abdomen/2ABB003/ct.nrrd,/workspace/data/1%/Task2/Abdomen/2ABB003/scan.mha,,/workspace/data/1%/Task2/Abdomen/2ABB003/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_large_4096.txt,FALSE,-1000,"[2,1,0]","[False,False,True]","[1,1,3]",FALSE,-1000
36 | 2ABC001,2,AB,/workspace/data/1%/Task2/Abdomen/2ABC001/CT.nii,/workspace/data/1%/Task2/Abdomen/2ABC001/CBCT.nii,,/workspace/data/1%/Task2/Abdomen/2ABC001/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
37 | 2ABC002,2,AB,/workspace/data/1%/Task2/Abdomen/2ABC002/CT.nii,/workspace/data/1%/Task2/Abdomen/2ABC002/CBCT.nii,,/workspace/data/1%/Task2/Abdomen/2ABC002/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
38 | 2ABC003,2,AB,/workspace/data/1%/Task2/Abdomen/2ABC003/CT.nii,/workspace/data/1%/Task2/Abdomen/2ABC003/CBCT.nii,,/workspace/data/1%/Task2/Abdomen/2ABC003/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
39 | 2HNA901,2,HN,/workspace/data/1%/Task2/HN/2HNA901/ct_or.nii.gz,/workspace/data/1%/Task2/HN/2HNA901/cbct_or.nii.gz,,/workspace/data/1%/Task2/HN/2HNA901/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_large_1024.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
40 | 2HNA902,2,HN,/workspace/data/1%/Task2/HN/2HNA902/ct_or.nii.gz,/workspace/data/1%/Task2/HN/2HNA902/cbct_or.nii.gz,,/workspace/data/1%/Task2/HN/2HNA902/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_large_1024.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
41 | 2HNA903,2,HN,/workspace/data/1%/Task2/HN/2HNA903/ct_or.nii.gz,/workspace/data/1%/Task2/HN/2HNA903/cbct_or.nii.gz,,/workspace/data/1%/Task2/HN/2HNA903/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_large_1024.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
42 | 2HNB001,2,HN,/workspace/data/1%/Task2/HN/2HNB001/ct.nrrd,/workspace/data/1%/Task2/HN/2HNB001/scan.mha,,/workspace/data/1%/Task2/HN/2HNB001/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1000,"[2,1,0]","[False,False,True]","[1,1,3]",FALSE,-1000
43 | 2HNB002,2,HN,/workspace/data/1%/Task2/HN/2HNB002/ct.nrrd,/workspace/data/1%/Task2/HN/2HNB002/scan.mha,,/workspace/data/1%/Task2/HN/2HNB002/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1000,"[2,1,0]","[False,False,True]","[1,1,3]",FALSE,-1000
44 | 2HNB003,2,HN,/workspace/data/1%/Task2/HN/2HNB003/ct.nrrd,/workspace/data/1%/Task2/HN/2HNB003/scan.mha,,/workspace/data/1%/Task2/HN/2HNB003/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1000,"[2,1,0]","[False,False,True]","[1,1,3]",FALSE,-1000
45 | 2HNC002,2,HN,/workspace/data/1%/Task2/HN/2HNC002/CT.nii,/workspace/data/1%/Task2/HN/2HNC002/CBCT.nii,,/workspace/data/1%/Task2/HN/2HNC002/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
46 | 2HNC003,2,HN,/workspace/data/1%/Task2/HN/2HNC003/CT.nii,/workspace/data/1%/Task2/HN/2HNC003/CBCT.nii,,/workspace/data/1%/Task2/HN/2HNC003/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
47 | 2HNC004,2,HN,/workspace/data/1%/Task2/HN/2HNC004/CT.nii,/workspace/data/1%/Task2/HN/2HNC004/CBCT.nii,,/workspace/data/1%/Task2/HN/2HNC004/output,TRUE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
48 | 2THA901,2,TH,/workspace/data/1%/Task2/Thorax/2THA901/ct_or.nii.gz,/workspace/data/1%/Task2/Thorax/2THA901/cbct_or.nii.gz,,/workspace/data/1%/Task2/Thorax/2THA901/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
49 | 2THA903,2,TH,/workspace/data/1%/Task2/Thorax/2THA903/ct_or.nii.gz,/workspace/data/1%/Task2/Thorax/2THA903/cbct_or.nii.gz,,/workspace/data/1%/Task2/Thorax/2THA903/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
50 | 2THA904,2,TH,/workspace/data/1%/Task2/Thorax/2THA904/ct_or.nii.gz,/workspace/data/1%/Task2/Thorax/2THA904/cbct_or.nii.gz,,/workspace/data/1%/Task2/Thorax/2THA904/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_large_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
51 | 2THB001,2,TH,/workspace/data/1%/Task2/Thorax/2THB001/ct.nrrd,/workspace/data/1%/Task2/Thorax/2THB001/scan.mha,,/workspace/data/1%/Task2/Thorax/2THB001/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1000,"[2,1,0]","[False,False,True]","[1,1,3]",FALSE,-1000
52 | 2THB002,2,TH,/workspace/data/1%/Task2/Thorax/2THB002/ct.nrrd,/workspace/data/1%/Task2/Thorax/2THB002/scan.mha,,/workspace/data/1%/Task2/Thorax/2THB002/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1000,"[2,1,0]","[False,False,True]","[1,1,3]",FALSE,-1000
53 | 2THB003,2,TH,/workspace/data/1%/Task2/Thorax/2THB003/ct.nrrd,/workspace/data/1%/Task2/Thorax/2THB003/scan.mha,,/workspace/data/1%/Task2/Thorax/2THB003/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1000,"[2,1,0]","[False,False,True]","[1,1,3]",FALSE,-1000
54 | 2THC001,2,TH,/workspace/data/1%/Task2/Thorax/2THC001/CT.nii,/workspace/data/1%/Task2/Thorax/2THC001/CBCT.nii,,/workspace/data/1%/Task2/Thorax/2THC001/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
55 | 2THC002,2,TH,/workspace/data/1%/Task2/Thorax/2THC002/CT.nii,/workspace/data/1%/Task2/Thorax/2THC002/CBCT.nii,,/workspace/data/1%/Task2/Thorax/2THC002/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
56 | 2THC003,2,TH,/workspace/data/1%/Task2/Thorax/2THC003/CT.nii,/workspace/data/1%/Task2/Thorax/2THC003/CBCT.nii,,/workspace/data/1%/Task2/Thorax/2THC003/output,FALSE,/workspace/code/preprocessing/configs/param_rigid_small_512.txt,FALSE,-1024,"[0,1,2]","[False,False,False]","[1,1,3]",FALSE,0
--------------------------------------------------------------------------------
/stage2.py:
--------------------------------------------------------------------------------
1 | import preprocessing_utils as utils
2 | import os
3 | import SimpleITK as sitk
4 | import logging
5 | import sys
6 |
7 | # Set this to true if you want to skip already pre-processsed patients (checks if output files already exists)
8 | skip_existing = True
9 |
10 | if __name__ == "__main__":
11 | ## set up logging to console and file
12 | log_file = 'stage2.log'
13 | logger = logging.getLogger()
14 | logger.setLevel(logging.INFO)
15 | file_handler = logging.FileHandler(log_file,mode = 'a')
16 | file_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
17 | console_handler = logging.StreamHandler()
18 | console_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
19 | logger.addHandler(file_handler)
20 | logger.addHandler(console_handler)
21 | logger.info('Starting stage 2 preprocessing')
22 |
23 | ## load pre-processing configuration from .csv file (sys.argv[1])
24 | file = sys.argv[1]
25 | if file.endswith('.csv'):
26 | patient_dict = utils.csv_to_dict(file)
27 | else:
28 | logger.error('Input file must be a csv file')
29 | sys.exit(1)
30 | for i in patient_dict:
31 | patient = patient_dict[i]
32 | # check if output files already exist and skip if flag is set
33 | if skip_existing:
34 | if patient['task'] == 1:
35 | if (os.path.isfile(os.path.join(patient['output_dir'],'mr_s2.nii.gz')) and
36 | os.path.isfile(os.path.join(patient['output_dir'],'ct_s2.nii.gz')) and
37 | os.path.isfile(os.path.join(patient['output_dir'],'ct_s2_def.nii.gz')) and
38 | os.path.isfile(os.path.join(patient['output_dir'],'mask_s2.nii.gz')) and
39 | os.path.isfile(os.path.join(patient['output_dir'],f'{patient["ID"]}.png'))):
40 | logger.info(f'Patient {i} already pre-processed. Skipping...')
41 | continue
42 | elif patient['task'] == 2:
43 | if (os.path.isfile(os.path.join(patient['output_dir'],'cbct_s2.nii.gz')) and
44 | os.path.isfile(os.path.join(patient['output_dir'],'ct_s2.nii.gz')) and
45 | os.path.isfile(os.path.join(patient['output_dir'],'ct_s2_def.nii.gz')) and
46 | os.path.isfile(os.path.join(patient['output_dir'],'mask_s2.nii.gz')) and
47 | os.path.isfile(os.path.join(patient['output_dir'],f'{patient["ID"]}.png'))):
48 | logger.info(f'Patient {i} already pre-processed. Skipping...')
49 | continue
50 |
51 | # log patient details
52 | logger.info(f'''Processing case {i}:
53 | Output_dir: {patient['output_dir']}''')
54 |
55 | #Read Files
56 | if patient['task'] == 1:
57 | input = utils.read_image(os.path.join(patient['output_dir'],'mr_s1.nii.gz'),log=logger)
58 | elif patient['task'] == 2:
59 | input = utils.read_image(os.path.join(patient['output_dir'],'cbct_s1.nii.gz'),log=logger)
60 | else:
61 | logger.error('Task not valid')
62 | sys.exit(1)
63 | ct = utils.read_image(os.path.join(patient['output_dir'],'ct_s1.nii.gz'),log=logger)
64 | fov_s1 = utils.read_image(os.path.join(patient['output_dir'],'fov_s1.nii.gz'),log=logger)
65 | if patient['defacing_correction'] == True:
66 | face = utils.read_image(os.path.join(patient['output_dir'],'defacing_mask.nii.gz'),log=logger)
67 |
68 | # Clip CT to valid HU range
69 | ct = utils.clip_image(ct,-1024,3071)
70 |
71 | # Perform cone correction for fov mask if task2
72 | if patient['task'] == 2:
73 | if patient['cone_correction']:
74 | fov_s1 = utils.cone_correction(fov_s1,log=logger)
75 |
76 | #Generate patient outline and postprocess it
77 | mask = utils.segment_outline(input,patient['mask_thresh'],log=logger)
78 | if patient['defacing_correction']:
79 | defacing_correction = os.path.join(patient['output_dir'],'defacing_mask.nii.gz')
80 | defacing_correction = utils.read_image(defacing_correction,log=logger)
81 | else:
82 | defacing_correction = None
83 | if patient['IS_correction']:
84 | IS_correction = 10
85 | else:
86 | IS_correction = None
87 | mask = utils.postprocess_outline(mask,
88 | fov_s1,
89 | defacing_correction=defacing_correction,
90 | IS_correction=IS_correction,
91 | log=logger)
92 |
93 | #Crop images using mask generated above
94 | input = utils.crop_image(input,fov_s1)
95 | ct = utils.crop_image(ct,fov_s1)
96 | mask = utils.crop_image(mask,fov_s1)
97 | fov = utils.crop_image(fov_s1,fov_s1)
98 |
99 | #deform CT to match input
100 | ct_deformed, transform = utils.deformable_registration(input,ct,patient['parameter_def'],mask=mask,log=logger)
101 | sitk.WriteParameterFile(transform, os.path.join(patient['output_dir'],'transform_def.txt'))
102 |
103 | # #deform defacing mask if necessary and apply to fov
104 | # if patient['defacing_correction']:
105 | # face_deformed = utils.warp_structure(face,transform)
106 | # fov[face_deformed == 1] = 0
107 |
108 | #apply fov mask to all images
109 | if patient['task'] == 1:
110 | mask_value = 0
111 | if patient['task'] == 2:
112 | mask_value = -1000
113 | ct_deformed = utils.mask_image(ct_deformed,fov,-1000)
114 | ct = utils.mask_image(ct,fov,-1000)
115 | input = utils.mask_image(input,fov,mask_value)
116 | mask = utils.mask_image(mask,fov,0)
117 |
118 | #preprocess structures
119 | logger.info('Preprocessing and warping structures...')
120 | rigid_reg = sitk.ReadTransform(os.path.join(patient['output_dir'],'transform.tfm'))
121 | ct_s1 = utils.read_image(os.path.join(patient['output_dir'],'ct_s1.nii.gz'),log=logger)
122 | #utils.preprocess_structures(patient,input,ct_s1,fov_s1,fov,rigid_reg,transform,mask,log=logger)
123 |
124 | # Stitch CT_def to CT_s1 for planning (structures are stitched above)
125 | ct_deformed_stitched = utils.stitch_image(ct_deformed, ct_s1, mask)
126 |
127 | #Save cropped images and transform
128 | if patient['task'] == 1:
129 | utils.save_image(input,os.path.join(patient['output_dir'],'mr_s2.nii.gz'),dtype='int16')
130 | if patient['task'] == 2:
131 | utils.save_image(input,os.path.join(patient['output_dir'],'cbct_s2.nii.gz'),dtype='int16')
132 | utils.save_image(ct,os.path.join(patient['output_dir'],'ct_s2.nii.gz'),dtype='int16')
133 | utils.save_image(mask,os.path.join(patient['output_dir'],'mask_s2.nii.gz'))
134 | utils.save_image(fov,os.path.join(patient['output_dir'],'fov_s2.nii.gz'))
135 | utils.save_image(ct_deformed,os.path.join(patient['output_dir'],'ct_s2_def.nii.gz'),dtype='int16')
136 | utils.save_image(ct_deformed_stitched, os.path.join(patient['output_dir'],'ct_s2_def_stitched.nii.gz'),dtype='int16')
137 |
138 | #Generate png overviews
139 | utils.generate_overview_png(ct,input,mask,patient)
140 | utils.generate_overview_planning(ct,input,ct_deformed,mask,patient)
141 |
--------------------------------------------------------------------------------
/stage2_config.csv:
--------------------------------------------------------------------------------
1 | ID,task,region,output_dir,mask_thresh,defacing_correction,cone_correction,IS_correction,parameter_def,invert_structures
2 | 1ABA901,1,AB,/workspace/data/1%/Task1/Abdomen/1ABA901/output,0.2,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_AB.txt,FALSE
3 | 1ABA902,1,AB,/workspace/data/1%/Task1/Abdomen/1ABA902/output,0.2,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_AB.txt,FALSE
4 | 1ABA906,1,AB,/workspace/data/1%/Task1/Abdomen/1ABA906/output,0.2,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_AB.txt,FALSE
5 | 1ABB001,1,AB,/workspace/data/1%/Task1/Abdomen/1ABB001/output,0.2,FALSE,FALSE,TRUE,/workspace/code/preprocessing/configs/param_def_mr_AB.txt,TRUE
6 | 1ABB002,1,AB,/workspace/data/1%/Task1/Abdomen/1ABB002/output,0.2,FALSE,FALSE,TRUE,/workspace/code/preprocessing/configs/param_def_mr_AB.txt,TRUE
7 | 1ABB003,1,AB,/workspace/data/1%/Task1/Abdomen/1ABB003/output,0.2,FALSE,FALSE,TRUE,/workspace/code/preprocessing/configs/param_def_mr_AB.txt,TRUE
8 | 1ABC001,1,AB,/workspace/data/1%/Task1/Abdomen/1ABC001/output,0.1,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_AB.txt,FALSE
9 | 1ABC002,1,AB,/workspace/data/1%/Task1/Abdomen/1ABC002/output,0.1,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_AB.txt,FALSE
10 | 1ABC003,1,AB,/workspace/data/1%/Task1/Abdomen/1ABC003/output,0.1,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_AB.txt,FALSE
11 | 1HNA901,1,HN,/workspace/data/1%/Task1/HN/1HNA901/output,0.2,TRUE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_HN.txt,FALSE
12 | 1HNA902,1,HN,/workspace/data/1%/Task1/HN/1HNA902/output,0.2,TRUE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_HN.txt,FALSE
13 | 1HNA903,1,HN,/workspace/data/1%/Task1/HN/1HNA903/output,0.2,TRUE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_HN.txt,FALSE
14 | 1HNA904,1,HN,/workspace/data/1%/Task1/HN/1HNA904/output,0.2,TRUE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_HN.txt,FALSE
15 | 1HNA905,1,HN,/workspace/data/1%/Task1/HN/1HNA905/output,0.2,TRUE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_HN.txt,FALSE
16 | 1HNA906,1,HN,/workspace/data/1%/Task1/HN/1HNA906/output,0.2,TRUE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_HN.txt,FALSE
17 | 1HNC001,1,HN,/workspace/data/1%/Task1/HN/1HNC001/output,0.6,TRUE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_HN.txt,FALSE
18 | 1HNC002,1,HN,/workspace/data/1%/Task1/HN/1HNC002/output,0.8,TRUE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_HN.txt,FALSE
19 | 1HNC004,1,HN,/workspace/data/1%/Task1/HN/1HNC004/output,0.6,TRUE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_HN.txt,FALSE
20 | 1THA901,1,TH,/workspace/data/1%/Task1/Thorax/1THA901/output,0.2,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_TH.txt,FALSE
21 | 1THA936,1,TH,/workspace/data/1%/Task1/Thorax/1THA936/output,0.2,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_TH.txt,FALSE
22 | 1THA9201,1,TH,/workspace/data/1%/Task1/Thorax/1THA9201/output,0.2,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_TH.txt,FALSE
23 | 1THB001,1,TH,/workspace/data/1%/Task1/Thorax/1THB001/output,0.2,FALSE,FALSE,TRUE,/workspace/code/preprocessing/configs/param_def_mr_TH.txt,TRUE
24 | 1THB002,1,TH,/workspace/data/1%/Task1/Thorax/1THB002/output,0.2,FALSE,FALSE,TRUE,/workspace/code/preprocessing/configs/param_def_mr_TH.txt,TRUE
25 | 1THB004,1,TH,/workspace/data/1%/Task1/Thorax/1THB004/output,0.2,FALSE,FALSE,TRUE,/workspace/code/preprocessing/configs/param_def_mr_TH.txt,TRUE
26 | 1THC001,1,TH,/workspace/data/1%/Task1/Thorax/1THC001/output,0.1,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_TH.txt,FALSE
27 | 1THC002,1,TH,/workspace/data/1%/Task1/Thorax/1THC002/output,0.1,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_TH.txt,FALSE
28 | 1THC004,1,TH,/workspace/data/1%/Task1/Thorax/1THC004/output,0.1,FALSE,FALSE,FALSE,/workspace/code/preprocessing/configs/param_def_mr_TH.txt,FALSE
29 | 2ABA902,2,AB,/workspace/data/1%/Task2/Abdomen/2ABA902/output,0.4,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_AB.txt,FALSE
30 | 2ABA903,2,AB,/workspace/data/1%/Task2/Abdomen/2ABA903/output,0.4,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_AB.txt,FALSE
31 | 2ABA904,2,AB,/workspace/data/1%/Task2/Abdomen/2ABA904/output,0.4,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_AB.txt,FALSE
32 | 2ABB001,2,AB,/workspace/data/1%/Task2/Abdomen/2ABB001/output,0.6,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_AB.txt,FALSE
33 | 2ABB002,2,AB,/workspace/data/1%/Task2/Abdomen/2ABB002/output,0.6,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_AB.txt,FALSE
34 | 2ABB003,2,AB,/workspace/data/1%/Task2/Abdomen/2ABB003/output,0.6,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_AB.txt,FALSE
35 | 2ABC001,2,AB,/workspace/data/1%/Task2/Abdomen/2ABC001/output,0.6,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_AB.txt,FALSE
36 | 2ABC002,2,AB,/workspace/data/1%/Task2/Abdomen/2ABC002/output,0.6,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_AB.txt,FALSE
37 | 2ABC003,2,AB,/workspace/data/1%/Task2/Abdomen/2ABC003/output,0.6,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_AB.txt,FALSE
38 | 2HNA901,2,HN,/workspace/data/1%/Task2/HN/2HNA901/output,0.4,TRUE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_HN.txt,FALSE
39 | 2HNA902,2,HN,/workspace/data/1%/Task2/HN/2HNA902/output,0.4,TRUE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_HN.txt,FALSE
40 | 2HNA903,2,HN,/workspace/data/1%/Task2/HN/2HNA903/output,0.4,TRUE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_HN.txt,FALSE
41 | 2HNB001,2,HN,/workspace/data/1%/Task2/HN/2HNB001/output,0.6,TRUE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_HN.txt,FALSE
42 | 2HNB002,2,HN,/workspace/data/1%/Task2/HN/2HNB002/output,0.6,TRUE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_HN.txt,FALSE
43 | 2HNB003,2,HN,/workspace/data/1%/Task2/HN/2HNB003/output,0.6,TRUE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_HN.txt,FALSE
44 | 2HNC002,2,HN,/workspace/data/1%/Task2/HN/2HNC002/output,0.4,TRUE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_HN.txt,FALSE
45 | 2HNC003,2,HN,/workspace/data/1%/Task2/HN/2HNC003/output,0.4,TRUE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_HN.txt,FALSE
46 | 2HNC004,2,HN,/workspace/data/1%/Task2/HN/2HNC004/output,0.4,TRUE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_HN.txt,FALSE
47 | 2THA901,2,TH,/workspace/data/1%/Task2/Thorax/2THA901/output,0.2,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_TH.txt,FALSE
48 | 2THA903,2,TH,/workspace/data/1%/Task2/Thorax/2THA903/output,0.2,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_TH.txt,FALSE
49 | 2THA904,2,TH,/workspace/data/1%/Task2/Thorax/2THA904/output,0.2,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_TH.txt,FALSE
50 | 2THB001,2,TH,/workspace/data/1%/Task2/Thorax/2THB001/output,0.4,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_TH.txt,FALSE
51 | 2THB002,2,TH,/workspace/data/1%/Task2/Thorax/2THB002/output,0.4,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_TH.txt,FALSE
52 | 2THB003,2,TH,/workspace/data/1%/Task2/Thorax/2THB003/output,0.4,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_TH.txt,FALSE
53 | 2THC001,2,TH,/workspace/data/1%/Task2/Thorax/2THC001/output,0.2,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_TH.txt,FALSE
54 | 2THC002,2,TH,/workspace/data/1%/Task2/Thorax/2THC002/output,0.2,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_TH.txt,FALSE
55 | 2THC003,2,TH,/workspace/data/1%/Task2/Thorax/2THC003/output,0.2,FALSE,TRUE,FALSE,/workspace/code/preprocessing/configs/param_def_cbct_TH.txt,FALSE
56 |
--------------------------------------------------------------------------------
/utilities/clip_data.py:
--------------------------------------------------------------------------------
1 | import shutil
2 | import os
3 | import fnmatch
4 | import SimpleITK as sitk
5 |
6 | def read_image(image_path:str)->sitk.Image:
7 | image = sitk.ReadImage(image_path)
8 | return image
9 |
10 | def save_image(image:sitk.Image, image_path:str, compression:bool=True, dtype:str=None):
11 | if dtype != None:
12 | if image.GetPixelIDTypeAsString() != '32-bit float':
13 | image = sitk.Cast(image,sitk.sitkFloat32)
14 | image = sitk.Round(image)
15 | if dtype == 'float32':
16 | image = sitk.Cast(image,sitk.sitkFloat32)
17 | elif dtype == 'int16':
18 | image = sitk.Cast(image,sitk.sitkInt16)
19 | else:
20 | raise ValueError('Invalid dtype/not implemented. Allowed dtypes: float32 and int16')
21 | sitk.WriteImage(image, image_path, useCompression=compression)
22 |
23 | def clip_image(image:sitk.Image,lower_bound:float, upper_bound:float)->sitk.Image:
24 | image[imageupper_bound] = upper_bound
26 | return image
27 |
28 | ### change theses path for source (non-clipped) and destination (clipped) ###
29 | ### use the same path twice if you want to overvwrite the original data ###
30 | dataset_root = '/workspace/data/full/releases/non-clipped/'
31 | dataset_dest_root = '/workspace/data/full/releases/clipped/'
32 |
33 | datasets = [
34 | 'synthRAD2025_Task1_Train',
35 | 'synthRAD2025_Task2_Train',
36 | 'synthRAD2025_Task1_Train_D',
37 | 'synthRAD2025_Task2_Train_D',
38 | ]
39 | datasets = os.listdir(dataset_root)
40 |
41 | for dataset in datasets:
42 | dataset_path = os.path.join(dataset_root, dataset)
43 | dataset_dest_path = os.path.join(dataset_dest_root, dataset)
44 |
45 | task = os.listdir(dataset_path)
46 | if len(task) > 1:
47 | # copy license
48 | file = fnmatch.filter(task, '*.txt')[0]
49 | if not os.path.exists(os.path.join(dataset_dest_path, file)):
50 | os.makedirs(dataset_dest_path, exist_ok=True)
51 | shutil.copy(os.path.join(dataset_path, file), os.path.join(dataset_dest_path, file))
52 | task = fnmatch.filter(task, 'Task*')[0]
53 | else:
54 | task = task[0]
55 | regions = os.listdir(os.path.join(dataset_path, task))
56 |
57 | for region in regions:
58 | region_path = os.path.join(dataset_path, task, region)
59 | for root, dirs, files in os.walk(region_path):
60 | print(f'Processing {root}')
61 | root_dest = root.replace(dataset_path, dataset_dest_path)
62 | os.makedirs(root_dest, exist_ok=True)
63 | for file in files:
64 | file_path = os.path.join(root, file)
65 | dest_path = os.path.join(root_dest, file)
66 | if file in ['ct.mha','cbct.mha','ct_def.mha']:
67 | image = read_image(file_path)
68 | image = clip_image(image, -1024, 3071)
69 | save_image(image, dest_path, compression=True, dtype='int16')
70 | else:
71 | if not os.path.exists(dest_path):
72 | shutil.copy(file_path, dest_path)
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/utilities/create_final_csvs.py:
--------------------------------------------------------------------------------
1 | import shutil
2 | import os
3 | import fnmatch
4 | import SimpleITK as sitk
5 | import pandas as pd
6 | import openpyxl
7 |
8 | # Define export parameters
9 | ROOT = "/workspace/data/full"
10 | DEST = "/workspace/data/full/releases/synthRAD2025_Task2_Val_Input_D/"
11 |
12 | CENTERS = ['D']
13 | TASK = ['2']
14 | REGIONS = ['HN','AB','TH']
15 | SETS = ['val']
16 | FILES = ['parameters']
17 |
18 | # Iterate through all centers, tasks and regions
19 | for center in CENTERS:
20 | for task in TASK:
21 | for region in REGIONS:
22 | for set in SETS:
23 | # Read patient IDs from Set file
24 | source = os.path.join(ROOT, center, f'Task{task}', region)
25 | source_file = os.path.join(source, f'{task}{region}{center}_parameters.xlsx')
26 | destination_file = os.path.join(DEST, f'Task{task}', region, 'overviews',f'{task}_{region}_{set}_parameters.xlsx')
27 | if not os.path.exists(destination_file):
28 | pd.DataFrame().to_excel(destination_file, index=False)
29 | set_file = os.path.join(source, f'{task}{region}{center}_Set.csv')
30 | if os.path.exists(set_file):
31 | with open(set_file) as f:
32 | lines = f.readlines()
33 | for i,line in enumerate(lines):
34 | if i > 0:
35 | line = line.strip()
36 | line = line.strip("'")
37 | if line == "":
38 | continue
39 | patient_id = line.split(",")[0].strip('"').strip("'")
40 | patient_set = line.split(",")[1].strip('"')
41 | print(patient_id, patient_set)
42 | if patient_set.lower() == set:
43 | df = pd.read_excel(source_file, sheet_name=None)
44 | patient_data = {}
45 | for sheet in df.keys():
46 | # Check if patient data exists in the source file
47 | data = df[sheet][df[sheet]['ID'] == patient_id]
48 | if len(data) > 0:
49 | patient_data[sheet] = data
50 | else:
51 | # Create a row with "-" for all columns, except patient ID
52 | empty_row = pd.DataFrame({col: ["-"] for col in df[sheet].columns})
53 | empty_row.at[0, 'ID'] = patient_id # Set first column to patient_id
54 | patient_data[sheet] = empty_row
55 |
56 | # Read any existing data from the destination Excel file
57 | current_data = {}
58 | if os.path.exists(destination_file) and os.path.getsize(destination_file) > 0:
59 | current_data = pd.read_excel(destination_file, sheet_name=None)
60 |
61 | # For each sheet in the patient data, append only new rows if they don't already exist
62 | for sheet, new_data in patient_data.items():
63 | if sheet in current_data and not current_data[sheet].empty:
64 | existing_ids = current_data[sheet]['ID'].tolist()
65 | new_data_filtered = new_data[~new_data['ID'].isin(existing_ids)]
66 | combined = pd.concat([current_data[sheet], new_data_filtered], ignore_index=True)
67 | else:
68 | combined = new_data
69 | current_data[sheet] = combined
70 |
71 | # Write the updated data back to the destination file
72 | with pd.ExcelWriter(destination_file, engine='openpyxl') as writer:
73 | for sheet, data in current_data.items():
74 | data.to_excel(writer, sheet_name=sheet, index=False)
75 | wb = openpyxl.load_workbook(destination_file)
76 | if "Sheet1" in wb.sheetnames:
77 | std = wb["Sheet1"]
78 | wb.remove(std)
79 | wb.save(destination_file)
80 | else:
81 | print(f'File {set_file} does not exist, continuing...')
--------------------------------------------------------------------------------
/utilities/create_final_release.py:
--------------------------------------------------------------------------------
1 | import shutil
2 | import os
3 | import fnmatch
4 | import SimpleITK as sitk
5 |
6 | def nii_to_mha(nii_file, mha_file, compression:bool=True):
7 | image = sitk.ReadImage(nii_file)
8 | try:
9 | image = sitk.Round(image)
10 | except:
11 | print('Could not round image ...')
12 | if image.GetPixelIDTypeAsString() != '16-bit signed integer':
13 | image = sitk.Cast(image, sitk.sitkInt16)
14 | sitk.WriteImage(image, mha_file, useCompression=compression)
15 |
16 | # Define export parameters
17 | ROOT = "/workspace/data/full"
18 | DEST = "/workspace/data/full/releases/synthRAD2025_Task1_Val_Input_D"
19 |
20 | CENTERS = ['D']
21 | TASK = ['1']
22 | REGIONS = ['HN','AB','TH']
23 | SETS = ['val']
24 | FILES = ['overview','mask_s2.nii.gz','mr_s2.nii.gz']
25 | #FILES = ['overview','ct_s2.nii.gz','ct_s2_def.nii.gz']
26 |
27 | # Iterate through all centers, tasks and regions
28 | for center in CENTERS:
29 | for task in TASK:
30 | for region in REGIONS:
31 | for set in SETS:
32 | # Read patient IDs from Set file
33 | source = os.path.join(ROOT, center, f'Task{task}', region)
34 | destination = os.path.join(DEST, f'Task{task}', region)
35 | set_file = os.path.join(source, f'{task}{region}{center}_Set.csv')
36 | if os.path.exists(set_file):
37 | if not os.path.exists(destination):
38 | os.makedirs(destination)
39 | with open(set_file) as f:
40 | lines = f.readlines()
41 | for i,line in enumerate(lines):
42 | if i > 0:
43 | line = line.strip()
44 | line = line.strip("'")
45 | if line == "":
46 | continue
47 | patient_id = line.split(",")[0].strip('"').strip("'")
48 | patient_set = line.split(",")[1].strip('"')
49 | print(patient_id, patient_set)
50 | if patient_set.lower() == set:
51 | for file in FILES:
52 | if file == 'overview_planning':
53 | if not os.path.exists(os.path.join(destination,'overviews')):
54 | os.makedirs(os.path.join(destination,'overviews'))
55 | source_file = os.path.join(source, patient_id,'output',f'{patient_id}_planning.png')
56 | destination_file = os.path.join(destination,'overviews', f'{patient_id}_{file}.png')
57 | if os.path.exists(source_file):
58 | shutil.copy(source_file, destination_file)
59 | else:
60 | print(f'File {source_file} does not exist')
61 | elif file == "overview":
62 | if set == 'test' or set == 'val':
63 | if not os.path.exists(os.path.join(destination,'overviews')):
64 | os.makedirs(os.path.join(destination,'overviews'))
65 | source_file = os.path.join(source, patient_id,'output',f'{patient_id}_def.png')
66 | destination_file = os.path.join(destination,'overviews', f'{patient_id}_{file}.png')
67 | if os.path.exists(source_file):
68 | shutil.copy(source_file, destination_file)
69 | else:
70 | print(f'File {source_file} does not exist')
71 | else:
72 | if not os.path.exists(os.path.join(destination,'overviews')):
73 | os.makedirs(os.path.join(destination,'overviews'))
74 | source_file = os.path.join(source, patient_id,'output',f'{patient_id}.png')
75 | destination_file = os.path.join(destination,'overviews', f'{patient_id}_{file}.png')
76 | if os.path.exists(source_file):
77 | shutil.copy(source_file, destination_file)
78 | else:
79 | print(f'File {source_file} does not exist')
80 |
81 | elif file == "ct_s2_def.nii.gz":
82 | source_file = os.path.join(source, patient_id,'output',f'{file}')
83 | file_name = file.replace('_s2_def.nii.gz','_def.mha')
84 | if not os.path.exists(os.path.join(destination,patient_id)):
85 | os.makedirs(os.path.join(destination,patient_id))
86 | dest_file = os.path.join(destination,patient_id,file_name)
87 | nii_to_mha(source_file, dest_file, compression=True)
88 |
89 | elif file == "structures_renamed":
90 | source_dir = os.path.join(source, patient_id,'output','structures_renamed')
91 | destination_dir = os.path.join(destination,patient_id,'structures_renamed')
92 | if not os.path.exists(os.path.join(destination,patient_id)):
93 | os.makedirs(os.path.join(destination,patient_id))
94 | if os.path.exists(source_dir):
95 | shutil.copytree(source_dir, destination_dir,dirs_exist_ok=True)
96 | else:
97 | print(f'File {source_dir} does not exist')
98 |
99 | elif file == "ct_s2_def_stitched.nii.gz":
100 | source_file = os.path.join(source, patient_id,'output',f'{file}')
101 | if not os.path.exists(os.path.join(destination,patient_id)):
102 | os.makedirs(os.path.join(destination,patient_id))
103 | dest_file = os.path.join(destination,patient_id,file)
104 | shutil.copy(source_file, dest_file)
105 |
106 | else:
107 | source_file = os.path.join(source, patient_id,'output',f'{file}')
108 | file_name = file.replace('_s2.nii.gz','.mha')
109 | if not os.path.exists(os.path.join(destination,patient_id)):
110 | os.makedirs(os.path.join(destination,patient_id))
111 | dest_file = os.path.join(destination,patient_id,file_name)
112 | nii_to_mha(source_file, dest_file, compression=True)
113 | else:
114 | print(f'File {set_file} does not exist, continuing...')
115 |
--------------------------------------------------------------------------------
/utilities/extract_dicom_tags.py:
--------------------------------------------------------------------------------
1 | #copied from synthrad2023 preprocessing https://github.com/SynthRAD2023/preprocessing/tree/main
2 | import pydicom as dcm
3 | import os
4 | import csv
5 | import argparse
6 | import openpyxl
7 | import SimpleITK as sitk
8 |
9 | # Function that reads a list of dicom tag names from a txt file and returns the tags in a list
10 | def read_tags(txt_file):
11 | file = open(txt_file,'r')
12 | tags = file.read().splitlines()
13 | return tags
14 |
15 | # Function to get the number of slices for a dicom image
16 | def get_number_of_slices(dcm_folder):
17 | files = os.listdir(dcm_folder)
18 | slices = 0
19 | UID = []
20 | for i in range(len(files)):
21 | tags = dcm.dcmread(os.path.join(dcm_folder,files[i]),stop_before_pixels=True)
22 | UID.append(tags['SeriesInstanceUID'].value)
23 | if i==0:
24 | slices = 1
25 | elif i!=0:
26 | if UID[i]==UID[i-1]:
27 | slices = slices+1
28 | return slices
29 |
30 | # Function that takes a DICOM folder as an input, reads dicom tags from the first slice and returns specified tags as a dict,
31 | # and if specified also adds dimension and spacing of post-processed image
32 | def extract_tags(dcm_folder,tags,pre_processed=None,csv=None,pt=None,phase=None):
33 | files = os.listdir(dcm_folder)
34 | tag_list = read_tags(tags)
35 | tags = dcm.dcmread(os.path.join(dcm_folder,files[0]),stop_before_pixels=True)
36 | tags_dict = {}
37 | for tag in tag_list:
38 | try:
39 | tags_dict[tag]=str(tags[tag].value)
40 | except:
41 | print('Tag: ' + str(tag) + ' not available!')
42 | tags_dict[tag]='empty'
43 | tags_dict['Slices']=str(get_number_of_slices(dcm_folder))
44 | if pre_processed!=None:
45 | size_pre,spacing_pre = extract_tags_post(pre_processed)
46 | tags_dict['Dim_pre']=str(size_pre)
47 | tags_dict['Spacing_pre']=str(spacing_pre)
48 | if csv!=None:
49 | if pt != None:
50 | write_dict_to_csv(tags_dict, csv, tag_list, pt, phase)
51 | else:
52 | write_dict_to_csv(tags_dict, csv, tag_list)
53 | # print(tags_dict)
54 | return tags_dict
55 |
56 | def extract_tags_post(image):
57 | im = sitk.ReadImage(image)
58 | imsize = im.GetSize()
59 | imspacing = im.GetSpacing()
60 | return [imsize,imspacing]
61 |
62 | # Function that creates a csv file based on the dicts with extracted tags
63 | def write_dict_to_csv(input_dict,output_csv,tag_list,pt=None,phase=None):
64 |
65 | # first check if dict is nested (required for file writing)
66 | if pt != None:
67 | input_dict['ID'] = pt
68 | input_dict['Set'] = phase
69 | tag_list.insert(0,'ID')
70 | tag_list.insert(1,'Set')
71 |
72 | if any(isinstance(i,dict) for i in input_dict.values()):
73 | input_dict_nested = input_dict
74 | else:
75 | input_dict_nested = {'1': input_dict}
76 | # print(input_dict_nested)
77 | tag_list.append('Slices')
78 | if 'Dim_pre' in input_dict:
79 | tag_list.append('Dim_pre')
80 | tag_list.append('Spacing_pre')
81 |
82 | # If file does not exist, create header, otherwise directly append the rows
83 | if os.path.isfile(output_csv):
84 | print("File exist")
85 | else:
86 | with open(output_csv, 'w+', newline='') as csvfile:
87 | writer = csv.DictWriter(csvfile, fieldnames=tag_list)
88 | writer.writeheader()
89 |
90 | with open(output_csv,'a', newline='') as csvfile:
91 | writer = csv.DictWriter(csvfile,fieldnames=tag_list)
92 | for k in input_dict_nested:
93 | writer.writerow({field: input_dict_nested[k].get(field) or k for field in tag_list})
94 | print('csv '+ output_csv +' written!')
95 |
96 | #Function that converts the csv file into an excel file
97 | def convert_csv_to_xlsx(input_csv, output_xlsx, sheetname=None):
98 | csv_data = []
99 | with open(input_csv) as file_obj:
100 | reader = csv.reader(file_obj)
101 | for row in reader:
102 | csv_data.append(row)
103 | if os.path.isfile(output_xlsx):
104 | workbook = openpyxl.load_workbook(output_xlsx)
105 | try:
106 | std = workbook['Sheet']
107 | workbook.remove(std)
108 | except:
109 | print('Worksheet Sheet already removed')
110 |
111 | else:
112 | workbook = openpyxl.Workbook()
113 | workbook.create_sheet(sheetname)
114 | sheet = workbook[sheetname]
115 | if sheetname!=None:
116 | sheet.title=sheetname
117 | for row in csv_data:
118 | sheet.append(row)
119 | workbook.save(output_xlsx)
120 |
121 | if __name__ == "__main__":
122 | parser = argparse.ArgumentParser(description='Define fixed, moving and output filenames')
123 | parser.add_argument('operation', help='select operation to perform (extract, to_csv, to_xlsx)')
124 | parser.add_argument('--tags', help='dictionary file listing the tags to extract')
125 | parser.add_argument('--pre', help='path to preprocessed nii.gz to extract sizes')
126 | parser.add_argument('--path', help='path of the folder containing the dicom')
127 | parser.add_argument('--csv', help='path of the output csv file')
128 | parser.add_argument('--xlsx', help='path of the output excel file')
129 | parser.add_argument('--pt', help='ID of the patient')
130 | parser.add_argument('--phase', help='Dataset of the patient')
131 | args = parser.parse_args()
132 |
133 | if args.operation == 'extract':
134 | if args.pre is None:
135 | extract_tags(args.path,args.tags,pre_processed=None)
136 | else:
137 | if args.csv is None:
138 | extract_tags(args.path,args.tags,args.pre,csv=None)
139 | else:
140 | if args.pt is None:
141 | extract_tags(args.path, args.tags, args.pre, args.csv, pt=None, phase=None)
142 | else:
143 | extract_tags(args.path, args.tags, args.pre, args.csv, args.pt, args.phase)
144 | elif args.operation == 'toxlsx':
145 | convert_csv_to_xlsx(args.csv, args.xlsx, args.tags)
146 | else:
147 | print('check help for usage instructions')
--------------------------------------------------------------------------------