TPCCLIB
Loading...
Searching...
No Matches
simelli.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <unistd.h>
13#include <math.h>
14#include <string.h>
15#include <time.h>
16/*****************************************************************************/
17#include "tpcextensions.h"
18#include "tpcift.h"
19#include "tpccsv.h"
20#include "tpctac.h"
21#include "tpcdcm.h"
22#include "tpcecat.h"
23#include "tpcnifti.h"
24#include "tpcimage.h"
25/*****************************************************************************/
26
27/*****************************************************************************/
28static char *info[] = {
29 "Create a 3D PET image file in NIfTI 1S format, with pixels values of 1",
30 "inside of a general ellipsoid and 0 outside of it,",
31 "for simple simulations and SW testing.",
32 "Matrix size and ellipsoid diameters must be given in pixels.",
33 " ",
34 "Usage: @P [Options] xdim ydim zdim xdiam ydiam zdiam imagefile",
35 " ",
36 "Options:",
37 " -cx=<pixels> || -cy=<pixels> || -cz=<pixels>",
38 " Move the centre of ellipsoid from the image centre",
39 " -stdoptions", // List standard options like --help, -v, etc
40 " ",
41 "See also: dft2img, tac2nii, flat2img, img2tif, img2dft, simboxes, pxl2mask",
42 " ",
43 "Keywords: image, NIfTI, simulation, software testing",
44 0};
45/*****************************************************************************/
46
47/*****************************************************************************/
48/* Turn on the globbing of the command line, since it is disabled by default in
49 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
50 In Unix&Linux wildcard command line processing is enabled by default. */
51/*
52#undef _CRT_glob
53#define _CRT_glob -1
54*/
55int _dowildcard = -1;
56/*****************************************************************************/
57
58/*****************************************************************************/
62/*****************************************************************************/
63int main(int argc, char **argv)
64{
65 int ai, help=0, version=0, verbose=1;
66 char dbname[FILENAME_MAX];
67 int dimx=0, dimy=0, dimz=0;
68 double diamx=0.0, diamy=0.0, diamz=0.0;
69 double cx=0.0, cy=0.0, cz=0.0;
70 int ret=0;
71
72 /*
73 * Get arguments
74 */
75 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
76 dbname[0]=(char)0;
77 /* Options */
78 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
79 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
80 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
81 if(strncasecmp(cptr, "CX=", 3)==0) {
82 cx=atofVerified(cptr+3); if(!isnan(cx)) continue;
83 } else if(strncasecmp(cptr, "CY=", 3)==0) {
84 cy=atofVerified(cptr+3); if(!isnan(cy)) continue;
85 } else if(strncasecmp(cptr, "CZ=", 3)==0) {
86 cz=atofVerified(cptr+3); if(!isnan(cz)) continue;
87 }
88 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
89 return(1);
90 } else break; // tac name argument may start with '-'
91
92 TPCSTATUS status; statusInit(&status);
93 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
94 status.verbose=verbose-1;
95
96 /* Print help or version? */
97 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
98 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
99 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
100
101 /* Process other arguments, starting from the first non-option */
102 ret=0;
103 if(ai<argc) {if(atoiCheck(argv[ai++], &dimx)) ret++;}
104 if(ai<argc) {if(atoiCheck(argv[ai++], &dimy)) ret++;}
105 if(ai<argc) {if(atoiCheck(argv[ai++], &dimz)) ret++;}
106 if(ret || dimx<1 || dimy<1 || dimz<1) {fprintf(stderr, "Error: invalid dimension.\n"); return(1);}
107 if(ai<argc) diamx=atofVerified(argv[ai++]);
108 if(ai<argc) diamy=atofVerified(argv[ai++]);
109 if(ai<argc) diamz=atofVerified(argv[ai++]);
110 if(isnan(diamx) || isnan(diamy) || isnan(diamz)) {
111 fprintf(stderr, "Error: invalid diameter.\n"); return(1);}
112 if(ai<argc) {strlcpy(dbname, argv[ai], FILENAME_MAX); ai++;}
113 if(ai<argc) {fprintf(stderr, "Error: too many arguments.\n"); return(1);}
114
115 /* Is something missing or wrong? */
116 if(!dbname[0]) {
117 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
118 return(1);
119 }
120
121 /* In verbose mode print arguments and options */
122 if(verbose>1) {
123 printf("dbname := %s\n", dbname);
124 printf("dimx := %d\n", dimx);
125 printf("dimy := %d\n", dimy);
126 printf("dimz := %d\n", dimz);
127 printf("diamx := %g\n", diamx);
128 printf("diamy := %g\n", diamy);
129 printf("diamz := %g\n", diamz);
130 printf("cx := %g\n", cx);
131 printf("cy := %g\n", cy);
132 printf("cz := %g\n", cz);
133 fflush(stdout);
134 }
135
136 /* Move centre to the middle of the matrix */
137 cx+=0.5*(double)dimx+0.5;
138 cy+=0.5*(double)dimy+0.5;
139 cz+=0.5*(double)dimz+0.5;
140
141
142 /*
143 * Make image data
144 */
145 if(verbose>1) printf("Allocate memory for xyz matrix\n");
146 size_t pxlNr=(size_t)dimz*dimy*dimx;
147 int *idata;
148 idata=(int*)calloc(pxlNr, sizeof(int));
149 if(idata==NULL) {fprintf(stderr, "Error: out of memory.\n"); return(4);}
150 if(verbose>1) printf("Fill the template\n");
151 for(int z=0; z<dimz; z++) for(int y=0; y<dimy; y++) for(int x=0; x<dimx; x++) {
152 size_t pos=((size_t)dimy*dimx)*z + dimx*y + x;
153 double dz=(2.0*((double)z-cz)/diamz);
154 double dy=(2.0*((double)y-cy)/diamy);
155 double dx=(2.0*((double)x-cx)/diamx);
156 if(dz*dz+dy*dy+dx*dx<=1.0) idata[pos]=1; else idata[pos]=0;
157 }
158
159
160 /*
161 * Set NIfTI header contents
162 */
163 if(verbose>1) printf("Fill NIfTI header\n");
164 NIFTI_DSR dsr;
165 dsr.n=1;
166 /* Set NIfTI byte order to current machines byte order */
168 /* Initiate header structures with zeroes */
169 memset(&dsr.h1, 0, sizeof(NIFTI_1_HEADER));
170 memset(&dsr.e, 0, sizeof(NIFTI_EXTENDER));
171 /* Set header */
173 strcpy(dsr.h1.data_type, "");
174 strlcpy(dsr.h1.db_name, dbname, 17);
175 dsr.h1.extents=16384; // not used in NIfTI, but required for Analyze compatibility
176 dsr.h1.regular='r'; // not used in NIfTI, but required for Analyze compatibility
177 dsr.h1.dim_info='\0'; // MRI slice ordering
178 /* Image dimension */
179 for(int i=0; i<8; i++) dsr.h1.dim[i]=1;
180 dsr.h1.dim[0]=3;
181 dsr.h1.dim[1]=dimx;
182 dsr.h1.dim[2]=dimy;
183 dsr.h1.dim[3]=dimz;
184 dsr.h1.dim[4]=1; // just one frame
185 dsr.h1.intent_p1=0.0;
186 dsr.h1.intent_p2=0.0;
187 dsr.h1.intent_p3=0.0;
189 dsr.h1.datatype=NIFTI_DT_SIGNED_INT; // For the template
190 dsr.h1.bitpix=32;
191 dsr.h1.slice_start=0;
192 for(int i=0; i<8; i++) dsr.h1.pixdim[i]=0.0;
193 // https://nifti.nimh.nih.gov/nifti-1/documentation/nifti1fields/nifti1fields_pages/qsform.html
194 dsr.h1.pixdim[0]=1.0; // Set to either 1.0 or -1.0
195 dsr.h1.pixdim[1]=1.0; // pixel size in x dimension
196 dsr.h1.pixdim[2]=1.0; // pixel size in y dimension
197 dsr.h1.pixdim[3]=1.0; // pixel size in z dimension
198 dsr.h1.vox_offset=352; // Would be 0 for 1D format
199 dsr.h1.scl_slope=1.0; // no need to scale pixel values
200 dsr.h1.scl_inter=0.0; // no need to scale pixel values
201 dsr.h1.slice_end=0;
202 dsr.h1.slice_code=0;
204 dsr.h1.cal_max=1.0; // This image has only zeroes and ones
205 dsr.h1.cal_min=0.0; // This image has only zeroes and ones
206 dsr.h1.slice_duration=0.0;
207 dsr.h1.toffset=0.0;
208 dsr.h1.glmax=dsr.h1.cal_max; // unused in NIfTI
209 dsr.h1.glmin=0; // unused in NIfTI
210 strlcpy(dsr.h1.descrip, "simelli", 80);
211 strcpy(dsr.h1.aux_file, "");
212 dsr.h1.qform_code=0;
213 dsr.h1.sform_code=0;
214 dsr.h1.quatern_b=0;
215 dsr.h1.quatern_c=0;
216 dsr.h1.quatern_d=0;
217 dsr.h1.qoffset_x=0;
218 dsr.h1.qoffset_y=0;
219 dsr.h1.qoffset_z=0;
220 for(int i=0; i<4; i++) dsr.h1.srow_x[i]=0;
221 for(int i=0; i<4; i++) dsr.h1.srow_y[i]=0;
222 for(int i=0; i<4; i++) dsr.h1.srow_z[i]=0;
223 strcpy(dsr.h1.intent_name, "");
224 strcpy(dsr.h1.magic, "n+1"); // Would be "ni1" for 1D format
225 /* Extension is left as 0 0 0 0 */
226
227
228 /*
229 * Write image.
230 */
231 if(verbose>1) printf("Make NIfTI file names\n");
232 char hdrfile[FILENAME_MAX], imgfile[FILENAME_MAX];
233 if(niftiCreateFNames(dbname, hdrfile, imgfile, NULL, IMG_FORMAT_NIFTI_1S)) {
234 fprintf(stderr, " Error: invalid NIfTI name %s\n", dbname);
235 free(idata); return(11);
236 }
237
238 if(verbose>1) printf("Writing NIfTI header\n");
239 /* Delete previous NIfTI */
240 if(fileExist(hdrfile)) remove(hdrfile);
241 if(fileExist(imgfile)) remove(imgfile);
242 /* Write NIfTI header */
243 if(niftiWriteHeader(hdrfile, &dsr, verbose-1)) {
244 fprintf(stderr, "Error: cannot write template header.\n");
245 free(idata);
246 return(12);
247 }
248
249 if(verbose>1) printf("Writing NIfTI image data\n");
250 FILE *fp=fopen(imgfile, "r+b");
251 if(fp==NULL) {
252 fprintf(stderr, "Error: cannot open %s for write.\n", imgfile);
253 free(idata);
254 if(fileExist(hdrfile)) remove(hdrfile);
255 if(fileExist(imgfile)) remove(imgfile);
256 return(13);
257 }
258 /* Move file pointer to the place of matrix data start */
259 if(fseeko(fp, (size_t)dsr.h1.vox_offset, SEEK_SET)!=0) {
260 fprintf(stderr, "Error: invalid file write position.\n");
261 fclose(fp); free(idata);
262 if(fileExist(hdrfile)) remove(hdrfile);
263 if(fileExist(imgfile)) remove(imgfile);
264 return(14);
265 }
266 /* Write pixel data */
267 if(fwrite(idata, sizeof(int), pxlNr, fp) != pxlNr) {
268 fprintf(stderr, "Error: cannot write template matrix.\n");
269 fclose(fp); free(idata);
270 if(fileExist(hdrfile)) remove(hdrfile);
271 if(fileExist(imgfile)) remove(imgfile);
272 return(15);
273 }
274 fclose(fp); free(idata);
275 if(verbose>0) printf("written %s\n", imgfile);
276
277 return(0);
278}
279/*****************************************************************************/
280
281/*****************************************************************************/
double atofVerified(const char *s)
Definition decpoint.c:75
int endianLittle()
Definition endian.c:53
int fileExist(const char *filename)
Definition filexist.c:17
int niftiCreateFNames(const char *filename, char *hdrfile, char *imgfile, char *siffile, int fileformat)
Definition imagenii.c:17
int atoiCheck(const char *s, int *v)
Definition intutil.c:25
int niftiWriteHeader(const char *filename, NIFTI_DSR *dsr, int verbose)
Definition niftiio.c:445
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:47
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:169
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:339
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:114
void statusInit(TPCSTATUS *s)
Definition statusmsg.c:104
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
float quatern_d
Definition tpcnifti.h:289
float quatern_c
Definition tpcnifti.h:287
short int qform_code
Definition tpcnifti.h:281
char db_name[18]
Definition tpcnifti.h:220
float qoffset_x
Definition tpcnifti.h:291
short int slice_start
Definition tpcnifti.h:247
short int slice_end
Definition tpcnifti.h:257
float slice_duration
Definition tpcnifti.h:267
short int datatype
Definition tpcnifti.h:243
float intent_p2
Definition tpcnifti.h:237
char aux_file[24]
Definition tpcnifti.h:278
float intent_p1
Definition tpcnifti.h:235
float srow_z[4]
Definition tpcnifti.h:301
float srow_x[4]
Definition tpcnifti.h:297
char intent_name[16]
Definition tpcnifti.h:303
float intent_p3
Definition tpcnifti.h:239
short int bitpix
Definition tpcnifti.h:245
float pixdim[8]
Definition tpcnifti.h:249
char data_type[10]
Definition tpcnifti.h:218
short int sform_code
Definition tpcnifti.h:283
float vox_offset
Definition tpcnifti.h:251
float srow_y[4]
Definition tpcnifti.h:299
float qoffset_y
Definition tpcnifti.h:293
char descrip[80]
Definition tpcnifti.h:276
char magic[4]
Definition tpcnifti.h:306
float scl_inter
Definition tpcnifti.h:255
float qoffset_z
Definition tpcnifti.h:295
short int dim[8]
Definition tpcnifti.h:233
short int intent_code
Definition tpcnifti.h:241
float quatern_b
Definition tpcnifti.h:285
float scl_slope
Definition tpcnifti.h:253
NIFTI_EXTENDER e
Definition tpcnifti.h:408
NIFTI_1_HEADER h1
Definition tpcnifti.h:404
int byte_order
Definition tpcnifti.h:412
int verbose
Verbose level, used by statusPrint() etc.
Header file for library libtpccsv.
Header file for libtpcdcm.
Header file for libtpcecat.
Header file for library libtpcextensions.
@ TPCERROR_OK
No error.
Header file for library libtpcift.
Header file for libtpcimage.
@ IMG_FORMAT_NIFTI_1S
NIfTI-1 single-file format.
Definition tpcimage.h:43
Header file for libtpcnifti.
#define NIFTI_DT_SIGNED_INT
Definition tpcnifti.h:98
#define NIFTI1_HEADER_SIZE
Definition tpcnifti.h:33
#define NIFTI_INTENT_NONE
Definition tpcnifti.h:129
#define NIFTI_UNITS_MM
Definition tpcnifti.h:48
Header file for library libtpctac.