#include "aaspi_file.h" #include "aaspi_path.h" #include "aaspi_file_info.h" #include // Translate enum data_format to string string AASPI_File::DatatypeToString(int dtyp) { string val; switch (dtyp) { case xdr_float: val="xdr_float"; break; case xdr_int: val="xdr_int"; break; case xdr_byte: val="xdr_byte"; break; case native_float: val="native_float"; break; case native_int: val="native_int"; break; case native_byte: val="native_byte"; break; default: val="unknown"; } return val; } // Translate string to enum data_format int AASPI_File::StringToDatatype(string dstr) { int val=0;; if (dstr == "xdr_float") val=xdr_float; else if (dstr == "xdr_int") val=xdr_int; else if (dstr == "xdr_byte") val=xdr_byte; else if (dstr == "native_float") val=native_float; else if (dstr == "native_int") val=native_int; else if (dstr == "native_byte") val=native_byte; return val; } bool AASPI_File::OpenIn(const string &fname) { bool rval; rval=hist.OpenIn(fname); if (rval) { hist.get_par("esize",esize); string df_name; hist.get_par("in",df_name); AASPI_Path binpath(df_name); if (binpath.is_relative()) { AASPI_Path dfpath(fname); dfpath.remove_filename(); dfpath+=binpath; df_name=dfpath.normalize_path(); } #ifdef _WIN32 if (binpath.extension() == "zgy" || binpath.extension() == "ZGY") {// zgy binary zgy_binary = true; rval = binf.OpenZGY(df_name, AASPI_BinFile::ReadOnly); updateDataRange(); } else { // assume everything else is AASPI binary #endif rval = binf.Open(df_name, AASPI_BinFile::ReadOnly); #ifdef _WIN32 } #endif if (!rval) { // Find out why cerr << "Could not open associated binary file:" << df_name << endl; AASPI_FileInfo afi(df_name); if (!afi.exists()) { cerr << "Error: Binary file: " << fname << " does not exist." << endl; return false; } if (!afi.isReadable()) { cerr << "Error: Binary file: " << fname << " is not readable." << endl; return false; } } } hist_name=fname; if (rval) rval=OpenInHeader(); if (rval) flags |= read_bit; return rval; } bool AASPI_File::OpenOut(const string &fname, int dformat, int esz, const string &dpath) { bool rval=false; rval=hist.OpenOut(fname); //cout << rval << endl; data_format=dformat; esize=esz; AASPI_Path datpath; if (rval) { if (fname == "stdout") { // create tempname here cerr << "dpath="< nkeys) return; ostringstream oss; oss << "hdrkey" << keyindex; hdr_hist.get_par(oss.str(),keyname); } void AASPI_File::get_key_index(const string &keyname, int &keyindex) { int ind, nkeys; string tstkey; keyindex=0; get_number_keys(nkeys); for (ind=1; ind <= nkeys; ++ind) { get_key_name(ind, tstkey); if (tstkey == keyname) { keyindex=ind; break; } } } void AASPI_File::get_key_format(const int keyindex, string &keyfmt) { keyfmt=""; int nkeys; get_number_keys(nkeys); if (keyindex < 1) return; if (keyindex > nkeys) return; ostringstream oss; oss << "hdrfmt" << keyindex; hdr_hist.get_par(oss.str(),keyfmt); } void AASPI_File::get_key_format(const int keyindex, int &keyfmt) { keyfmt=0; string fmt; get_key_format(keyindex,fmt); if (!fmt.empty()) { keyfmt=StringToDatatype(fmt); } } void AASPI_File::get_key_type(const int keyindex, string &keytyp) { keytyp=""; int nkeys; get_number_keys(nkeys); if (keyindex < 1) return; if (keyindex > nkeys) return; ostringstream oss; oss << "hdrtype" << keyindex; hdr_hist.get_par(oss.str(),keytyp); } void AASPI_File::get_key_val_by_index(int recno, const int keyindex, int nval, int *vals) { // Record numbers start at one if ( !has_header_file ) return; aaspi_off_t pos=hdr_esize*(hdr_n1*aaspi_off_t(recno-1)+keyindex-1); aaspi_off_t step=hdr_esize*hdr_n1; int i; for (i=0; i>2; // data is 4 bytes unsigned int *ptr=(unsigned int*) buf; unsigned int *ptre=ptr+len; for (; ptr < ptre; ++ptr) { unsigned int v=*ptr; *ptr= ((v & 0x000000ff) << 24) | ((v & 0x0000ff00) << 8) | ((v & 0x00ff0000) >> 8) | ((v & 0xff000000) >> 24); } } } void AASPI_File::translate_to(void *buf, size_t len) { // Simple byte swap code assumes 4 byte unsigned integers if ((data_format == xdr_int) || (data_format == xdr_float) ) { len=len>>2; // divide byte length by 4 unsigned int *ptr=(unsigned int*) buf; unsigned int *ptre=ptr+len; for (; ptr < ptre; ++ptr) { unsigned int v=*ptr; *ptr= ((v & 0x000000ff) << 24) | ((v & 0x0000ff00) << 8) | ((v & 0x00ff0000) >> 8) | ((v & 0xff000000) >> 24); } } } #ifdef _WIN32 // A procedure to determine whether to write data binary as zgy format // from default parameter settings. // User need to specify write_zgy_binary=1 in the default parameter file // to enable writing data binary as zgy format bool AASPI_File::write_zgy_binary() { string global_path = std::getenv("AASPIHOME"); string local_path; global_path = global_path + PATHSEP + "par" + PATHSEP + "aaspi_default_parameters"; local_path = "aaspi_default_parameters"; AASPI_HistoryFile default_parameters_hist; AASPI_FileInfo finfo(local_path); if (finfo.exists()) {// try to load the local default parameters file first default_parameters_hist.OpenIn(local_path); } else {// if local default_parameters default_parameters_hist.OpenIn(global_path); } bool rv; if (default_parameters_hist.has_par("write_zgy_binary")){ default_parameters_hist.get_par("write_zgy_binary", rv); } else { rv = false; // default is NOT writing to ZGY binary } default_parameters_hist.Close(); return rv; } // A procedure to get the desired data type for writing ZGY binary. // 3 types: 8, 16, 32 <=> SignedInt8, SignedInt16, and Float32. int AASPI_File::get_zgy_data_type() { string global_path = std::getenv("AASPIHOME"); string local_path; global_path = global_path + PATHSEP + "par" + PATHSEP + "aaspi_default_parameters"; local_path = "aaspi_default_parameters"; AASPI_HistoryFile default_parameters_hist; AASPI_FileInfo finfo(local_path); if (finfo.exists()) {// try to load the local default parameters file first default_parameters_hist.OpenIn(local_path); } else {// if local default_parameters default_parameters_hist.OpenIn(global_path); } if (default_parameters_hist.has_par("zgy_data_type")){ int dtype; default_parameters_hist.get_par("zgy_data_type", dtype); default_parameters_hist.Close(); // Don't forget to close the opened file before exiting this function if (dtype == 8) { return ZgyApi::DataType::SignedInt8; } else if (dtype == 16) { return ZgyApi::DataType::SignedInt16; } else { // assume everything else is float 32 bit return ZgyApi::DataType::Float32; } } else { default_parameters_hist.Close(); // Don't forget to close the opened file before exiting this function return ZgyApi::DataType::Float32; // default is 32-bit } } // A procedure to update zgy binary metadata before writing // Assume we have all the parameters critical to metadata construction (n1, n2, n3). // Hopefully the user already defined the other parameters before aaspi_write. We have to trust the current history file. No other way. // There is no header yet to be written out. // Otherwise we have to bet our luck on the default. // For example, max and min of data is impossible to get before hand. void AASPI_File::update_zgy_meta() { int n1, n2, n3; float o1, o2, o3; float d1, d2, d3; string unit1, unit2, unit3; double dcdp, dline; double x1, x2, x3, x4, y1, y2, y3, y4; float line1, line2, line3, line4, cdp1, cdp2, cdp3, cdp4; getParam("n1", n1); getParam("n2", n2); if (hasParam("n3")) getParam("n3", n3); else n3 = 1; // default is that we always have 1 volume getParam("o1", o1); getParam("o2", o2); if (hasParam("o3")) getParam("o3", o3); else o3 = 1; // let's say the first volume is 1. getParam("d1", d1); getParam("d2", d2); if (hasParam("d3")) getParam("d3", d3); else d3 = 1; // increment should not be zero. getParam("unit1", unit1); getParam("unit2", unit2); getParam("unit3", unit3); getParam("dcdp", dcdp); getParam("dline", dline); // Thang Ha, 20181203: since I'm reading from a history file that is supposed to be written out, // things get a bit messy // all string parameters are now formatted, and thus have "" at the beginning and end. // We need to de-format them. unit1 = unit1.substr(1, unit1.length()-2); unit2 = unit2.substr(1, unit2.length() - 2); unit3 = unit3.substr(1, unit3.length() - 2); if (hist.has_par("y4")) {// 4 corners of the survey is defined. Get them getParam("x1", x1); getParam("y1", y1); getParam("line1", line1); getParam("cdp1", cdp1); getParam("x2", x2); getParam("y2", y2); getParam("line2", line2); getParam("cdp2", cdp2); getParam("x3", x3); getParam("y3", y3); getParam("line3", line3); getParam("cdp3", cdp3); getParam("x4", x4); getParam("y4", y4); getParam("line4", line4); getParam("cdp4", cdp4); } else { // fake them. Use my best intuition. Most likely this won't happen if the original data is imported correctly x1 = 0.f; y1 = 0.f; line1 = o3; cdp1 = o2; x2 = dcdp*d2*(n2 - 1); // inline direction is assumed to be parallel to x axis. Xline, therefore, increase along x axis y2 = 0.f; line2 = o3; cdp2 = o2 + d2*(n2 - 1); x3 = 0.f; y3 = dline*d3*(n3-1); line3 = o3 + d3*(n3 - 1); cdp3 = o2; x4 = x2; y4 = y3; line4 = line3; cdp4 = cdp2; } // Reconstruct ZGY metadata from AASPI history information binf.zgy_meta.size[2] = n1; binf.zgy_meta.z0 = o1; binf.zgy_meta.dz = d1; binf.zgy_meta.size[1] = n2; binf.zgy_meta.hannot0[1] = o2; binf.zgy_meta.dhannot[1] = d2; binf.zgy_meta.size[0] = n3; binf.zgy_meta.hannot0[0] = o3; binf.zgy_meta.dhannot[0] = d3; binf.zgy_meta.hcornerxy[AASPI_ZGY_MetaData::Corner00][0] = x1; // min inline, min crossline binf.zgy_meta.hcornerxy[AASPI_ZGY_MetaData::Corner00][1] = y1; binf.zgy_meta.hcornerxy[AASPI_ZGY_MetaData::Corner0N][0] = x2; // min inline, max crossline binf.zgy_meta.hcornerxy[AASPI_ZGY_MetaData::Corner0N][1] = y2; binf.zgy_meta.hcornerxy[AASPI_ZGY_MetaData::CornerM0][0] = x4; // max inline, min crossline binf.zgy_meta.hcornerxy[AASPI_ZGY_MetaData::CornerM0][1] = y4; binf.zgy_meta.hcornerxy[AASPI_ZGY_MetaData::CornerMN][0] = x3; // max inline, max crossline // THang Ha, 20181203: this is the cause: point 3, not 4, is the MN corner equivalent of Petrel metadata binf.zgy_meta.hcornerxy[AASPI_ZGY_MetaData::CornerMN][1] = y3; // Take care of units if (unit1 == "s" || unit1 == "ms") { binf.zgy_meta.zunitdim = ZgyApi::UnitDim::Time; binf.zgy_meta.zunitname = "ms"; // force ms output. Most zgy volumes are in ms instead of s. binf.zgy_meta.zunitfactor = 0.001; if (unit1 == "s") { // most likely for AASPI. Convert it to ms anyway. binf.zgy_meta.z0 *= 1000.; binf.zgy_meta.dz *= 1000.; } } else { binf.zgy_meta.zunitdim = ZgyApi::UnitDim::Length; binf.zgy_meta.zunitname = unit1; if (unit1 == "km") { binf.zgy_meta.zunitfactor = 1000.; // 1km = 1000m } else if (unit1 == "kft") { binf.zgy_meta.zunitfactor = 304.8; // 1kft = 304.8m } else if (unit1 == "ft") { binf.zgy_meta.zunitfactor = 0.3048; // 1ft = 0.3048m } else { binf.zgy_meta.zunitfactor = 1.; // either meter or some weirdo unit. } } binf.zgy_meta.hunitdim = ZgyApi::UnitDim::Length; binf.zgy_meta.hunitname = unit2; if (unit2 == "ft") { binf.zgy_meta.hunitfactor = 0.3048; // 1ft = 0.3048m } else { binf.zgy_meta.hunitfactor = 1.; // either meter or some weirdo unit. } binf.zgy_meta.datatype = get_zgy_data_type(); // get desired output data type from aaspi_default_parameters file updateDataRange(); } void AASPI_File::updateDataRange() { // Update data range and type range for each data type if (binf.zgy_meta.datatype == ZgyApi::DataType::SignedInt8) { binf.type_min = -128.0f; binf.type_max = 127.0f; binf.type_range = 255.0f; } if (binf.zgy_meta.datatype == ZgyApi::DataType::SignedInt16) { binf.type_min = -32768.0f; binf.type_max = 32767.0f; binf.type_range = 65535.0f; } // Seems like this is max min of the actual data stored in zgy cube // The expected max and min is only acquired through history file. binf.zgy_meta.datamin = binf.type_min; binf.zgy_meta.datamax = binf.type_max; getParam("min_amplitude", binf.data_min); getParam("max_amplitude", binf.data_max); if (binf.data_min >= binf.data_max || isnan(binf.data_min) || isnan(binf.data_max)) { // invalid data min and max // Replaced by a default binf.data_min = -1.0f; binf.data_max = 1.0f; binf.data_range = 2.0f; } binf.data_range = binf.data_max - binf.data_min; } #endif