mirror of
https://asciireactor.com/otho/industry-website.git
synced 2024-11-23 01:35:06 +00:00
495 lines
15 KiB
C++
495 lines
15 KiB
C++
|
#ifndef spectral_lines_hpp
|
||
|
#define spectral_lines_hpp
|
||
|
|
||
|
#include "agn.hpp"
|
||
|
//#include "png++-0.2.5/gray_pixel.hpp"
|
||
|
//#include "png++-0.2.5/image.hpp"
|
||
|
|
||
|
|
||
|
namespace agn {
|
||
|
|
||
|
const double EQWIDTH_MIN_VAL = 1E-7;
|
||
|
const double EQWIDTH_MIN_VAL_LOG = -7;
|
||
|
const double SIGMA_THRESHOLD_MULTIPLIER = 1.0;
|
||
|
const double RATIO_THRESHOLD_MULTIPLIER = .06;
|
||
|
|
||
|
typedef std::list<std::string> line_list;
|
||
|
line_list read_line_list(std::ifstream&);
|
||
|
|
||
|
// Trims whitespace from line labels
|
||
|
std::string label_trim(std::string);
|
||
|
|
||
|
// Emission line flux contours are represented by a singly-nested sorted map.
|
||
|
struct eqwidth_table {
|
||
|
std::string header[2];
|
||
|
table2d value;
|
||
|
};
|
||
|
bool is_zero(const eqwidth_table&);
|
||
|
eqwidth_table read_eqwidth_table(std::ifstream& table_file);
|
||
|
std::string format_eqwidth_table(eqwidth_table table);
|
||
|
std::string format_eqwidth_table_slice(eqwidth_table table,iterator2d x);
|
||
|
gridcoordlist find_outliers(eqwidth_table table);
|
||
|
gridcoordlist known_outliers();
|
||
|
eqwidth_table smooth(eqwidth_table&, gridcoordlist coordlist);
|
||
|
std::list<eqwidth_table> compile_eqwidth_tables(cloudy_grid,line_list,double = 1.0);
|
||
|
// Operator<< prints table formatted for a "fort file".
|
||
|
std::ostream& operator<< (std::ostream&,eqwidth_table);
|
||
|
|
||
|
} // end namespace agn
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Definitions
|
||
|
|
||
|
bool agn::is_zero(const eqwidth_table& table_to_check) {
|
||
|
agn::table2d::const_iterator x_it = table_to_check.value.begin();
|
||
|
while (x_it != table_to_check.value.end()) {
|
||
|
agn::table1d::const_iterator y_it= x_it->second.begin();
|
||
|
while (y_it != x_it->second.end()) {
|
||
|
if (y_it->second != EQWIDTH_MIN_VAL)
|
||
|
return false;
|
||
|
y_it++;
|
||
|
}
|
||
|
x_it++;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
agn::eqwidth_table agn::read_eqwidth_table(std::ifstream& table_file) {
|
||
|
agn::eqwidth_table resultant;
|
||
|
double hden, phi, flux;
|
||
|
int number_of_lines = 0;
|
||
|
std::string null;
|
||
|
while (std::getline(table_file, null))
|
||
|
++number_of_lines;
|
||
|
int table_entries = number_of_lines - 2;
|
||
|
table_file.clear();
|
||
|
table_file.seekg(0);
|
||
|
getline(table_file,resultant.header[0]);
|
||
|
getline(table_file,resultant.header[1]);
|
||
|
for (int i=0; i<table_entries; i++) {
|
||
|
table_file >> hden >> phi >> flux;
|
||
|
resultant.value[hden][phi]=flux;
|
||
|
}
|
||
|
return resultant;
|
||
|
}
|
||
|
|
||
|
std::string agn::format_eqwidth_table(agn::eqwidth_table table) {
|
||
|
std::stringstream output;
|
||
|
output
|
||
|
<< table.header[0]
|
||
|
<< "\n"
|
||
|
<< table.header[1]
|
||
|
<< "\n";
|
||
|
agn::iterator2d hden_it = table.value.begin();
|
||
|
while(hden_it != table.value.end()) {
|
||
|
agn::iterator1d phi_it = table.value[hden_it->first].begin();
|
||
|
while(phi_it != table.value[hden_it->first].end()) {
|
||
|
output
|
||
|
<< std::fixed
|
||
|
<< std::setprecision(3)
|
||
|
<< hden_it->first
|
||
|
<< " "
|
||
|
<< phi_it->first
|
||
|
<< " "
|
||
|
<< std::scientific
|
||
|
<< std::setprecision(4)
|
||
|
<< phi_it->second
|
||
|
<< "\n";
|
||
|
phi_it++;
|
||
|
}
|
||
|
hden_it++;
|
||
|
}
|
||
|
return output.str();
|
||
|
}
|
||
|
|
||
|
std::string agn::format_eqwidth_table_slice(agn::eqwidth_table table,agn::iterator2d fixed) {
|
||
|
std::stringstream output("");
|
||
|
// output
|
||
|
// << table.header[0]
|
||
|
// << " - constant="
|
||
|
// << fixed->first
|
||
|
// << "\n";
|
||
|
iterator1d x=fixed->second.begin();
|
||
|
while(x!=fixed->second.end()) {
|
||
|
output
|
||
|
<< std::fixed
|
||
|
<< std::setprecision(3)
|
||
|
<< x->first
|
||
|
<< "\t"
|
||
|
<< std::scientific
|
||
|
<< std::setprecision(4)
|
||
|
<< x->second
|
||
|
<< "\n";
|
||
|
x++;
|
||
|
}
|
||
|
return output.str();
|
||
|
}
|
||
|
|
||
|
|
||
|
std::ostream& agn::operator<< ( std::ostream& outstream,
|
||
|
agn::eqwidth_table table) {
|
||
|
std::string header0_trimmed = agn::label_trim(table.header[0]);
|
||
|
outstream
|
||
|
<< header0_trimmed
|
||
|
<< std::endl
|
||
|
<< table.header[1]
|
||
|
<< std::endl;
|
||
|
agn::table2d::iterator x_it = table.value.begin();
|
||
|
while (x_it != table.value.end()) {
|
||
|
agn::table1d::iterator y_it= x_it->second.begin();
|
||
|
while (y_it != x_it->second.end()) {
|
||
|
outstream.width(6);
|
||
|
outstream
|
||
|
<< std::fixed
|
||
|
<< std::setprecision(3)
|
||
|
<< x_it->first
|
||
|
<< "\t"
|
||
|
<< y_it->first
|
||
|
<< "\t"
|
||
|
<< std::scientific
|
||
|
<< std::setprecision(4)
|
||
|
<< y_it->second
|
||
|
<< "\n";
|
||
|
y_it++;
|
||
|
}
|
||
|
x_it++;
|
||
|
}
|
||
|
return outstream;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Returns a table as the difference between two tables
|
||
|
//agn::eqwidth_table main(int argc, char const *argv[])
|
||
|
//{ // Copied from fortfile subtractor
|
||
|
// std::ifstream table1;
|
||
|
// table1.open(argv[1]);
|
||
|
// std::ifstream table2;
|
||
|
// table2.open(argv[2]);
|
||
|
//
|
||
|
// std::string line;
|
||
|
//
|
||
|
// int table1_numlines = 0;
|
||
|
// while (std::getline(table1, line))
|
||
|
// ++table1_numlines;
|
||
|
// table1.clear();
|
||
|
// table1.seekg(0);
|
||
|
//
|
||
|
// int table_entries = table1_numlines - 2;
|
||
|
//
|
||
|
//// int table2_numlines = 0;
|
||
|
//// while (std::getline(table1, line))
|
||
|
//// ++table2_numlines;
|
||
|
////
|
||
|
//// int table2_entries = table2_numlines - 2;
|
||
|
//// table2.clear();
|
||
|
//// table2.seekg(0);
|
||
|
//
|
||
|
// double hden1[table_entries];
|
||
|
// double phi1[table_entries];
|
||
|
// double magnitude1[table_entries];
|
||
|
// double resultant_magnitude[table_entries];
|
||
|
//
|
||
|
// std::string first_line, second_line, scratch;
|
||
|
// getline(table1,first_line);
|
||
|
// getline(table1,second_line);
|
||
|
// getline(table2,scratch);
|
||
|
// getline(table2,scratch);
|
||
|
//
|
||
|
// first_line[0] = argv[3][0];
|
||
|
// first_line[1] = argv[3][1];
|
||
|
// first_line[2] = argv[3][2];
|
||
|
// first_line[3] = argv[3][3];
|
||
|
//
|
||
|
// for (int i=0; i<table_entries; i++) {
|
||
|
// table1 >> hden1[i] >> phi1[i] >> magnitude1 [i];
|
||
|
// }
|
||
|
//
|
||
|
//
|
||
|
// int i=0;
|
||
|
// double hden2, phi2, magnitude2;
|
||
|
// for (int i=0; i<table_entries; i++) {
|
||
|
// if ( table2.eof() ) {
|
||
|
// resultant_magnitude[i]=magnitude1[i];
|
||
|
// }
|
||
|
// else {
|
||
|
// table2 >> hden2 >> phi2 >> magnitude2;
|
||
|
// resultant_magnitude[i] = magnitude1[i] - magnitude2;
|
||
|
// }
|
||
|
// if ( resultant_magnitude[i] < 1e-10 )
|
||
|
// resultant_magnitude[i]=1e-10;
|
||
|
// }
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
// std::cout
|
||
|
// << first_line
|
||
|
// << std::endl
|
||
|
// //<< "HDen Phi(H) ScaInten"
|
||
|
// << second_line
|
||
|
// << std::endl;
|
||
|
//
|
||
|
// for (int i=0; i<table_entries; i++) {
|
||
|
// std::cout
|
||
|
// << std::fixed
|
||
|
// << std::setprecision(3)
|
||
|
// << hden1[i]
|
||
|
// << " "
|
||
|
// << phi1[i]
|
||
|
// << " "
|
||
|
// << std::scientific
|
||
|
// << std::setprecision(4)
|
||
|
// << resultant_magnitude[i]
|
||
|
// << std::endl;
|
||
|
// }
|
||
|
//
|
||
|
// table1.close();
|
||
|
// table2.close();
|
||
|
// return 0;
|
||
|
//}
|
||
|
|
||
|
|
||
|
agn::line_list agn::read_line_list(std::ifstream& inputfile) {
|
||
|
line_list list;
|
||
|
line_list nfnulist;
|
||
|
line_list inwtlist;
|
||
|
line_list inwclist;
|
||
|
inputfile.clear();
|
||
|
inputfile.seekg(0);
|
||
|
std::string line,label;
|
||
|
while(!inputfile.eof()) {
|
||
|
getline(inputfile,line);
|
||
|
if (line[0] == '#' || line.size() < 2) continue;
|
||
|
if (line[0] == ' ' && line[1] == ' ') continue;
|
||
|
if (line[0] == ' ')
|
||
|
label = line.substr(1,agn::LABELSTR_LEN);
|
||
|
else
|
||
|
label = line.substr(0,agn::LABELSTR_LEN);
|
||
|
// above is only good for c17?
|
||
|
if(agn::debug) std::cout
|
||
|
<< "Adding label "
|
||
|
<< label
|
||
|
<< " to capture list.\n";
|
||
|
std::string applabel = label.substr(4);
|
||
|
if (label.substr(0,4).compare(std::string("nFnu")) == 0) {
|
||
|
nfnulist.push_back(std::string("nFnu").append(applabel));
|
||
|
//list.push_back(std::string("nInu").append(applabel));
|
||
|
inwtlist.push_back(std::string("InwT").append(applabel));
|
||
|
inwclist.push_back(std::string("InwC").append(applabel));
|
||
|
continue;
|
||
|
}
|
||
|
list.push_back(label);
|
||
|
//if (label.substr(0,4) != "Inci" && applabel != " 0 ")
|
||
|
// list.push_back(std::string("Inwd").append(applabel));
|
||
|
}
|
||
|
list.insert(list.end(),nfnulist.begin(),nfnulist.end());
|
||
|
list.insert(list.end(),inwtlist.begin(),inwtlist.end());
|
||
|
list.insert(list.end(),inwclist.begin(),inwclist.end());
|
||
|
return list;
|
||
|
}
|
||
|
|
||
|
|
||
|
std::list<agn::eqwidth_table> agn::compile_eqwidth_tables(agn::cloudy_grid grid,agn::line_list line_labels,double scale_factor) {
|
||
|
std::list<eqwidth_table> table_list_eq_width,table_list_radiated_energy;
|
||
|
agn::line_list::iterator line_label_it = line_labels.begin();
|
||
|
// Iterate over labels, creating table for each:
|
||
|
while (line_label_it != line_labels.end()) {
|
||
|
double x,y;
|
||
|
agn::cloudy_line_data data;
|
||
|
agn::eqwidth_table new_table;
|
||
|
std::string label = *line_label_it;
|
||
|
if(agn::debug) std::cout
|
||
|
<< "Processing label "
|
||
|
<< label
|
||
|
<< std::endl;
|
||
|
std::stringstream header0;
|
||
|
header0
|
||
|
<< label;
|
||
|
new_table.header[0] = header0.str();
|
||
|
new_table.header[1] = "Hden Phi(H) F(line)/Inci(1215) ";
|
||
|
agn::cloudy_grid::iterator result_it = grid.begin();
|
||
|
while (result_it != grid.end()) {
|
||
|
x = result_it->first.first;
|
||
|
y = result_it->first.second;
|
||
|
// if no data exist under this label, initialize some:
|
||
|
if ( result_it->second.intrinsic_line_intensity.count(label) == 0 ) {
|
||
|
data.radiated_energy=-35.0;
|
||
|
data.eq_width=0.0;
|
||
|
}
|
||
|
else {
|
||
|
data = result_it->second.intrinsic_line_intensity[label];
|
||
|
data.eq_width /= scale_factor;
|
||
|
if(agn::line_debug) std::cout
|
||
|
<< "Added "
|
||
|
<< std::setprecision(2)
|
||
|
<< std::fixed
|
||
|
<< x
|
||
|
<< ", "
|
||
|
<< y
|
||
|
<< " -- "
|
||
|
<< std::scientific
|
||
|
<< data.radiated_energy
|
||
|
<< ", "
|
||
|
<< data.eq_width
|
||
|
<< "\n";
|
||
|
if ( data.has_duplicates ) {
|
||
|
// This needs to be expanded to catch all duplicate values j=1,2,etc.
|
||
|
// For now, just blindly use the value the program finds...
|
||
|
// the functionality is written in the agn.hpp sections, but is not
|
||
|
// implemented here, and as of 2017, the agn.hpp function writes the
|
||
|
// last-encountered instance of the emission line value to the label
|
||
|
// probably needs to be fixed for the inwd part too
|
||
|
}
|
||
|
}
|
||
|
if ( data.radiated_energy < EQWIDTH_MIN_VAL_LOG || data.eq_width < EQWIDTH_MIN_VAL) {
|
||
|
data.radiated_energy = EQWIDTH_MIN_VAL_LOG;
|
||
|
data.eq_width = EQWIDTH_MIN_VAL;
|
||
|
}
|
||
|
new_table.value[x][y] = data.eq_width;
|
||
|
result_it++;
|
||
|
}
|
||
|
table_list_eq_width.push_back(new_table);
|
||
|
// Add inward table for emission lines, and only works for c17
|
||
|
if (label.substr(agn::LABELSTR_POS,4) != "Inci" &&
|
||
|
label.substr(agn::LABELSTR_POS,4) != "FeKa" &&
|
||
|
//label.substr(agn::LABELSTR_POS,4) != "Blnd" &&
|
||
|
label.substr(agn::LABELSTR_POS,3) != "nFn" &&
|
||
|
label.substr(agn::LABELSTR_POS,3) != "Inw" &&
|
||
|
label.substr(LABELSTR_LEN - 14) != " 0 ") {
|
||
|
// These lines are known to not have inward fractions, so
|
||
|
// should be skipped.
|
||
|
if (label == "Blnd 1657.00A" ||
|
||
|
label == "Blnd 2326.00A" ||
|
||
|
label == "Blnd 2798.00A" ||
|
||
|
label == "Blnd 1335.00A" ||
|
||
|
label == "Blnd 977.000A" ||
|
||
|
label == "Blnd 1909.00A" ||
|
||
|
label == "Blnd 1176.00A" ||
|
||
|
label == "Blnd 2141.00A" ||
|
||
|
label == "Blnd 1085.00A" ||
|
||
|
label == "Blnd 1750.00A" ||
|
||
|
label == "Blnd 990.000A" ||
|
||
|
label == "Blnd 1486.00A" ||
|
||
|
label == "Blnd 765.000A" ||
|
||
|
label == "Blnd 1304.00A" ||
|
||
|
label == "Blnd 8446.00A" ||
|
||
|
label == "Blnd 1666.00A" ||
|
||
|
label == "Blnd 835.000A" ||
|
||
|
label == "Blnd 1402.00A" ||
|
||
|
label == "Blnd 630.000A" ||
|
||
|
label == "Blnd 1218.00A" ||
|
||
|
label == "Blnd 774.000A" ||
|
||
|
label == "Blnd 5892.00A" ||
|
||
|
label == "Blnd 615.000A" ||
|
||
|
label == "Blnd 2665.00A" ||
|
||
|
label == "Blnd 1860.00A" ||
|
||
|
label == "Blnd 2335.00A" ||
|
||
|
label == "Blnd 1888.00A" ||
|
||
|
label == "Blnd 1397.00A" ||
|
||
|
label == "Blnd 1256.00A" ||
|
||
|
label == "Blnd 1720.00A" ||
|
||
|
label == "Blnd 1198.00A" ||
|
||
|
label == "Blnd 1406.00A" ||
|
||
|
label == "Blnd 1199.00A" ||
|
||
|
label == "Blnd 8579.00A" ||
|
||
|
label == "Blnd 3933.00A"
|
||
|
) {
|
||
|
line_label_it++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if(agn::debug) std::cout
|
||
|
<< "Processing Inwd for label "
|
||
|
<< label
|
||
|
<< std::endl;
|
||
|
std::stringstream inwdheader0;
|
||
|
agn::eqwidth_table inwd_table;
|
||
|
inwdheader0
|
||
|
<< "Inwd "
|
||
|
<< label.substr(5);
|
||
|
inwd_table.header[0] = inwdheader0.str();
|
||
|
inwd_table.header[1] = "Hden Phi(H) F(line)/Inci(1215)";
|
||
|
result_it = grid.begin();
|
||
|
agn::cloudy_line_data inwddata;
|
||
|
while (result_it != grid.end()) {
|
||
|
x = result_it->first.first;
|
||
|
y = result_it->first.second;
|
||
|
// if no data exist under this label, initialize some:
|
||
|
if ( result_it->second.intrinsic_line_inward_intensity.count(label) == 0 ) {
|
||
|
inwddata.radiated_energy=-35.0;
|
||
|
inwddata.eq_width=0.0;
|
||
|
}
|
||
|
else {
|
||
|
inwddata = result_it->second.intrinsic_line_inward_intensity[label];
|
||
|
inwddata.eq_width /= scale_factor;
|
||
|
}
|
||
|
if(agn::line_debug) std::cout
|
||
|
<< "Added "
|
||
|
<< std::setprecision(2)
|
||
|
<< std::fixed
|
||
|
<< x
|
||
|
<< ", "
|
||
|
<< y
|
||
|
<< " -- "
|
||
|
<< std::scientific
|
||
|
<< inwddata.radiated_energy
|
||
|
<< ", "
|
||
|
<< inwddata.eq_width
|
||
|
<< "\n";
|
||
|
if ( inwddata.has_duplicates ) {
|
||
|
// This needs to be expanded to catch all duplicate values j=1,2,etc.
|
||
|
// For now, just blindly use the value the program finds...
|
||
|
// the functionality is written in the agn.hpp sections, but is not
|
||
|
// implemented here, and as of 2017, the agn.hpp function writes the
|
||
|
// last-encountered instance of the emission line value to the label
|
||
|
// probably needs to be fixed for the inwd part too
|
||
|
}
|
||
|
if ( inwddata.radiated_energy < EQWIDTH_MIN_VAL_LOG ||
|
||
|
inwddata.eq_width < EQWIDTH_MIN_VAL) {
|
||
|
inwddata.radiated_energy = EQWIDTH_MIN_VAL_LOG;
|
||
|
inwddata.eq_width = EQWIDTH_MIN_VAL;
|
||
|
}
|
||
|
inwd_table.value[x][y] = inwddata.eq_width;
|
||
|
result_it++;
|
||
|
}
|
||
|
table_list_eq_width.push_back(inwd_table);
|
||
|
}
|
||
|
line_label_it++;
|
||
|
}
|
||
|
return table_list_eq_width;
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif
|