openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
igbhead.cc
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // openCARP is an open cardiac electrophysiology simulator.
3 //
4 // Copyright (C) 2020 openCARP project
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 // ----------------------------------------------------------------------------
19 
20 
21 /**********************************************************************
22 
23  igbhead - program to display and remove/modify/create IGB headers
24 
25  usage igbhead [options] file
26 
27  author: Edward Vigmond
28 
29  **********************************************************************/
30 #include<cstdio>
31 #include<string>
32 #include<iostream>
33 #include<libgen.h>
34 #include "IGBheader.h"
35 #include "head_cmdline.h"
36 
37 using namespace std;
38 
39 void output_header( IGBheader* );
40 size_t jive(IGBheader *header, gzFile in );
41 bool iswrite(int i );
42 bool has_gzip_extension(const string& fn);
43 
44 
52 void write_to_binary( IGBheader *h, gzFile in, FILE *out_fp, int skip )
53 {
54  char *buffer = new char[h->slice_sz()*h->data_size()];
55 
56  int nr;
57  int tm = 0;
58  char lbuf[2048];
59 
60  for( int i=0; i<skip; i++ )
61  gzgets( in, lbuf, 2048 );
62 
63  do {
64  nr = 0;
65  double d[9];
66  for( int i=0; i<h->slice_sz(); i++ ) {
67  if( !gzgets( in, lbuf, 2048 ) )
68  break;
69  if( sscanf( lbuf, "%lf %lf %lf %lf %lf %lf %lf %lf %lf", d, d+1,
70  d+2, d+3, d+4, d+5, d+6, d+7, d+8 ) != h->num_components() )
71  break;
72  nr++;
73  h->to_bin( buffer+i*h->data_size(), d );
74  }
75  if( nr==h->slice_sz() )
76  fwrite( buffer, h->data_size(), h->slice_sz(), out_fp );
77  }while( nr==h->slice_sz() && ++tm<h->t() );
78 
79  if( tm != h->t() )
80  fprintf( stderr, "\nTimes do not match!!!!!!!!!!!\n\n" );
81 
82  delete[] buffer;
83 }
84 
85 
86 int main( int argc, char* argv[] )
87 {
88  gengetopt_args_info args_info;
89 
90  // let's call our cmdline parser
91  if (cmdline_parser (argc, argv, &args_info) != 0)
92  exit(1);
93 
94  if( argc == 1 || args_info.inputs_num != 1 ) {
95  cmdline_parser_print_help();
96  exit(0);
97  }
98 
99  // the last arg must be a file name
100  gzFile in = gzopen( args_info.inputs[0], "r" );
101  if( in == NULL ) {
102  cerr << "File not found: " << args_info.inputs[0] << endl;
103  exit(1);
104  }
105  IGBheader* head_in= new IGBheader( in );
106  if( head_in->read(true) != 0 ) gzrewind( in );
107 
108  // just output the current header
109  if( argc==2 ) {
110  output_header( head_in );
111  gzclose( in );
112  exit(0);
113  }
114 
115  IGBheader* head_out = args_info.convert_data_flag ? new IGBheader(head_in) : head_in;
116 
117  if( args_info.x_given ) head_out->x( static_cast<size_t>(args_info.x_arg) );
118  if( args_info.y_given ) head_out->y( static_cast<size_t>(args_info.y_arg) );
119  if( args_info.z_given ) head_out->z( static_cast<size_t>(args_info.z_arg) );
120  if( args_info.t_given ) head_out->t( static_cast<size_t>(args_info.t_arg) );
121  if( args_info.data_type_given ) head_out->type( args_info.data_type_arg );
122  if( args_info.system_given ) head_out->systeme( args_info.system_arg==system_arg_big ? "big_endian" : "little_endian" );
123  if( args_info.dim_x_given ) head_out->dim_x( args_info.dim_x_arg );
124  if( args_info.dim_y_given ) head_out->dim_y( args_info.dim_y_arg );
125  if( args_info.dim_z_given ) head_out->dim_z( args_info.dim_z_arg );
126  if( args_info.dim_t_given ) head_out->dim_t( args_info.dim_t_arg );
127  if( args_info.org_x_given ) head_out->org_x( args_info.org_x_arg );
128  if( args_info.org_y_given ) head_out->org_y( args_info.org_y_arg );
129  if( args_info.org_z_given ) head_out->org_z( args_info.org_z_arg );
130  if( args_info.org_t_given ) head_out->org_t( args_info.org_t_arg );
131  if( args_info.inc_x_given ) head_out->inc_x( args_info.inc_x_arg );
132  if( args_info.inc_y_given ) head_out->inc_y( args_info.inc_y_arg );
133  if( args_info.inc_z_given ) head_out->inc_z( args_info.inc_z_arg );
134  if( args_info.inc_t_given ) head_out->inc_t( args_info.inc_t_arg );
135  if( args_info.x_units_given ) head_out->unites_x( args_info.x_units_arg );
136  if( args_info.y_units_given ) head_out->unites_y( args_info.y_units_arg );
137  if( args_info.z_units_given ) head_out->unites_z( args_info.z_units_arg );
138  if( args_info.t_units_given ) head_out->unites_t( args_info.t_units_arg );
139  if( args_info.clear_comment_given ) head_out->comment(NULL);
140  if( args_info.comment_given ) head_out->comment( args_info.comment_arg );
141  if( args_info.data_factor_given ) head_out->facteur(args_info.data_factor_arg);
142  if( args_info.data_zero_given ) head_out->zero( args_info.data_zero_arg );
143  if( args_info.author_given ) head_out->aut_name( args_info.author_arg );
144  if( args_info.transparent_given ){
145  if( strlen(args_info.transparent_arg)!=2*Data_Size[head_out->type()] ){
146  cerr << "Incorrect tranparent value specified\n";
147  exit(1);
148  }
149  // convert hex digits to bytes
150  char* v = new char[Data_Size[head_out->type()]];
151  char s[3], *pp;
152  s[2] = '\0';
153  for( int i=0; i<Data_Size[head_out->type()]; i++ ){
154  s[0] = args_info.transparent_arg[i*2];
155  s[1] = args_info.transparent_arg[i*2+1];
156  v[i] = strtol( s, &pp, 16 );
157  }
158  head_out->transparent( v );
159  }
160  if( args_info.no_transparent_given ) head_out->transparent( NULL );
161 
162  // count the number of data bytes
163  if( args_info.jive_time_given )
164  jive( head_in, in );
165 
166  // make a temporary file
167  string tmpfn = ".";
168  tmpfn += basename(args_info.inputs[0]);
169  tmpfn += ".tmp";
170 
171  // determine output file
172  string ofn;
173  if( args_info.frankenstein_given ){
174  ofn = args_info.frankenstein_arg;
175  gzclose( in );
176  IGBheader *h = new IGBheader(in=gzopen( args_info.frankenstein_arg,"r" ));
177  if( h->read() != 0 ) gzrewind( in );
178  delete h;
179  }
180  else
181  ofn = args_info.inputs[0];
182 
183  if(args_info.output_file_given)
184  ofn = args_info.output_file_arg;
185 
186  if( has_gzip_extension(ofn) ) {
187  cerr << "Compressed IGB output is not supported. Use -f <name>.igb to write an uncompressed copy." << endl;
188  gzclose(in);
189  return 1;
190  }
191 
192  FILE* out_fp = fopen( tmpfn.c_str(), "wb" );
193  if( out_fp == NULL ) {
194  cerr << "Unable to open temporary output file: " << tmpfn << endl;
195  gzclose(in);
196  return 1;
197  }
198  head_out->fileptr(out_fp);
199 
200  if( !args_info.decapitate_given )
201  head_out->write();
202 
203  if( args_info.create_given )
204  write_to_binary( head_out, in, out_fp, args_info.create_arg );
205  else if( args_info.convert_data_flag ) {
206  double *slice_data = new double[head_in->slice_sz()];
207  for( int t=0; t<head_in->t(); t++ ) {
208  head_in->read_data( slice_data );
209  head_out->write_data( slice_data );
210  }
211  delete [] slice_data;
212  } else if( args_info.transpose_flag ) {
213  int ds = head_out->data_size();
214  long offset = head_out->t()*ds;
215  long datStart = gztell( in );
216  char *buf = (char *)malloc( head_out->slice_sz()*ds );
217  for( int i=0; i<head_out->t(); i++ ) {
218  for( int j=0; j<head_out->slice_sz(); j++ ) {
219  gzseek( in,datStart+offset*j+i*ds, SEEK_SET );
220  gzread( in, buf+j*ds, ds*1 );
221  }
222  fwrite( buf, ds, head_out->slice_sz(), out_fp );
223  }
224  delete [] buf;
225  } else {
226  const int bufsize=1000000;
227  char* buf = new char[bufsize];
228  int nb;
229  while( (nb=gzread( in, buf, bufsize )) > 0 ) fwrite( buf, 1, nb, out_fp );
230  delete [] buf;
231  }
232 
233  fclose(out_fp);
234  gzclose( in );
235  rename( tmpfn.c_str(), ofn.c_str() );
236  return 0;
237 }
238 
239 void output_header( IGBheader* header )
240 {
241  bool tf;
242  printf( "x dimension:\t%zu\n", header->x() );
243  printf( "y dimension:\t%zu\n", header->y() );
244  printf( "z dimension:\t%zu\n", header->z() );
245  printf( "t dimension:\t%zu\n", header->t() );
246  printf( "data type:\t%s\n", Header_Type[header->type()] );
247  header->unites(tf);
248  if( tf ) {
249  printf( "Pixel units:\t%s\n", header->unites() );
250  }
251  if( header->transparent() != NULL ) {
252  printf( "Transparent:\t%s\n", header->transparentstr() );
253  }
254  header->zero(tf);
255  if( tf ) {
256  printf( "Pixel zero:\t%g\n", header->zero() );
257  }
258  header->unites(tf);
259  if( tf ) {
260  printf( "Pixel scaling:\t%g\n", header->facteur() );
261  }
262  header->dim_x(tf);
263  if( tf ) {
264  printf( "X size:\t\t%g\n", header->dim_x() );
265  }
266  header->unites_x(tf);
267  if( tf ) {
268  printf( "X units:\t%s\n", header->unites_x() );
269  }
270  header->inc_x(tf);
271  if( tf ) {
272  printf( "Increment in x:\t%g\n", header->inc_x() );
273  }
274  header->org_x(tf);
275  if( tf ) {
276  printf( "X origin:\t%g\n", header->org_x() );
277  }
278  header->dim_y(tf);
279  if( tf ) {
280  printf( "Y size:\t\t%g\n", header->dim_y() );
281  }
282  header->unites_y(tf);
283  if( tf ) {
284  printf( "Y units:\t%s\n", header->unites_y() );
285  }
286  header->inc_y(tf);
287  if( tf ) {
288  printf( "Increment in y:\t%g\n", header->inc_y() );
289  }
290  header->org_y(tf);
291  if( tf ) {
292  printf( "Y origin:\t%g\n", header->org_y() );
293  }
294  header->dim_z(tf);
295  if( tf ) {
296  printf( "Z size:\t\t%g\n", header->dim_z() );
297  }
298  header->unites_z(tf);
299  if( tf ) {
300  printf( "Z units:\t%s\n", header->unites_z() );
301  }
302  header->inc_z(tf);
303  if( tf ) {
304  printf( "Increment in z:\t%g\n", header->inc_z() );
305  }
306  header->org_z(tf);
307  if( tf ) {
308  printf( "Z origin:\t%g\n", header->org_z() );
309  }
310  header->dim_t(tf);
311  if( tf ) {
312  printf( "T size:\t\t%g\n", header->dim_t() );
313  }
314  header->unites_t(tf);
315  if( tf ) {
316  printf( "T units:\t%s\n", header->unites_t() );
317  }
318  header->inc_t(tf);
319  if( tf ) {
320  printf( "Increment in t:\t%g\n", header->inc_t() );
321  }
322  header->org_t(tf);
323  if( tf ) {
324  printf( "T origin:\t%g\n", header->org_t() );
325  }
326  printf( "Created on:\t%s\n", header->systemestr());
327  header->aut_name(tf);
328  if( tf ) {
329  printf( "Author:\t\t%s\n", header->aut_name() );
330  }
331  if( header->comment() != NULL ){
332  char **cm = header->comment();
333  int i=0;
334  while( cm[i] != NULL )
335  printf( "#%s\n", cm[i++] );
336  }
337 }
338 
340 size_t jive(IGBheader *header, gzFile in )
341 {
342  z_off_t zo = gztell( in );
343  const int bufsize=8196;
344  char buff[bufsize];
345  long nb=0, nr;
346  while( (nr=gzread( in, buff, bufsize )) == bufsize )
347  nb += nr;
348  nb += nr;
349  size_t slicesize = header->x()*header->y()*header->z()*header->data_size();
350  header->t( nb/slicesize );
351  gzseek( in, zo, SEEK_SET );
352  if( header->dim_t() )
353  header->dim_t( (header->t()-1)*header->inc_t() );
354  return(slicesize);
355 }
356 
357 bool has_gzip_extension(const string& fn)
358 {
359  return fn.size() >= 3 && fn.compare(fn.size()-3, 3, ".gz") == 0;
360 }
float org_x(void)
Definition: IGBheader.h:308
float org_z(void)
Definition: IGBheader.h:314
void inc_z(float a)
Definition: IGBheader.h:326
void to_bin(void *buf, T d)
Definition: IGBheader.h:535
char * transparentstr(void)
Definition: IGBheader.h:377
void dim_y(float a)
Definition: IGBheader.h:335
int read(bool quiet=false)
Definition: IGBheader.cc:750
float org_t(void)
Definition: IGBheader.h:317
void unites_t(const char *a)
Definition: IGBheader.h:362
void dim_t(float a)
Definition: IGBheader.h:341
size_t x(void)
Definition: IGBheader.h:268
void unites_y(const char *a)
Definition: IGBheader.h:356
void zero(float a)
Definition: IGBheader.h:347
void inc_x(float a)
Definition: IGBheader.h:320
void comment(const char *)
Definition: IGBheader.cc:1232
int type(void)
Definition: IGBheader.h:280
unsigned short num_components()
Definition: IGBheader.h:378
int systeme(void)
Definition: IGBheader.h:297
const char * systemestr(void)
Definition: IGBheader.cc:1256
void facteur(float a)
Definition: IGBheader.h:344
size_t t(void)
Definition: IGBheader.h:277
void inc_y(float a)
Definition: IGBheader.h:323
void unites_z(const char *a)
Definition: IGBheader.h:359
void aut_name(const char *a)
Definition: IGBheader.h:371
int read_data(T *dp, size_t numt=1, char *buf=NULL)
Definition: IGBheader.h:433
size_t y(void)
Definition: IGBheader.h:271
float org_y(void)
Definition: IGBheader.h:311
size_t data_size(void)
Definition: IGBheader.h:267
void unites_x(const char *a)
Definition: IGBheader.h:353
void fileptr(gzFile f)
Definition: IGBheader.cc:329
int write()
Definition: IGBheader.cc:343
void transparent(void *a)
Definition: IGBheader.h:374
void write_data(T *dp, size_t numt=1, char *buf=NULL)
Definition: IGBheader.h:398
size_t z(void)
Definition: IGBheader.h:274
size_t slice_sz()
Definition: IGBheader.h:263
void unites(const char *a)
Definition: IGBheader.h:365
void inc_t(float a)
Definition: IGBheader.h:329
void dim_z(float a)
Definition: IGBheader.h:338
void dim_x(float a)
Definition: IGBheader.h:332
int main(int argc, char *argv[])
Definition: igbhead.cc:86
void write_to_binary(IGBheader *h, gzFile in, FILE *out_fp, int skip)
Definition: igbhead.cc:52
void output_header(IGBheader *)
Definition: igbhead.cc:239
size_t jive(IGBheader *header, gzFile in)
Definition: igbhead.cc:340
bool has_gzip_extension(const string &fn)
Definition: igbhead.cc:357
bool iswrite(int i)
const char * Header_Type[]
Definition: IGBheader.cc:249
unsigned short Data_Size[]
Definition: IGBheader.cc:264