#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int XSGlobal::xsTclout(ClientData cdata,Tcl_Interp* interp,int objc, Tcl_Obj* CONST objv[] ) { using namespace std; using namespace XSContainer; enum SUBCOMS {HELP, AREASCAL, ARF, BACKGRND, BACKSCAL, CHAIN, CHATTER, COMPINFO, COSMO, COVARIANCE, DATAGRP, DATASETS, DOF, ENERGIES, EQWIDTH, ERROR, EXPOS, FILENAME, FLUX, FTEST, GENPOP, GOODNESS, IDLINE, LUMIN, MARGIN, MODEL, MODCOMP, MODPAR, MODVAL, NOTICED, PARAM, PEAKRSID, PINFO, PLINK, PLOT, PLOTGRP, QUERY, RATE, RESPONSE, SIMPARS, SOLAB, STAT, STATMETHOD, STEPPAR, VARPAR, WEIGHT, XFLT}; static map option; const string cmd (static_cast(cdata)); if (!option.size()) { option["?"] = HELP; option["areascal"] = AREASCAL; option["arf"] = ARF; option["backgrnd"] = BACKGRND; option["backscal"] = BACKSCAL; option["chain"] = CHAIN; option["chatter"] = CHATTER; option["compinfo"] = COMPINFO; option["cosmo"] = COSMO; option["covariance"] = COVARIANCE; option["datagrp"] = DATAGRP; option["datasets"] = DATASETS; option["dof"] = DOF; option["energies"] = ENERGIES; option["eqwidth"] = EQWIDTH; option["error"] = ERROR; option["expos"] = EXPOS; option["filename"] = FILENAME; option["flux"] = FLUX; option["ftest"] = FTEST; option["genpop"] = GENPOP; option["goodness"] = GOODNESS; option["idline"] = IDLINE; option["lumin"] = LUMIN; option["margin"] = MARGIN; option["model"] = MODEL; option["modcomp"] = MODCOMP; option["modpar"] = MODPAR; option["modval"] = MODVAL; option["noticed"] = NOTICED; option["param"] = PARAM; option["peakrsid"] = PEAKRSID; option["pinfo"] = PINFO; option["plink"] = PLINK; option["plot"] = PLOT; option["plotgrp"] = PLOTGRP; option["query"] = QUERY; option["rate"] = RATE; option["response"] = RESPONSE; option["simpars"] = SIMPARS; option["solab"] = SOLAB; option["stat"] = STAT; option["statmethod"] = STATMETHOD; option["steppar"] = STEPPAR; option["varpar"] = VARPAR; option["weight"] = WEIGHT; option["xflt"] = XFLT; } if (objc == 1) { XSutility::printValidOptions(tcout, cmd, option); return TCL_OK; } string inputOpt(Tcl_GetString(objv[1])); map::const_iterator itOpt(option.lower_bound(inputOpt)); map::const_iterator itOptEnd(option.end()); if (itOpt != itOptEnd && itOpt->first.find(inputOpt) == 0) { const size_t selected = itOpt->second; const string& opt = itOpt->first; size_t specNum=0; string outToTcl; std::ostringstream ss; char XSPEC_TCLOUT[] = "xspec_tclout"; switch (selected) { case HELP: // ? XSutility::printValidOptions(tcout, cmd, option); break; case AREASCAL: // areascal n s|b (default to s) case BACKSCAL: // backscal n s|b case EXPOS: // exposure n s|b if (!HandlerUtils::getSpecNumParameter(objc, objv, opt, 3, specNum)) { return TCL_ERROR; } else { const SpectralData* sd = datasets->lookup(specNum); bool isBackground = false; const RealArray* pScaleArray = 0; Real exposTime = -999.0; if (objc > 3) { string sOrB(Tcl_GetString(objv[3])); if (sOrB[0] == 'b' || sOrB[0] == 'B') isBackground = true; } if (isBackground) { const Background* back = sd->background(); if (!back) { tcerr << "No background data exists for spectrum " << specNum << std::endl; return TCL_ERROR; } const SpectralData* bsd = back->data(); if (selected == AREASCAL|| selected == BACKSCAL) { pScaleArray = (selected == AREASCAL) ? &bsd->areaScale() : &bsd->backgroundScale(); } else { exposTime = bsd->exposureTime(); } } else { if (selected == AREASCAL|| selected == BACKSCAL) { pScaleArray = (selected == AREASCAL) ? &sd->areaScale() : &sd->backgroundScale(); } else { exposTime = sd->exposureTime(); } } if (exposTime >= .0) { ss << exposTime; } else { size_t sz = pScaleArray->size(); for (size_t i=0; ilookup(specNum); string arfNames(""); const std::vector& resps = sd->detector(); for (size_t i=0; i(resps[i]); if (rrsp) { arfNames += rrsp->arfName(); arfNames += " "; } else { const MultiResponse* mrsp = dynamic_cast(resps[i]); if (mrsp) { const StringArray& arfs = mrsp->arfNames(); for (size_t j=0; jlookup(specNum); const string& backFile = sd->backgroundFile(); ss << backFile; } break; case CHAIN: // last|proposal|stat { const string chainLast("last"); const string chainProposal("proposal"); const string chainStat("stat"); if (objc > 2) { string secondOpt = XSutility::lowerCase(string(Tcl_GetString(objv[2]))); if (chainLast.find(secondOpt)==0) { if (objc > 3) { const string fileName = string(Tcl_GetString(objv[3])); // First see if this file happens to be a loaded chain. // If not, attempt to create a temporary new chain // from it. const Chain* chain = fit->chainManager()->getChain(fileName); std::auto_ptr apChain(0); if (!chain) { // Create a new Chain. We don't know the file format // or even if it exists. std::auto_ptr apIO(0); try { apIO.reset(new AsciiChain(fileName)); } catch (ChainIO::ChainIOError&) { // If in here, file cannot even be opened. return TCL_ERROR; } catch (YellowAlert&) { // File exists, but not in the proper text format. try { apIO.reset(new FITSChain(fileName)); } catch (YellowAlert&) { tcerr << "***Error: Chain file has an unrecognized format." << std::endl; return TCL_ERROR; } } // File exists and we now know which format to try. try { apChain.reset(new Chain(apIO.get(), fileName)); apIO.release(); } catch (YellowAlert&) { return TCL_ERROR; } // apChain will still own the memory. chain = apChain.get(); } try { // A chain object can't exist with width = 0, so // this is safe. RealArray lastPoint(.0, chain->width()-1); chain->openForReadPoints(); chain->readPointFromLine(chain->length()-1, lastPoint); chain->closeFile(); for (size_t i=0; icloseFile(); } return TCL_ERROR; } } else { tcerr << "Tclout chain last also requires a file name argument." << std::endl; return TCL_ERROR; } } else if (chainProposal.find(secondOpt)==0) // distribution|matrix { const string chainDist("distribution"); const string chainMatrix("matrix"); if (objc > 3) { string infoSpec = XSutility::lowerCase(string(Tcl_GetString(objv[3]))); if (chainDist.find(infoSpec)==0) { ss << fit->chainManager()->chainProposal()->name(); } else if (chainMatrix.find(infoSpec)==0) { const RealArray* pCovarMatrix = fit->chainManager()->chainProposal()->covariance(fit); if (pCovarMatrix) { const RealArray& covarMatrix = *pCovarMatrix; // For consistency with chain prop covariance input, // only print out the lower half and diagonal. // We're going to ASSUME this is a square matrix. const size_t nPar = static_cast (sqrt(static_cast(covarMatrix.size()))); for (size_t i=0; ichainManager()->lastStatCalc(); } // end if chain stat else { tcerr << "Valid chain options: last | proposal | stat" << std::endl; return TCL_ERROR; } } // end if objc > 2 else { tcerr << "Valid chain options: last | proposal | stat" << std::endl; return TCL_ERROR; } } break; case CHATTER: // chatter { ss << tpout.consoleChatterLevel() << " " << tpout.logChatterLevel(); } break; case COMPINFO: // compinfo :n { string modName; size_t idx = string::npos; const Component* comp = 0; if (HandlerUtils::verifyStringInt(objc, objv, 3, modName, idx)) { comp = HandlerUtils::lookupStringIntObj(modName, idx); } if (!comp) { return TCL_ERROR; } else { size_t dgNum = 1; size_t groupPos = 0; if (objc > 3) { size_t tmpNum = XSutility::isInteger(string(Tcl_GetString(objv[3]))); if (tmpNum != string::npos) { dgNum = tmpNum; } } const Model* mod = HandlerUtils::getModFromName(modName); // If the earlier call to retrieve the component // succeeded, there should be no way for this to // fail. Still, just to be safe..... if (!mod) { return TCL_ERROR; } if (!mod->isActive()) { if (dgNum > 1) { tcerr << "Invalid data group number specified." <<"\n Model is currently not active" << std::endl; return TCL_ERROR; } groupPos = 1; } else { std::map >::const_iterator itSource = datasets->sourceToDgs().find(mod->sourceNumber()); if (itSource != datasets->sourceToDgs().end()) { std::map::const_iterator itGroup = itSource->second.find(dgNum); if (itGroup != itSource->second.end()) { groupPos = itGroup->second; } } if (!groupPos) { tcerr << "Invalid data group number specified for model." << std::endl; return TCL_ERROR; } } size_t nTotPar = mod->numberOfParameters(); const std::vector& compPars = comp->parameterSet(); size_t nPar = compPars.size(); size_t firstPar = 0; if (nPar) { firstPar = compPars[0]->index(); firstPar += (groupPos-1)*nTotPar; } ss << comp->name() << " " << firstPar << " " <cosmo().H0 << " " << models->cosmo().q0 << " " << models->cosmo().lambda0; break; case COVARIANCE: // covariance [m, n] { const RealArray& covar = fit->fitMethod()->covariance(); size_t sz = covar.size(); if (sz) { // Just assumes covar is NxN or empty. size_t N = static_cast(sqrt(static_cast(sz))); if (objc > 2) { StringArray inArgs, outArgs; IntegerArray dummy; for (int i=2; i N || n > N) { tcerr << "Covariance index is out of range." << " Valid range is 1 - " << N << endl; return TCL_ERROR; } ss << covar[(m-1)*N + n-1]; } else { for (size_t i=0; inumberOfGroups(); } else { if (!HandlerUtils::getSpecNumParameter(objc, objv, opt, 3, specNum)) { return TCL_ERROR; } else { size_t dummyRow=0; const DataSet* ds = datasets->dataSetLookup(specNum, dummyRow); ss << ds->dataGroup(); } } break; case DATASETS: // datasets ss << datasets->numberOfSpectra(); break; case DOF: // dof { int degrees(0); size_t bins(0); fit->statMethod()->degreesOfFreedom(fit,degrees,bins); ss << degrees << " " << bins; } break; case ENERGIES: // energies n if (models->autonomousEnergy().size()) { const RealArray& engs = models->autonomousEnergy(); for (size_t i=0; inumberOfSpectra() && objc == 2) || (objc > 2 && string(Tcl_GetString(objv[2]))[0] == '0' )) { // use singleton dummy response const Response* dummyrsp = responses->responseList(DUMMY_RSP,1); if (dummyrsp) { const RealArray& engs = dummyrsp->energies(); for (size_t i=0; ilookup(specNum); const Response* rsp = sd->detector(sourceNum-1); if (rsp) { const RealArray *engs=0; RealArray ext; if (models->isExtended()) { const Model* mod = models->lookup(rsp); if (mod) { ArrayContainer::const_iterator itEngs = mod->energy().find(specNum); engs = &(itEngs->second); } else { ext.resize(rsp->energies().size()); ext = rsp->energies(); Model::makeExtendArray(models->extendedEnergy(), ext); engs = &ext; } } else { engs = &rsp->energies(); } for (size_t i=0; isize(); ++i) { ss << (*engs)[i] << " "; } } else { tcerr << "No response associated with spectrum " << specNum << " source 1." << std::endl; return TCL_ERROR; } } } } break; case EQWIDTH: // eqwidth n if (!HandlerUtils::getSpecNumParameter(objc, objv, opt, 3, specNum)) { return TCL_ERROR; } else { const SpectralData* sd = datasets->lookup(specNum); const SpectralData::FluxCalc& eqWidth = sd->lastEqWidthCalc(); ss << eqWidth.value << " " << eqWidth.errLow << " " << eqWidth.errHigh; } break; case ERROR: // error n errCode { const Parameter* param = HandlerUtils::getFromStringInt(objc, objv); if (!param) { return TCL_ERROR; } try { const ModParam* mPar = dynamic_cast(param); ss << mPar->emn() << " " << mPar->epe() << " " << mPar->lastErrorStatus(); } catch (std::bad_cast) { tcerr << " Parameter is not a fit parameter." << std::endl; return TCL_ERROR; } } break; case FILENAME: // filename n if (!HandlerUtils::getSpecNumParameter(objc, objv, opt, 3, specNum)) { return TCL_ERROR; } else { size_t dum=0; const DataSet* ds = datasets->dataSetLookup(specNum, dum); string fileName = ds->getFullPathName(); ss << fileName; } break; case FLUX: // flux [n] if(datasets->numberOfSpectra()) { if (datasets->numberOfSpectra() > 1 && objc == 2) { tcerr << "***XSPEC Error: More than 1 spectrum is currently loaded." <<"\n Must specify spectrum number n: \"tclout flux \"" <lookup(specNum); size_t nFlux = sd->lastModelFluxCalc().size(); for (size_t i=0; ilastModelFluxCalc(i); ss << flux.value <<" "<< flux.errLow <<" "<< flux.errHigh <<" " << flux.photonValue <<" "<< flux.photonLow <<" " << flux.photonHigh <<" "; } if (!nFlux) ss << "0. 0. 0. 0. 0. 0."; } else { //get vector of Model pointers std::vector mods = XSutility::values< std::map, Model*>(models->modelSet().begin(), models->modelSet().end()); if(mods.size()) { //sort based on sourcenumber using binary predicate CompareSource() std::sort(mods.begin(), mods.end(), HandlerUtils::CompareSource()); std::vector::iterator begMods = mods.begin(), endMods = mods.end(); while(begMods != endMods) { if(models->activeModelNames((*begMods)->name())) { Model* m = *begMods; const SpectralData::FluxCalc& lumin = m->lastModelFluxCalc(); ss << lumin.value <<" "<< lumin.errLow <<" "<< lumin.errHigh<<" " << lumin.photonValue <<" "<< lumin.photonLow <<" " << lumin.photonHigh <<" "; } ++begMods; } } else { tcerr << "No spectra are loaded: Unable to process " << opt << " option" << std::endl; return TCL_ERROR; } } break; case FTEST: // ftest ss << Fit::lastFtest(); break; case GOODNESS: ss << Fit::lastGoodness(); break; case IDLINE: // idline e d if (objc < 4) { tcerr << "Option requires 2 arguments: idline energy del(energy)" << std::endl; return TCL_ERROR; } else { RealArray input(.0,2); for (size_t i=0; i<2; ++i) { string arg(Tcl_GetString(objv[i+2])); if (!XSutility::isReal(arg, input[i])) { tcerr << "Argument is not a number" << std::endl; return TCL_ERROR; } } Real lowE = input[0] - input[1]; Real highE = input[0] + input[1]; LineList *lineList = 0; try { lineList = LineList::get("bearden"); if (lineList) { std::ostringstream ssTmp; lineList->initialize(lowE, highE, .0, .0, false); // This can throw: lineList->showList(ssTmp); outToTcl = ssTmp.str(); } else { tcerr << "***Warning: \"bearden\" is an unrecognized list name." << std::endl; } lineList = LineList::get("mekal"); if (lineList) { std::ostringstream ssTmp; lineList->initialize(lowE, highE, .0, .0, false); // This can throw: lineList->showList(ssTmp); outToTcl += ssTmp.str(); } else { tcerr << "***Warning: \"mekal\" is an unrecognized list name." << std::endl; } ss << outToTcl; } catch (YellowAlert&) { delete lineList; return TCL_ERROR; } delete lineList; } break; case LUMIN: // lumin n if(datasets->numberOfSpectra()) { HandlerUtils::getSpecNumParameter(objc, objv, opt, 3, specNum); const SpectralData* sd = datasets->lookup(specNum); size_t nFlux = sd->lastModelLuminCalc().size(); for (size_t i=0; ilastModelLuminCalc(i); ss << lumin.value <<" "<< lumin.errLow <<" "<< lumin.errHigh<<" " << lumin.photonValue <<" "<< lumin.photonLow <<" " << lumin.photonHigh <<" "; } if (!nFlux) { ss << "0. 0. 0. 0. 0. 0."; } } else { std::vector mods = XSutility::values< std::map, Model*>(models->modelSet().begin(), models->modelSet().end()); if(mods.size()) { //sort based on sourcenumber using binary predicate CompareSource() std::sort(mods.begin(), mods.end(), HandlerUtils::CompareSource()); std::vector::iterator begMods = mods.begin(), endMods = mods.end(); while(begMods != endMods) { if(models->activeModelNames((*begMods)->name())) { Model* m = *begMods; const SpectralData::FluxCalc& lumin = m->lastModelLuminCalc(); ss << lumin.value <<" "<< lumin.errLow <<" "<< lumin.errHigh<<" " << lumin.photonValue <<" "<< lumin.photonLow <<" " << lumin.photonHigh << " "; } ++begMods; } } else { tcerr << "No spectra are loaded: Unable to process " << opt << " option" << std::endl; return TCL_ERROR; } } break; case MODEL: //model if (!XSContainer::models->modelSet().empty()) { const ModelMap& mods = XSContainer::models->modelSet(); ModelMapConstIter mod = mods.begin(); ModelMapConstIter modEnd = mods.end(); while (mod != modEnd) { if (mod->second->name() != Model::DEFAULT()) { ss << mod->second->name() << ": "; } ss << mod->second->fullExpression() << std::endl; ++mod; } } break; case MODCOMP: // modcomp name { const Model* mod = HandlerUtils::getModFromArg(objc, objv); if (!mod) ss << 0; else ss << mod->numberOfComponents(); } break; case MODPAR: // modpar name { const Model* mod = HandlerUtils::getModFromArg(objc, objv); if (!mod) ss << 0; else { size_t numPar = mod->numberOfParameters(); if (mod->isActive()) { numPar *= datasets->getNumberOfGroupsForSource(mod->sourceNumber()); } ss << numPar; } } break; case MODVAL: // modval [ []] if (!HandlerUtils::getSpecNumParameter(objc, objv, opt, 3, specNum)) { return TCL_ERROR; } else { string modName(Model::DEFAULT()); string errMsg("Default (unnamed) model"); if (objc >= 4) { modName = string(Tcl_GetString(objv[3])); errMsg = string("Model ") + modName; } size_t dummyRow=0; size_t dgNum = datasets->dataSetLookup(specNum, dummyRow)->dataGroup(); const Model* mod = models->lookup(modName, dgNum); if (!mod) { tcerr << errMsg << " not found associated with spectrum " << specNum << endl; return TCL_ERROR; } try { const RealArray& modFlux = mod->modelFlux(specNum); size_t nE = modFlux.size(); for (size_t i=0; i] | energy [] { const string enString("energy"); string enTest; if (objc > 2) enTest = XSutility::lowerCase(string(Tcl_GetString(objv[2]))); if (objc > 2 && enString.find(enTest) == 0) { // output noticed energy ranges if (!HandlerUtils::getSpecNumParameter(objc, objv, opt, 4, specNum)) { return TCL_ERROR; } else { const SpectralData* sd = datasets->lookup(specNum); const BoolArray& noticedChans = sd->noticedChannels(); std::vector::const_iterator itDet = sd->detector().begin(); std::vector::const_iterator itDetEnd = sd->detector().end(); const Response* firstResp=0; while (!firstResp && itDet != itDetEnd) { if (*itDet) firstResp = *itDet; ++itDet; } if (!firstResp) { tcerr << "\nNo response associated with spectrum " << specNum <<". Cannot convert channels to energies." << std::endl; return TCL_ERROR; } const RealArray& eMin = firstResp->eboundsMin(); const RealArray& eMax = firstResp->eboundsMax(); const size_t nChans = sd->channels(); const size_t offset = sd->startChan()-sd->firstChan(); bool isPrevNoticed = false; bool isWave = SpectralData::wavelengthSpace(); Real startRange=0.0, endRange=0.0; for (size_t i=0; i indirectNotice; const SpectralData* sd = datasets->lookup(specNum); sd->buildIndirectNotice(indirectNotice); size_t n = indirectNotice.size(); // Using a for loop rather than just valarray += 1 due to some // unexplained compiler issue on Solaris. for (size_t i=0; i(objc, objv); if (!param) { return TCL_ERROR; } const string delim(" "); const string fullString = param->stringVal(); string valueString; // 6 values for ModParams, 1 for Switch and Scale. size_t nVals = 6; if (!dynamic_cast(param)) nVals = 1; string::size_type iPos = 0; for (size_t i=0; i range(0,0); if ( objc >= 5) { string argn(Tcl_GetString(objv[3])); string argn2(Tcl_GetString(objv[4])); if (!isReal(argn,range.first) || !isReal(argn2,range.second)) { tcerr << " syntax error: arguments following spectrum number " << " must be real energy range. \n"; return TCL_ERROR; } } std::pair max(0,0); std::pair min(0,0); fit->peakResidual(max,min,specNum,range); ss << max.second <<" "<(objc, objv); if (!param) { return TCL_ERROR; } string parVal = param->stringVal(); int c(0); int ignore(7); if ( !dynamic_cast(param)) ignore = 1; // ignore the first "ignore" arguments, // 7 for ModParams and 1 for Switch and Scale types. while ( c++ < ignore) XSparse::returnDelimitedArgument(parVal," "); ss << parVal; } break; case PLINK: // plink modelName:n { const Parameter* par = HandlerUtils::getFromStringInt(objc, objv); if (!par) { return TCL_ERROR; } if (par->isLinked() ) { const string link(par->parameterSetting()); ss << "T " << link; } else { ss << "F"; } } break; case PLOT: // plot