6 #include "EDILexer.hpp"
7 #include "EDIParser.hpp"
21 #include <boost/filesystem/operations.hpp>
22 #include <boost/filesystem/convenience.hpp>
23 #include <boost/algorithm/string.hpp>
24 #include <boost/bind.hpp>
25 #include <boost/tokenizer.hpp>
37 boost::filesystem::path p(name);
38 name = p.stem().string();
41 void MTStation::InitialSetup()
49 MTStation::MTStation()
54 MTStation::~MTStation()
58 MTStation::MTStation(
const std::string filename)
64 MTStation::MTStation(
const int size) :
90 void MTStation::DoRotate(
const int i,
const double angle)
92 dcomp newxx, newxy, newyx, newyy;
93 newxx = MTData.at(i).Zxx * std::pow(cos(angle), 2)
94 + (MTData.at(i).Zxy + MTData.at(i).Zyx) * sin(angle) * cos(angle)
95 + MTData.at(i).Zyy * std::pow(sin(angle), 2);
96 newxy = MTData.at(i).Zxy * std::pow(cos(angle), 2)
97 - (MTData.at(i).Zxx - MTData.at(i).Zyy) * sin(angle) * cos(angle)
98 - MTData.at(i).Zyx * std::pow(sin(angle), 2);
99 newyx = MTData.at(i).Zyx * std::pow(cos(angle), 2)
100 - (MTData.at(i).Zxx - MTData.at(i).Zyy) * sin(angle) * cos(angle)
101 - MTData.at(i).Zxy * std::pow(sin(angle), 2);
102 newyy = MTData.at(i).Zyy * std::pow(cos(angle), 2)
103 - (MTData.at(i).Zxy + MTData.at(i).Zyx) * sin(angle) * cos(angle)
104 + MTData.at(i).Zxx * std::pow(sin(angle), 2);
105 MTData.at(i).Zxx = newxx;
106 MTData.at(i).Zxy = newxy;
107 MTData.at(i).Zyx = newyx;
108 MTData.at(i).Zyy = newyy;
109 MTData.at(i).rotangle += angle;
117 for (
unsigned int i = 0; i < MTData.size(); ++i)
119 DoRotate(i, rotangle);
128 for (
unsigned int i = 0; i < MTData.size(); ++i)
130 DoRotate(i, -MTData.at(i).rotangle);
138 trealdata temp(MTData.size());
139 transform(MTData.begin(), MTData.end(), temp.begin(), [](
MTTensor val)
140 {
return val.GetFrequency();});
147 const unsigned int nfreqs = freqs.size();
148 if (MTData.size() != nfreqs)
150 MTData.resize(nfreqs);
151 TFData.resize(nfreqs);
153 for (
unsigned int i = 0; i < nfreqs; ++i)
154 MTData.at(i).frequency = freqs.at(i);
155 assert(MTData.size() == TFData.size());
159 void MTStation::ReadMtf(
const std::string filename)
161 std::ifstream mtffile(filename.c_str());
167 std::string latline = FindToken(mtffile,
">LATITUDE");
170 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
171 boost::char_separator<char> sep(
":");
172 tokenizer tok(latline, sep);
173 tokenizer::iterator beg = tok.begin();
175 convert(*beg, latitude);
177 std::string lonline = FindToken(mtffile,
">LONGITUDE");
180 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
181 boost::char_separator<char> sep(
":");
182 tokenizer tok(lonline, sep);
183 tokenizer::iterator beg = tok.begin();
185 convert(*beg, longitude);
187 std::string line = FindToken(mtffile,
"//SECTION=IMP");
188 double rotangle, period;
189 double zxx_re, zxx_im, zxy_re, zxy_im, zyx_re, zyx_im, zyy_re, zyy_im;
190 double dzxx, dzxy, dzyx, dzyy;
192 while (mtffile.good())
195 mtffile >> period >> rotangle >> zxx_re >> zxx_im >> dzxx >> zxy_re >> zxy_im
196 >> dzxy >> zyx_re >> zyx_im >> dzyx >> zyy_re >> zyy_im >> dzyy;
200 CurrentImp.frequency = 1.0 / period;
201 CurrentImp.Zxx = (zxx_re - I * zxx_im);
202 CurrentImp.Zxy = (zxy_re - I * zxy_im);
203 CurrentImp.Zyx = (zyx_re - I * zyx_im);
204 CurrentImp.Zyy = (zyy_re - I * zyy_im);
205 CurrentImp.dZxx = dzxx;
206 CurrentImp.dZxy = dzxy;
207 CurrentImp.dZyx = dzyx;
208 CurrentImp.dZyy = dzyy;
209 CurrentImp.rotangle = rotangle;
210 MTData.push_back(CurrentImp);
211 TFData.push_back(MagneticTF());
218 void MTStation::ReadZmm(
const std::string filename)
220 std::ifstream zmmfile(filename.c_str());
226 double dummy, rotangle;
227 std::string line = FindToken(zmmfile,
"orientations");
228 zmmfile >> dummy >> rotangle;
231 while (zmmfile.good())
235 std::string periodline = FindToken(zmmfile,
"period");
238 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
240 boost::char_separator<char> sep(
" ");
241 tokenizer tok(periodline, sep);
242 tokenizer::iterator beg = tok.begin();
244 std::cout << *beg << std::endl;
245 convert(*beg, period);
247 FindToken(zmmfile,
"Transfer");
250 double zxx_re, zxx_im, zxy_re, zxy_im, zyx_re, zyx_im, zyy_re, zyy_im;
251 zmmfile >> zxx_re >> zxx_im >> zxy_re >> zxy_im >> zyx_re >> zyx_im
253 CurrentImp.frequency = 1.0 / period;
254 CurrentImp.Zxx = (zxx_re + I * zxx_im);
255 CurrentImp.Zxy = (zxy_re + I * zxy_im);
256 CurrentImp.Zyx = (zyx_re + I * zyx_im);
257 CurrentImp.Zyy = (zyy_re + I * zyy_im);
260 double s11_re, s11_im, s21_re, s21_im, s22_re, s22_im;
261 FindToken(zmmfile,
"Inverse Coherent Signal Power Matrix");
264 zmmfile >> s11_re >> s11_im >> s21_re >> s21_im >> s22_re >> s22_im;
266 FindToken(zmmfile,
"Residual");
267 double cov11_re, cov11_im, cov21_re, cov21_im, cov22_re, cov22_im;
270 zmmfile >> cov11_re >> cov11_im >> cov21_re >> cov21_im >> cov22_re
273 CurrentImp.dZxx = sqrt(
275 complex<double>(cov11_re, cov11_im)
276 * complex<double>(s11_re, s11_im)));
277 CurrentImp.dZxy = sqrt(
279 complex<double>(cov11_re, cov11_im)
280 * complex<double>(s22_re, s22_im)));
281 CurrentImp.dZyx = sqrt(
283 complex<double>(cov22_re, cov22_im)
284 * complex<double>(s11_re, s11_im)));
285 CurrentImp.dZyy = sqrt(
287 complex<double>(cov22_re, cov22_im)
288 * complex<double>(s22_re, s22_im)));
289 CurrentImp.rotangle = rotangle;
290 MTData.push_back(CurrentImp);
291 TFData.push_back(MagneticTF());
300 void MTStation::ReadNetCDF(
const std::string filename)
302 std::vector<double> Frequencies,StatXCoord, StatYCoord, StatZCoord;
303 gplib::rvec Impedances;
305 if (StatXCoord.size() != 1)
307 throw FatalException(
"Cannot have data for more than one station in netcdf file !");
309 const size_t nfreq = Frequencies.size();
310 for (
size_t i = 0; i < nfreq; ++i)
313 CurrentImp.frequency = Frequencies[i];
314 CurrentImp.Zxx = (Impedances(i*8) + I * Impedances(i*8 +1));
315 CurrentImp.Zxy = (Impedances(i*8 +2) + I * Impedances(i*8 +3));
316 CurrentImp.Zyx = (Impedances(i*8 + 4) + I * Impedances(i*8 +5));
317 CurrentImp.Zyy = (Impedances(i*8 + 6) + I * Impedances(i*8 +7));
318 MTData.push_back(CurrentImp);
319 TFData.push_back(MagneticTF());
327 void MTStation::ReadEdi(
const std::string filename)
329 using namespace antlr;
330 std::ifstream infile(filename.c_str());
331 const double invalid = 1e30;
337 EDILexer lexer(infile);
338 EDIParser parser(lexer);
340 latitude = parser.latitude;
341 longitude = parser.longitude;
342 elevation = parser.elevation;
343 azimuth = parser.azimuth;
346 unsigned int valfreqs = 0;
347 for (
unsigned int i = 0; i < parser.frequency.size(); ++i)
349 if (abs(parser.DataXX.at(i)) > invalid)
351 parser.frequency.at(i) = 0;
361 if (!parser.rotangles.empty())
363 azimuth += parser.rotangles.at(0) * 180. / PI;
366 unsigned int mtindex = 0;
370 for (
unsigned int i = 0; i < parser.rotangles.size(); ++i)
372 if (abs(parser.DataXX.at(i)) < invalid)
374 MTData.at(mtindex).frequency = parser.frequency.at(i);
375 MTData.at(mtindex).rotangle = parser.rotangles.at(i)
377 MTData.at(mtindex).Zxx = parser.DataXX.at(i);
378 MTData.at(mtindex).Zxy = parser.DataXY.at(i);
379 MTData.at(mtindex).Zyx = parser.DataYX.at(i);
380 MTData.at(mtindex).Zyy = parser.DataYY.at(i);
381 MTData.at(mtindex).dZxx = parser.dDataXX.at(i);
382 MTData.at(mtindex).dZxy = parser.dDataXY.at(i);
383 MTData.at(mtindex).dZyx = parser.dDataYX.at(i);
384 MTData.at(mtindex).dZyy = parser.dDataYY.at(i);
389 if (parser.DataZY.empty() ==
false)
391 for (
unsigned int i = 0; i < parser.DataZY.size(); ++i)
393 if (abs(parser.DataZX.at(i)) < invalid)
395 TFData.at(mtindex).frequency = parser.frequency.at(
397 TFData.at(mtindex).Tx = parser.DataZX.at(i);
398 TFData.at(mtindex).Ty = parser.DataZY.at(i);
399 TFData.at(mtindex).dTx = parser.dDataZX.at(i);
400 TFData.at(mtindex).dTy = parser.dDataZY.at(i);
406 catch (ANTLRException& e)
408 cerr <<
"Parse exception: " << e.toString() << endl;
414 throw FatalException(
"File not found: " + filename);
419 void MTStation::ReadPek1D(
const std::string filename)
421 ifstream infile(filename.c_str());
424 const double convfactor = 1. / (1000. * mu);
425 double period, rxx, imxx, rxy, imxy, ryx, imyx, ryy, imyy;
426 while (infile.good())
428 infile >> period >> rxx >> imxx >> rxy >> imxy >> ryx >> imyx >> ryy
434 CurrentImp.frequency = 1. / period;
435 CurrentImp.Zxx = (rxx + I * imxx) * convfactor;
436 CurrentImp.Zxy = (rxy + I * imxy) * convfactor;
437 CurrentImp.Zyx = (ryx + I * imyx) * convfactor;
438 CurrentImp.Zyy = (ryy + I * imyy) * convfactor;
439 MTData.push_back(CurrentImp);
440 TFData.push_back(MagneticTF());
448 throw FatalException(
"File not found: " + filename);
453 void MTStation::ReadJ(
const std::string filename)
456 using namespace antlr;
457 ifstream infile(filename.c_str());
463 JLexer lexer(infile);
464 JParser parser(lexer);
466 latitude = parser.latitude;
467 longitude = parser.longitude;
468 elevation = parser.elevation;
469 azimuth = parser.azimuth;
472 Assign(parser.frequency.size());
475 if (parser.zassigned ==
false && parser.rassigned ==
false)
477 cerr <<
"No MT data in file !" << endl;
481 for (
unsigned int i = 0; i < parser.frequency.size(); ++i)
483 MTData.at(i).frequency = parser.frequency.at(i);
484 MTData.at(i).rotangle = parser.azimuth;
485 MTData.at(i).Zxx = parser.DataXX.at(i);
486 MTData.at(i).Zxy = parser.DataXY.at(i);
487 MTData.at(i).Zyx = parser.DataYX.at(i);
488 MTData.at(i).Zyy = parser.DataYY.at(i);
489 MTData.at(i).dZxx = parser.dDataXX.at(i);
490 MTData.at(i).dZxy = parser.dDataXY.at(i);
491 MTData.at(i).dZyx = parser.dDataYX.at(i);
492 MTData.at(i).dZyy = parser.dDataYY.at(i);
493 MTData.at(i).Rx = parser.Rx.at(i);
494 MTData.at(i).Ry = parser.Ry.at(i);
497 if (parser.tassigned)
499 for (
unsigned int i = 0; i < parser.DataZY.size(); ++i)
501 TFData.at(i).frequency = parser.frequency.at(i);
502 TFData.at(i).Tx = parser.DataZX.at(i);
503 TFData.at(i).Ty = parser.DataZY.at(i);
504 TFData.at(i).dTx = parser.dDataZX.at(i);
505 TFData.at(i).dTy = parser.dDataZY.at(i);
506 TFData.at(i).Rz = parser.Rz.at(i);
510 catch (ANTLRException& e)
512 cerr <<
"Parse exception: " << e.toString() << endl;
518 throw FatalException(
"File not found: " + filename);
524 void MTStation::ReadMtt(
const std::string filename)
527 double currentreal, currentimag;
529 infile.open(filename.c_str());
530 while (infile.good())
532 infile >> currentreal;
536 if (((nentries - 1) % 23) != 0)
537 throw FatalException(
"Number of records does not match expected: " + filename);
538 const int nrecords = (nentries - 1) / 23;
540 infile.open(filename.c_str());
541 int currentrecord = 0;
544 while (infile.good())
546 infile >> currentreal;
549 MTData.at(currentrecord).frequency = currentreal;
550 TFData.at(currentrecord).frequency = currentreal;
551 infile >> currentreal;
552 MTData.at(currentrecord).Nu = currentreal;
553 infile >> currentreal >> currentimag;
554 MTData.at(currentrecord).Zxx = (currentreal + I * currentimag);
555 infile >> currentreal >> currentimag;
556 MTData.at(currentrecord).Zxy = (currentreal + I * currentimag);
557 infile >> currentreal >> currentimag;
558 MTData.at(currentrecord).Zyx = (currentreal + I * currentimag);
559 infile >> currentreal >> currentimag;
560 MTData.at(currentrecord).Zyy = (currentreal + I * currentimag);
561 infile >> currentreal;
562 MTData.at(currentrecord).dZxx = currentreal;
563 infile >> currentreal;
564 MTData.at(currentrecord).dZxy = currentreal;
565 infile >> currentreal;
566 MTData.at(currentrecord).dZyx = currentreal;
567 infile >> currentreal;
568 MTData.at(currentrecord).dZyy = currentreal;
569 infile >> currentreal >> currentimag;
570 TFData.at(currentrecord).Tx = currentreal + I * currentimag;
571 infile >> currentreal >> currentimag;
572 TFData.at(currentrecord).Ty = currentreal + I * currentimag;
573 infile >> currentreal;
574 TFData.at(currentrecord).dTx = currentreal;
575 infile >> currentreal;
576 TFData.at(currentrecord).dTy = currentreal;
577 infile >> currentreal;
578 MTData.at(currentrecord).Rx = currentreal;
579 infile >> currentreal;
580 MTData.at(currentrecord).Ry = currentreal;
581 infile >> currentreal;
582 TFData.at(currentrecord).Rz = currentreal;
592 throw FatalException(
"File not found: " + filename);
599 if (!boost::filesystem::exists(filename))
601 string ending = boost::filesystem::extension(filename);
602 boost::to_lower(ending);
605 cerr <<
"File has no extension ! " << filename << endl;
641 ReadNetCDF(filename);
648 "Unknown File Format for Reading ! This should not happen");
650 assert(MTData.size() == TFData.size());
676 "Unknown File Format for Writing ! This should not happen");
684 WriteMtt((filename +
".mtt").c_str());
692 void MTStation::WriteJBlock(boost::function<complex<double>(
const MTTensor*)> Comp,
693 boost::function<
double(
const MTTensor*)> Err, ofstream &outfile,
694 const double convfactor)
696 for (
unsigned int i = 0; i < MTData.size(); ++i)
698 if (MTData.at(i).frequency != 0)
700 outfile << setfill(
' ') << setw(15) << resetiosflags(ios::fixed)
701 << 1. / MTData.at(i).frequency <<
" ";
702 outfile << setfill(
' ') << setw(15)
703 << convfactor * boost::bind(Comp, &MTData.at(i))().real() <<
" ";
704 outfile << setfill(
' ') << setw(15)
705 << convfactor * boost::bind(Comp, &MTData.at(i))().imag() <<
" ";
706 outfile << setfill(
' ') << setw(15)
707 << convfactor * boost::bind(Err, &MTData.at(i))() <<
" ";
708 outfile << setfill(
' ') << setw(15) << setiosflags(ios::fixed) << 1.000
717 outfile.open((filename +
".j").c_str());
719 const double convfactor = 4. * acos(-1.) * 1e-4;
721 outfile <<
"# J-File Produced by CJData.cpp" << endl;
722 outfile <<
">LATITUDE = " << latitude << endl;
723 outfile <<
">LONGITUDE = " << longitude << endl;
724 outfile <<
">ELEVATION = " << elevation << endl;
725 outfile <<
">AZIMUTH = " << azimuth << endl;
726 outfile << name << endl;
727 for (
unsigned int i = 0; i < MTData.size(); ++i)
728 if (MTData.at(i).frequency != 0)
730 outfile <<
"ZXX S.I." << endl;
731 outfile << actfreqs << endl;
734 outfile <<
"ZXY S.I." << endl;
735 outfile << actfreqs << endl;
738 outfile <<
"ZYX S.I." << endl;
739 outfile << actfreqs << endl;
742 outfile <<
"ZYY S.I." << endl;
743 outfile << actfreqs << endl;
762 void inline MttLine(std::ofstream &outfile,
double value)
764 outfile << setw(15) << setfill(
' ') << setprecision(8) << setiosflags(ios::fixed)
768 void MTStation::WriteMtt(
const std::string filename)
772 outfile.open(filename.c_str());
773 std::map<double, int> FreqOrder;
774 for (
size_t i = 0; i < MTData.size(); ++i)
776 FreqOrder.insert(std::make_pair(MTData.at(i).frequency, i));
779 assert(MTData.size() == TFData.size());
780 for (
auto currfreq : FreqOrder)
782 int i = currfreq.second;
783 if (MTData.at(i).frequency > 0)
787 outfile << setw(15) << setfill(
' ') << setprecision(8)
788 << setiosflags(ios::scientific) << MTData.at(i).frequency;
789 outfile <<
" " << resetiosflags(ios::scientific) << setprecision(5)
790 << MTData.at(i).Nu <<
"\n";
794 MttLine(outfile, MTData.at(i).Zxx.real());
795 MttLine(outfile, MTData.at(i).Zxx.imag());
796 MttLine(outfile, MTData.at(i).Zxy.real());
797 MttLine(outfile, MTData.at(i).Zxy.imag());
798 MttLine(outfile, MTData.at(i).Zyx.real());
799 MttLine(outfile, MTData.at(i).Zyx.imag());
800 MttLine(outfile, MTData.at(i).Zyy.real());
801 MttLine(outfile, MTData.at(i).Zyy.imag());
803 MttLine(outfile, MTData.at(i).dZxx);
804 MttLine(outfile, MTData.at(i).dZxy);
805 MttLine(outfile, MTData.at(i).dZyx);
806 MttLine(outfile, MTData.at(i).dZyy);
807 MttLine(outfile, TFData.at(i).Tx.real());
808 MttLine(outfile, TFData.at(i).Tx.imag());
809 MttLine(outfile, TFData.at(i).Ty.real());
810 MttLine(outfile, TFData.at(i).Ty.imag());
812 MttLine(outfile, TFData.at(i).dTx);
813 MttLine(outfile, TFData.at(i).dTy);
814 MttLine(outfile, MTData.at(i).Rx);
815 MttLine(outfile, MTData.at(i).Ry);
816 MttLine(outfile, TFData.at(i).Rz);
817 outfile <<
"\n" << resetiosflags(ios::fixed);
825 latitude(old.latitude), longitude(old.longitude), elevation(old.elevation), name(
826 old.name), azimuth(old.azimuth), MTData(old.MTData), TFData(old.TFData),
828 dataformat(old.dataformat)
837 copy(source.MTData.begin(), source.MTData.end(), back_inserter(this->MTData));
838 copy(source.TFData.begin(), source.TFData.end(), back_inserter(this->TFData));
840 this->latitude = source.latitude;
841 this->longitude = source.longitude;
842 this->elevation = source.elevation;
843 this->azimuth = source.azimuth;
844 this->name = source.name;
845 this->dataformat = source.dataformat;
double GetdZxx() const
Return tensor element errors.
virtual void WriteData(const std::string filename)
void AssignAll(const int nfreq)
MTStation & operator=(const MTStation &source)
void WriteAsEdi(const std::string filename)
Write data as edi (no functionality yet)
void WriteAsJ(const std::string filename)
Write data to j-file.
std::complex< double > GetZyx() const
std::complex< double > GetZxy() const
void TrimFilename(std::string &name)
void MttLine(std::ofstream &outfile, double value)
The class MTStation is used to store the transfer functions and related information for a MT-site...
Store th local magnetic transfer function (tipper)
void Rotate(void)
Rotate to zero rotation angle.
void WriteAsMtt(const std::string filename)
Write data in goettingen .mtt format.
void Assign(const int nfreq)
Assign() assigns zero to all derived quantities, this makes the calculation.
Stores MT-Tensor components at a single frequency, calculates derived quantities. ...
void ReadImpedancesFromNetCDF(const std::string &filename, std::vector< double > &Frequencies, std::vector< double > &StatXCoord, std::vector< double > &StatYCoord, std::vector< double > &StatZCoord, gplib::rvec &Impedances)
Read magnetotelluric impedances from a netcdf file.
std::complex< double > GetZxx() const
void WriteBack()
Write data back in original format, with filename given by station name.
std::complex< double > GetZyy() const
Return tensor elements.
trealdata GetFrequencies() const
return the available frequencies in a single vector
void SetFrequencies(const trealdata &freqs)
Set the frequencies of the tensor elements, invalidates the previously stored impedance data...
The basic exception class for all errors that arise in gplib.
void Update()
Update all derived quantities.