20#include "TObjString.h"
23#include "TObjString.h"
39 return std::make_unique<Interface> (std::move(
accessor));
48 return std::make_unique<Interface> (std::move(
accessor));
58 return std::make_unique<Interface> (std::move(
accessor));
68 return std::make_unique<Interface> (std::move(
accessor));
108 for (
unsigned int i = 0; i <
nChannels(); i++)
119 history->setInterface(
this);
128 history->setInterface(
this);
154 for (
unsigned int i = 0; i <
nChannels(); i++)
163 unsigned int nNull = 0;
165 bool ok = (
size > 0);
168 for (
unsigned int i = 0; i <
nChannels(); i++) {
171 bool ok = (
size > 0);
177 cout << i1 <<
"-" << i2 << endl;
199 std::vector<unsigned int> hashV, indexV;
200 unsigned int nTot = 0;
202 for (
unsigned int i = 0; i <
nChannels(); i++) {
204 if (!history)
continue;
205 for (
unsigned int j = 0; j < history->
nData(); j++) {
208 if (
data.isDisconnected())
continue;
209 if (nTot % 10000 == 0) cout << nTot << endl;
210 if (
data.energy() > eCut) {
211 cout <<
"E = " <<
data.energy() <<
" " << i <<
" " << j << endl;
218 hashes.Set(hashV.size());
219 indices.Set(indexV.size());
221 for (
unsigned int i = 0; i < hashV.size(); i++) {
222 hashes[i] = hashV[i];
223 indices[i] = indexV[i];
226 cout << hashV.size() <<
"/" << nTot << endl;
233 for (
unsigned int i = 0; i <
nChannels(); i++) {
235 if (!history)
continue;
237 cout <<
"Invalid LArSamplesHistory at hash = " << i << endl;
248 std::vector<const Interface*> interfaces {
this, &other };
249 return merge(interfaces, fileName);
253std::unique_ptr<Interface>
Interface::merge(
const std::vector<const Interface*>& interfaces,
const TString& fileName)
255 std::vector<const Accessor*> accessors;
256 for (
unsigned int i = 0; i < interfaces.size(); i++)
257 accessors.push_back(&interfaces[i]->accessor());
259 return std::make_unique<Interface>(std::move(newAccessor));
264 std::vector<const Interface*> interfaces {
this, &other };
265 return merge(interfaces, fileName, LBFile);
269std::unique_ptr<Interface>
Interface::merge(
const std::vector<const Interface*>& interfaces,
const TString& fileName,
const TString& LBFile)
271 std::vector<const Accessor*> accessors;
272 for (
unsigned int i = 0; i < interfaces.size(); i++)
273 accessors.push_back(&interfaces[i]->accessor());
274 std::unique_ptr<TreeAccessor> newAccessor =
TreeAccessor::merge(accessors, fileName, LBFile);
275 return std::make_unique<Interface>(std::move(newAccessor));
279std::unique_ptr<Interface>
Interface::merge(
const TString& listFileName,
const TString& fileName)
281 std::unique_ptr<const Interface> multi =
openList(listFileName);
282 if (!multi)
return nullptr;
283 std::vector<const Interface*> justOne { multi.get() };
284 return merge(justOne, fileName);
287std::unique_ptr<Interface>
Interface::merge(
const TString& listFileName,
const TString& fileName,
const TString& LBFile)
289 std::unique_ptr<const Interface> multi =
openList(listFileName);
290 if (!multi)
return nullptr;
291 std::vector<const Interface*> justOne { multi.get() };
292 return merge(justOne, fileName, LBFile);
300 std::unique_ptr<TObjArray> list (filters.Tokenize(
",;"));
301 if (list->GetEntries() == 0) {
302 cout <<
"No filtering specified, exiting.";
306 for (
int k = 0; k < list->GetEntries(); k++) {
307 TObjString* tobs = (TObjString*)(list->At(k));
308 std::unique_ptr<TObjArray> items (tobs->String().Tokenize(
":"));
309 if (items->GetEntries() != 2) {
310 cout <<
"Invalid filter entry " << tobs->String() <<
", exiting." << endl;
313 TString params = ((TObjString*)(items->At(0)))->String();
314 TString suffix = ((TObjString*)(items->At(1)))->String();
316 if (!f.set(params))
return 0;
317 cout <<
"---" << endl;
323 if (!tweak.
set(tweaks))
return 0;
325 std::unique_ptr<const Interface> multi =
openList(listFileName);
326 if (!multi)
return 0;
331 std::vector<std::unique_ptr<MultiTreeAccessor> > filtered_mts = mt->
filterComponents(filterList, tweak);
332 if (filtered_mts.size() != filterList.
size()){
335 cout <<
"Component filtering done!" << endl;
339 for (
unsigned int f = 0; f < filtered_mts.size(); f++) {
340 std::vector<TString>
files;
341 for (
unsigned int i = 0; i < filtered_mts[f]->nAccessors(); i++) {
343 cout <<
"Added " <<
files.back() << endl;
345 std::unique_ptr<const Interface> filtered_multi =
open(
files);
347 std::vector<const Interface*> justOne { filtered_multi.get() };
348 std::unique_ptr<Interface>
interface =
merge(justOne, filterList.fileName(f));
355std::unique_ptr<Interface>
Interface::filter(
const TString&
sel,
const TString& fileName,
const TString& tweaks)
const
358 if (!f.set(
sel))
return nullptr;
361 if (!tweak.
set(tweaks))
return nullptr;
363 TString thisFN = fileName;
366 if (not pAccess)
return nullptr;
367 TString newFN =
addSuffix(pAccess->fileName(), fileName);
368 if (newFN !=
"") thisFN = std::move(newFN);
370 return filter(f, tweak, thisFN);
376 TString rootName = fileName;
377 if (fileName(fileName.Length() - 5, 5) ==
".root") rootName = fileName(0, fileName.Length() - 5);
379 return rootName +
"_" + suffix +
".root";
386 return std::make_unique<Interface>(std::move(newAcc));
393 return std::make_unique<Interface>(std::move(newAcc));
403 return filter(f, tw, newFileName);
409 for (
unsigned int i = 0; i <
nChannels(); i++) {
410 std::unique_ptr<const CellInfo> info =
cellInfo(i);
413 if (info->layer() != layer)
continue;
414 if (info->iEta() != iEta)
continue;
415 if (info->iPhi() != iPhi)
continue;
416 if (info->region() != region)
continue;
426 for (
unsigned int i = 0; i <
nChannels(); i++) {
427 std::unique_ptr<const CellInfo> info =
cellInfo(i);
430 if (info->feb() != feb)
continue;
431 if (info->channel() != channel)
continue;
441 for (
unsigned int i = 0; i <
nChannels(); i++) {
442 std::unique_ptr<const CellInfo> info =
cellInfo(i);
445 if (ft >= 0 && info->feedThrough() != ft)
continue;
446 if (slot >= 0 && info->slot() != slot)
continue;
447 if (channel >= 0 && info->channel() != channel)
continue;
455TH1D*
Interface::Draw(
const TString& var,
int nBins,
double xMin,
double xMax,
const TString&
sel,
const TString& opt)
const
459 if (!f.set(
sel))
return nullptr;
461 std::vector<TString> vars;
462 std::vector<DataFuncSet> funcs;
463 std::vector<DataFuncArgs> args;
465 cout <<
"Invalid variable specification " << var << endl;
469 TString title = vars[0];
470 if (TString(
sel) !=
"") title = title +
", " +
sel;
472 TH1D*
h = m.dist(funcs[0], args[0], vars[0], nBins, xMin, xMax,
473 title, vars[0],
"digits", f);
474 if (!
h)
return nullptr;
481 int nBinsY,
double yMin,
double yMax,
482 const TString&
sel,
const TString& opt)
const
486 if (!f.set(
sel))
return nullptr;
488 std::vector<TString> vars;
489 std::vector<DataFuncSet> funcs;
490 std::vector<DataFuncArgs> args;
492 cout <<
"Invalid variable specification " << varList << endl;
496 TString title = vars[1] +
" vs. " + vars[0];
498 if (TString(
sel) !=
"") title = title +
", " +
sel;
499 TH2D*
h = m.dist(funcs[0], args[0], funcs[1], args[1], vars[0] +
"_" + vars[1],
500 nBinsX, xMin, xMax, nBinsY, yMin, yMax,
501 title, vars[0], vars[1], f);
502 if (!
h)
return nullptr;
509 const TString&
sel,
const TString& opt,
514 if (!f.set(
sel))
return nullptr;
516 std::vector<TString> vars;
517 std::vector<DataFuncSet> funcs;
518 std::vector<DataFuncArgs> args;
520 cout <<
"Invalid variable specification " << var << endl;
525 title = title +
", " +
Id::str(partition);
526 if (TString(
sel) !=
"") title = title +
", " +
sel;
528 TH2D*
h = m.partitionMap(funcs[0], args[0], var, partition, title, comb, f);
529 if (!
h)
return nullptr;
536 const TString&
sel,
const TString& opt,
541 if (!f.set(
sel))
return nullptr;
543 std::vector<TString> vars;
544 std::vector<DataFuncSet> funcs;
545 std::vector<DataFuncArgs> args;
547 cout <<
"Invalid variable specification " << var << endl;
551 title += Form(
", %s, layer %d",
Id::str(calo).
Data(), layer);
552 if (TString(
sel) !=
"") title = title +
", " +
sel;
554 TH2D*
h = m.etaPhiMap(funcs[0], args[0], var, calo, layer, title, comb, f);
555 if (!
h)
return nullptr;
565 if (!f.set(
sel))
return 0;
566 return m.dump(vars, f, verbosity);
574 if (!f.set(
sel))
return 0;
575 return m.dump(vars, comb, f, ranges, verbosity);
582 if (!history)
return false;
590 if (!f.set(
sel))
return false;
591 for (
unsigned int i = 0; i <
nChannels(); i++) {
593 if (!history)
continue;
594 std::unique_ptr<History> filtered = history->
filter(
sel);
595 TString hDesc = filtered->description(verbosity);
596 if (hDesc ==
"")
continue;
597 cout << Form(
"Hash = %-5d : ", i) << hDesc
598 <<
"-----------------------------------------------------------------------------"
608 if (!f.set(
sel))
return false;
609 std::map< std::pair<unsigned int, unsigned int>,
unsigned int > eventCells;
610 std::map< std::pair<unsigned int, unsigned int>,
double > eventEnergy;
613 for (
unsigned int i = 0; i <
nChannels(); i++) {
614 if ((i+1) % 50000 == 0) cout <<
"Cell # " << i+1 <<
"/" <<
nChannels() << endl;
616 if (!history)
continue;
617 for (
unsigned int j = 0; j < history->
nData(); j++) {
618 std::pair<unsigned int, unsigned int>
ev = std::make_pair(history->
data(j)->
run(), history->
data(j)->
event());
624 for (
unsigned int i = 0; i <
nEvents(); i++) {
626 std::pair<unsigned int, unsigned int> id(evtData->
run(), evtData->
event());
627 TString printout = Form(
"%d : ", i) + evtData->
description(verbosity);
629 printout += Form(
" : %6d LAr hits, %7.1f MeV", eventCells[
id], eventEnergy[
id]);
630 cout << printout << endl;
639 std::map<unsigned int, unsigned int> events;
642 for (
unsigned int i = 0; i <
nEvents(); i++)
646 for (
unsigned int i = 0; i <
nRuns(); i++) {
650 printout += Form(
" : %6d events", events[rData->
run()]);
651 cout << printout << endl;
662 if (!f.set(
sel))
return 0;
664 std::vector<TString> vars;
665 std::vector<DataFuncSet> funcs;
666 std::vector<DataFuncArgs> args;
668 cout <<
"Invalid variable specification " << varList << endl;
672 TVectorD
mean(vars.size()), meanErr(vars.size());
673 TMatrixD covMatrix(vars.size(), vars.size()), covMatrixErr(vars.size(), vars.size());
674 if (!m.statParams(funcs, args,
mean, meanErr, covMatrix, covMatrixErr, f))
return false;
677 cout <<
"---------------------------" << endl;
678 for (
unsigned int i = 0; i < vars.size(); i++)
679 cout << Form(
"| %10s | %-9.4g |", vars[i].
Data(),
mean(i)) << endl;
680 cout <<
"---------------------------" << endl << endl;
683 for (
unsigned int i = 0; i < vars.size(); i++) cout <<
" |";
684 cout << endl <<
"--------------";
685 for (
unsigned int i = 0; i < vars.size(); i++) cout <<
"-------------";
687 for (
unsigned int i1 = 0; i1 < vars.size(); i1++) {
688 cout << Form(
"| %10s |", vars[i1].
Data());
689 for (
unsigned int i2 = 0; i2 < vars.size(); i2++)
690 cout << Form(
" %-9.4g |", covMatrix(i1, i2));
693 cout <<
"--------------";
694 for (
unsigned int i = 0; i < vars.size(); i++) cout <<
"-------------";
698 cout <<
"---------------------------" << endl;
699 for (
unsigned int i = 0; i < vars.size(); i++)
700 cout << Form(
"| %10s | %-9.4g +/- %-9.4g |", vars[i].
Data(),
mean(i), meanErr(i)) << endl;
701 cout <<
"---------------------------" << endl << endl;
704 for (
unsigned int i = 0; i < vars.size(); i++) cout <<
" |";
705 cout << endl <<
"--------------";
706 for (
unsigned int i = 0; i < vars.size(); i++) cout <<
"---------------------------";
708 for (
unsigned int i1 = 0; i1 < vars.size(); i1++) {
709 cout << Form(
"| %10s |", vars[i1].
Data());
710 for (
unsigned int i2 = 0; i2 < vars.size(); i2++)
711 cout << Form(
" %-9.4g +/- %-9.4g |", covMatrix(i1, i2), covMatrixErr(i1, i2));
714 cout <<
"--------------";
715 for (
unsigned int i = 0; i < vars.size(); i++) cout <<
"---------------------------";
725 for (
unsigned int i = 0; i <
nChannels(); i++) {
726 std::unique_ptr<const CellInfo> otherCell =
cellInfo(i);
727 if (!otherCell)
continue;
728 if (cell.position().DeltaR(otherCell->position()) > dRCut)
continue;
738 std::unique_ptr<const CellInfo> cell =
cellInfo(hash);
739 if (!cell)
return true;
741 if (layer < 0)
return true;
742 std::vector<unsigned int> allHashes;
745 if (!
neighbors(*cell, 0.15, cache.second))
return false;
748 for (
unsigned int h : cache.second) {
749 std::unique_ptr<const CellInfo> info =
cellInfo(
h);
751 if (info->layer() == layer) hashes.push_back(
h);
758 std::vector<std::unique_ptr<const Data> >&
data)
const
763 for (std::vector<unsigned int>::const_iterator hash = hashes.begin(); hash != hashes.end(); ++hash) {
771 if (!history)
continue;
772 const Data* dataForEvent = history->data_for_event(event);
773 if (dataForEvent)
data.push_back(std::make_unique<Data>(*dataForEvent));
781 std::vector<float> floatVars;
782 std::vector<int> intVars;
783 std::vector<std::vector<float> > floatVects;
784 std::vector<std::vector<int> > intVects;
785 std::map<TString, unsigned int> varIndex;
787 std::vector<TString> vars;
788 std::vector<DataFuncSet> funcs;
789 std::vector<DataFuncArgs> args;
792 cout <<
"Making trees..." << endl;
794 std::unique_ptr<TFile> flatFile (TFile::Open(fileName +
"_tmpFlatFile.root",
"RECREATE"));
795 TTree flatTree = TTree(
"flatTree",
"Flat tree");
797 std::unique_ptr<TFile> eventFile (TFile::Open(fileName,
"RECREATE"));
798 TTree eventTree (
"eventTree",
"Event tree");
801 intVars.reserve (vars.size());
802 intVects.reserve (vars.size());
803 floatVars.reserve (vars.size());
804 floatVects.reserve (vars.size());
806 for (
unsigned int j = 0; j < vars.size(); j++) {
807 unsigned int index = 0;
808 if (funcs[j].isNull())
return false;
809 if (funcs[j].isInt()) {
810 index = intVars.size();
811 intVars.push_back(0);
812 intVects.push_back (std::vector<int>());
813 flatTree.Branch(vars[j], &intVars.back());
814 eventTree.Branch(vars[j], &intVects.back());
817 index = floatVars.size();
818 floatVars.push_back(0);
819 floatVects.push_back(std::vector<float>());
820 flatTree.Branch(vars[j], &floatVars.back());
821 eventTree.Branch(vars[j], &floatVects.back());
823 varIndex[vars[j]] =
index;
824 cout << vars[j] <<
" -> " <<
index << endl;
826 std::map< unsigned int, std::map< unsigned int, std::vector<long long> > > runEventIndices;
827 cout <<
"Making flat ntuple" << endl;
828 unsigned int count = 0;
830 const History* hist = iter.history();
832 if (
count % 100 == 0) cout <<
"Processing entry " <<
count <<
" (hash = " << iter.pos() <<
"), size = " << hist->nData() << endl;
833 for (
unsigned int k = 0; k < hist->nData(); k++) {
834 for (
unsigned int j = 0; j < vars.size(); j++) {
835 if (funcs[j].isInt())
836 intVars[varIndex[vars[j]]] = int(funcs[j].intVal(*hist->data(k), args[j]));
838 floatVars[varIndex[vars[j]]] = funcs[j].doubleVal(*hist->data(k), args[j]);
840 runEventIndices[hist->data(k)->run()][hist->data(k)->event()].push_back(flatTree.GetEntries());
845 cout <<
"Making event tuple" << endl;
846 unsigned int runCount = 0;
847 for (
const auto&
run : runEventIndices) {
849 cout <<
"Processing run " <<
run.first <<
" (" << runCount <<
" of " << runEventIndices.size() <<
")" << endl;
850 unsigned int eventCount = 0;
851 for (
const auto& event :
run.second) {
853 if (eventCount % 1000 == 0)
854 cout <<
" processing event " <<
event.first <<
" (" << eventCount <<
" of " <<
run.second.size() <<
"), size = " <<
event.second.size() << endl;
855 for (std::vector<int>& v : intVects) v.clear();
856 for (std::vector<float>& v : floatVects) v.clear();
857 for (
long long index : event.second) {
858 flatTree.GetEntry(
index);
859 for (
unsigned int j = 0; j < vars.size(); j++) {
860 size_t vi = varIndex[vars[j]];
861 if (funcs[j].isInt())
862 intVects[vi].push_back(intVars[vi]);
864 floatVects[vi].push_back(floatVars[vi]);
871 cout <<
"Writing data..." << endl;
877 cout <<
"Done!" << endl;
virtual std::unique_ptr< const History > getCellHistory(unsigned int i) const =0
virtual std::unique_ptr< const History > getSCHistory(unsigned int i) const =0
virtual unsigned int nChannels() const
const History * pass(unsigned int i, const FilterParams &f) const
virtual std::unique_ptr< const CellInfo > getCellInfo(unsigned int i) const
virtual const History * cellHistory(unsigned int i) const
virtual std::unique_ptr< const History > newCellHistory(unsigned int i) const
virtual std::unique_ptr< const CellInfo > cellInfo(unsigned int i) const
virtual unsigned int historySize(unsigned int i) const =0
void setRefit(bool refit=true)
void setFitParams(Chi2Params params)
bool set(const TString &tweaks)
TString description(unsigned int verbosity) const
void add(const FilterParams ¶ms, const TString &fileName)
unsigned int size() const
storage of the time histories of all the cells
TString description(unsigned int verbosity=1) const
const Data * data(unsigned int i) const
void setShapeErrorGetter(const AbsShapeErrorGetter *err) const
unsigned int nData() const
std::unique_ptr< History > filter(const TString &cuts) const
void setInterface(const Interface *interface) const
static TString str(CaloId id)
static bool matchCalo(CaloId id, CaloId idSpec)
std::pair< bool, std::vector< unsigned int > > CacheEntry_t
Interface(std::unique_ptr< const Accessor > accessor)
Constructor.
const Accessor & accessor() const
const AbsShapeErrorGetter * m_shapeErrorGetter
static std::unique_ptr< Interface > openWild(const TString &wcName)
virtual std::unique_ptr< const CellInfo > getCellInfo(unsigned int i) const override
std::unique_ptr< Interface > filter(const TString &sel, const TString &fileName, const TString &tweaks="") const
std::unique_ptr< Interface > refit(const TString &newFileName, Chi2Params pars=DefaultChi2) const
virtual const EventData * eventData(unsigned int i) const override
bool ShowRuns(unsigned int verbosity=1) const
bool data(const std::vector< unsigned int > &hashes, const EventData &event, std::vector< std::unique_ptr< const Data > > &data) const
std::vector< unsigned int > m_neighborHistoryPos
static std::unique_ptr< Interface > open(const TString &fileName)
static bool filterAndMerge(const TString &listFileName, const TString &outFile, const TString &filters, const TString &tweaks="")
virtual const RunData * runData(unsigned int i) const override
TH2D * DrawPartition(PartitionId partition, const TString &var, const TString &sel="", const TString &opt="", CombinationType comb=TotalValue) const
HistoryIterator findEtaPhi(CaloId calo, short layer, short iEta, short iPhi, short region=0) const
virtual unsigned int nEvents() const override
bool highEData(double eCut, TArrayI &hashes, TArrayI &indices) const
bool firstNeighbors(unsigned int hash, std::vector< unsigned int > &hashes, short layer=-2) const
std::vector< std::unique_ptr< const History > > m_neighborHistories
bool neighbors(const CellInfo &cell, double dRCut, std::vector< unsigned int > &hashes) const
void printFilledRanges(unsigned int skip=0) const
virtual unsigned int historySize(unsigned int i) const override
virtual const History * cellHistory(unsigned int i) const override
bool ShowEvents(const TString &sel="", unsigned int verbosity=1) const
virtual std::unique_ptr< const History > getSCHistory(unsigned int i) const override
std::unique_ptr< const AbsShapeErrorGetter > m_ownedShapeErrorGetter
unsigned int nFilledChannels() const
TH2D * DrawEtaPhi(CaloId calo, short layer, const TString &var, const TString &sel="", const TString &opt="", CombinationType comb=TotalValue) const
unsigned int size() const
HistoryIterator begin(unsigned int pos=0, double eMin=-1, double adcMaxMin=-1) const
bool Scan(const TString &vars, const TString &sel="", unsigned int verbosity=1) const
bool ShowStats(const TString &varList, const TString &sel="", bool withErrors=false) const
virtual unsigned int nRuns() const override
void setShapeError(double k)
std::unique_ptr< Interface > merge(const Interface &other, const TString &fileName) const
std::vector< CacheEntry_t > m_neighborCache
std::unique_ptr< Interface > makeTemplate(const TString &fileName) const
static TString addSuffix(const TString &fileName, const TString &suffix)
HistoryIterator findFTSlotChannel(CaloId calo, short ft, short slot, short channel) const
HistoryIterator findFebChannel(CaloId calo, short feb, short channel) const
TH1D * Draw(const TString &var, int nBins, double xMin, double xMax, const TString &sel="", const TString &opt="") const
std::unique_ptr< const Accessor > m_accessor
static std::unique_ptr< Interface > openList(const TString &fileList)
void setShapeErrorGetter(const AbsShapeErrorGetter *err)
bool dumpEventTuple(const TString &variables, const TString &fileName) const
virtual std::unique_ptr< const History > getCellHistory(unsigned int i) const override
bool Show(unsigned int hash, unsigned int verbosity=1) const
static bool parseVariables(TString varStr, std::vector< TString > &vars, std::vector< DataFuncSet > &funcs, std::vector< DataFuncArgs > &args)
static std::unique_ptr< MultiTreeAccessor > open(const std::vector< TString > &files)
std::vector< std::unique_ptr< MultiTreeAccessor > > filterComponents(const FilterList &filterList, const DataTweaker &tweaker) const
static std::unique_ptr< MultiTreeAccessor > openList(const TString &fileList)
static std::unique_ptr< MultiTreeAccessor > openWild(const TString &wcName)
TString description(unsigned int verbosity) const
static std::unique_ptr< TreeAccessor > merge(const std::vector< const Accessor * > &accessors, const TString &fileName="")
static std::unique_ptr< TreeAccessor > open(const TString &fileName)
static std::unique_ptr< TreeAccessor > makeTemplate(const Accessor &accessor, const TString &fileName)
static std::unique_ptr< TreeAccessor > filter(const Accessor &accessor, const FilterParams &filterParams, const TString &fileName, const DataTweaker &tweaker)
void mean(std::vector< double > &bins, std::vector< double > &values, const std::vector< std::string > &files, const std::string &histname, const std::string &tplotname, const std::string &label="")
std::vector< std::string > files
file names and file pointers
int count(std::string s, const std::string ®x)
count how many occurances of a regx are in a string
bool inInterval(const cool::ValidityKey n, const cool::ValidityKey from, const cool::ValidityKey to)
int run(int argc, char *argv[])