#ifndef AASPI_SEGY_H #define AASPI_SEGY_H #include "aaspi_types.h" #include "aaspi_file_io.h" #include #include #include #include #define SEGY_HEADER_SIZE 3600 #define SEGY_TEXT_HEADER_SIZE 3200 #define SEGY_BIN_HEADER_SIZE 400 #define SEGY_TRC_HEADER_SIZE 240 #define SEGY_TEXT_LINE_SIZE 80 #define SEGY_NUM_TEXT_LINES 40 #define SEGY_NS_OFFSET 114 #define SEGY_DT_OFFSET 116 #define SEGY_TYPE_NONE 0 #define SEGY_TYPE_IBM 1 #define SEGY_TYPE_I32 2 #define SEGY_TYPE_I16 3 #define SEGY_TYPE_FPG 4 #define SEGY_TYPE_IEEE 5 #define SEGY_TYPE_I8 8 using namespace std; struct header_map_entry { header_map_entry() : hdr_name(""), start_pos(0), data_type(0) {} header_map_entry(const string &nm,int pos,int typ) : hdr_name(nm), start_pos(pos), data_type(typ) {} header_map_entry(const header_map_entry &hme) : hdr_name(hme.hdr_name), start_pos(hme.start_pos), data_type(hme.data_type) {} const header_map_entry &operator=(const header_map_entry &hme) { hdr_name=hme.hdr_name; start_pos=hme.start_pos; data_type=hme.data_type; return *this; } string hdr_name; int start_pos; int data_type; }; //------------------------------------------------------------------ // Converters //------------------------------------------------------------------ int get_null_int(void *, bool big_endian=true); void put_int_as_null(int val, void *ptr, bool big_endian=true); int get_i8_as_int(void *, bool big_endian=true); int get_i16_as_int(void *ptr, bool big_endian=true); int get_i32_as_int(void *ptr, bool big_endian=true); int get_ibm_as_int(void *ptr, bool big_endian=true); int get_ieee_as_int(void *ptr, bool big_endian=true); int get_fpg_as_int(void *ptr, bool big_endian=true); float get_i8_as_float(void *ptr, bool big_endian=true); float get_i16_as_float(void *ptr, bool big_endian=true); float get_i32_as_float(void *ptr, bool big_endian=true); float get_ibm_as_float(void *ptr, bool big_endian=true); float get_ieee_as_float(void *ptr, bool big_endian=true); float get_fpg_as_float(void *ptr, bool big_endian=true); void put_int_as_i8(int val, void *ptr, bool big_endian=true); void put_int_as_i16(int val, void *ptr, bool big_endian=true); void put_int_as_i32(int val, void *ptr, bool big_endian=true); void put_int_as_ibm(int val, void *ptr, bool big_endian=true); void put_int_as_ieee(int val, void *ptr, bool big_endian=true); void put_int_as_fpg(int val, void *ptr, bool big_endian=true); void put_float_as_i8(float val, void *ptr, bool big_endian=true); void put_float_as_i16(float val, void *ptr, bool big_endian=true); void put_float_as_i32(float val, void *ptr, bool big_endian=true); void put_float_as_ibm(float val, void *ptr, bool big_endian=true); void put_float_as_ieee(float val, void *ptr, bool big_endian=true); void put_float_as_fpg(float val, void *ptr, bool big_endian=true); //------------------------------------------------------------------ //! \brief General class for specifying binary data fields //! //! This is used for both the SEGY binary and trace headers class HeaderMap { public: HeaderMap() {} ~HeaderMap() { } inline void clear() { hmap.clear(); } inline void add(const header_map_entry &hme) { hmap[hme.hdr_name]=hme; } inline void add(const string &nm,int pos,int typ) { hmap[nm]=header_map_entry(nm,pos,typ); } inline void remove(const string &hmn) { hmap.erase(hmn); } inline header_map_entry get(const string &hmn) { map::iterator it; it=hmap.find(hmn); if (it != hmap.end()) { return it->second; } else { return header_map_entry(); } } inline bool has_key(const string &hmn) { return ( hmap.find(hmn) != hmap.end() ); } void setBinaryHeaderDefault(); void setTraceHeaderDefault(); list getNameList(); inline int size() { return hmap.size(); } bool readFile(const string &fname); bool writeFile(const string &fname); static void decodeDataType(const string &dts, int &dtype, int &dlen); static int getDataTypeLength(int dtype); private: map hmap; }; //! \brief Class representing the SEGY Text Header //! //! Provides functions for reading and writing to individual //! header lines with conversion done automatically //! depending on the conversion options class segyTextHeader { public: segyTextHeader() { init(); } ~segyTextHeader() {} //! \brief Get line_no of text header as string //! //! Removing trailing spaces is done as necessary string getLine(int line_no); //! \brief put string into line_no of header //! //! Truncating an padding are done as necessary void putLine(int line_no, const string &str); //! \brief Get pointer to raw header data //! //! Used for fast block I/O char *rawHeader() { return (char *) &raw_head; } //! \brief Convert current format to ASCII if needed //! void convertToASCII(); //! \brief Convert current format to EBCDIC if needed //! void convertToEBCDIC(); //! \brief Check to see if header is EBCDIC //! bool isEBCDIC() { return header_is_ebcdic; } //! \brief Check to see if header is ASCII //! bool isASCII() { return !header_is_ebcdic; } void setASCII(){ header_is_ebcdic=false; } void setEBCDIC(){ header_is_ebcdic=true; } private: char raw_head[SEGY_TEXT_HEADER_SIZE]; /*!< segy text header */ char line_buff[SEGY_TEXT_LINE_SIZE]; bool header_is_ebcdic; /*!< Current raw_header is ebcdic */ void init(); void EBCDICtoASCII(unsigned char *buff, int n); void ASCIItoEBCDIC(unsigned char *buff, int n); }; struct header_translator_entry { header_translator_entry() : name(""), byte_loc(0), cnv_in(0), cnv_out(0) {} header_translator_entry(const header_translator_entry &hte) : name(hte.name), byte_loc(hte.byte_loc), cnv_in(hte.cnv_in), cnv_out(hte.cnv_out) {} const header_translator_entry &operator=(const header_translator_entry &hte) { name=hte.name; byte_loc=hte.byte_loc; cnv_in=hte.cnv_in; cnv_out=hte.cnv_out; return *this; } string name; int byte_loc; int (*cnv_in)(void *, bool); void (*cnv_out)(int, void *, bool); }; //! \brief SEGY Header Translator //! //! Translate headers to byte positions for both binary //! and trace headers class segyHeaderTranslator { public: segyHeaderTranslator() { init(); } segyHeaderTranslator(const segyHeaderTranslator &sht) { big_endian=sht.big_endian; nhead=sht.nhead; key_name_map=sht.key_name_map; conv_table=new header_translator_entry [ nhead ]; int i; for (i=0; i hlist, HeaderMap hmap); void build(HeaderMap hmap); void get_ints(void *dptr, int *hdr_dat, int n); void put_ints(void *dptr, int *hdr_dat, int n); int get_int(void *dptr,const string &name); void put_int(void *dptr,const string &name,int val); inline void setBigEndian(bool be=true) { big_endian=be; } inline void setLittleEndian(bool le=true) { big_endian=!le; } inline int size() { return nhead; } inline string keyName(int idx) { if ( (idx < 0) || (idx >=nhead) ) return string("UNKNOWN"); return conv_table[idx].name; } int keyIndex(const string &name); private: bool big_endian; int nhead; header_translator_entry *conv_table; map key_name_map; inline void init() { big_endian=true; nhead=0; conv_table=0; } }; class segyBinaryHeader { public: segyBinaryHeader() { init(); } segyBinaryHeader(const segyBinaryHeader &sbh) { big_endian=sbh.big_endian; hmap=sbh.hmap; sht=sbh.sht; memcpy(raw_head,sbh.raw_head,SEGY_BIN_HEADER_SIZE); } ~segyBinaryHeader() { } const segyBinaryHeader& operator=(const segyBinaryHeader &sbh) { big_endian=sbh.big_endian; hmap=sbh.hmap; sht=sbh.sht; memcpy(raw_head,sbh.raw_head,SEGY_BIN_HEADER_SIZE); return *this; } //! \brief Get pointer to raw header data //! //! Used for fast block I/O inline char *rawHeader() { return (char *) &raw_head; } //! \brief Set Header Description inline void putValue(const string &nam, int val) { sht.put_int(raw_head,nam,val); } inline int getValue(const string &nam) { return sht.get_int(raw_head,nam); } inline bool hasKey(const string &nam) {return hmap.has_key(nam); } inline int numHeaders() { return sht.size(); } inline string keyName(int idx) { return sht.keyName(idx); } inline int keyIndex(const string &name) { return sht.keyIndex(name); } inline void setBigEndian(bool be=true) { big_endian=be; sht.setBigEndian(big_endian); } inline void setLittleEndian(bool le=true) { big_endian=!le; sht.setBigEndian(big_endian); } private: unsigned char raw_head[SEGY_BIN_HEADER_SIZE]; bool big_endian; HeaderMap hmap; segyHeaderTranslator sht; inline void init() { memset(raw_head,0,SEGY_BIN_HEADER_SIZE); big_endian=true; hmap.setBinaryHeaderDefault(); sht.setBigEndian(big_endian); sht.build(set_default_keys(),hmap); } list set_default_keys(); }; struct headerOverride { headerOverride() : pos(0),data_type(0),ival(0) {} headerOverride(int p, int dtyp, int iv) : pos(p),data_type(dtyp),ival(iv) {} headerOverride(const headerOverride &ho) : pos(ho.pos),data_type(ho.data_type),ival(ho.ival) {} int pos; // trace header position int data_type; // SEGY data type int ival; // override value }; class segyTraceInterpreter { public: segyTraceInterpreter() { init(); } ~segyTraceInterpreter() { } void getData(void *trc_ptr, float *dat, int n); void putData(void *trc_ptr, float *dat, int n); void getHeaders(void *trc_ptr, int *hdr, int n); void putHeaders(void *trc_ptr, int *hdr, int n); void setDataType(int dtyp); inline void setHeaderMap(const HeaderMap &hdrmap) { hmap=hdrmap; sht.build(hmap); } inline void setHeaderList(list hdrlist) { sht.build(hdrlist,hmap); } inline const HeaderMap &headerMap() const { return hmap; } inline void setNumSamples(int ns) { nsamples=ns; calcTraceLen(); } inline void setBigEndian(bool be=true) { big_endian=be; } inline int traceLength() { calcTraceLen(); return trace_length; } inline int numHeaders() { return sht.size(); } inline string keyName(int idx) { return sht.keyName(idx); } inline int keyIndex(const string &name) { return sht.keyIndex(name); } inline void prepTrace(char *ptr, int ns, float dt) { memset(ptr,tsize,0); put_int_as_i16(ns,ptr+SEGY_NS_OFFSET,big_endian); put_int_as_i16(int(dt*1e6+.5),ptr+SEGY_DT_OFFSET,big_endian); } inline void clearOverrides() { overrides.clear(); } inline void addOverride(int pos, int type, int val) // Note position starts at one! { overrides.push_back(headerOverride(pos-1,type,val)); } void applyOverrideValues(char *ptr); private: int tsize; // Trace length bool big_endian; HeaderMap hmap; segyHeaderTranslator sht; int data_type; int nsamples; int esize; int trace_length; float (*cnv_in)(void *, bool); void (*cnv_out)(float, void *, bool); list overrides; // Fixed trace header overrides i.e. for laga, etc. inline void init() { hmap.setTraceHeaderDefault(); sht.build(set_default_keys(),hmap); big_endian=true; esize=4; setDataType(SEGY_TYPE_IBM); nsamples=1; calcTraceLen(); } list set_default_keys(); inline void calcTraceLen() { trace_length=SEGY_TRC_HEADER_SIZE+esize*nsamples; } }; class segyFile { public: enum OpenFlags { NotOpen = 0x00, ReadOnly = 0x01, WriteOnly = 0x02 }; segyFile() { init(); } ~segyFile() { Close(); } bool OpenIn(const string &name, bool big_end=true); bool OpenOut(const string &name, int ns, float delt, int dtype=SEGY_TYPE_IBM, bool big_end=true); bool Close(); inline int numSamples() { return nsamp; } inline int dataType() { return data_type; } inline float Dt() { return dt; } inline segyTextHeader &textHeader() { return thead; } inline segyBinaryHeader &binaryHeader() { return bhead; } inline segyTraceInterpreter &traceInterpreter() { return sti; } inline int traceBufferSize() { return buff_ntrace; } int numTraces(); void setNumSamples(int ns); void setDataType(int dtyp); void setDt(float dt); void setTraceBufferSize(int ntrace); bool seekTrace(int sp); int readTraces(int ntrc, int ndat, int nhdr, float *dat, int *hdr); int writeTraces(int ntrc, int ndat, int nhdr, float *dat, int *hdr); bool write_headers(); private: AASPI_BinFile fil; segyTextHeader thead; segyBinaryHeader bhead; segyTraceInterpreter sti; int flags; char *tbuf; int buff_ntrace; int nsamp; int data_type; int trc_size; float dt; bool headers_written; void init() { tbuf=0; flags=NotOpen; nsamp=0; data_type=SEGY_TYPE_NONE; trc_size=0; dt=0.f; buff_ntrace=1024; headers_written=false; } bool read_headers(); bool allocate_buffer(); }; #endif