TPCCLIB
Loading...
Searching...
No Matches
simcirc.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 <string.h>
14#include <math.h>
15/*****************************************************************************/
16#include "tpcextensions.h"
17#include "tpcift.h"
18#include "tpccsv.h"
19/*****************************************************************************/
20
21/*****************************************************************************/
22static char *info[] = {
23 "Draw circle in x,y matrix with 1 inside circle and 0 outside of it",
24 "for simple simulations, SW testing, and creating ROI masks.",
25 "Matrix size and circle diameter must be given in pixels.",
26 " ",
27 "Usage: @P [Options] dimension diameter outputfile",
28 " ",
29 "Options:",
30 " -format=<<TSV>|<CSV>|<float>|<short>>",
31 " Matrix data can be saved as tab separated values (TSV, default),",
32 " comma separated values (CSV), or as binary flat files with either",
33 " floats or short ints.",
34 " -diam2=<2nd diameter>",
35 " If the second diameter is specified, then a ring is created.",
36 " -iring=<value inside hole>",
37 " With option -diam2, the integer value for hole inside ring;",
38 " by default 0.",
39 " -segm=<Number of segments>",
40 " Divide circle or ring into given number of segments with increasing",
41 " value in each.",
42 " -inv",
43 " Write 0 inside the circle or ring, and 1 outside of it.",
44 " Not applicable with options -iring and -segm.",
45 " -stdoptions", // List standard options like --help, -v, etc
46 " ",
47 "Example #1:",
48 " @P 256 224 circle.txt",
49 "Example #2:",
50 " @P -format=float 256 64 circle.bin",
51 " flat2nii circle.bin 256 256 1 1 circle",
52 " ",
53 "See also: flat2nii, asc2flat, simiart, simboxes, simelli, imgadd, imglkup",
54 " ",
55 "Keywords: simulation, image, mask, software testing",
56 0};
57/*****************************************************************************/
58
59/*****************************************************************************/
60/* Turn on the globbing of the command line, since it is disabled by default in
61 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
62 In Unix&Linux wildcard command line processing is enabled by default. */
63/*
64#undef _CRT_glob
65#define _CRT_glob -1
66*/
67int _dowildcard = -1;
68/*****************************************************************************/
69
70/*****************************************************************************/
74int main(int argc, char **argv)
75{
76 int ai, help=0, version=0, verbose=1;
77 char *cptr, outfile[FILENAME_MAX];
78 int dim=-1;
79 int csv_separator=2; // 0=comma, 1=semi-colon, 2=tab, 3=space
80 int output_format=0; // 0=ASCII, 1=float binary, 2=short int binary
81 double diameter=-1, diameter2=-1;
82 int invert=0; // 0 or 1
83 int segments=1; // divide circle or ring into nr of segments
84 int iring=0; // value inside ring hole
85
86
87 /*
88 * Get arguments
89 */
90 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
91 outfile[0]=(char)0;
92 /* Options */
93 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
94 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
95 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
96 if(strncasecmp(cptr, "DIAM2=", 6)==0) {
97 diameter2=atofVerified(cptr+6);
98 if(!isnan(diameter2) && diameter2>0.0) continue;
99 } else if(strncasecmp(cptr, "SEGM=", 5)==0) {
100 if(atoiCheck(cptr+5, &segments)==0 && segments>0) continue;
101 } else if(strncasecmp(cptr, "IRING=", 6)==0) {
102 if(atoiCheck(cptr+6, &iring)==0 && iring>=0) continue;
103 } else if(strncasecmp(cptr, "F=", 2)==0) {
104 cptr+=2;
105 if(!strcasecmp(cptr, "TSV")) {csv_separator=2; output_format=0; continue;}
106 if(!strcasecmp(cptr, "CSV")) {csv_separator=0; output_format=0; continue;}
107 if(!strcasecmp(cptr, "FLOAT")) {output_format=1; continue;}
108 if(!strcasecmp(cptr, "SHORT")) {output_format=2; continue;}
109 } else if(strncasecmp(cptr, "FORMAT=", 7)==0) {
110 cptr+=7;
111 if(!strcasecmp(cptr, "TSV")) {csv_separator=2; output_format=0; continue;}
112 if(!strcasecmp(cptr, "CSV")) {csv_separator=0; output_format=0; continue;}
113 if(!strcasecmp(cptr, "FLOAT")) {output_format=1; continue;}
114 if(!strcasecmp(cptr, "SHORT")) {output_format=2; continue;}
115 } else if(strncasecmp(cptr, "INVERT", 3)==0) {
116 invert=1; continue;
117 }
118 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
119 return(1);
120 } else break; // tac name argument may start with '-'
121
122 TPCSTATUS status; statusInit(&status);
123 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
124 status.verbose=verbose-1;
125
126 /* Print help or version? */
127 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
128 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
129 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
130
131 /* Process other arguments, starting from the first non-option */
132 if(ai<argc) {
133 if(atoiCheck(argv[ai], &dim) || dim<3) {
134 fprintf(stderr, "Error: invalid dimension.\n");
135 return(1);
136 }
137 ai++;
138 }
139 if(ai<argc) {
140 if(atofCheck(argv[ai], &diameter) || diameter<1.0 || diameter==diameter2) {
141 fprintf(stderr, "Error: invalid diameter.\n");
142 return(1);
143 }
144 ai++;
145 }
146 if(ai<argc) {strlcpy(outfile, argv[ai], FILENAME_MAX); ai++;}
147 if(ai<argc) {fprintf(stderr, "Error: too many arguments.\n"); return(1);}
148
149 /* Is something missing or wrong? */
150 if(!outfile[0]) {
151 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
152 return(1);
153 }
154 if(invert && iring>0) {
155 fprintf(stderr, "Error: options invert and iring cannot be combined.\n");
156 return(1);
157 }
158 if(invert && segments>1) {
159 fprintf(stderr, "Error: options invert and segm cannot be combined.\n");
160 return(1);
161 }
162
163 /* Make sure that optional diameter2 is larger than diameter */
164 if(diameter2>0.0 && diameter>diameter2) {
165 double v; v=diameter2; diameter2=diameter; diameter=v;
166 }
167
168
169 /* In verbose mode print arguments and options */
170 if(verbose>1) {
171 printf("outfile := %s\n", outfile);
172 printf("dim := %d\n", dim);
173 printf("diameter := %g\n", diameter);
174 if(diameter2>0.0) printf("diameter2 := %g\n", diameter2);
175 if(segments>1) printf("segments := %d\n", segments);
176 if(iring!=0) printf("iring := %d\n", iring);
177 printf("csv_separator := %d\n", csv_separator);
178 printf("output_format := %d\n", output_format);
179 printf("invert := %d\n", invert);
180 }
181
182
183 /*
184 * Allocate memory for int list
185 */
186 int *ilist, *lptr;
187 ilist=(int*)malloc(dim*dim*sizeof(int));
188 if(ilist==NULL) {
189 fprintf(stderr, "Error: out of memory.\n");
190 return(2);
191 }
192
193
194 /*
195 * Make the matrix data as a list of integers
196 */
197
198 int i=0;
199 if(diameter2<=0.0) {
200 int x, y;
201 double cx, cy, dx, dy, d, radius;
202 /*
203 * Write 1 inside circle, 0 outside
204 */
205 i=roundf(diameter);
206 cx=cy=0.5*(double)dim;
207 if((dim%2==0 && i%2==0) || (dim%2!=0 && i%2!=0)) {cx+=0.5; cy+=0.5;}
208 //printf("center=%g,%g\n", cx,cy);
209 radius=0.5*diameter;
210 lptr=ilist; i=0;
211 for(y=1; y<=dim; y++) for(x=1; x<=dim; x++) {
212 dx=cx-(double)x; dy=cy-(double)y;
213 d=hypot(dx, dy);
214 if(d<=radius) {
215 *lptr=1;
216 if(segments>1 && (dx!=0.0 || dy!=0.0)) {
217 double ra=M_PI+atan2(dx,dy);
218 int s=1+ra*(double)segments/(2.0*M_PI);
219 *lptr=s;
220 }
221 i++;
222 } else
223 *lptr=0;
224 lptr++;
225 if(verbose>10) printf("d(%d,%d) := %g\n", x, y, d);
226 }
227 } else {
228 int x, y;
229 double cx, cy, dx, dy, d, radius, radius2;
230 /*
231 * Write 1 inside a ring, 0 outside
232 */
233 i=roundf(diameter);
234 cx=cy=0.5*(double)dim;
235 if((dim%2==0 && i%2==0) || (dim%2!=0 && i%2!=0)) {cx+=0.5; cy+=0.5;}
236 //printf("center=%g,%g\n", cx,cy);
237 radius=0.5*diameter; radius2=0.5*diameter2;
238 lptr=ilist; i=0;
239 for(y=1; y<=dim; y++) for(x=1; x<=dim; x++) {
240 dx=cx-(double)x; dy=cy-(double)y;
241 d=hypot(dx, dy);
242 if(d>radius2) {
243 *lptr=0;
244 } else if(d<=radius) {
245 *lptr=iring;
246 } else {
247 *lptr=1+iring;
248 if(segments>1 && (dx!=0.0 || dy!=0.0)) {
249 double ra=M_PI+atan2(dx,dy);
250 int s=1+iring+ra*(double)segments/(2.0*M_PI);
251 *lptr=s;
252 }
253 i++;
254 }
255 lptr++;
256 if(verbose>10) printf("d(%d,%d) := %g\n", x, y, d);
257 }
258 }
259 if(i==0) {
260 fprintf(stderr, "Error: with these settings all matrix values are 0.\n");
261 free(ilist); return(4);
262 }
263 /* Invert ones and zeroes if requested */
264 if(invert!=0) {
265 lptr=ilist;
266 for(int i=0; i<dim*dim; i++, lptr++) if(*lptr==0) *lptr=1; else *lptr=0;
267 }
268
269
270 /*
271 * Write ints into CSV or TSV file, if requested
272 */
273 if(output_format==0) {
274 int x, y, ret;
275 CSV csv; csvInit(&csv);
276 if(csvAllocate(&csv, dim*dim)!=TPCERROR_OK) {
277 fprintf(stderr, "Error: out of memory.\n");
278 free(ilist); return(6);
279 }
280 lptr=ilist; ret=TPCERROR_OK;
281 for(y=0; y<dim && ret==TPCERROR_OK; y++) {
282 for(x=0; x<dim && ret==TPCERROR_OK; x++, lptr++) {
283 if(x==0 && y>0) ret=csvPutInt(&csv, *lptr, 1);
284 else ret=csvPutInt(&csv, *lptr, 0);
285 }
286 }
287 if(ret!=TPCERROR_OK) {
288 fprintf(stderr, "Error: cannot fill CSV data.\n");
289 free(ilist); csvFree(&csv); return(7);
290 }
291 free(ilist);
292 /* Set the field separator */
293 if(csv_separator==0) csv.separator=',';
294 else if(csv_separator==1) csv.separator=';';
295 else if(csv_separator==2) csv.separator='\t';
296 else csv.separator=' ';
297 /* Open file */
298 FILE *fp;
299 if(strcasecmp(outfile, "stdout")==0) {
300 fp=stdout;
301 } else {
302 fp=fopen(outfile, "w");
303 if(fp==NULL) {
304 fprintf(stderr, "Error: cannot open file for write.\n");
305 csvFree(&csv); return(10);
306 }
307 }
308 /* Write matrix data */
309 ret=csvWrite(&csv, 0, fp, &status);
310 csvFree(&csv); fclose(fp);
311 if(ret!=TPCERROR_OK) {
312 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
313 if(verbose>1) printf("ret := %d\n", ret);
314 return(11);
315 }
316 // We are ready
317 return(0);
318 }
319
320 /*
321 * Write matrix data as flat binary file
322 */
323 /* Open file */
324 FILE *fp;
325 fp=fopen(outfile, "wb");
326 if(fp==NULL) {
327 fprintf(stderr, "Error: cannot open file for write.\n");
328 free(ilist); return(10);
329 }
330 /* Write data */
331 lptr=ilist;
332 if(output_format==1) { // binary floats
333 float f;
334 for(int i=0; i<dim*dim; i++, lptr++) {
335 f=(float)*lptr;
336 if(fwrite(&f, sizeof(float), 1, fp) != 1) {
337 fprintf(stderr, "Error: cannot write in %s\n", outfile);
338 fclose(fp); free(ilist); return(12);
339 }
340 }
341 } else if(output_format==2) { // binary short int
342 short int s;
343 for(i=0; i<dim*dim; i++, lptr++) {
344 s=(short int)*lptr;
345 if(fwrite(&s, sizeof(short int), 1, fp) != 1) {
346 fprintf(stderr, "Error: cannot write in %s\n", outfile);
347 fclose(fp); free(ilist); return(12);
348 }
349 }
350 }
351 fclose(fp); free(ilist);
352
353 return(0);
354}
355/*****************************************************************************/
356
357/*****************************************************************************/
void csvInit(CSV *csv)
Definition csv.c:22
int csvPutInt(CSV *csv, int v, int newline)
Definition csv.c:222
int csvAllocate(CSV *csv, int nr)
Definition csv.c:58
void csvFree(CSV *csv)
Definition csv.c:38
int csvWrite(CSV *csv, int regular, FILE *fp, TPCSTATUS *status)
Definition csvio.c:52
double atofVerified(const char *s)
Definition decpoint.c:75
int atofCheck(const char *s, double *v)
Definition decpoint.c:94
int atoiCheck(const char *s, int *v)
Definition intutil.c:25
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
char * errorMsg(tpcerror e)
Definition statusmsg.c:68
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
Definition tpccsv.h:36
char separator
Definition tpccsv.h:49
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
Header file for library libtpccsv.
Header file for library libtpcextensions.
@ TPCERROR_OK
No error.
Header file for library libtpcift.