diff options
author | Aaron LI <aaronly.me@outlook.com> | 2017-02-20 12:26:17 +0800 |
---|---|---|
committer | Aaron LI <aaronly.me@outlook.com> | 2017-02-20 12:26:17 +0800 |
commit | 4ea7a05ea9a7352602f1f48a860fd81c36e8bc04 (patch) | |
tree | beab7ec18d48c3e2093cd35fd8c79bd66f604a03 /src | |
parent | 9cec16d87f6dc2e0b34b605d88d0837a4a48d18c (diff) | |
download | chandra-acis-analysis-4ea7a05ea9a7352602f1f48a860fd81c36e8bc04.tar.bz2 |
Rename mass_profile to src; Add install & uninstall to Makefile
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 98 | ||||
-rw-r--r-- | src/README.md | 37 | ||||
-rw-r--r-- | src/beta.hpp | 45 | ||||
-rw-r--r-- | src/beta_cfg.cpp | 85 | ||||
-rw-r--r-- | src/beta_cfg.hpp | 23 | ||||
-rw-r--r-- | src/calc_lx_beta.cpp | 497 | ||||
-rw-r--r-- | src/calc_lx_dbeta.cpp | 548 | ||||
-rw-r--r-- | src/chisq.hpp | 206 | ||||
-rw-r--r-- | src/dbeta.hpp | 108 | ||||
-rw-r--r-- | src/dump_fit_qdp.cpp | 55 | ||||
-rw-r--r-- | src/dump_fit_qdp.hpp | 16 | ||||
-rw-r--r-- | src/fit_beta_sbp.cpp | 534 | ||||
-rw-r--r-- | src/fit_dbeta_sbp.cpp | 586 | ||||
-rw-r--r-- | src/fit_nfw_mass.cpp | 159 | ||||
-rw-r--r-- | src/fit_wang2012_model.cpp | 195 | ||||
-rw-r--r-- | src/nfw.hpp | 56 | ||||
-rw-r--r-- | src/projector.hpp | 214 | ||||
-rw-r--r-- | src/report_error.cpp | 39 | ||||
-rw-r--r-- | src/report_error.hpp | 6 | ||||
-rw-r--r-- | src/spline.hpp | 110 | ||||
-rw-r--r-- | src/vchisq.hpp | 137 | ||||
-rw-r--r-- | src/wang2012_model.hpp | 67 |
22 files changed, 3821 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..76ddeaa --- /dev/null +++ b/src/Makefile @@ -0,0 +1,98 @@ +# +# Makefile for `chandra-acis-analysis/mass_profile` tools +# +# Junhua GU +# Weitian LI +# 2016-06-07 +# + + +CXX ?= g++ +CXXFLAGS += -Wall +CXXFLAGS += -Werror + +ifdef OPENMP + CXXFLAGS += -fopenmp +endif + +ifdef DEBUG + CXXFLAGS += -g +else + CXXFLAGS += -O2 +endif + +OPT_UTIL_INC ?= -I../opt_utilities + +TARGETS= fit_dbeta_sbp fit_beta_sbp fit_wang2012_model \ + fit_nfw_mass calc_lx_dbeta calc_lx_beta +HEADERS= projector.hpp spline.hpp vchisq.hpp + +all: $(TARGETS) + +# NOTE: +# Object/source files should placed *before* libraries (order matters) + +fit_dbeta_sbp: fit_dbeta_sbp.o beta_cfg.o report_error.o + $(CXX) $(CXXFLAGS) $^ -o $@ $(OPT_UTIL_INC) + +fit_beta_sbp: fit_beta_sbp.o beta_cfg.o dump_fit_qdp.o + $(CXX) $(CXXFLAGS) $^ -o $@ $(OPT_UTIL_INC) + +fit_wang2012_model: fit_wang2012_model.o + $(CXX) $(CXXFLAGS) $^ -o $@ $(OPT_UTIL_INC) + +fit_nfw_mass: fit_nfw_mass.o + $(CXX) $(CXXFLAGS) $^ -o $@ $(OPT_UTIL_INC) + +calc_lx_dbeta: calc_lx_dbeta.o beta_cfg.o report_error.o + $(CXX) $(CXXFLAGS) $^ -o $@ $(OPT_UTIL_INC) + +calc_lx_beta: calc_lx_beta.o beta_cfg.o dump_fit_qdp.o + $(CXX) $(CXXFLAGS) $^ -o $@ $(OPT_UTIL_INC) + + +fit_dbeta_sbp.o: fit_dbeta_sbp.cpp $(HEADERS) + $(CXX) $(CXXFLAGS) -c $< $(OPT_UTIL_INC) + +fit_beta_sbp.o: fit_beta_sbp.cpp beta.hpp $(HEADERS) + $(CXX) $(CXXFLAGS) -c $< $(OPT_UTIL_INC) + +fit_wang2012_model.o: fit_wang2012_model.cpp wang2012_model.hpp chisq.hpp + $(CXX) $(CXXFLAGS) -c $< $(OPT_UTIL_INC) + +fit_nfw_mass.o: fit_nfw_mass.cpp nfw.hpp chisq.hpp + $(CXX) $(CXXFLAGS) -c $< $(OPT_UTIL_INC) + +calc_lx_dbeta.o: calc_lx_dbeta.cpp $(HEADERS) + $(CXX) $(CXXFLAGS) -c $< $(OPT_UTIL_INC) + +calc_lx_beta.o: calc_lx_beta.cpp beta.hpp $(HEADERS) + $(CXX) $(CXXFLAGS) -c $< $(OPT_UTIL_INC) + +beta_cfg.o: beta_cfg.cpp beta_cfg.hpp + $(CXX) $(CXXFLAGS) -c $< + +report_error.o: report_error.cpp report_error.hpp + $(CXX) $(CXXFLAGS) -c $< + +dump_fit_qdp.o: dump_fit_qdp.cpp dump_fit_qdp.hpp + $(CXX) $(CXXFLAGS) -c $< $(OPT_UTIL_INC) + +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< $(OPT_UTIL_INC) + + +clean: + rm -f *.o $(TARGETS) + + +install: $(TARGETS) + @for f in $(TARGETS); do \ + (cd ../bin && ln -svf ../src/$$f . ); \ + done + + +uninstall: + @for f in $(TARGETS); do \ + rm -fv ../bin/$$f; \ + done diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..0c61821 --- /dev/null +++ b/src/README.md @@ -0,0 +1,37 @@ +Mass/Luminosity/Flux Calculation Tools +============================== + +Junhua GU, Weitian LI, Zhenghao ZHU + + +Introduction +------------ +This directory contains the tools/scripts used to fit the temperature +profile and surface brightness file, to calculate the gas density profile +and gravitational mass profile, to calculate luminosity and flux and +other related quantities. + + +NOTE +---- +* Mass calculation references: + + Walker et al. 2012, MNRAS, 422, 3503-3515, + [ADS:2012MNRAS.422.3503W](http://adsabs.harvard.edu/abs/2012MNRAS.422.3503W) + + Ettori et al. 2013, Space Science Reviews, 177, 119-154, + [ADS:2013SSRv..177..119E](http://adsabs.harvard.edu/abs/2013SSRv..177..119E) +* Errors are calculated at 68% confident level. +* NFW profile is employed to extrapolate the mass profile. +* We use a self-proposed model (see ``wang2012_model.hpp``) to describe/fit + the gas temperature profile. +* The single-beta and double-beta models (with a constant background) are used + to describe the gas density profile. + + +TODO +---- +* Merge the scripts/tools for single-beta and double-beta SBP models + (to reduce code duplications) +* Uncertainties/errors calculation **maybe** inappropriate/problematic + (e.g., ``analyze_mass_profile.py``); + why not just use the quantile-based (e.g., Q84.15-Q15.85 ~= 68.3%) + uncertainties or standard deviation??? diff --git a/src/beta.hpp b/src/beta.hpp new file mode 100644 index 0000000..6ae70ac --- /dev/null +++ b/src/beta.hpp @@ -0,0 +1,45 @@ +#ifndef BETA +#define BETA +#include "projector.hpp" + +namespace opt_utilities +{ + template <typename T> + class beta + :public model<std::vector<T>,std::vector<T>,std::vector<T> > + { + public: + beta() + { + this->push_param_info(param_info<std::vector<T>,std::string>("n0",1,0,1E99)); + this->push_param_info(param_info<std::vector<T>,std::string>("beta",.66,0,1E99)); + this->push_param_info(param_info<std::vector<T>,std::string>("rc",100,0,1E99)); + } + + public: + beta<T>* do_clone()const + { + return new beta<T>(*this); + } + + std::vector<T> do_eval(const std::vector<T> & x, + const std::vector<T>& p) + { + T n0=std::abs(p[0]); + T beta=p[1]; + T rc=p[2]; + + std::vector<T> result(x.size()-1); + for(size_t i=1;i<x.size();++i) + { + T xi=(x[i]+x[i-1])/2; + T yi=0; + yi=n0*pow(1+xi*xi/rc/rc,-3./2.*beta); + result[i-1]=yi; + } + return result; + } + }; +} + +#endif diff --git a/src/beta_cfg.cpp b/src/beta_cfg.cpp new file mode 100644 index 0000000..c373688 --- /dev/null +++ b/src/beta_cfg.cpp @@ -0,0 +1,85 @@ +#include "beta_cfg.hpp" +#include <sstream> +#include <cstdlib> +using namespace std; + +cfg_map parse_cfg_file(std::istream& is) +{ + cfg_map result; + result.rmin_pixel=-1; + result.rmin_kpc=-1; + for(;;) + { + std::string line; + getline(is,line); + line+="\n"; + if(!is.good()) + { + break; + } + string key; + istringstream iss(line); + iss>>key; + if(key=="sbp_data") + { + string value; + iss>>value; + result.sbp_data=value; + } + else if(key=="cfunc_profile") + { + string value; + iss>>value; + result.cfunc_profile=value; + } + else if(key=="tprofile") + { + string value; + iss>>value; + result.tprofile=value; + } + else if(key=="z") + { + double z; + iss>>z; + result.z=z; + } + else if(key=="cm_per_pixel") + { + double cm_per_pixel; + iss>>cm_per_pixel; + result.cm_per_pixel=cm_per_pixel; + } + else if(key=="rmin_pixel") + { + double v; + iss>>v; + result.rmin_pixel=v; + } + else if(key=="rmin_kpc") + { + double v; + iss>>v; + result.rmin_kpc=v; + } + else + { + std::vector<double> value; + for(;;) + { + double v; + iss>>v; + if(!iss.good()) + { + break; + } + value.push_back(v); + } + if(!value.empty()) + { + result.param_map[key]=value; + } + } + } + return result; +} diff --git a/src/beta_cfg.hpp b/src/beta_cfg.hpp new file mode 100644 index 0000000..27148df --- /dev/null +++ b/src/beta_cfg.hpp @@ -0,0 +1,23 @@ +#ifndef BETA_CFG +#define BETA_CFG + +#include <map> +#include <vector> +#include <string> +#include <iostream> + +struct cfg_map +{ + std::string sbp_data; + std::string cfunc_profile; + std::string tprofile; + double z; + double cm_per_pixel; + double rmin_kpc; + double rmin_pixel; + std::map<std::string,std::vector<double> > param_map; +}; + +cfg_map parse_cfg_file(std::istream& is); + +#endif diff --git a/src/calc_lx_beta.cpp b/src/calc_lx_beta.cpp new file mode 100644 index 0000000..11d7b04 --- /dev/null +++ b/src/calc_lx_beta.cpp @@ -0,0 +1,497 @@ +/** + * Calculate the total luminosity and flux within the specified radius. + * + * Base on 'fit_beta_sbp.cpp' and supersede 'calc_lx.cpp' + * + * Author: Junhua Gu + */ + +#include <iostream> +#include <fstream> +#include <sstream> +#include <list> +#include <algorithm> +#include "beta_cfg.hpp" +#include "dump_fit_qdp.hpp" +#include "report_error.hpp" +#include "vchisq.hpp" +#include "chisq.hpp" +#include "beta.hpp" +#include "models/beta1d.hpp" +#include <data_sets/default_data_set.hpp> +#include <methods/powell/powell_method.hpp> +#include <core/freeze_param.hpp> +#include <error_estimator/error_estimator.hpp> +#include "spline.hpp" + +using namespace std; +using namespace opt_utilities; +//double s=5.63136645E20; +const double kpc=3.086E21;//kpc in cm +const double Mpc=kpc*1000; + +double beta_func(double r, double n0, double rc, double beta) +{ + return abs(n0) * pow(1+r*r/rc/rc, -3./2.*abs(beta)); +} + +//A class enclosing the spline interpolation method +class spline_func_obj + :public func_obj<double,double> +{ + //has an spline object + spline<double> spl; +public: + //This function is used to calculate the intepolated value + double do_eval(const double& x) + { + return spl.get_value(x); + } + + //we need this function, when this object is performing a clone of itself + spline_func_obj* do_clone()const + { + return new spline_func_obj(*this); + } + +public: + //add points to the spline object, after which the spline will be initialized + void add_point(double x,double y) + { + spl.push_point(x,y); + } + + //before getting the intepolated value, the spline should be initialzied by calling this function + void gen_spline() + { + spl.gen_spline(0,0); + } +}; + +int main(int argc,char* argv[]) +{ + if(argc<4) + { + cerr<<argv[0]<<" <sbp.conf> <rout_kpc> <cfunc_erg> [cfunc2_erg ...]"<<endl; + return -1; + } + //initialize the parameters list + ifstream cfg_file(argv[1]); + assert(cfg_file.is_open()); + cfg_map cfg=parse_cfg_file(cfg_file); + + const double z=cfg.z; + + //initialize the radius list, sbp list and sbp error list + std::vector<double> radii; + std::vector<double> sbps; + std::vector<double> sbpe; + std::vector<double> radii_all; + std::vector<double> sbps_all; + std::vector<double> sbpe_all; + //prepend the zero point to radius list + radii.push_back(0.0); + radii_all.push_back(0.0); + //read sbp and sbp error data + ifstream ifs(cfg.sbp_data.c_str()); + std::string line; + if (ifs.is_open()) + { + while(std::getline(ifs, line)) + { + if (line.empty()) + continue; + + std::istringstream iss(line); + double x, xe, y, ye; + if ((iss >> x >> xe >> y >> ye)) + { + std::cerr << "sbprofile data: " + << x << ", " << xe << ", " << y << ", " << ye + << std::endl; + radii.push_back(x+xe); /* NOTE: use outer radii of regions */ + radii_all.push_back(x+xe); + sbps.push_back(y); + sbps_all.push_back(y); + sbpe.push_back(ye); + sbpe_all.push_back(ye); + } + else + { + std::cerr << "skipped line: " << line << std::endl; + } + } + } + else + { + std::cerr << "ERROR: cannot open file: " << cfg.sbp_data.c_str() + << std::endl; + return 1; + } + + //initialize the cm/pixel value + double cm_per_pixel=cfg.cm_per_pixel; + double rmin; + if(cfg.rmin_pixel>0) + { + rmin=cfg.rmin_pixel; + } + else + { + rmin=cfg.rmin_kpc*kpc/cm_per_pixel; + } + + cerr<<"rmin="<<rmin<<" (pixel)"<<endl; + std::list<double> radii_tmp,sbps_tmp,sbpe_tmp; + radii_tmp.resize(radii.size()); + sbps_tmp.resize(sbps.size()); + sbpe_tmp.resize(sbpe.size()); + copy(radii.begin(),radii.end(),radii_tmp.begin()); + copy(sbps.begin(),sbps.end(),sbps_tmp.begin()); + copy(sbpe.begin(),sbpe.end(),sbpe_tmp.begin()); + for(list<double>::iterator i=radii_tmp.begin();i!=radii_tmp.end();) + { + if(*i<rmin) + { + radii_tmp.pop_front(); + sbps_tmp.pop_front(); + sbpe_tmp.pop_front(); + i=radii_tmp.begin(); + continue; + } + ++i; + } + radii.resize(radii_tmp.size()); + sbps.resize(sbps_tmp.size()); + sbpe.resize(sbpe_tmp.size()); + copy(radii_tmp.begin(),radii_tmp.end(),radii.begin()); + copy(sbps_tmp.begin(),sbps_tmp.end(),sbps.begin()); + copy(sbpe_tmp.begin(),sbpe_tmp.end(),sbpe.begin()); + + //read cooling function data + spline_func_obj cf; + for(ifstream ifs(cfg.cfunc_profile.c_str());;) + { + assert(ifs.is_open()); + double x,y; + ifs>>x>>y; + if(!ifs.good()) + { + break; + } + cerr<<x<<"\t"<<y<<endl; + if(x>radii.back()) + { + break; + } + cf.add_point(x,y); + } + cf.gen_spline(); + + //read temperature profile data + spline_func_obj Tprof; + int tcnt=0; + for(ifstream ifs1(cfg.tprofile.c_str());;++tcnt) + { + assert(ifs1.is_open()); + double x,y; + ifs1>>x>>y; + if(!ifs1.good()) + { + break; + } + cerr<<x<<"\t"<<y<<endl; +#if 0 + if(tcnt==0) + { + Tprof.add_point(0,y); + } +#endif + Tprof.add_point(x,y); + } + + + Tprof.gen_spline(); + + default_data_set<std::vector<double>,std::vector<double> > ds; + ds.add_data(data<std::vector<double>,std::vector<double> >(radii,sbps,sbpe,sbpe,radii,radii)); + + //initial fitter + fitter<vector<double>,vector<double>,vector<double>,double> f; + f.load_data(ds); + //initial the object, which is used to calculate projection effect + projector<double> a; + beta<double> betao; + //attach the cooling function + a.attach_cfunc(cf); + a.set_cm_per_pixel(cm_per_pixel); + a.attach_model(betao); + f.set_model(a); + //chi^2 statistic + vchisq<double> c; + c.verbose(true); + c.set_limit(); + f.set_statistic(c); + //optimization method + f.set_opt_method(powell_method<double,std::vector<double> >()); + //initialize the initial values + /* + double n0=0; + double beta=0; + double rc=0; + */ + double bkg_level=0; + + for(std::map<std::string,std::vector<double> >::iterator i=cfg.param_map.begin(); + i!=cfg.param_map.end();++i) + { + std::string pname=i->first; + f.set_param_value(pname,i->second.at(0)); + if(i->second.size()==3) + { + double a1=i->second[1]; + double a2=i->second[2]; + double u=std::max(a1,a2); + double l=std::min(a1,a2); + f.set_param_upper_limit(pname,u); + f.set_param_lower_limit(pname,l); + } + else + { + if(pname=="beta") + { + f.set_param_lower_limit(pname,.3); + f.set_param_upper_limit(pname,1.4); + } + } + } + + f.fit(); + f.fit(); + std::vector<double> p=f.get_all_params(); + /* + n0=f.get_param_value("n0"); + rc=f.get_param_value("rc"); + beta=f.get_param_value("beta"); + */ + //output the datasets and fitting results + ofstream param_output("lx_beta_param.txt"); + for(size_t i=0;i<f.get_num_params();++i) + { + if(f.get_param_info(i).get_name()=="rc") + { + cerr<<"rc_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + param_output<<"rc_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + } + cerr<<f.get_param_info(i).get_name()<<"\t"<<abs(f.get_param_info(i).get_value())<<endl; + param_output<<f.get_param_info(i).get_name()<<"\t"<<abs(f.get_param_info(i).get_value())<<endl; + } + cerr<<"reduced_chi^2="<<f.get_statistic_value()/(radii.size()-f.get_model().get_num_free_params())<<endl; + param_output<<"reduced_chi^2="<<f.get_statistic_value()/(radii.size()-f.get_model().get_num_free_params())<<endl; + + std::vector<double> mv=f.eval_model_raw(radii_all,p); + int sbps_inner_cut_size=int(sbps_all.size()-sbps.size()); + ofstream ofs_sbp("lx_sbp_fit.qdp"); + ofs_sbp<<"read serr 2"<<endl; + ofs_sbp<<"skip single"<<endl; + ofs_sbp<<"line off "<<endl; + if(sbps_inner_cut_size>=1) + { + ofs_sbp<<"line on 2"<<endl; + ofs_sbp<<"line on 3"<<endl; + ofs_sbp<<"line on 4"<<endl; + ofs_sbp<<"line on 5"<<endl; + ofs_sbp<<"ls 2 on 2"<<endl; + ofs_sbp<<"ls 2 on 4"<<endl; + ofs_sbp<<"ls 2 on 5"<<endl; + ofs_sbp<<"line on 7"<<endl; + ofs_sbp<<"ls 2 on 7"<<endl; + + ofs_sbp<<"ma 1 on 2"<<endl; + ofs_sbp<<"color 1 on 1"<<endl; + ofs_sbp<<"color 2 on 2"<<endl; + ofs_sbp<<"color 3 on 3"<<endl; + ofs_sbp<<"color 4 on 4"<<endl; + ofs_sbp<<"color 5 on 5"<<endl; + + ofs_sbp<<"win 1"<<endl; + ofs_sbp<<"yplot 1 2 3 4 5"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .4 .9 .9"<<endl; + ofs_sbp<<"la y cnt/s/pixel/cm^2"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"log y"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[sbps.size()-2]+radii[sbps.size()-1])/2*cm_per_pixel/kpc<<endl; + ofs_sbp<<"win 2"<<endl; + ofs_sbp<<"yplot 6 7"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .1 .9 .4"<<endl; + ofs_sbp<<"la x radius (kpc)"<<endl; + ofs_sbp<<"la y chi"<<endl; + ofs_sbp<<"log y off"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[sbps.size()-2]+radii[sbps.size()-1])/2*cm_per_pixel/kpc<<endl; + } + else + { + ofs_sbp<<"line on 2"<<endl; + ofs_sbp<<"line on 3"<<endl; + ofs_sbp<<"line on 4"<<endl; + ofs_sbp<<"ls 2 on 3"<<endl; + ofs_sbp<<"ls 2 on 4"<<endl; + ofs_sbp<<"line on 6"<<endl; + ofs_sbp<<"ls 2 on 6"<<endl; + + ofs_sbp<<"color 1 on 1"<<endl; + ofs_sbp<<"color 3 on 2"<<endl; + ofs_sbp<<"color 4 on 3"<<endl; + ofs_sbp<<"color 5 on 4"<<endl; + //ofs_sbp<<"ma 1 on 2"<<endl; + + ofs_sbp<<"win 1"<<endl; + ofs_sbp<<"yplot 1 2 3 4"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .4 .9 .9"<<endl; + ofs_sbp<<"la y cnt/s/pixel/cm^2"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"log y"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[radii.size()-2]+radii[radii.size()-1])/2*cm_per_pixel/kpc<<endl; + ofs_sbp<<"win 2"<<endl; + ofs_sbp<<"yplot 5 6"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .1 .9 .4"<<endl; + ofs_sbp<<"la x radius (kpc)"<<endl; + ofs_sbp<<"la y chi"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"log y off"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[radii.size()-2]+radii[radii.size()-1])/2*cm_per_pixel/kpc<<endl; + + } + // cout<<sbps_all.size()<<"\t"<<sbps.size()<<"\t"<<sbps_inner_cut_size<<endl; + for(size_t i=1;i<sbps_all.size();++i) + { + double x=(radii_all[i]+radii_all[i-1])/2; + double y=sbps_all[i-1]; + double ye=sbpe_all[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<y<<"\t"<<ye<<endl; + } + if(sbps_inner_cut_size>=1) + { + ofs_sbp<<"no no no"<<endl; + for(int i=1;i<sbps_inner_cut_size+1;++i) + { + double x=(radii_all[i]+radii_all[i-1])/2; + double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<ym<<"\t"<<"0"<<endl; + } + } + ofs_sbp<<"no no no"<<endl; + for(size_t i=sbps_inner_cut_size;i<sbps_all.size();++i) + { + double x=(radii_all[i]+radii_all[i-1])/2; + double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<ym<<"\t"<<"0"<<endl; + } + ofs_sbp<<"no no no"<<endl; + //bkg level + bkg_level=abs(f.get_param_value("bkg")); + for(size_t i=0;i<sbps_all.size();++i) + { + double x=(radii_all[i]+radii_all[i-1])/2; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<bkg_level<<"\t0"<<endl; + } + ofs_sbp<<"no no no"<<endl; + //rc + double rc_kpc=abs(f.get_param_value("rc")*cm_per_pixel/kpc); + double max_sbp=*max_element(sbps_all.begin(),sbps_all.end()); + double min_sbp=*min_element(sbps_all.begin(),sbps_all.end()); + for(double x=min_sbp;x<=max_sbp;x+=(max_sbp-min_sbp)/100) + { + ofs_sbp<<rc_kpc<<"\t"<<x<<"\t"<<"0"<<endl; + } + //resid + ofs_sbp<<"no no no"<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + //double y=sbps[i-1]; + //double ye=sbpe[i-1]; + double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<(ym-sbps[i-1])/sbpe[i-1]<<"\t"<<1<<endl; + } + + //zero level of resid + ofs_sbp<<"no no no"<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + //double y=sbps[i-1]; + //double ye=sbpe[i-1]; + //double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<0<<"\t"<<0<<endl; + } + + mv=betao.eval(radii,p); + ofstream ofs_rho("lx_rho_fit.qdp"); + ofstream ofs_rho_data("lx_rho_fit.dat"); + + ofs_rho<<"la x radius (kpc)"<<endl; + ofs_rho<<"la y density (cm\\u-3\\d)"<<endl; + /* + for(int i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + double ym=mv[i-1]; + ofs_rho<<x*cm_per_pixel/kpc<<"\t"<<ym<<endl; + } + */ + p.back()=0; + radii.clear(); + double rout=atof(argv[2])*kpc; + + for(double r=0;r<rout;r+=1*kpc)//step size=1kpc + { + double r_pix=r/cm_per_pixel; + radii.push_back(r_pix); + } + + double Da=cm_per_pixel/(.492/3600./180.*pi); + double Dl=Da*(1+z)*(1+z); + cout<<"dl="<<Dl/kpc<<endl; + + for(int n=3;n<argc;++n) + { + spline_func_obj cf_erg; + for(ifstream ifs(argv[n]);;) + { + assert(ifs.is_open()); + double x,y; + ifs>>x>>y; + if(!ifs.good()) + { + break; + } + //cerr<<x<<"\t"<<y<<endl; + + cf_erg.add_point(x,y);//change with source + } + cf_erg.gen_spline(); + + projector<double>& pj=dynamic_cast<projector<double>&>(f.get_model()); + pj.attach_cfunc(cf_erg); + + + + mv=f.eval_model_raw(radii,p); + double flux_erg=0; + for(size_t i=0;i<radii.size()-1;++i) + { + double S=pi*(radii[i+1]+radii[i])*(radii[i+1]-radii[i]); + flux_erg+=S*mv[i]; + } + cout<<flux_erg*4*pi*Dl*Dl<<endl; + cout<<flux_erg<<endl; + param_output<<"Lx"<<n-2<<"\t"<<flux_erg*4*pi*Dl*Dl<<endl; + param_output<<"Fx"<<n-2<<"\t"<<flux_erg<<endl; + } +} diff --git a/src/calc_lx_dbeta.cpp b/src/calc_lx_dbeta.cpp new file mode 100644 index 0000000..31addeb --- /dev/null +++ b/src/calc_lx_dbeta.cpp @@ -0,0 +1,548 @@ +/** + * Calculate the total luminosity and flux within the specified radius. + * + * Base on 'fit_dbeta_sbp.cpp' and supersede 'calc_lx.cpp' + * + * Author: Junhua Gu + */ + +#include <iostream> +#include <fstream> +#include <sstream> +#include <list> +#include "vchisq.hpp" +#include "dbeta.hpp" +#include "beta_cfg.hpp" +#include <data_sets/default_data_set.hpp> +#include <methods/powell/powell_method.hpp> +#include <core/freeze_param.hpp> +#include <error_estimator/error_estimator.hpp> +#include "spline.hpp" + +using namespace std; +using namespace opt_utilities; +//double s=5.63136645E20; +const double kpc=3.086E21;//kpc in cm +const double Mpc=kpc*1000; + +double dbeta_func(double r, double n01, double rc1, double beta1, + double n02, double rc2, double beta2) +{ + double v1 = abs(n01) * pow(1+r*r/rc1/rc1, -3./2.*abs(beta1)); + double v2 = abs(n02) * pow(1+r*r/rc2/rc2, -3./2.*abs(beta2)); + return v1 + v2; +} + + +//A class enclosing the spline interpolation method +class spline_func_obj + :public func_obj<double,double> +{ + //has an spline object + spline<double> spl; +public: + //This function is used to calculate the intepolated value + double do_eval(const double& x) + { + return spl.get_value(x); + } + + //we need this function, when this object is performing a clone of itself + spline_func_obj* do_clone()const + { + return new spline_func_obj(*this); + } + +public: + //add points to the spline object, after which the spline will be initialized + void add_point(double x,double y) + { + spl.push_point(x,y); + } + + //before getting the intepolated value, the spline should be initialzied by calling this function + void gen_spline() + { + spl.gen_spline(0,0); + } +}; + +int main(int argc,char* argv[]) +{ + if(argc<4) + { + cerr<<argv[0]<<" <sbp.conf> <rout_kpc> <cfunc_erg> [cfunc2_erg ...]"<<endl; + return -1; + } + //initialize the parameters list + ifstream cfg_file(argv[1]); + assert(cfg_file.is_open()); + cfg_map cfg=parse_cfg_file(cfg_file); + + const double z=cfg.z; + + //initialize the radius list, sbp list and sbp error list + std::vector<double> radii; + std::vector<double> sbps; + std::vector<double> sbpe; + std::vector<double> radii_all; + std::vector<double> sbps_all; + std::vector<double> sbpe_all; + //prepend the zero point to radius list + radii.push_back(0.0); + radii_all.push_back(0.0); + //read sbp and sbp error data + ifstream ifs(cfg.sbp_data.c_str()); + std::string line; + if (ifs.is_open()) + { + while(std::getline(ifs, line)) + { + if (line.empty()) + continue; + + std::istringstream iss(line); + double x, xe, y, ye; + if ((iss >> x >> xe >> y >> ye)) + { + std::cerr << "sbprofile data: " + << x << ", " << xe << ", " << y << ", " << ye + << std::endl; + radii.push_back(x+xe); /* NOTE: use outer radii of regions */ + radii_all.push_back(x+xe); + sbps.push_back(y); + sbps_all.push_back(y); + sbpe.push_back(ye); + sbpe_all.push_back(ye); + } + else + { + std::cerr << "skipped line: " << line << std::endl; + } + } + } + else + { + std::cerr << "ERROR: cannot open file: " << cfg.sbp_data.c_str() + << std::endl; + return 1; + } + + //initialize the cm/pixel value + double cm_per_pixel=cfg.cm_per_pixel; + double rmin; + if(cfg.rmin_pixel>0) + { + rmin=cfg.rmin_pixel; + } + else + { + rmin=cfg.rmin_kpc*kpc/cm_per_pixel; + } + + cerr<<"rmin="<<rmin<<" (pixel)"<<endl; + std::list<double> radii_tmp,sbps_tmp,sbpe_tmp; + radii_tmp.resize(radii.size()); + sbps_tmp.resize(sbps.size()); + sbpe_tmp.resize(sbpe.size()); + copy(radii.begin(),radii.end(),radii_tmp.begin()); + copy(sbps.begin(),sbps.end(),sbps_tmp.begin()); + copy(sbpe.begin(),sbpe.end(),sbpe_tmp.begin()); + for(list<double>::iterator i=radii_tmp.begin();i!=radii_tmp.end();) + { + if(*i<rmin) + { + radii_tmp.pop_front(); + sbps_tmp.pop_front(); + sbpe_tmp.pop_front(); + i=radii_tmp.begin(); + continue; + } + ++i; + } + radii.resize(radii_tmp.size()); + sbps.resize(sbps_tmp.size()); + sbpe.resize(sbpe_tmp.size()); + copy(radii_tmp.begin(),radii_tmp.end(),radii.begin()); + copy(sbps_tmp.begin(),sbps_tmp.end(),sbps.begin()); + copy(sbpe_tmp.begin(),sbpe_tmp.end(),sbpe.begin()); + + //read cooling function data + spline_func_obj cf; + for(ifstream ifs(cfg.cfunc_profile.c_str());;) + { + assert(ifs.is_open()); + double x,y; + ifs>>x>>y; + if(!ifs.good()) + { + break; + } + cerr<<x<<"\t"<<y<<endl; + if(x>radii.back()) + { + break; + } + cf.add_point(x,y); + } + cf.gen_spline(); + + //read temperature profile data + spline_func_obj Tprof; + int tcnt=0; + for(ifstream ifs1(cfg.tprofile.c_str());;++tcnt) + { + assert(ifs1.is_open()); + double x,y; + ifs1>>x>>y; + if(!ifs1.good()) + { + break; + } + cerr<<x<<"\t"<<y<<endl; +#if 0 + if(tcnt==0) + { + Tprof.add_point(0,y); + } +#endif + Tprof.add_point(x,y); + } + + + Tprof.gen_spline(); + + default_data_set<std::vector<double>,std::vector<double> > ds; + ds.add_data(data<std::vector<double>,std::vector<double> >(radii,sbps,sbpe,sbpe,radii,radii)); + + //initial fitter + fitter<vector<double>,vector<double>,vector<double>,double> f; + f.load_data(ds); + //initial the object, which is used to calculate projection effect + projector<double> a; + bool tie_beta=false; + if(cfg.param_map.find("beta")!=cfg.param_map.end() + &&cfg.param_map.find("beta1")==cfg.param_map.end() + &&cfg.param_map.find("beta2")==cfg.param_map.end()) + { + dbeta2<double> dbetao; + a.attach_model(dbetao); + tie_beta=true; + } + else if((cfg.param_map.find("beta1")!=cfg.param_map.end() + ||cfg.param_map.find("beta2")!=cfg.param_map.end()) + &&cfg.param_map.find("beta")==cfg.param_map.end()) + { + dbeta<double> dbetao; + a.attach_model(dbetao); + tie_beta=false; + } + else + { + cerr<<"Error, cannot decide whether to tie beta together or let them vary freely!"<<endl; + assert(0); + } + + //attach the cooling function + a.attach_cfunc(cf); + a.set_cm_per_pixel(cm_per_pixel); + + f.set_model(a); + //chi^2 statistic + vchisq<double> c; + c.verbose(true); + c.set_limit(); + f.set_statistic(c); + //optimization method + f.set_opt_method(powell_method<double,std::vector<double> >()); + //initialize the initial values + /* + double =0; + double rc1=0; + double n02=0; + double rc2=0; + double beta=0; + */ + double bkg_level=0; + + if(tie_beta) + { + f.set_param_value("beta",.7); + f.set_param_lower_limit("beta",.3); + f.set_param_upper_limit("beta",1.4); + } + else + { + f.set_param_value("beta1",.7); + f.set_param_lower_limit("beta1",.3); + f.set_param_upper_limit("beta1",1.4); + f.set_param_value("beta2",.7); + f.set_param_lower_limit("beta2",.3); + f.set_param_upper_limit("beta2",1.4); + } + for(std::map<std::string,std::vector<double> >::iterator i=cfg.param_map.begin(); + i!=cfg.param_map.end();++i) + { + std::string pname=i->first; + f.set_param_value(pname,i->second.at(0)); + if(i->second.size()==3) + { + double a1=i->second[1]; + double a2=i->second[2]; + double u=std::max(a1,a2); + double l=std::min(a1,a2); + f.set_param_upper_limit(pname,u); + f.set_param_lower_limit(pname,l); + } + else + { + if(pname=="beta"||pname=="beta1"||pname=="beta2") + { + f.set_param_lower_limit(pname,.3); + f.set_param_upper_limit(pname,1.4); + } + } + } + + + + //perform the fitting, first freeze beta1, beta2, rc1, and rc2 + if(tie_beta) + { + f.set_param_modifier(freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("beta")+ + freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("rc1")+ + freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("rc2") + ); + } + else + { + f.set_param_modifier(freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("beta1")+ + freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("beta2")+ + freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("rc1")+ + freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("rc2") + ); + } + + f.fit(); + + f.clear_param_modifier(); + + //then perform the fitting, freeze beta1 and beta2 + //f.set_param_modifier(freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("beta")); + //f.set_param_modifier(freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("bkg")); + f.fit(); + //f.clear_param_modifier(); + + //finally thaw all parameters + f.fit(); + + /* + double beta1=0; + double beta2=0; + + n01=f.get_param_value("n01"); + rc1=f.get_param_value("rc1"); + n02=f.get_param_value("n02"); + rc2=f.get_param_value("rc2"); + if(tie_beta) + { + beta=f.get_param_value("beta"); + beta1=beta; + beta2=beta; + } + else + { + beta1=f.get_param_value("beta1"); + beta2=f.get_param_value("beta2"); + } + */ + + //output the params + ofstream param_output("lx_dbeta_param.txt"); + //output the datasets and fitting results + for(size_t i=0;i<f.get_num_params();++i) + { + if(f.get_param_info(i).get_name()=="rc1") + { + cerr<<"rc1_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + param_output<<"rc1_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + } + if(f.get_param_info(i).get_name()=="rc2") + { + cerr<<"rc2_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + param_output<<"rc2_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + } + cerr<<f.get_param_info(i).get_name()<<"\t"<<abs(f.get_param_info(i).get_value())<<endl; + param_output<<f.get_param_info(i).get_name()<<"\t"<<abs(f.get_param_info(i).get_value())<<endl; + } + cerr<<"reduced_chi^2="<<f.get_statistic_value()/(radii.size()-f.get_model().get_num_free_params())<<endl; + param_output<<"reduced_chi^2="<<f.get_statistic_value()/(radii.size()-f.get_model().get_num_free_params())<<endl; + + //c.verbose(false); + //f.set_statistic(c); + //f.fit(); + std::vector<double> p=f.get_all_params(); + f.clear_param_modifier(); + std::vector<double> mv=f.eval_model(radii,p); + + + ofstream ofs_sbp("lx_sbp_fit.qdp"); + ofs_sbp<<"read serr 2"<<endl; + ofs_sbp<<"skip single"<<endl; + + ofs_sbp<<"line on 2"<<endl; + ofs_sbp<<"line on 3"<<endl; + ofs_sbp<<"line on 4"<<endl; + ofs_sbp<<"line on 5"<<endl; + ofs_sbp<<"line on 7"<<endl; + ofs_sbp<<"ls 2 on 7"<<endl; + ofs_sbp<<"ls 2 on 3"<<endl; + ofs_sbp<<"ls 2 on 4"<<endl; + ofs_sbp<<"ls 2 on 5"<<endl; + + + + ofs_sbp<<"!LAB POS Y 4.00"<<endl; + ofs_sbp<<"!LAB ROT"<<endl; + ofs_sbp<<"win 1"<<endl; + ofs_sbp<<"yplot 1 2 3 4 5"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .4 .9 .9"<<endl; + ofs_sbp<<"la y cnt/s/pixel/cm\\u2\\d"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"log y"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[sbps.size()-2]+radii[sbps.size()-1])/2*cm_per_pixel/kpc<<endl; + ofs_sbp<<"win 2"<<endl; + ofs_sbp<<"yplot 6 7"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .1 .9 .4"<<endl; + ofs_sbp<<"la x radius (kpc)"<<endl; + ofs_sbp<<"la y chi"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"log y off"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[sbps.size()-2]+radii[sbps.size()-1])/2*cm_per_pixel/kpc<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + double y=sbps[i-1]; + double ye=sbpe[i-1]; + //double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<y<<"\t"<<ye<<endl; + } + ofs_sbp<<"no no no"<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + //double y=sbps[i-1]; + //double ye=sbpe[i-1]; + double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<ym<<"\t"<<0<<endl; + } + //bkg + ofs_sbp<<"no no no"<<endl; + bkg_level=abs(f.get_param_value("bkg")); + for(size_t i=0;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<bkg_level<<"\t0"<<endl; + } + //rc1 + ofs_sbp<<"no no no"<<endl; + double rc1_kpc=abs(f.get_param_value("rc1")*cm_per_pixel/kpc); + double max_sbp=*max_element(sbps.begin(),sbps.end()); + double min_sbp=*min_element(sbps.begin(),sbps.end()); + for(double x=min_sbp;x<=max_sbp;x+=(max_sbp-min_sbp)/100) + { + ofs_sbp<<rc1_kpc<<"\t"<<x<<"\t"<<"0"<<endl; + } + //rc2 + ofs_sbp<<"no no no"<<endl; + double rc2_kpc=abs(f.get_param_value("rc2")*cm_per_pixel/kpc); + for(double x=min_sbp;x<=max_sbp;x+=(max_sbp-min_sbp)/100) + { + ofs_sbp<<rc2_kpc<<"\t"<<x<<"\t"<<"0"<<endl; + } + //resid + ofs_sbp<<"no no no"<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + //double y=sbps[i-1]; + //double ye=sbpe[i-1]; + double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<(ym-sbps[i-1])/sbpe[i-1]<<"\t"<<1<<endl; + } + //zero level in resid map + ofs_sbp<<"no no no"<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + //double y=sbps[i-1]; + //double ye=sbpe[i-1]; + //double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<0<<"\t"<<0<<endl; + } + + + mv=f.eval_model_raw(radii,p); + ofstream ofs_rho("lx_rho_fit.qdp"); + ofstream ofs_rho_data("lx_rho_fit.dat"); + //ofstream ofs_entropy("entropy.qdp"); + ofs_rho<<"la x radius (kpc)"<<endl; + ofs_rho<<"la y density (cm\\u-3\\d)"<<endl; + /* + for(int i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + double ym=mv[i-1]; + ofs_rho<<x*cm_per_pixel/kpc<<"\t"<<ym<<endl; + } + */ + + p.back()=0; + + radii.clear(); + double rout=atof(argv[2])*kpc; + for(double r=0;r<rout;r+=1*kpc)//step size=1kpc + { + double r_pix=r/cm_per_pixel; + radii.push_back(r_pix); + } + + double Da=cm_per_pixel/(.492/3600./180.*pi); + double Dl=Da*(1+z)*(1+z); + cout<<"dl="<<Dl/kpc<<endl; + for(int n=3;n<argc;++n) + { + spline_func_obj cf_erg; + for(ifstream ifs(argv[n]);;) + { + assert(ifs.is_open()); + double x,y; + ifs>>x>>y; + if(!ifs.good()) + { + break; + } + //cerr<<x<<"\t"<<y<<endl; + + cf_erg.add_point(x,y);//change with source + } + cf_erg.gen_spline(); + + projector<double>& pj=dynamic_cast<projector<double>&>(f.get_model()); + pj.attach_cfunc(cf_erg); + + mv=f.eval_model_raw(radii,p); + double flux_erg=0; + for(size_t i=0;i<radii.size()-1;++i) + { + double S=pi*(radii[i+1]+radii[i])*(radii[i+1]-radii[i]); + flux_erg+=S*mv[i]; + } + cout<<flux_erg*4*pi*Dl*Dl<<endl; + cout<<flux_erg<<endl; + param_output<<"Lx"<<n-2<<"\t"<<flux_erg*4*pi*Dl*Dl<<endl; + param_output<<"Fx"<<n-2<<"\t"<<flux_erg<<endl; + } +} diff --git a/src/chisq.hpp b/src/chisq.hpp new file mode 100644 index 0000000..0e58200 --- /dev/null +++ b/src/chisq.hpp @@ -0,0 +1,206 @@ +/**
+ \file chisq.hpp
+ \brief chi-square statistic
+ \author Junhua Gu
+ */
+
+#ifndef CHI_SQ_HPP
+#define CHI_SQ_HPP
+
+#define OPT_HEADER
+
+#include <core/fitter.hpp>
+#include <iostream>
+#include <vector>
+#include <misc/optvec.hpp>
+#include <cmath>
+
+using std::cerr;
+using std::endl;
+
+namespace opt_utilities
+{
+ static const int display_interval=10;
+ /**
+ \brief chi-square statistic
+ \tparam Ty the return type of model
+ \tparam Tx the type of the self-var
+ \tparam Tp the type of model parameter
+ \tparam Ts the type of the statistic
+ \tparam Tstr the type of the string used
+ */
+ template<typename Ty,typename Tx,typename Tp,typename Ts,typename Tstr>
+ class chisq
+ :public statistic<Ty,Tx,Tp,Ts,Tstr>
+ {
+ };
+ template<>
+ class chisq<double,double,std::vector<double>,double,std::string>
+ :public statistic<double,double,std::vector<double> ,double,std::string>
+ {
+ public:
+ typedef double Ty;
+ typedef double Tx;
+ typedef std::vector<double> Tp;
+ typedef double Ts;
+ typedef std::string Tstr;
+ private:
+ bool verb;
+ bool limit_bound;
+ int n;
+
+ statistic<Ty,Tx,Tp,Ts,Tstr>* do_clone()const
+ {
+ // return const_cast<statistic<Ty,Tx,Tp>*>(this);
+ return new chisq<Ty,Tx,Tp,Ts,Tstr>(*this);
+ }
+
+ const char* do_get_type_name()const
+ {
+ return "chi^2 statistics (specialized for double)";
+ }
+ public:
+ void verbose(bool v)
+ {
+ verb=v;
+ }
+
+ void set_limit()
+ {
+ limit_bound=true;
+ }
+
+ void clear_limit()
+ {
+ limit_bound=false;
+ }
+ public:
+ chisq()
+ :verb(true),limit_bound(false)
+ {}
+
+ Ty do_eval(const Tp& p)
+ {
+ if(limit_bound)
+ {
+ Tp p1=this->get_fitter().get_model().reform_param(p);
+ for(size_t i=0;i<p1.size();++i)
+ {
+ if(p1[i]>this->get_fitter().get_param_info(i).get_upper_limit()||
+ p1[i]<this->get_fitter().get_param_info(i).get_lower_limit())
+ {
+ return 1e99;
+ }
+ }
+ }
+ Ty result(0);
+ std::vector<float> vx;
+ std::vector<float> vy;
+ std::vector<float> vye1;
+ std::vector<float> vye2;
+ std::vector<float> my;
+ float xmin=1e99,xmax=-1e99,ymin=1e99,ymax=-1e99;
+ if(verb)
+ {
+ n++;
+ if(n%display_interval==0)
+ {
+ vx.resize(this->get_data_set().size());
+ vy.resize(this->get_data_set().size());
+ vye1.resize(this->get_data_set().size());
+ vye2.resize(this->get_data_set().size());
+ my.resize(this->get_data_set().size());
+ }
+ }
+
+ for(int i=(this->get_data_set()).size()-1;i>=0;--i)
+ {
+
+#ifdef HAVE_X_ERROR
+ Tx x1=this->get_data_set().get_data(i).get_x()-this->get_data_set().get_data(i).get_x_lower_err();
+ Tx x2=this->get_data_set().get_data(i).get_x()+this->get_data_set().get_data(i).get_x_upper_err();
+ Tx x=this->get_data_set().get_data(i).get_x();
+ Ty errx1=(this->eval_model(x1,p)-this->eval_model(x,p));
+ Ty errx2=(this->eval_model(x2,p)-this->eval_model(x,p));
+ //Ty errx=0;
+#else
+ Ty errx1=0;
+ Ty errx2=0;
+#endif
+
+ Ty y_model=this->eval_model(this->get_data_set().get_data(i).get_x(),p);
+ Ty y_obs=this->get_data_set().get_data(i).get_y();
+ Ty y_err;
+
+ Ty errx=0;
+ if(errx1<errx2)
+ {
+ if(y_obs<y_model)
+ {
+ errx=errx1>0?errx1:-errx1;
+ }
+ else
+ {
+ errx=errx2>0?errx2:-errx2;
+ }
+ }
+ else
+ {
+ if(y_obs<y_model)
+ {
+ errx=errx2>0?errx2:-errx2;
+ }
+ else
+ {
+ errx=errx1>0?errx1:-errx1;
+ }
+ }
+
+ if(y_model>y_obs)
+ {
+ y_err=this->get_data_set().get_data(i).get_y_upper_err();
+ }
+ else
+ {
+ y_err=this->get_data_set().get_data(i).get_y_lower_err();
+ }
+
+ Ty chi=(y_obs-y_model)/std::sqrt(y_err*y_err+errx*errx);
+
+ result+=chi*chi;
+
+ if(verb&&n%display_interval==0)
+ {
+ vx.at(i)=this->get_data_set().get_data(i).get_x();
+ vy.at(i)=this->get_data_set().get_data(i).get_y();
+ vye1.at(i)=std::abs(this->get_data_set().get_data(i).get_y_lower_err());
+ vye2.at(i)=std::abs(this->get_data_set().get_data(i).get_y_upper_err());
+ my.at(i)=y_model;
+
+ xmin=std::min(vx.at(i),xmin);
+ ymin=std::min(vy.at(i),ymin-vye1[i]);
+ xmax=std::max(vx.at(i),xmax);
+ ymax=std::max(vy.at(i),ymax+vye2[i]);
+ }
+
+ }
+ if(verb)
+ {
+ if(n%display_interval==0)
+ {
+ cerr<<result<<"\t";
+ for(size_t i=0;i<get_size(p);++i)
+ {
+ cerr<<get_element(p,i)<<",";
+ }
+ cerr<<endl;
+ //cerr<<x1<<"\t"<<x2<<endl;
+ }
+ }
+
+ return result;
+ }
+ };
+}
+
+#endif /* CHI_SQ_HPP */
diff --git a/src/dbeta.hpp b/src/dbeta.hpp new file mode 100644 index 0000000..7246b44 --- /dev/null +++ b/src/dbeta.hpp @@ -0,0 +1,108 @@ +#ifndef DBETA +#define DBETA +#include "projector.hpp" + +/** + dbeta: double beta model for density + dbeta2: double beta model for density with only one beta +*/ + + +namespace opt_utilities +{ + template <typename T> + class dbeta + :public model<std::vector<T>,std::vector<T>,std::vector<T> > + { + public: + dbeta() + { + this->push_param_info(param_info<std::vector<T>,std::string>("n01",1)); + this->push_param_info(param_info<std::vector<T>,std::string>("beta1",.66)); + this->push_param_info(param_info<std::vector<T>,std::string>("rc1",100)); + + this->push_param_info(param_info<std::vector<T>,std::string>("n02",1)); + this->push_param_info(param_info<std::vector<T>,std::string>("beta2",.67)); + this->push_param_info(param_info<std::vector<T>,std::string>("rc2",110)); + + } + + public: + dbeta<T>* do_clone()const + { + return new dbeta<T>(*this); + } + + std::vector<T> do_eval(const std::vector<T> & x, + const std::vector<T>& p) + { + T n01=std::abs(p[0]); + T beta1=p[1]; + T rc1=p[2]; + + T n02=std::abs(p[3]); + T beta2=p[4]; + T rc2=p[5]; + + + + std::vector<T> result(x.size()-1); + for(size_t i=1;i<x.size();++i) + { + T xi=(x[i]+x[i-1])/2; + T yi=0; + yi=n01*pow(1+xi*xi/rc1/rc1,-3./2.*beta1)+n02*pow(1+xi*xi/rc2/rc2,-3./2.*beta2); + result[i-1]=yi; + } + return result; + } + }; + + template <typename T> + class dbeta2 + :public model<std::vector<T>,std::vector<T>,std::vector<T> > + { + public: + dbeta2() + { + this->push_param_info(param_info<std::vector<T>,std::string>("n01",1)); + this->push_param_info(param_info<std::vector<T>,std::string>("rc1",100)); + this->push_param_info(param_info<std::vector<T>,std::string>("n02",1)); + this->push_param_info(param_info<std::vector<T>,std::string>("rc2",110)); + this->push_param_info(param_info<std::vector<T>,std::string>("beta",.67)); + + } + + public: + dbeta2<T>* do_clone()const + { + return new dbeta2<T>(*this); + } + + std::vector<T> do_eval(const std::vector<T> & x, + const std::vector<T>& p) + { + T n01=std::abs(p[0]); + T rc1=p[1]; + + T n02=std::abs(p[2]); + T rc2=p[3]; + T beta=p[4]; + T beta1=beta; + T beta2=beta; + + std::vector<T> result(x.size()-1); + for(size_t i=1;i<x.size();++i) + { + T xi=(x[i]+x[i-1])/2; + T yi=0; + yi=n01*pow(1+xi*xi/rc1/rc1,-3./2.*beta1)+n02*pow(1+xi*xi/rc2/rc2,-3./2.*beta2); + result[i-1]=yi; + } + return result; + } + }; + +} + +#endif diff --git a/src/dump_fit_qdp.cpp b/src/dump_fit_qdp.cpp new file mode 100644 index 0000000..85307d1 --- /dev/null +++ b/src/dump_fit_qdp.cpp @@ -0,0 +1,55 @@ +#include "dump_fit_qdp.hpp" + +namespace opt_utilities +{ + const static double kpc=3.086E21; + void dump_sbp_beta(std::ostream& os,fitter<double,double,std::vector<double>,double,std::string>& f,double cm_per_pixel,const std::vector<double>& r,const std::vector<double>& y,const std::vector<double>& ye) + { + os<<"read serr 1 2"<<std::endl; + os<<"skip single"<<std::endl; + os<<"la x \"radius (kpc)\""<<std::endl; + os<<"la y \"surface brightness (cts s\\u-1\\d pixel\\u-2\\d)\""<<std::endl; + os<<"li on 2"<<std::endl; + for(size_t i=1;i<r.size();++i) + { + os<<(r[i]+r[i-1])/2*cm_per_pixel/kpc<<"\t"<<(r[i]-r[i-1])/2*cm_per_pixel/kpc<<"\t"<<y[i-1]<<"\t"<<ye[i-1]<<std::endl; + } + os<<"no no no"<<std::endl; + std::vector<double> p=f.get_all_params(); + for(size_t i=1;i<r.size();++i) + { + double x=(r[i]+r[i-1])/2; + os<<x*cm_per_pixel/kpc<<"\t"<<0<<"\t"<<f.eval_model_raw(x,p)<<"\t"<<0<<std::endl; + } + } + + void dump_rho_beta(std::ostream& os,fitter<std::vector<double>,std::vector<double>,std::vector<double>,double,std::string>& f,double cm_per_pixel,const std::vector<double>& r,const std::vector<double>& sbps,const std::vector<double>& sbpe) + { + os<<"read serr 1 2"<<std::endl; + os<<"skip single"<<std::endl; + os<<"la x \"radius (kpc)\""<<std::endl; + os<<"la y \"density (cm\\u-3\\d)\""<<std::endl; + os<<"li on 2"<<std::endl; + + for(size_t i=1;i<r.size();++i) + { + double x=(r[i]+r[i-1])/2; + double y=sbps[i-1]; + double ye=sbpe[i-1]; + os<<x*cm_per_pixel/kpc<<"\t0\t"<<y<<"\t"<<ye<<std::endl; + } + + os<<"no no no"<<std::endl; + std::vector<double> p=f.get_all_params(); + std::vector<double> mv=f.eval_model_raw(r,p); + for(size_t i=1;i<r.size();++i) + { + double x=(r[i]+r[i-1])/2; + double y=mv[i-1]; + double ye=0; + os<<x*cm_per_pixel/kpc<<"\t0\t"<<y<<"\t"<<ye<<std::endl; + } + + } + +}; diff --git a/src/dump_fit_qdp.hpp b/src/dump_fit_qdp.hpp new file mode 100644 index 0000000..8364dfd --- /dev/null +++ b/src/dump_fit_qdp.hpp @@ -0,0 +1,16 @@ +#ifndef DUMP_FIT_QDP_HPP +#define DUMP_FIT_QDP_HPP + +#include <core/fitter.hpp> +#include <vector> +#include <iostream> +#include <string> + +namespace opt_utilities +{ + void dump_sbp_beta(std::ostream& os,fitter<double,double,std::vector<double>,double,std::string>& f,double cm_per_pixel,const std::vector<double>& r,const std::vector<double>& y,const std::vector<double>& ye); + void dump_rho_beta(std::ostream& os,fitter<std::vector<double>,std::vector<double>,std::vector<double>,double,std::string>& f,double cm_per_pixel,const std::vector<double>& r,const std::vector<double>& sbps,const std::vector<double>& sbpe); + void dump_rho_dbeta(std::ostream& os,fitter<std::vector<double>,std::vector<double>,std::vector<double>,double,std::string>& f,double cm_per_pixel); +}; + +#endif diff --git a/src/fit_beta_sbp.cpp b/src/fit_beta_sbp.cpp new file mode 100644 index 0000000..295fa1e --- /dev/null +++ b/src/fit_beta_sbp.cpp @@ -0,0 +1,534 @@ +/* + Perform a double-beta density model fitting to the surface brightness data + Author: Junhua Gu + Last modified: 2016.06.07 + This code is distributed with no warrant +*/ + +#include <iostream> +#include <fstream> +#include <sstream> +#include <list> +#include <algorithm> +#include "beta_cfg.hpp" +#include "dump_fit_qdp.hpp" +#include "report_error.hpp" +#include "vchisq.hpp" +#include "chisq.hpp" +#include "beta.hpp" +#include "models/beta1d.hpp" +#include <data_sets/default_data_set.hpp> +#include <methods/powell/powell_method.hpp> +#include <core/freeze_param.hpp> +#include <error_estimator/error_estimator.hpp> +#include "spline.hpp" + +using namespace std; +using namespace opt_utilities; +//double s=5.63136645E20; +const double kpc=3.086E21;//kpc in cm +const double Mpc=kpc*1000; + +double beta_func(double r, double n0, double rc, double beta) +{ + return abs(n0) * pow(1+r*r/rc/rc, -3./2.*abs(beta)); +} + +//calculate critical density from z, under following cosmological constants +static double calc_critical_density(double z, + const double H0=2.3E-18, + const double Omega_m=.27) +{ + const double G=6.673E-8;//cm^3 g^-1 s^2 + const double E=std::sqrt(Omega_m*(1+z)*(1+z)*(1+z)+1-Omega_m); + const double H=H0*E; + return 3*H*H/8/pi/G; +} + + +//A class enclosing the spline interpolation method +class spline_func_obj + :public func_obj<double,double> +{ + //has an spline object + spline<double> spl; +public: + //This function is used to calculate the intepolated value + double do_eval(const double& x) + { + return spl.get_value(x); + } + + //we need this function, when this object is performing a clone of itself + spline_func_obj* do_clone()const + { + return new spline_func_obj(*this); + } + +public: + //add points to the spline object, after which the spline will be initialized + void add_point(double x,double y) + { + spl.push_point(x,y); + } + + //before getting the intepolated value, the spline should be initialzied by calling this function + void gen_spline() + { + spl.gen_spline(0,0); + } +}; + +int main(int argc,char* argv[]) +{ + if(argc!=2) + { + cerr<<argv[0]<<" <configure file>"<<endl; + return -1; + } + //initialize the parameters list + ifstream cfg_file(argv[1]); + assert(cfg_file.is_open()); + cfg_map cfg=parse_cfg_file(cfg_file); + + const double z=cfg.z; + + //initialize the radius list, sbp list and sbp error list + std::vector<double> radii; + std::vector<double> sbps; + std::vector<double> sbpe; + std::vector<double> radii_all; + std::vector<double> sbps_all; + std::vector<double> sbpe_all; + //prepend the zero point to radius list + radii.push_back(0.0); + radii_all.push_back(0.0); + //read sbp and sbp error data + cerr << "Read surface brightness profile data ..." << endl; + ifstream ifs(cfg.sbp_data.c_str()); + std::string line; + if (ifs.is_open()) + { + while(std::getline(ifs, line)) + { + if (line.empty()) + continue; + + std::istringstream iss(line); + double x, xe, y, ye; + if ((iss >> x >> xe >> y >> ye)) + { + std::cerr << "sbprofile data: " + << x << ", " << xe << ", " << y << ", " << ye + << std::endl; + radii.push_back(x+xe); /* NOTE: use outer radii of regions */ + radii_all.push_back(x+xe); + sbps.push_back(y); + sbps_all.push_back(y); + sbpe.push_back(ye); + sbpe_all.push_back(ye); + } + else + { + std::cerr << "skipped line: " << line << std::endl; + } + } + } + else + { + std::cerr << "ERROR: cannot open file: " << cfg.sbp_data.c_str() + << std::endl; + return 1; + } + + //initialize the cm/pixel value + double cm_per_pixel=cfg.cm_per_pixel; + double rmin; + if(cfg.rmin_pixel>0) + { + rmin=cfg.rmin_pixel; + } + else + { + rmin=cfg.rmin_kpc*kpc/cm_per_pixel; + } + + cerr<<"rmin="<<rmin<<" (pixel)"<<endl; + std::list<double> radii_tmp,sbps_tmp,sbpe_tmp; + radii_tmp.resize(radii.size()); + sbps_tmp.resize(sbps.size()); + sbpe_tmp.resize(sbpe.size()); + copy(radii.begin(),radii.end(),radii_tmp.begin()); + copy(sbps.begin(),sbps.end(),sbps_tmp.begin()); + copy(sbpe.begin(),sbpe.end(),sbpe_tmp.begin()); + for(list<double>::iterator i=radii_tmp.begin();i!=radii_tmp.end();) + { + if(*i<rmin) + { + radii_tmp.pop_front(); + sbps_tmp.pop_front(); + sbpe_tmp.pop_front(); + i=radii_tmp.begin(); + continue; + } + ++i; + } + radii.resize(radii_tmp.size()); + sbps.resize(sbps_tmp.size()); + sbpe.resize(sbpe_tmp.size()); + copy(radii_tmp.begin(),radii_tmp.end(),radii.begin()); + copy(sbps_tmp.begin(),sbps_tmp.end(),sbps.begin()); + copy(sbpe_tmp.begin(),sbpe_tmp.end(),sbpe.begin()); + + //read cooling function data + cerr << "Read cooling function profile data ..." << endl; + spline_func_obj cf; + for(ifstream ifs(cfg.cfunc_profile.c_str());;) + { + assert(ifs.is_open()); + double x,y; + ifs>>x>>y; + if(!ifs.good()) + { + break; + } + cerr<<x<<"\t"<<y<<endl; + if(x>radii.back()) + { + cerr << "radius_max: " << radii.back() << endl; + break; + } + cf.add_point(x,y); + } + cf.gen_spline(); + + //read temperature profile data + cerr << "Read temperature profile data ..." << endl; + spline_func_obj Tprof; + int tcnt=0; + for(ifstream ifs1(cfg.tprofile.c_str());;++tcnt) + { + assert(ifs1.is_open()); + double x,y; + ifs1>>x>>y; + if(!ifs1.good()) + { + break; + } + cerr<<x<<"\t"<<y<<endl; +#if 0 + if(tcnt==0) + { + Tprof.add_point(0,y); + } +#endif + Tprof.add_point(x,y); + } + Tprof.gen_spline(); + + default_data_set<std::vector<double>,std::vector<double> > ds; + ds.add_data(data<std::vector<double>,std::vector<double> >(radii,sbps,sbpe,sbpe,radii,radii)); + + //initial fitter + fitter<vector<double>,vector<double>,vector<double>,double> f; + f.load_data(ds); + //initial the object, which is used to calculate projection effect + projector<double> a; + beta<double> betao; + //attach the cooling function + a.attach_cfunc(cf); + a.set_cm_per_pixel(cm_per_pixel); + a.attach_model(betao); + f.set_model(a); + //chi^2 statistic + vchisq<double> c; + c.verbose(true); + c.set_limit(); + f.set_statistic(c); + //optimization method + f.set_opt_method(powell_method<double,std::vector<double> >()); + //initialize the initial values + double n0=0; + //double beta=atof(arg_map["beta"].c_str()); + double beta=0; + double rc=0; + double bkg_level=0; + + for(std::map<std::string,std::vector<double> >::iterator i=cfg.param_map.begin(); + i!=cfg.param_map.end();++i) + { + std::string pname=i->first; + f.set_param_value(pname,i->second.at(0)); + if(i->second.size()==3) + { + double a1=i->second[1]; + double a2=i->second[2]; + double u=std::max(a1,a2); + double l=std::min(a1,a2); + f.set_param_upper_limit(pname,u); + f.set_param_lower_limit(pname,l); + } + else + { + if(pname=="beta") + { + f.set_param_lower_limit(pname,.3); + f.set_param_upper_limit(pname,1.4); + } + } + } + + f.fit(); + f.fit(); + std::vector<double> p=f.get_all_params(); + n0=f.get_param_value("n0"); + rc=f.get_param_value("rc"); + beta=f.get_param_value("beta"); + //output the datasets and fitting results + ofstream param_output("beta_param.txt"); + for(size_t i=0;i<f.get_num_params();++i) + { + if(f.get_param_info(i).get_name()=="rc") + { + cerr<<"rc_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + param_output<<"rc_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + } + cerr<<f.get_param_info(i).get_name()<<"\t"<<abs(f.get_param_info(i).get_value())<<endl; + param_output<<f.get_param_info(i).get_name()<<"\t"<<abs(f.get_param_info(i).get_value())<<endl; + } + cerr<<"reduced_chi^2="<<f.get_statistic_value()/(radii.size()-f.get_model().get_num_free_params())<<endl; + param_output<<"reduced_chi^2="<<f.get_statistic_value()/(radii.size()-f.get_model().get_num_free_params())<<endl; + + std::vector<double> mv=f.eval_model_raw(radii_all,p); + int sbps_inner_cut_size=int(sbps_all.size()-sbps.size()); + ofstream ofs_sbp("sbp_fit.qdp"); + ofs_sbp<<"read serr 2"<<endl; + ofs_sbp<<"skip single"<<endl; + ofs_sbp<<"line off "<<endl; + if(sbps_inner_cut_size>=1) + { + ofs_sbp<<"line on 2"<<endl; + ofs_sbp<<"line on 3"<<endl; + ofs_sbp<<"line on 4"<<endl; + ofs_sbp<<"line on 5"<<endl; + ofs_sbp<<"ls 2 on 2"<<endl; + ofs_sbp<<"ls 2 on 4"<<endl; + ofs_sbp<<"ls 2 on 5"<<endl; + ofs_sbp<<"line on 7"<<endl; + ofs_sbp<<"ls 2 on 7"<<endl; + + ofs_sbp<<"ma 1 on 2"<<endl; + ofs_sbp<<"color 1 on 1"<<endl; + ofs_sbp<<"color 2 on 2"<<endl; + ofs_sbp<<"color 3 on 3"<<endl; + ofs_sbp<<"color 4 on 4"<<endl; + ofs_sbp<<"color 5 on 5"<<endl; + + ofs_sbp<<"win 1"<<endl; + ofs_sbp<<"yplot 1 2 3 4 5"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .4 .9 .9"<<endl; + ofs_sbp<<"la y cnt/s/pixel/cm^2"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"log y"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[sbps.size()-2]+radii[sbps.size()-1])/2*cm_per_pixel/kpc<<endl; + ofs_sbp<<"win 2"<<endl; + ofs_sbp<<"yplot 6 7"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .1 .9 .4"<<endl; + ofs_sbp<<"la x radius (kpc)"<<endl; + ofs_sbp<<"la y chi"<<endl; + ofs_sbp<<"log y off"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[sbps.size()-2]+radii[sbps.size()-1])/2*cm_per_pixel/kpc<<endl; + } + else + { + ofs_sbp<<"line on 2"<<endl; + ofs_sbp<<"line on 3"<<endl; + ofs_sbp<<"line on 4"<<endl; + ofs_sbp<<"ls 2 on 3"<<endl; + ofs_sbp<<"ls 2 on 4"<<endl; + ofs_sbp<<"line on 6"<<endl; + ofs_sbp<<"ls 2 on 6"<<endl; + + ofs_sbp<<"color 1 on 1"<<endl; + ofs_sbp<<"color 3 on 2"<<endl; + ofs_sbp<<"color 4 on 3"<<endl; + ofs_sbp<<"color 5 on 4"<<endl; + //ofs_sbp<<"ma 1 on 2"<<endl; + + ofs_sbp<<"win 1"<<endl; + ofs_sbp<<"yplot 1 2 3 4"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .4 .9 .9"<<endl; + ofs_sbp<<"la y cnt/s/pixel/cm^2"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"log y"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[radii.size()-2]+radii[radii.size()-1])/2*cm_per_pixel/kpc<<endl; + ofs_sbp<<"win 2"<<endl; + ofs_sbp<<"yplot 5 6"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .1 .9 .4"<<endl; + ofs_sbp<<"la x radius (kpc)"<<endl; + ofs_sbp<<"la y chi"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"log y off"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[radii.size()-2]+radii[radii.size()-1])/2*cm_per_pixel/kpc<<endl; + + } + // cout<<sbps_all.size()<<"\t"<<sbps.size()<<"\t"<<sbps_inner_cut_size<<endl; + for(size_t i=1;i<sbps_all.size();++i) + { + double x=(radii_all[i]+radii_all[i-1])/2; + double y=sbps_all[i-1]; + double ye=sbpe_all[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<y<<"\t"<<ye<<endl; + } + if(sbps_inner_cut_size>=1) + { + ofs_sbp<<"no no no"<<endl; + for(int i=1;i<sbps_inner_cut_size+1;++i) + { + double x=(radii_all[i]+radii_all[i-1])/2; + double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<ym<<"\t"<<"0"<<endl; + } + } + ofs_sbp<<"no no no"<<endl; + for(size_t i=sbps_inner_cut_size;i<sbps_all.size();++i) + { + double x=(radii_all[i]+radii_all[i-1])/2; + double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<ym<<"\t"<<"0"<<endl; + } + ofs_sbp<<"no no no"<<endl; + //bkg level + bkg_level=abs(f.get_param_value("bkg")); + for(size_t i=0;i<sbps_all.size();++i) + { + double x=(radii_all[i]+radii_all[i-1])/2; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<bkg_level<<"\t0"<<endl; + } + ofs_sbp<<"no no no"<<endl; + //rc + double rc_kpc=abs(f.get_param_value("rc")*cm_per_pixel/kpc); + double max_sbp=*max_element(sbps_all.begin(),sbps_all.end()); + double min_sbp=*min_element(sbps_all.begin(),sbps_all.end()); + for(double x=min_sbp;x<=max_sbp;x+=(max_sbp-min_sbp)/100) + { + ofs_sbp<<rc_kpc<<"\t"<<x<<"\t"<<"0"<<endl; + } + //resid + ofs_sbp<<"no no no"<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + //double y=sbps[i-1]; + //double ye=sbpe[i-1]; + double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<(ym-sbps[i-1])/sbpe[i-1]<<"\t"<<1<<endl; + } + + //zero level of resid + ofs_sbp<<"no no no"<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + //double y=sbps[i-1]; + //double ye=sbpe[i-1]; + //double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<0<<"\t"<<0<<endl; + } + + mv=betao.eval(radii,p); + ofstream ofs_rho("rho_fit.qdp"); + ofstream ofs_rho_data("rho_fit.dat"); + ofstream ofs_entropy("entropy.qdp"); + ofs_rho<<"la x radius (kpc)"<<endl; + ofs_rho<<"la y density (cm\\u-3\\d)"<<endl; + /* + for(int i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + double ym=mv[i-1]; + ofs_rho<<x*cm_per_pixel/kpc<<"\t"<<ym<<endl; + } + */ + + //double lower,upper; + double dr=1; + //calculate the mass profile + //const double G=6.673E-8;//cm^3 g^-1 s^-2 + // Molecular weight per electron + // Reference: Ettori et al. 2013, Space Sci. Rev., 177, 119-154; Eq.(9) below + static const double mu=1.155; + static const double mp=1.67262158E-24;//g + static const double M_sun=1.98892E33;//g + //static const double k=1.38E-16; + + ofstream ofs_mass("mass_int.qdp"); + ofstream ofs_mass_dat("mass_int.dat"); + ofstream ofs_overdensity("overdensity.qdp"); + ofstream ofs_gas_mass("gas_mass_int.qdp"); + //ofs_mass<<"la x radius (kpc)"<<endl; + //ofs_mass<<"la y mass enclosed (solar mass)"<<endl; + //ofs_overdensity<<"la x radius (kpc)"<<endl; + //ofs_overdensity<<"la y overdensity"<<endl; + double gas_mass=0; + for(double r=1;r<200000;r+=dr) + { + dr=r/100; + double r1=r+dr; + double r_cm=r*cm_per_pixel; + double r1_cm=r1*cm_per_pixel; + double dr_cm=dr*cm_per_pixel; + double V_cm3=4./3.*pi*(dr_cm*(r1_cm*r1_cm+r_cm*r_cm+r_cm*r1_cm)); + double ne=beta_func(r,n0,rc,beta);//cm^-3 + + double dmgas=V_cm3*ne*mu*mp/M_sun; + gas_mass+=dmgas; + + ofs_gas_mass<<r*cm_per_pixel/kpc<<"\t"<<gas_mass<<endl; + double ne1=beta_func(r1,n0,rc,beta);//cm^3 + + double T_keV=Tprof(r); + double T1_keV=Tprof(r1); + + //double T_K=T_keV*11604505.9; + //double T1_K=T1_keV*11604505.9; + + double dlnT=log(T1_keV/T_keV); + double dlnr=log(r+dr)-log(r); + double dlnn=log(ne1/ne); + + //double r_kpc=r_cm/kpc; + double r_Mpc=r_cm/Mpc; + //double M=-r_cm*T_K*k/G/mu/mp*(dlnT/dlnr+dlnn/dlnr); + //ref:http://adsabs.harvard.edu/abs/2012MNRAS.422.3503W + //Walker et al. 2012 + double M=-3.68E13*M_sun*T_keV*r_Mpc*(dlnT/dlnr+dlnn/dlnr); + double rho=M/(4./3.*pi*r_cm*r_cm*r_cm); + + double S=T_keV/pow(ne,2./3.); + //cout<<r<<"\t"<<M/M_sun<<endl; + //cout<<r<<"\t"<<T_keV<<endl; + + ofs_rho<<r*cm_per_pixel/kpc<<"\t"<<ne<<endl; + ofs_rho_data<<r*cm_per_pixel/kpc<<"\t"<<ne<<endl; + ofs_entropy<<r*cm_per_pixel/kpc<<"\t"<<S<<endl; +#if 0 + if(r*cm_per_pixel/kpc<5) + { + continue; + } +#endif + ofs_mass<<r*cm_per_pixel/kpc<<"\t"<<M/M_sun<<endl; + if(r<radii.at(sbps.size())) + { + ofs_mass_dat<<r*cm_per_pixel/kpc<<"\t0\t"<<M/M_sun<<"\t"<<M/M_sun*.1<<endl; + } + ofs_overdensity<<r*cm_per_pixel/kpc<<"\t"<<rho/calc_critical_density(z)<<endl; + + } +} diff --git a/src/fit_dbeta_sbp.cpp b/src/fit_dbeta_sbp.cpp new file mode 100644 index 0000000..71b3089 --- /dev/null +++ b/src/fit_dbeta_sbp.cpp @@ -0,0 +1,586 @@ +/* + Perform a double-beta density model fitting to the surface brightness data + Author: Junhua Gu + Last modified: 2016.06.07 + This code is distributed with no warrant +*/ + + +#include <iostream> +#include <fstream> +#include <sstream> +#include <list> +#include "vchisq.hpp" +#include "dbeta.hpp" +#include "beta_cfg.hpp" +#include <data_sets/default_data_set.hpp> +#include <methods/powell/powell_method.hpp> +#include <core/freeze_param.hpp> +#include <error_estimator/error_estimator.hpp> +#include "spline.hpp" + +using namespace std; +using namespace opt_utilities; +//double s=5.63136645E20; +const double kpc=3.086E21;//kpc in cm +const double Mpc=kpc*1000; + +double dbeta_func(double r, double n01, double rc1, double beta1, + double n02, double rc2, double beta2) +{ + double v1 = abs(n01) * pow(1+r*r/rc1/rc1, -3./2.*abs(beta1)); + double v2 = abs(n02) * pow(1+r*r/rc2/rc2, -3./2.*abs(beta2)); + return v1 + v2; +} + +//calculate critical density from z, under following cosmological constants +static double calc_critical_density(double z, + const double H0=2.3E-18, + const double Omega_m=.27) +{ + const double G=6.673E-8;//cm^3 g^-1 s^2 + const double E=std::sqrt(Omega_m*(1+z)*(1+z)*(1+z)+1-Omega_m); + const double H=H0*E; + return 3*H*H/8/pi/G; +} + + +//A class enclosing the spline interpolation method +class spline_func_obj + :public func_obj<double,double> +{ + //has an spline object + spline<double> spl; +public: + //This function is used to calculate the intepolated value + double do_eval(const double& x) + { + return spl.get_value(x); + } + + //we need this function, when this object is performing a clone of itself + spline_func_obj* do_clone()const + { + return new spline_func_obj(*this); + } + +public: + //add points to the spline object, after which the spline will be initialized + void add_point(double x,double y) + { + spl.push_point(x,y); + } + + //before getting the intepolated value, the spline should be initialzied by calling this function + void gen_spline() + { + spl.gen_spline(0,0); + } +}; + +int main(int argc,char* argv[]) +{ + if(argc!=2) + { + cerr<<argv[0]<<" <configure file>"<<endl; + return -1; + } + //initialize the parameters list + ifstream cfg_file(argv[1]); + assert(cfg_file.is_open()); + cfg_map cfg=parse_cfg_file(cfg_file); + + const double z=cfg.z; + + //initialize the radius list, sbp list and sbp error list + std::vector<double> radii; + std::vector<double> sbps; + std::vector<double> sbpe; + std::vector<double> radii_all; + std::vector<double> sbps_all; + std::vector<double> sbpe_all; + //prepend the zero point to radius list + radii.push_back(0.0); + radii_all.push_back(0.0); + //read sbp and sbp error data + ifstream ifs(cfg.sbp_data.c_str()); + std::string line; + if (ifs.is_open()) + { + while(std::getline(ifs, line)) + { + if (line.empty()) + continue; + + std::istringstream iss(line); + double x, xe, y, ye; + if ((iss >> x >> xe >> y >> ye)) + { + std::cerr << "sbprofile data: " + << x << ", " << xe << ", " << y << ", " << ye + << std::endl; + radii.push_back(x+xe); /* NOTE: use outer radii of regions */ + radii_all.push_back(x+xe); + sbps.push_back(y); + sbps_all.push_back(y); + sbpe.push_back(ye); + sbpe_all.push_back(ye); + } + else + { + std::cerr << "skipped line: " << line << std::endl; + } + } + } + else + { + std::cerr << "ERROR: cannot open file: " << cfg.sbp_data.c_str() + << std::endl; + return 1; + } + + //initialize the cm/pixel value + double cm_per_pixel=cfg.cm_per_pixel; + double rmin; + if(cfg.rmin_pixel>0) + { + rmin=cfg.rmin_pixel; + } + else + { + rmin=cfg.rmin_kpc*kpc/cm_per_pixel; + } + + cerr<<"rmin="<<rmin<<" (pixel)"<<endl; + std::list<double> radii_tmp,sbps_tmp,sbpe_tmp; + radii_tmp.resize(radii.size()); + sbps_tmp.resize(sbps.size()); + sbpe_tmp.resize(sbpe.size()); + copy(radii.begin(),radii.end(),radii_tmp.begin()); + copy(sbps.begin(),sbps.end(),sbps_tmp.begin()); + copy(sbpe.begin(),sbpe.end(),sbpe_tmp.begin()); + for(list<double>::iterator i=radii_tmp.begin();i!=radii_tmp.end();) + { + if(*i<rmin) + { + radii_tmp.pop_front(); + sbps_tmp.pop_front(); + sbpe_tmp.pop_front(); + i=radii_tmp.begin(); + continue; + } + ++i; + } + radii.resize(radii_tmp.size()); + sbps.resize(sbps_tmp.size()); + sbpe.resize(sbpe_tmp.size()); + copy(radii_tmp.begin(),radii_tmp.end(),radii.begin()); + copy(sbps_tmp.begin(),sbps_tmp.end(),sbps.begin()); + copy(sbpe_tmp.begin(),sbpe_tmp.end(),sbpe.begin()); + + //read cooling function data + spline_func_obj cf; + for(ifstream ifs(cfg.cfunc_profile.c_str());;) + { + assert(ifs.is_open()); + double x,y; + ifs>>x>>y; + if(!ifs.good()) + { + break; + } + cerr<<x<<"\t"<<y<<endl; + if(x>radii.back()) + { + break; + } + cf.add_point(x,y); + } + cf.gen_spline(); + + //read temperature profile data + spline_func_obj Tprof; + int tcnt=0; + for(ifstream ifs1(cfg.tprofile.c_str());;++tcnt) + { + assert(ifs1.is_open()); + double x,y; + ifs1>>x>>y; + if(!ifs1.good()) + { + break; + } + cerr<<x<<"\t"<<y<<endl; +#if 0 + if(tcnt==0) + { + Tprof.add_point(0,y); + } +#endif + Tprof.add_point(x,y); + } + + + Tprof.gen_spline(); + + default_data_set<std::vector<double>,std::vector<double> > ds; + ds.add_data(data<std::vector<double>,std::vector<double> >(radii,sbps,sbpe,sbpe,radii,radii)); + + //initial fitter + fitter<vector<double>,vector<double>,vector<double>,double> f; + f.load_data(ds); + //initial the object, which is used to calculate projection effect + projector<double> a; + bool tie_beta=false; + if(cfg.param_map.find("beta")!=cfg.param_map.end() + &&cfg.param_map.find("beta1")==cfg.param_map.end() + &&cfg.param_map.find("beta2")==cfg.param_map.end()) + { + dbeta2<double> dbetao; + a.attach_model(dbetao); + tie_beta=true; + } + else if((cfg.param_map.find("beta1")!=cfg.param_map.end() + ||cfg.param_map.find("beta2")!=cfg.param_map.end()) + &&cfg.param_map.find("beta")==cfg.param_map.end()) + { + dbeta<double> dbetao; + a.attach_model(dbetao); + tie_beta=false; + } + else + { + cerr<<"Error, cannot decide whether to tie beta together or let them vary freely!"<<endl; + assert(0); + } + + //attach the cooling function + a.attach_cfunc(cf); + a.set_cm_per_pixel(cm_per_pixel); + + f.set_model(a); + //chi^2 statistic + vchisq<double> c; + c.verbose(true); + c.set_limit(); + f.set_statistic(c); + //optimization method + f.set_opt_method(powell_method<double,std::vector<double> >()); + //initialize the initial values + double n01=0; + double rc1=0; + double n02=0; + double rc2=0; + double beta=0; + double bkg_level=0; + if(tie_beta) + { + f.set_param_value("beta",.7); + f.set_param_lower_limit("beta",.3); + f.set_param_upper_limit("beta",1.4); + } + else + { + f.set_param_value("beta1",.7); + f.set_param_lower_limit("beta1",.3); + f.set_param_upper_limit("beta1",1.4); + f.set_param_value("beta2",.7); + f.set_param_lower_limit("beta2",.3); + f.set_param_upper_limit("beta2",1.4); + } + for(std::map<std::string,std::vector<double> >::iterator i=cfg.param_map.begin(); + i!=cfg.param_map.end();++i) + { + std::string pname=i->first; + f.set_param_value(pname,i->second.at(0)); + if(i->second.size()==3) + { + double a1=i->second[1]; + double a2=i->second[2]; + double u=std::max(a1,a2); + double l=std::min(a1,a2); + f.set_param_upper_limit(pname,u); + f.set_param_lower_limit(pname,l); + } + else + { + if(pname=="beta"||pname=="beta1"||pname=="beta2") + { + f.set_param_lower_limit(pname,.3); + f.set_param_upper_limit(pname,1.4); + } + } + } + + + + //perform the fitting, first freeze beta1, beta2, rc1, and rc2 + if(tie_beta) + { + f.set_param_modifier(freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("beta")+ + freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("rc1")+ + freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("rc2") + ); + } + else + { + f.set_param_modifier(freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("beta1")+ + freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("beta2")+ + freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("rc1")+ + freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("rc2") + ); + } + + f.fit(); + + f.clear_param_modifier(); + + //then perform the fitting, freeze beta1 and beta2 + //f.set_param_modifier(freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("beta")); + //f.set_param_modifier(freeze_param<std::vector<double>,std::vector<double>,std::vector<double>,std::string>("bkg")); + f.fit(); + //f.clear_param_modifier(); + + //finally thaw all parameters + f.fit(); + double beta1=0; + double beta2=0; + + n01=f.get_param_value("n01"); + rc1=f.get_param_value("rc1"); + n02=f.get_param_value("n02"); + rc2=f.get_param_value("rc2"); + if(tie_beta) + { + beta=f.get_param_value("beta"); + beta1=beta; + beta2=beta; + } + else + { + beta1=f.get_param_value("beta1"); + beta2=f.get_param_value("beta2"); + } + //output the params + ofstream param_output("dbeta_param.txt"); + //output the datasets and fitting results + for(size_t i=0;i<f.get_num_params();++i) + { + if(f.get_param_info(i).get_name()=="rc1") + { + cerr<<"rc1_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + param_output<<"rc1_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + } + if(f.get_param_info(i).get_name()=="rc2") + { + cerr<<"rc2_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + param_output<<"rc2_kpc"<<"\t"<<abs(f.get_param_info(i).get_value())*cm_per_pixel/kpc<<endl; + } + cerr<<f.get_param_info(i).get_name()<<"\t"<<abs(f.get_param_info(i).get_value())<<endl; + param_output<<f.get_param_info(i).get_name()<<"\t"<<abs(f.get_param_info(i).get_value())<<endl; + } + cerr<<"reduced_chi^2="<<f.get_statistic_value()/(radii.size()-f.get_model().get_num_free_params())<<endl; + param_output<<"reduced_chi^2="<<f.get_statistic_value()/(radii.size()-f.get_model().get_num_free_params())<<endl; + + //c.verbose(false); + //f.set_statistic(c); + //f.fit(); + std::vector<double> p=f.get_all_params(); + f.clear_param_modifier(); + std::vector<double> mv=f.eval_model(radii,p); + + + ofstream ofs_sbp("sbp_fit.qdp"); + ofs_sbp<<"read serr 2"<<endl; + ofs_sbp<<"skip single"<<endl; + + ofs_sbp<<"line on 2"<<endl; + ofs_sbp<<"line on 3"<<endl; + ofs_sbp<<"line on 4"<<endl; + ofs_sbp<<"line on 5"<<endl; + ofs_sbp<<"line on 7"<<endl; + ofs_sbp<<"ls 2 on 7"<<endl; + ofs_sbp<<"ls 2 on 3"<<endl; + ofs_sbp<<"ls 2 on 4"<<endl; + ofs_sbp<<"ls 2 on 5"<<endl; + + + + ofs_sbp<<"!LAB POS Y 4.00"<<endl; + ofs_sbp<<"!LAB ROT"<<endl; + ofs_sbp<<"win 1"<<endl; + ofs_sbp<<"yplot 1 2 3 4 5"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .4 .9 .9"<<endl; + ofs_sbp<<"la y cnt/s/pixel/cm^2"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"log y"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[sbps.size()-2]+radii[sbps.size()-1])/2*cm_per_pixel/kpc<<endl; + ofs_sbp<<"win 2"<<endl; + ofs_sbp<<"yplot 6 7"<<endl; + ofs_sbp<<"loc 0 0 1 1"<<endl; + ofs_sbp<<"vie .1 .1 .9 .4"<<endl; + ofs_sbp<<"la x radius (kpc)"<<endl; + ofs_sbp<<"la y chi"<<endl; + ofs_sbp<<"log x"<<endl; + ofs_sbp<<"log y off"<<endl; + ofs_sbp<<"r x "<<(radii[1]+radii[0])/2*cm_per_pixel/kpc<<" "<<(radii[sbps.size()-2]+radii[sbps.size()-1])/2*cm_per_pixel/kpc<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + double y=sbps[i-1]; + double ye=sbpe[i-1]; + //double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<y<<"\t"<<ye<<endl; + } + ofs_sbp<<"no no no"<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + //double y=sbps[i-1]; + //double ye=sbpe[i-1]; + double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<ym<<"\t"<<0<<endl; + } + //bkg + ofs_sbp<<"no no no"<<endl; + bkg_level=abs(f.get_param_value("bkg")); + for(size_t i=0;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<bkg_level<<"\t0"<<endl; + } + //rc1 + ofs_sbp<<"no no no"<<endl; + double rc1_kpc=abs(f.get_param_value("rc1")*cm_per_pixel/kpc); + double max_sbp=*max_element(sbps.begin(),sbps.end()); + double min_sbp=*min_element(sbps.begin(),sbps.end()); + for(double x=min_sbp;x<=max_sbp;x+=(max_sbp-min_sbp)/100) + { + ofs_sbp<<rc1_kpc<<"\t"<<x<<"\t"<<"0"<<endl; + } + //rc2 + ofs_sbp<<"no no no"<<endl; + double rc2_kpc=abs(f.get_param_value("rc2")*cm_per_pixel/kpc); + for(double x=min_sbp;x<=max_sbp;x+=(max_sbp-min_sbp)/100) + { + ofs_sbp<<rc2_kpc<<"\t"<<x<<"\t"<<"0"<<endl; + } + //resid + ofs_sbp<<"no no no"<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + //double y=sbps[i-1]; + //double ye=sbpe[i-1]; + double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<(ym-sbps[i-1])/sbpe[i-1]<<"\t"<<1<<endl; + } + //zero level in resid map + ofs_sbp<<"no no no"<<endl; + for(size_t i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + //double y=sbps[i-1]; + //double ye=sbpe[i-1]; + //double ym=mv[i-1]; + ofs_sbp<<x*cm_per_pixel/kpc<<"\t"<<0<<"\t"<<0<<endl; + } + + + mv=f.eval_model_raw(radii,p); + ofstream ofs_rho("rho_fit.qdp"); + ofstream ofs_rho_data("rho_fit.dat"); + ofstream ofs_entropy("entropy.qdp"); + ofs_rho<<"la x radius (kpc)"<<endl; + ofs_rho<<"la y density (cm\\u-3\\d)"<<endl; + /* + for(int i=1;i<sbps.size();++i) + { + double x=(radii[i]+radii[i-1])/2; + double ym=mv[i-1]; + ofs_rho<<x*cm_per_pixel/kpc<<"\t"<<ym<<endl; + } + */ + + //double lower,upper; + double dr=1; + //calculate the mass profile + //const double G=6.673E-8;//cm^3 g^-1 s^-2 + // Molecular weight per electron + // Reference: Ettori et al. 2013, Space Sci. Rev., 177, 119-154; Eq.(9) below + static const double mu=1.155; + static const double mp=1.67262158E-24;//g + static const double M_sun=1.98892E33;//g + //static const double k=1.38E-16; + + ofstream ofs_mass("mass_int.qdp"); + ofstream ofs_mass_dat("mass_int.dat"); + ofstream ofs_overdensity("overdensity.qdp"); + ofstream ofs_gas_mass("gas_mass_int.qdp"); + //ofs_mass<<"la x radius (kpc)"<<endl; + //ofs_mass<<"la y mass enclosed (solar mass)"<<endl; + //ofs_overdensity<<"la x radius (kpc)"<<endl; + //ofs_overdensity<<"la y overdensity"<<endl; + double gas_mass=0; + for(double r=1;r<200000;r+=dr) + { + dr=r/100; + double r1=r+dr; + double r_cm=r*cm_per_pixel; + double r1_cm=r1*cm_per_pixel; + double dr_cm=dr*cm_per_pixel; + double V_cm3=4./3.*pi*(dr_cm*(r1_cm*r1_cm+r_cm*r_cm+r_cm*r1_cm)); + double ne=dbeta_func(r,n01,rc1,beta1, + n02,rc2,beta2);//cm^3 + + double dmgas=V_cm3*ne*mu*mp/M_sun; + gas_mass+=dmgas; + + ofs_gas_mass<<r*cm_per_pixel/kpc<<"\t"<<gas_mass<<endl; + double ne_beta1=dbeta_func(r,n01,rc1,beta1, 0,rc2,beta2); + + double ne_beta2=dbeta_func(r,0,rc1,beta1, n02,rc2,beta2); + + double ne1=dbeta_func(r1,n01,rc1,beta1, n02,rc2,beta2);//cm^3 + + double T_keV=Tprof(r); + double T1_keV=Tprof(r1); + + //double T_K=T_keV*11604505.9; + //double T1_K=T1_keV*11604505.9; + + double dlnT=log(T1_keV/T_keV); + double dlnr=log(r+dr)-log(r); + double dlnn=log(ne1/ne); + + //double r_kpc=r_cm/kpc; + double r_Mpc=r_cm/Mpc; + //double M=-r_cm*T_K*k/G/mu/mp*(dlnT/dlnr+dlnn/dlnr); + //ref:http://adsabs.harvard.edu/abs/2012MNRAS.422.3503W + //Walker et al. 2012 + double M=-3.68E13*M_sun*T_keV*r_Mpc*(dlnT/dlnr+dlnn/dlnr); + double rho=M/(4./3.*pi*r_cm*r_cm*r_cm); + + double S=T_keV/pow(ne,2./3.); + //cout<<r<<"\t"<<M/M_sun<<endl; + //cout<<r<<"\t"<<T_keV<<endl; + + ofs_rho<<r*cm_per_pixel/kpc<<"\t"<<ne<<"\t"<<ne_beta1<<"\t"<<ne_beta2<<endl; + ofs_rho_data<<r*cm_per_pixel/kpc<<"\t"<<ne<<endl; + ofs_entropy<<r*cm_per_pixel/kpc<<"\t"<<S<<endl; +#if 0 + if(r*cm_per_pixel/kpc<5) + { + continue; + } +#endif + ofs_mass<<r*cm_per_pixel/kpc<<"\t"<<M/M_sun<<endl; + if(r<radii.back()) + { + ofs_mass_dat<<r*cm_per_pixel/kpc<<"\t0\t"<<M/M_sun<<"\t"<<M/M_sun*.1<<endl; + } + ofs_overdensity<<r*cm_per_pixel/kpc<<"\t"<<rho/calc_critical_density(z)<<endl; + + } +} diff --git a/src/fit_nfw_mass.cpp b/src/fit_nfw_mass.cpp new file mode 100644 index 0000000..fae74ef --- /dev/null +++ b/src/fit_nfw_mass.cpp @@ -0,0 +1,159 @@ +/* + Fitting nfw mass profile model + Author: Junhua Gu + Last modification 20120721 +*/ + +#include "nfw.hpp" +#include <core/optimizer.hpp> +#include <core/fitter.hpp> +#include <data_sets/default_data_set.hpp> +#include "chisq.hpp" +#include <methods/powell/powell_method.hpp> +#include <iostream> +#include <fstream> +#include <vector> +#include <string> + +using namespace opt_utilities; +using namespace std; +const double cm=1; +const double kpc=3.08568e+21*cm; +const double pi=4*atan(1); +static double calc_critical_density(double z, + const double H0=2.3E-18, + const double Omega_m=.27) +{ + const double G=6.673E-8;//cm^3 g^-1 s^2 + const double E=std::sqrt(Omega_m*(1+z)*(1+z)*(1+z)+1-Omega_m); + const double H=H0*E; + return 3*H*H/8/pi/G; +} + + +int main(int argc,char* argv[]) +{ + if(argc<3) + { + cerr<<"Usage:"<<argv[0]<<" <data file with 4 columns of x, xe, y, ye> <z> [rmin in kpc]"<<endl; + return -1; + } + double rmin_kpc=1; + if(argc>=4) + { + rmin_kpc=atof(argv[3]); + } + double z=0; + z=atof(argv[2]); + //define the fitter + fitter<double,double,vector<double>,double,std::string> fit; + //define the data set + default_data_set<double,double> ds; + //open the data file + ifstream ifs(argv[1]); + //cout<<"read serr 2"<<endl; + ofstream ofs_fit_result("nfw_fit_result.qdp"); + + ofs_fit_result<<"read serr 1 2"<<endl; + ofs_fit_result<<"skip single"<<endl; + ofs_fit_result<<"line off"<<endl; + ofs_fit_result<<"li on 2"<<endl; + ofs_fit_result<<"li on 4"<<endl; + ofs_fit_result<<"ls 2 on 4"<<endl; + + ofs_fit_result<<"win 1"<<endl; + ofs_fit_result<<"yplot 1 2"<<endl; + ofs_fit_result<<"loc 0 0 1 1"<<endl; + ofs_fit_result<<"vie .1 .4 .9 .9"<<endl; + ofs_fit_result<<"la y Mass (solar)"<<endl; + ofs_fit_result<<"log x"<<endl; + ofs_fit_result<<"log y"<<endl; + ofs_fit_result<<"win 2"<<endl; + ofs_fit_result<<"yplot 3 4"<<endl; + ofs_fit_result<<"loc 0 0 1 1"<<endl; + ofs_fit_result<<"vie .1 .1 .9 .4"<<endl; + ofs_fit_result<<"la x radius (kpc)"<<endl; + ofs_fit_result<<"la y chi"<<endl; + ofs_fit_result<<"log x"<<endl; + ofs_fit_result<<"log y off"<<endl; + for(;;) + { + //read radius, temperature and error + double r,re,m,me; + ifs>>r>>re>>m>>me; + if(!ifs.good()) + { + break; + } + if(r<rmin_kpc) + { + continue; + } + data<double,double> d(r,m,me,me,re,re); + ofs_fit_result<<r<<"\t"<<re<<"\t"<<m<<"\t"<<me<<endl; + ds.add_data(d); + } + ofs_fit_result<<"no no no"<<endl; + //load data + fit.load_data(ds); + //define the optimization method + fit.set_opt_method(powell_method<double,vector<double> >()); + //use chi^2 statistic + fit.set_statistic(chisq<double,double,vector<double>,double,std::string>()); + fit.set_model(nfw<double>()); + //fit.set_param_value("rs",4); + //fit.set_param_value("rho0",100); + fit.fit(); + fit.fit(); + vector<double> p=fit.fit(); + //output parameters + ofstream ofs_param("nfw_param.txt"); + for(size_t i=0;i<fit.get_num_params();++i) + { + cout<<fit.get_param_info(i).get_name()<<"\t"<<fit.get_param_info(i).get_value()<<endl; + ofs_param<<fit.get_param_info(i).get_name()<<"\t"<<fit.get_param_info(i).get_value()<<endl; + } + cout<<"reduced chi^2="<<fit.get_statistic_value()<<endl; + ofs_param<<"reduced chi^2="<<fit.get_statistic_value()<<endl; + ofstream ofs_model("nfw_dump.qdp"); + ofstream ofs_overdensity("overdensity.qdp"); + //const double G=6.673E-8;//cm^3 g^-1 s^-2 + //static const double mu=1.4074; + //static const double mp=1.67262158E-24;//g + static const double M_sun=1.98892E33;//g + //static const double k=1.38E-16; + + double xmax=0; + for(double x=std::max(rmin_kpc,ds.get_data(0).get_x());;x+=1) + { + double model_value=fit.eval_model(x,p); + ofs_model<<x<<"\t"<<model_value<<endl; + ofs_fit_result<<x<<"\t0\t"<<model_value<<"\t0"<<endl; + double V=4./3.*pi*pow(x*kpc,3); + double m=model_value*M_sun; + double rho=m/V;//g/cm^3 + double over_density=rho/calc_critical_density(z); + ofs_overdensity<<x<<"\t"<<over_density<<endl; + xmax=x; + if(over_density<100) + { + break; + } + } + ofs_fit_result<<"no no no"<<endl; + for(size_t i=0;i<ds.size();++i) + { + data<double,double> d=ds.get_data(i); + double x=d.get_x(); + double y=d.get_y(); + double ye=d.get_y_lower_err(); + double ym=fit.eval_model(x,p); + ofs_fit_result<<x<<"\t"<<0<<"\t"<<(y-ym)/ye<<"\t"<<1<<endl; + } + ofs_fit_result<<"no no no"<<endl; + for(double x=std::max(rmin_kpc,ds.get_data(0).get_x());x<xmax;x+=1) + { + ofs_fit_result<<x<<"\t"<<0<<"\t"<<0<<"\t"<<0<<endl; + } + +} diff --git a/src/fit_wang2012_model.cpp b/src/fit_wang2012_model.cpp new file mode 100644 index 0000000..f15a2b1 --- /dev/null +++ b/src/fit_wang2012_model.cpp @@ -0,0 +1,195 @@ +/* + Fitting Jy Wang's temperature profile model + Author: Jingying Wang + Last modification 20120819 + +*/ + +#include "wang2012_model.hpp" +#include <core/optimizer.hpp> +#include <core/fitter.hpp> +#include <data_sets/default_data_set.hpp> +#include "chisq.hpp" +#include <methods/powell/powell_method.hpp> +#include <core/freeze_param.hpp> +#include <iostream> +#include <fstream> +#include <vector> +#include <string> + +using namespace opt_utilities; +using namespace std; +const double cm=1; +const double kpc=3.08568e+21*cm; + +int main(int argc,char* argv[]) +{ + if(argc<2) + { + cerr<<"Usage:"<<argv[0]<<" <data file with 4 columns of x, xe, y, ye> [param file] [cm per pixel]"<<endl; + return -1; + } + double cm_per_pixel=-1; + if(argc>=4) + { + cm_per_pixel=atof(argv[3]); + } + + //define the fitter + fitter<double,double,vector<double>,double,std::string> fit; + //define the data set + default_data_set<double,double> ds; + //open the data file + ifstream ifs(argv[1]); + double min_r=1e9; + //cout<<"read serr 2"<<endl; + ofstream ofs_fit_result("fit_result.qdp"); + ofs_fit_result<<"read serr 1 2"<<endl; + ofs_fit_result<<"skip single"<<endl; + if(cm_per_pixel>0) + { + ofs_fit_result<<"la x radius (kpc)"<<endl; + } + else + { + ofs_fit_result<<"la x radius (pixel)"<<endl; + } + ofs_fit_result<<"la y temperature (keV)"<<endl; + for(;;) + { + //read radius, temperature and error + double r,re,t,te; + ifs>>r>>re>>t>>te; + if(!ifs.good()) + { + break; + } + min_r=min(r,min_r); + data<double,double> d(r,t,te,te,re,re); + //std::cerr<<r<<"\t"<<t<<"\t"<<te<<endl; + if(cm_per_pixel>0) + { + ofs_fit_result<<r*cm_per_pixel/kpc<<"\t"<<re*cm_per_pixel/kpc<<"\t"<<t<<"\t"<<te<<endl; + } + else + { + ofs_fit_result<<r<<"\t"<<re<<"\t"<<t<<"\t"<<te<<endl; + } + ds.add_data(d); + } + ofs_fit_result<<"no no no"<<endl; + //load data + fit.load_data(ds); + //define the optimization method + fit.set_opt_method(powell_method<double,vector<double> >()); + //use chi^2 statistic + chisq<double,double,vector<double>,double,std::string> chisq_object; + chisq_object.set_limit(); + fit.set_statistic(chisq_object); + //fit.set_statistic(chisq<double,double,vector<double>,double,std::string>()); + fit.set_model(wang2012_model<double>()); + + if(argc>=3&&std::string(argv[2])!="NONE") + { + std::vector<std::string> freeze_list; + ifstream ifs_param(argv[2]); + assert(ifs_param.is_open()); + for(;;) + { + string pname; + double pvalue; + double lower,upper; + char param_status; + ifs_param>>pname>>pvalue>>lower>>upper>>param_status; + if(!ifs_param.good()) + { + break; + } + if(param_status=='F') + { + freeze_list.push_back(pname); + } + if(pvalue<=lower||pvalue>=upper) + { + cerr<<"Invalid initial value, central value not enclosed by the lower and upper boundaries, adjust automatically"<<endl; + pvalue=std::max(pvalue,lower); + pvalue=std::min(pvalue,upper); + } + fit.set_param_value(pname,pvalue); + fit.set_param_lower_limit(pname,lower); + fit.set_param_upper_limit(pname,upper); + } + if(!freeze_list.empty()) + { + freeze_param<double,double,std::vector<double>,std::string> fp(freeze_list[0]); + fit.set_param_modifier(fp); + for(size_t i=1;i<freeze_list.size();++i) + { + dynamic_cast<freeze_param<double,double,std::vector<double>,std::string>&>(fit.get_param_modifier())+=freeze_param<double,double,std::vector<double>,std::string>(freeze_list[i]); + } + } + } + + for(int i=0;i<100;++i) + { + fit.fit(); + } + vector<double> p=fit.fit(); +#if 0 + ofstream output_param; + if(argc>=3&&std::string(argv[2])!="NONE") + { + output_param.open(argv[2]); + } + else + { + output_param.open("para0.txt"); + } +#endif + //output parameters + for(size_t i=0;i<fit.get_num_params();++i) + { + std::string pname=fit.get_param_info(i).get_name(); + std::string pstatus=fit.get_model().report_param_status(pname); + + if(pstatus==""||pstatus=="thawed") + { + pstatus="T"; + } + else + { + pstatus="F"; + } + cout<<fit.get_param_info(i).get_name()<<"\t"<<fit.get_param_info(i).get_value()<<"\t"<<fit.get_param_info(i).get_lower_limit()<<"\t"<<fit.get_param_info(i).get_upper_limit()<<"\t"<<pstatus<<endl; + //if(argc>=3&&std::string(argv[2])!="NONE") +#if 0 + { + output_param<<fit.get_param_info(i).get_name()<<"\t"<<fit.get_param_info(i).get_value()<<"\t"<<fit.get_param_info(i).get_lower_limit()<<"\t"<<fit.get_param_info(i).get_upper_limit()<<"\t"<<pstatus<<endl; + } +#endif + } + + //cout<<"T0"<<"\t"<<fit.get_param_value("T0")<<endl; + //cout<<"T1"<<"\t"<<fit.get_param_value("T1")<<endl; + //cout<<"xt"<<"\t"<<fit.get_param_value("xt")<<endl; + //cout<<"eta"<<"\t"<<fit.get_param_value("eta")<<endl; + //dump the data for checking + ofstream ofs_model("wang2012_dump.qdp"); + + + min_r=0; + for(double x=min_r;x<3000;x+=10) + { + double model_value=fit.eval_model_raw(x,p); + + ofs_model<<x<<"\t"<<model_value<<endl; + if(cm_per_pixel>0) + { + ofs_fit_result<<x*cm_per_pixel/kpc<<"\t0\t"<<model_value<<"\t0"<<endl; + } + else + { + ofs_fit_result<<x<<"\t0\t"<<model_value<<"\t0"<<endl; + } + } +} diff --git a/src/nfw.hpp b/src/nfw.hpp new file mode 100644 index 0000000..8e3e59e --- /dev/null +++ b/src/nfw.hpp @@ -0,0 +1,56 @@ +/** + \file nfw.hpp + \brief Jingying Wang's model + \author Jingying Wang + */ + + +#ifndef NFW +#define NFW +#define OPT_HEADER +#include <core/fitter.hpp> +#include <cmath> + +namespace opt_utilities +{ + template <typename T> + class nfw + :public model<T,T,std::vector<T>,std::string> + { + private: + model<T,T,std::vector<T> >* do_clone()const + { + return new nfw<T>(*this); + } + + const char* do_get_type_name()const + { + return "1d power law"; + } + public: + nfw() + { + this->push_param_info(param_info<std::vector<T> >("rho0",1,0,1e99)); + this->push_param_info(param_info<std::vector<T> >("rs",100,0,1e99)); + } + + T do_eval(const T& r,const std::vector<T>& param) + { + T rho0=std::abs(param[0]); + T rs=std::abs(param[1]); + static const T pi=4*std::atan(1); + return 4*pi*rho0*rs*rs*rs*(std::log((r+rs)/rs)-r/(r+rs)); + } + + private: + std::string do_get_information()const + { + return ""; + } + }; +} + + + +#endif +//EOF diff --git a/src/projector.hpp b/src/projector.hpp new file mode 100644 index 0000000..4ef4b32 --- /dev/null +++ b/src/projector.hpp @@ -0,0 +1,214 @@ +#ifndef PROJ_HPP +#define PROJ_HPP +/* + Defining the class that is used to consider the projection effect + Author: Junhua Gu + Last modified: 2011.01.01 +*/ + + +#include <core/fitter.hpp> +#include <vector> +#include <cmath> + +static const double pi=4*atan(1); +// Ratio of the electron density (n_e) to the proton density (n_p) +// n_gas = n_e + n_p ~= 1.826 n_e => n_e / n_p ~= 1.21 +// Reference: Ettori et al. 2013, Space Sci. Rev., 177, 119-154; Eq.(9) below +static const double ne_np_ratio = 1.21; + +namespace opt_utilities +{ + //This is used to project a 3-D surface brightness model to 2-D profile + template <typename T> + class projector + :public model<std::vector<T>,std::vector<T>,std::vector<T> > + { + private: + //Points to a 3-D model that is to be projected + model<std::vector<T>,std::vector<T>,std::vector<T> >* pmodel; + func_obj<T,T>* pcfunc; + T cm_per_pixel; + public: + //default cstr + projector() + :pmodel(NULL_PTR),pcfunc(NULL_PTR),cm_per_pixel(1) + {} + //copy cstr + projector(const projector& rhs) + :cm_per_pixel(rhs.cm_per_pixel) + { + attach_model(*(rhs.pmodel)); + if(rhs.pcfunc) + { + pcfunc=rhs.pcfunc->clone(); + } + else + { + pcfunc=NULL_PTR; + } + } + //assign operator + projector& operator=(const projector& rhs) + { + cm_per_pixel=rhs.cm_per_pixel; + if(pmodel) + { + pmodel->destroy(); + } + if(pcfunc) + { + pcfunc->destroy(); + } + if(rhs.pcfunc) + { + pcfunc=rhs.pcfunc->clone(); + } + if(rhs.pmodel) + { + pmodel=rhs.pmodel->clone(); + } + } + //destr + ~projector() + { + if(pmodel) + { + pmodel->destroy(); + } + if(pcfunc) + { + pcfunc->destroy(); + } + } + //used to clone self + model<std::vector<T>,std::vector<T>,std::vector<T> >* + do_clone()const + { + return new projector(*this); + } + + public: + void set_cm_per_pixel(const T& x) + { + cm_per_pixel=x; + } + + //attach the model that is to be projected + void attach_model(const model<std::vector<T>,std::vector<T>,std::vector<T> >& m) + { + this->clear_param_info(); + for(size_t i=0;i<m.get_num_params();++i) + { + this->push_param_info(m.get_param_info(i)); + } + this -> push_param_info(param_info<std::vector<T>, + std::string>("bkg",0,0,1E99)); + pmodel=m.clone(); + pmodel->clear_param_modifier(); + } + + void attach_cfunc(const func_obj<T,T>& cf) + { + if(pcfunc) + { + pcfunc->destroy(); + } + pcfunc=cf.clone(); + } + + public: + //calc the volume + /* + This is a sphere that is subtracted by a cycline. + /| |\ + / | | \ + | | | | + | | | | + \ | | / + \| |/ + */ + T calc_v_ring(T rsph,T rcyc) + { + if(rcyc<rsph) + { + double a=rsph*rsph-rcyc*rcyc; + return 4.*pi/3.*std::sqrt(a*a*a); + } + return 0; + } + + //calc the No. nsph sphere's projection volume on the No. nrad pie region + T calc_v(const std::vector<T>& rlist,int nsph,int nrad) + { + if(nsph<nrad) + { + return 0; + } + else if(nsph==nrad) + { + return calc_v_ring(rlist[nsph+1], rlist[nrad]); + } + else { + return (calc_v_ring(rlist[nsph+1], rlist[nrad]) - + calc_v_ring(rlist[nsph], rlist[nrad]) - + calc_v_ring(rlist[nsph+1], rlist[nrad+1]) + + calc_v_ring(rlist[nsph], rlist[nrad+1])); + } + } + public: + bool do_meets_constraint(const std::vector<T>& p)const + { + std::vector<T> p1(this->reform_param(p)); + for(size_t i=0;i!=p1.size();++i) + { + if(get_element(p1,i)>this->get_param_info(i).get_upper_limit()|| + get_element(p1,i)<this->get_param_info(i).get_lower_limit()) + { + // std::cerr<<this->get_param_info(i).get_name()<<"\t"<<p1[i]<<std::endl; + return false; + } + } + std::vector<T> p2(p1.size()-1); + for(size_t i=0;i<p1.size()-1;++i) + { + p2.at(i)=p1[i]; + } + + return pmodel->meets_constraint(p2); + } + public: + //Perform the projection + std::vector<T> do_eval(const std::vector<T>& x,const std::vector<T>& p) + { + T bkg=std::abs(p.back()); + //I think following codes are clear enough :). + std::vector<T> unprojected(pmodel->eval(x,p)); + std::vector<T> projected(unprojected.size()); + + for(size_t nrad=0; nrad<x.size()-1; ++nrad) + { + for(size_t nsph=nrad; nsph<x.size()-1; ++nsph) + { + double v = calc_v(x, nsph, nrad) * pow(cm_per_pixel, 3); + if(pcfunc) + { + double cfunc = (*pcfunc)((x[nsph+1] + x[nsph]) / 2.0); + projected[nrad] += (unprojected[nsph] * unprojected[nsph] * + cfunc * v / ne_np_ratio); + } + else + { + projected[nrad] += unprojected[nsph] * unprojected[nsph] * v; + } + } + double area = pi * (x[nrad+1]*x[nrad+1] - x[nrad]*x[nrad]); + projected[nrad] /= area; + projected[nrad] += bkg; + } + return projected; + } + }; +}; + +#endif diff --git a/src/report_error.cpp b/src/report_error.cpp new file mode 100644 index 0000000..23e6a26 --- /dev/null +++ b/src/report_error.cpp @@ -0,0 +1,39 @@ +#include <iostream> + +using namespace std; +void report_error(const char* message) +{ + cerr<<"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"<<endl; + cerr<<"MMMMMMMMMMMM MMMMMMMMMMMM"<<endl; + cerr<<"MMMMMMMMMM MMMMMMMMMM"<<endl; + cerr<<"MMMMMMMMM MMMMMMMMM"<<endl; + cerr<<"MMMMMMMM MMMMMMMM"<<endl; + cerr<<"MMMMMMM MMMMMMMM"<<endl; + cerr<<"MMMMMMM MMMMMMM"<<endl; + cerr<<"MMMMMMM MMMMMMM"<<endl; + cerr<<"MMMMMMM MMM MMM MMMMMMM"<<endl; + cerr<<"MMMMMMM MMMMM MMMM MMMMMMM"<<endl; + cerr<<"MMMMMMM MMMMM MMMM MMMMMMM"<<endl; + cerr<<"MMMMMMMM MMMM M MMMM MMMMMMMM"<<endl; + cerr<<"MMMMMMMM M MMMMMMM"<<endl; + cerr<<"MMMMMMMM MMM MMMMMMMM"<<endl; + cerr<<"MMMMMMMMMMMM MMM MMMMMMMMMMMM"<<endl; + cerr<<"MMMMMMMMMM MM M MMMMMMMMM"<<endl; + cerr<<"MMMMMMMMMM M M M M M MMMMMMMMMM"<<endl; + cerr<<"MMMM MMMMM MMMMMMMMM MMMMM MM"<<endl; + cerr<<"MMM MMMM M MMMMM M MMMM MM"<<endl; + cerr<<"MMM MMMM M M M MMMMM MMM"<<endl; + cerr<<"MMMM MMMM MMM MM"<<endl; + cerr<<"MMM MMMM MMMM MM"<<endl; + cerr<<"MMM MMMMMMMM M MMM"<<endl; + cerr<<"MMMM MMM MMM MMMMMMMM"<<endl; + cerr<<"MMMMMMMMMMM MM MMMMMMM M"<<endl; + cerr<<"MMM MMMMMMM MMMMMMMMM M"<<endl; + cerr<<"MM MMM MM M"<<endl; + cerr<<"MM MMMM MM"<<endl; + cerr<<"MMM MMMMMMMMMMMMM M"<<endl; + cerr<<"MM MMMMMMMMMMMMMMMMMMM M"<<endl; + cerr<<"MMM MMMMMMMMMMMMMMMMMMMMMM M"<<endl; + cerr<<"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"<<endl; + cerr<<message<<endl; +} diff --git a/src/report_error.hpp b/src/report_error.hpp new file mode 100644 index 0000000..30607e5 --- /dev/null +++ b/src/report_error.hpp @@ -0,0 +1,6 @@ +#ifndef REPORT_ERR +#define REPORT_ERR + +void report_error(const char* message); + +#endif diff --git a/src/spline.hpp b/src/spline.hpp new file mode 100644 index 0000000..1027b61 --- /dev/null +++ b/src/spline.hpp @@ -0,0 +1,110 @@ +#ifndef SPLINE_HPP +#define SPLINE_HPP + +#include <vector> +#include <cstdlib> +#include <cassert> +#include <cmath> +#include <limits> + +template <typename T> +class spline +{ +public: + std::vector<T> x_list; + std::vector<T> y_list; + std::vector<T> y2_list; + +public: + void push_point(T x,T y) + { + if(!x_list.empty()) + { + assert(x>*(x_list.end()-1)); + } + x_list.push_back(x); + y_list.push_back(y); + } + + T get_value(T x) + { + if(x<=x_list[0]) + { + return y_list[0]; + } + if(x>=x_list.back()) + { + return y_list.back(); + } + assert(x_list.size()==y2_list.size()); + assert(x>x_list[0]); + assert(x<x_list.back()); + int n1,n2; + n1=0; + n2=x_list.size()-1; + while((n2-n1)!=1) + { + //cerr<<n1<<"\t"<<n2<<endl; + if(x_list[n1+1]<=x) + { + n1++; + } + if(x_list[n2-1]>x) + { + n2--; + } + } + T h=x_list[n2]-x_list[n1]; + double a=(x_list[n2]-x)/h; + double b=(x-x_list[n1])/h; + return a*y_list[n1]+b*y_list[n2]+((a*a*a-a)*y2_list[n1]+ + (b*b*b-b)*y2_list[n2])*(h*h)/6.; + + } + + void gen_spline(T y2_0,T y2_N) + { + int n=x_list.size(); + y2_list.resize(0); + y2_list.resize(x_list.size()); + std::vector<T> u(x_list.size()); + if(std::abs(y2_0)<std::numeric_limits<T>::epsilon()) + { + y2_list[0]=0; + u[0]=0; + } + else + { + y2_list[0]=-.5; + u[0]=(3./(x_list[1]-x_list[0]))*((y_list[1]-y_list[0])/(x_list[1]-x_list[0])-y2_0); + } + for(int i=1;i<n-1;++i) + { + double sig=(x_list[i]-x_list[i-1])/(x_list[i+1]-x_list[i-1]); + double p=sig*y2_list[i-1]+2.; + y2_list[i]=(sig-1.)/p; + u[i]=(y_list[i+1]-y_list[i])/(x_list[i+1]-x_list[i]) + -(y_list[i]-y_list[i-1])/(x_list[i]-x_list[i-1]); + u[i]=(6.*u[i]/(x_list[i+1]-x_list[i-1])-sig*u[i-1])/p; + } + double qn,un; + if(std::abs(y2_N)<std::numeric_limits<T>::epsilon()) + { + qn=un=0; + } + else + { + qn=.5; + un=(3./(x_list[n-1]-x_list[n-2]))*(y2_N-(y_list[n-1]-y_list[n-2])/(x_list[n-1]-x_list[n-2])); + + } + y2_list[n-1]=(un-qn*u[n-2])/(qn*y2_list[n-2]+1.); + for(int i=n-2;i>=0;--i) + { + y2_list[i]=y2_list[i]*y2_list[i+1]+u[i]; + } + } + +}; + +#endif /* SPLINE_HPP */ diff --git a/src/vchisq.hpp b/src/vchisq.hpp new file mode 100644 index 0000000..8cd8481 --- /dev/null +++ b/src/vchisq.hpp @@ -0,0 +1,137 @@ +/**
+ \file vchisq.hpp
+ \brief chi-square statistic
+ \author Junhua Gu
+ */
+
+#ifndef VCHI_SQ_HPP
+#define VCHI_SQ_HPP
+
+#define OPT_HEADER
+
+#include <core/fitter.hpp>
+#include <iostream>
+#include <vector>
+#include <misc/optvec.hpp>
+#include <cmath>
+
+using std::cerr;
+using std::endl;
+
+namespace opt_utilities
+{
+ template<typename T>
+ class vchisq
+ :public statistic<std::vector<T>,std::vector<T>,std::vector<T>,T,std::string>
+ {
+ private:
+ bool verb;
+ int n;
+ bool limit_bound;
+ typedef std::vector<T> Tp;
+
+ vchisq<T>* do_clone()const
+ {
+ return new vchisq<T>(*this);
+ }
+
+ const char* do_get_type_name()const
+ {
+ return "chi^2 statistic";
+ }
+
+ public:
+ void verbose(bool v)
+ {
+ verb=v;
+ }
+
+ void set_limit()
+ {
+ limit_bound=true;
+ }
+
+ void clear_limit()
+ {
+ limit_bound=false;
+ }
+ public:
+ vchisq()
+ :verb(false),limit_bound(false)
+ {}
+
+ T do_eval(const std::vector<T>& p)
+ {
+ if(limit_bound)
+ {
+ if(!this->get_fitter().get_model().meets_constraint(p))
+ {
+ return 1e99;
+ }
+ }
+ T result(0);
+ std::vector<float> vx;
+ std::vector<float> vy;
+ std::vector<float> vye;
+ std::vector<float> my;
+ float x1=1e99,x2=-1e99,y1=1e99,y2=-1e99;
+ if(verb)
+ {
+ n++;
+ if(n%100==0)
+ {
+ vx.resize(this->get_data_set().get_data(0).get_y().size());
+ vy.resize(this->get_data_set().get_data(0).get_y().size());
+ vye.resize(this->get_data_set().get_data(0).get_y().size());
+ my.resize(this->get_data_set().get_data(0).get_y().size());
+ }
+ }
+ for(int i=(this->get_data_set()).size()-1;i>=0;--i)
+ {
+ const std::vector<double> y_model(this->eval_model(this->get_data_set().get_data(i).get_x(),p));
+ const std::vector<double>& y=this->get_data_set().get_data(i).get_y();
+ const std::vector<double>& ye=this->get_data_set().get_data(i).get_y_lower_err();
+ for(size_t j=0;j<y.size();++j)
+ {
+ double chi=(y_model[j]-y[j])/ye[j];
+ result+=chi*chi;
+ }
+
+ if(verb&&n%100==0)
+ {
+ for(size_t j=0;j<y.size();++j)
+ {
+ vx.at(j)=((this->get_data_set().get_data(i).get_x().at(j)+this->get_data_set().get_data(i).get_x().at(j+1))/2.);
+ vy.at(j)=(y[j]);
+ vye.at(j)=ye[j];
+ my.at(j)=(y_model[j]);
+ x1=std::min(vx.at(j),x1);
+ y1=std::min(vy.at(j),y1);
+ x2=std::max(vx.at(j),x2);
+ y2=std::max(vy.at(j),y2);
+ vye[j]=log10(vy[j]+vye[j])-log10(vy[j]);
+ vx[j]=log10(vx[j]);
+ vy[j]=log10(vy[j]);
+ my[j]=log10(my[j]);
+ }
+ }
+ }
+ if(verb)
+ {
+ if(n%100==0)
+ {
+ cerr<<result<<"\t";
+ for(size_t i=0;i<get_size(p);++i)
+ {
+ cerr<<get_element(p,i)<<",";
+ }
+ cerr<<endl;
+ }
+ }
+
+ return result;
+ }
+ };
+
+}
+#endif
diff --git a/src/wang2012_model.hpp b/src/wang2012_model.hpp new file mode 100644 index 0000000..c678970 --- /dev/null +++ b/src/wang2012_model.hpp @@ -0,0 +1,67 @@ +/** + \file wang2012_model.hpp + \brief Jingying Wang's model + \author Jingying Wang + */ + + +#ifndef WANG2012_MODEL +#define WANG2012_MODEL +#define OPT_HEADER +#include <core/fitter.hpp> +#include <cmath> + +namespace opt_utilities +{ + template <typename T> + class wang2012_model + :public model<T,T,std::vector<T>,std::string> + { + private: + model<T,T,std::vector<T> >* do_clone()const + { + return new wang2012_model<T>(*this); + } + + const char* do_get_type_name()const + { + return "1d power law"; + } + public: + wang2012_model() + { + this->push_param_info(param_info<std::vector<T> >("A",5,0,500)); + this->push_param_info(param_info<std::vector<T> >("n",1.66,0,10)); + this->push_param_info(param_info<std::vector<T> >("xi",0.45,0,1)); + this->push_param_info(param_info<std::vector<T> >("a2",1500,0,1e8)); + this->push_param_info(param_info<std::vector<T> >("a3",50,0,1e8)); + this->push_param_info(param_info<std::vector<T> >("beta",0.49,0.1,0.7)); + this->push_param_info(param_info<std::vector<T> >("T0",0,0,10)); + + } + + T do_eval(const T& x,const std::vector<T>& param) + { + T A=param[0]; + T n=param[1]; + T xi=param[2]; + T a2=param[3]; + T a3=param[4]; + T beta=param[5]; + T T0=param[6]; + return A*(pow(x,n)+xi*a2)/(pow(x,n)+a2)/pow(1+x*x/a3/a3,beta)+T0; + //return A*(pow(x,n)+a1)/(pow(x,n)+1)/pow(1+x*x/a3/a3,beta)+T0; + } + + private: + std::string do_get_information()const + { + return ""; + } + }; +} + + + +#endif +//EOF |