1 #include <odindata/data.h>
2 #include <odindata/fileio.h>
3 #include <odindata/utils.h>
4 #include <odindata/statistics.h>
5 #include <odindata/correlation.h>
6 #include <odindata/filter.h>
66 STD_cout <<
"micalc: Performs basic mathematics with data sets" << STD_endl;
67 STD_cout <<
" File formats are automatically identified by their file extension." << STD_endl;
68 STD_cout <<
" For binary operations with two input files, the protocol of the first input file will be used for the output file." << STD_endl;
71 STD_cout <<
"micalc can be used in one of the following modes:" << STD_endl;
72 STD_cout <<
" Binary operation with data sets and/or scalar numbers:" << STD_endl;
73 STD_cout <<
" micalc [-if1 <input-file1> | -in1 <input-number1>] -op <operation(+,-,*,/,min,max,lcorr,kcorr)> [-if2 <input-file2> | -in2 <input-number1>] -of <output-file>" << STD_endl;
74 STD_cout <<
" Accumulation/reduction of one data set:" << STD_endl;
75 STD_cout <<
" micalc -if <input-file> -op <operation(+,*,mean,median,stdev,min,max)>" << STD_endl;
76 STD_cout <<
" Transformation (magnitude, logarithm, ...) of one data set:" << STD_endl;
77 STD_cout <<
" micalc -if <input-file> -op <operation(abs,sqrt,log,exp,-,/,acos)> -of <output-file>" << STD_endl;
78 STD_cout <<
" Statistics of one data set:" << STD_endl;
79 STD_cout <<
" micalc -if <input-file>" << STD_endl;
80 STD_cout <<
" [-mean <time-mean-file>] [-stdev <time-stdev-file>] [-fluct <relative-time-stdev-file>] [-tcourse <average time course of all voxels>]" << STD_endl;
81 STD_cout <<
" [-hist <histogram> -histslots <numofslots> [-histmin <minval>] [-histmax <maxval>] [-rightstairs] [-histfract] [-loghist] [-histslotmap <file>]]" << STD_endl;
82 STD_cout <<
" [-cog <center-of-gravity-file>]" << STD_endl;
84 STD_cout <<
"Extra options:" << STD_endl;
85 STD_cout <<
"\t-mask <Binary mask file: voxels with zeroes are discarded>" << STD_endl;
86 STD_cout <<
"Protocol options (overrides parameters in input data):" << STD_endl;
87 STD_cout << prot.get_cmdline_usage(
"\t");
88 STD_cout <<
"File read options (will be applied to input data before processing):" << STD_endl;
89 STD_cout << ropts.get_cmdline_usage(
"\t");
90 STD_cout <<
"File write options (will be applied to output data after processing):" << STD_endl;
91 STD_cout << wopts.get_cmdline_usage(
"\t");
92 STD_cout <<
"Filters/processing applied to input file(s) and mask, applied in the order they appear on the command line:" << STD_endl;
94 STD_cout <<
"Other options:" << STD_endl;
96 STD_cout <<
"\t" <<
helpUsage() << STD_endl;
97 STD_cout <<
"Supported file extensions(formats):" << STD_endl;
110 if(datain.
autoread(filename,ropts,&prot, progmeter)<0)
return false;
111 if(!filterchain.
apply(prot,datain))
return false;
112 data.resize(datain.shape());
123 int main(
int argc,
char* argv[]) {
128 Range all=Range::all();
141 char optval[ODIN_MAXCHAR];
142 STD_string operation;
160 bool accumulate=
false;
161 bool transform=
false;
170 if(
getCommandlineOption(argc,argv,
"-in1",optval,ODIN_MAXCHAR)) {innumber1=atof(optval); i1flag=
true;}
171 if(
getCommandlineOption(argc,argv,
"-in2",optval,ODIN_MAXCHAR)) {innumber2=atof(optval); i2flag=
true;}
184 STD_string fluctfile;
185 STD_string stdevfile;
186 STD_string tcoursefile;
187 STD_string histslots;
190 STD_string histslotmapfile;
206 ropts.parse_cmdline_options(argc,argv);
207 wopts.parse_cmdline_options(argc,argv);
208 prot.parse_cmdline_options(argc,argv);
211 ProgressDisplayConsole display;
218 if(i1flag && i2flag && opflag) binaryop=
true;
219 if(ifflag && opflag) {
220 if(offlag) transform=
true;
221 else accumulate=
true;
223 if(ifflag && (!opflag)) stateval=
true;
225 if( !( binaryop || accumulate || transform || stateval ) ) {usage(prot);
return 0;}
227 if(accumulate || stateval) FileIO::set_trace_status(
false);
229 if(binaryop && infile1==
"" && infile2==
"") {
230 ODINLOG(odinlog,errorLog) <<
"Specify at least one file" << STD_endl;
238 if(!read_infile(infile1, data1, ropts, prot, filterchain,&progmeter))
return -1;
241 if(binaryop && infile2!=
"") {
244 if(infile1==
"") prot2p=&prot;
245 if(!read_infile(infile2, data2, ropts, *prot2p, filterchain,&progmeter))
return -1;
248 TinyVector<int,4> outshape;
251 if(binaryop || transform) {
253 bool has_shape1=sum(data1.shape());
254 bool has_shape2=sum(data2.shape());
256 if( has_shape1 && has_shape2 && !
same_shape(data1,data2) ) {
257 ODINLOG(odinlog,errorLog) <<
"Shape mismatch: data1shape/data2shape=" << data1.shape() <<
"/" << data2.shape() << STD_endl;
259 }
else outshape=data1.shape();
261 if(has_shape1 && !has_shape2) {
262 outshape=data1.shape();
263 data2.resize(outshape);
266 if(!has_shape1 && has_shape2) {
267 outshape=data2.shape();
268 data1.resize(outshape);
271 if(!has_shape1 && !has_shape2) {
272 ODINLOG(odinlog,errorLog) <<
"Specify at least one valid file" << STD_endl;
284 if(!read_infile(maskfile, inmaskdata, ropts, maskprot, filterchain,&progmeter))
return -1;
286 if( inmaskdata.extent(0) &&
same_shape(data1, inmaskdata, TinyVector<int,4>(0,1,1,1) ) ) {
287 maskdata.resize(data1.shape());
289 for(
unsigned int i=0; i<data1.numElements(); i++) {
291 TinyVector<int,4> maskindex=index; maskindex(0)=0;
292 if(inmaskdata(maskindex)!=0.0) maskdata(index)=1.0;
296 ODINLOG(odinlog,errorLog) <<
"Shape mismatch: datashape/maskshape=" << data1.shape() <<
"/" << inmaskdata.shape() << STD_endl;
306 ODINLOG(odinlog,normalDebug) <<
"data1/data2/maskdata" << data1.shape() <<
"/" << data2.shape() <<
"/" << maskdata.shape() << STD_endl;
307 data1=data1*maskdata;
308 data2=data2*maskdata;
311 if(operation==
"lcorr" || operation==
"kcorr") {
312 int npts=data1.size();
313 if(maskptr) npts=int(sum(maskdata)+0.5);
314 Array<float,1> vec1(npts);
315 Array<float,1> vec2(npts);
317 for(
unsigned int i=0; i<data1.numElements(); i++) {
320 if( maskptr && maskdata(index)==0.0 ) include=
false;
322 vec1(vecindex)=data1(index);
323 vec2(vecindex)=data2(index);
328 if(operation==
"lcorr") coresult=
correlation(vec1, vec2);
329 if(operation==
"kcorr") coresult=
kendall(vec1, vec2);
330 STD_cout <<
"r/p/z(" << npts <<
")=" << coresult.
r <<
"/" << coresult.
p <<
"/" << coresult.
z << STD_endl;
333 ODINLOG(odinlog,infoLog) <<
"calculating " << data1.shape() <<
" " << operation <<
" " << data2.shape() <<
" ..." << STD_endl;
335 if(operation==
"+") {validop=
true; result=data1+data2;}
336 if(operation==
"-") {validop=
true; result=data1-data2;}
337 if(operation==
"*") {validop=
true; result=data1*data2;}
338 if(operation==
"/") {validop=
true; result=
secureDivision(data1,data2);}
339 if(operation==
"min" || operation==
"max") {
342 for(
unsigned int i=0; i<data1.numElements(); i++) {
344 minval(index)=STD_min(data1(index), data2(index));
345 maxval(index)=STD_max(data1(index), data2(index));
347 if(operation==
"min") result=minval;
352 ODINLOG(odinlog,errorLog) <<
"invalid binary operation: " << operation << STD_endl;
355 if(result.autowrite(outfile,wopts,&prot)<0)
return -1;
362 data1=data1*maskdata;
364 double accuresult=0.0;
366 if(operation==
"+") {validop=
true; accuresult=sum(data1);}
367 if(operation==
"*") {validop=
true; accuresult=product(data1);}
368 if(operation==
"mean") {validop=
true; accuresult=
statistics(data1).
mean;}
369 if(operation==
"median") {validop=
true; accuresult=
median(data1);}
370 if(operation==
"stdev") {validop=
true; accuresult=
statistics(data1).
stdev;}
371 if(operation==
"min") {validop=
true; accuresult=min(data1);}
372 if(operation==
"max") {validop=
true; accuresult=max(data1);}
374 ODINLOG(odinlog,errorLog) <<
"invalid accumulation operator: " << operation << STD_endl;
377 STD_cout << accuresult << STD_endl;
382 data1=data1*maskdata;
385 ODINLOG(odinlog,infoLog) <<
"Calculating " << operation <<
" " << data1.shape() <<
" ..." << STD_endl;
387 if(operation==
"abs") {validop=
true; result=fabs(data1);}
388 if(operation==
"sqrt") {validop=
true; result=sqrt(data1);}
389 if(operation==
"log") {validop=
true; result=where(Array<float,4>(data1)>0.0, Array<float,4>(log(data1)),
float(0.0));}
390 if(operation==
"exp") {validop=
true; result=exp(data1);}
391 if(operation==
"-") {validop=
true; result=-data1;}
392 if(operation==
"/") {validop=
true; result=where(Array<float,4>(data1)!=0.0, Array<float,4>(1.0/data1),
float(0.0));}
393 if(operation==
"acos") {validop=
true; result=where(Array<float,4>(data1)>=-1.0 && Array<float,4>(data1)<=1.0, Array<float,4>(acos(data1)),
float(0.0));}
395 ODINLOG(odinlog,errorLog) <<
"invalid unary operation: " << operation << STD_endl;
398 if(result.autowrite(outfile,wopts,&prot)<0)
return -1;
406 int nvals=data1.numElements();
409 for(
unsigned int i=0; i<maskdata.numElements(); i++) {
411 if( maskdata(index)>0.0 ) {
418 if(histslots==
"") {usage(prot);
return -1;}
419 int nslots=atoi(histslots.c_str());
423 float minval=stats.
min;
424 if(histmin!=
"") minval=atof(histmin.c_str());
425 float maxval=stats.
max;
426 if(histmax!=
"") maxval=atof(histmax.c_str());
427 ODINLOG(odinlog,infoLog) <<
"calculating histogram with nslots/minval/maxval=" << nslots <<
"/" << minval <<
"/" << maxval << STD_endl;
430 ODINLOG(odinlog,errorLog) <<
"histmax must be larger than histmin" << STD_endl;
434 float stairoffset=0.5;
435 if(rightstairs) stairoffset=0.0;
447 if( minval<=0.0 || maxval<=0.0 ) {
448 ODINLOG(odinlog,errorLog) <<
"positive minval/maxval required for log histogram, current minval/maxval=" << minval <<
"/" << maxval << STD_endl;
452 float minpow=log10(minval);
453 float maxpow=log10(maxval);
454 float powrange=maxpow-minpow;
456 ODINLOG(odinlog,normalDebug) <<
"minpow/maxpow/powrange/step=" << minpow <<
"/" << maxpow <<
"/" << powrange <<
"/" << step << STD_endl;
458 for(
int i=0; i<nslots; i++) xvals(i)=pow(
float(10.0),
float(minpow+(
float(i)+stairoffset)*step));
460 for(
unsigned int i=0; i<data1.numElements(); i++) {
462 if( !(maskptr && maskdata(index)==0.0) ) {
463 float pow=log10(data1(index));
465 ODINLOG(odinlog,normalDebug) <<
"pow/slot=" << pow <<
"/" << slot << STD_endl;
466 if(slot>=0 && slot<nslots) {
468 histslotmap(index)=slot+stairoffset;
476 float range=maxval-minval;
478 ODINLOG(odinlog,normalDebug) <<
"range/step=" << range <<
"/" << step << STD_endl;
480 for(
int i=0; i<nslots; i++) xvals(i)=minval+(float(i)+stairoffset)*step;
482 for(
unsigned int i=0; i<data1.numElements(); i++) {
484 if( !(maskptr && maskdata(index)==0.0) ) {
485 float val=data1(index);
487 ODINLOG(odinlog,normalDebug) <<
"val/slot=" << val <<
"/" << slot << STD_endl;
488 if(slot>=0 && slot<nslots) {
490 histslotmap(index)=slot+stairoffset;
496 if(histfract) yvals/=sum(yvals);
497 yvals.write_asc_file(histfile, xvals);
499 if(histslotmapfile!=
"")
if(histslotmap.autowrite(histslotmapfile,wopts,&prot)<0)
return -1;
504 if(meanfile!=
"" || fluctfile!=
"" || stdevfile!=
"" || tcoursefile!=
"" || cogfile!=
"") {
505 TinyVector<int,4> inshape=data1.shape();
507 ODINLOG(odinlog,infoLog) <<
"calculating general statistics for shape " << outshape <<
" ..." << STD_endl;
512 Data<float,1> tcourseresult(data1.extent(0)); tcourseresult=0.0;
514 farray cogsum(inshape(0), 3);
518 for(
unsigned int i=0; i<meanresult.numElements(); i++) {
519 TinyVector<int,4> index=meanresult.create_index(i);
520 if( !(maskptr && maskdata(index)==0.0) ) {
522 meanresult(index)= stats.
mean;
524 stdevresult(index)=stats.
stdev;
525 tcourseresult(all)+=data1(all,index(1),index(2),index(3));
526 ODINLOG(odinlog,normalDebug) <<
"mean/stdev(" << index <<
")=" << stats.
mean <<
"/" << stats.
stdev << STD_endl;
528 for(
int irep=0; irep<inshape(0); irep++) {
529 float mass=data1(irep,index(1),index(2),index(3));
531 for(
int idim=0; idim<3; idim++) {
532 cogsum(irep,idim)+=mass*index(1+idim);
539 ODINLOG(odinlog,infoLog) <<
"maskpoints=" << maskpoints << STD_endl;
540 tcourseresult/=float(maskpoints);
542 if(meanfile!=
"")
if(meanresult.autowrite(meanfile,wopts,&prot)<0)
return -1;
543 if(fluctfile!=
"")
if(fluctresult.autowrite(fluctfile,wopts,&prot)<0)
return -1;
544 if(stdevfile!=
"")
if(stdevresult.autowrite(stdevfile,wopts,&prot)<0)
return -1;
545 if(tcoursefile!=
"")
if(tcourseresult.autowrite(tcoursefile,wopts,&prot)<0)
return -1;
549 for(
int irep=0; irep<inshape(timeDim); irep++) {
550 cogstr+=
ftos(cogsum(irep, 0)/masssum[irep])+
" "+
ftos(cogsum(irep, 1)/masssum[irep])+
" "+
ftos(cogsum(irep, 2)/masssum[irep])+
"\n";
552 write(cogstr, cogfile);
557 STD_cout <<
statistics(data1,maskptr) << STD_endl;
int autoread(const STD_string &filename, const FileReadOpts &opts=FileReadOpts(), Protocol *prot=0, ProgressMeter *progmeter=0)
TinyVector< int, N_rank > create_index(unsigned long index) const
static STD_string autoformats_str(const STD_string &indent="")
STD_string get_cmdline_usage(const STD_string &lineprefix) const
bool apply(FileIO::ProtocolDataMap &pdmap) const
static bool set_log_levels(int argc, char *argv[], bool trigger_error=true)
static STD_string get_usage()
SeqPars & set_MatrixSize(direction dir, unsigned int size, parameterMode parmode=edit)
System & set_data_type(const STD_string &type)
T median(const Array< T, N_rank > &ensemble, const Array< T, N_rank > *mask=0)
correlationResult correlation(const Array< T, N_rank > &x, const Array< T, N_rank > &y)
correlationResult kendall(const Array< T, N_rank > &x, const Array< T, N_rank > &y)
bool same_shape(const Array< T, N_rank > &a1, const Array< T, N_rank > &a2, const TinyVector< int, N_rank > &dimmask=1)
statisticResult statistics(const Array< T, N_rank > &ensemble, const Array< T, N_rank > *mask=0)
const char * configInfo()
int isCommandlineOption(int argc, char *argv[], const char *option, bool modify=true)
double secureDivision(double numerator, double denominator)
int write(const STD_string &str, const STD_string &filename, fopenMode mode=overwriteMode)
int hasHelpOption(int argc, char *argv[])
int getCommandlineOption(int argc, char *argv[], const char *option, char *returnvalue, int maxchar, bool modify=true)
STD_string ftos(double f, unsigned int digits=_DEFAULT_DIGITS_, expFormat eformat=autoExp)