├── .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 | Logo 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') --------------------------------------------------------------------------------