зеркало из https://github.com/softlandia/glasio.git
v0.2.2 read to sections containers
This commit is contained in:
Родитель
bf5b565bcb
Коммит
f2ff4d7df5
7
HIST.md
7
HIST.md
|
@ -1,4 +1,9 @@
|
|||
## ver 0.2.1 // 2020.06.22 ##
|
||||
## ver 0.2.2 // 2020.06.25 ##
|
||||
|
||||
- read all parameters to section containers / чтение всех параметров из заголовка в соответствующие контейнеры
|
||||
- пока только чтение и хранение, в работе не используется
|
||||
|
||||
## ver 0.2.1 // 2020.06.22 ##
|
||||
|
||||
- add check to monotony of depth on reading добавлена проверка при чтении на монотонность колонки глубины
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
**file: data\more_20_warnings.las**
|
||||
0, line: 24, "__WRN__ STRT: 0.000 == STOP: 0.000"
|
||||
1, line: 24, "__WRN__ STEP parameter equal 0"
|
||||
0, line: 24, "__WRN__ STEP parameter equal 0"
|
||||
1, line: 24, "__WRN__ STRT: 0.000 == STOP: 0.000"
|
||||
2, line: 24, "error convert string: '6.2.24' to number, set to NULL"
|
||||
3, line: 25, "line contains 5 columns, expected: 6"
|
||||
4, line: 25, "error convert string: '528.07202215.58' to number, set to NULL"
|
||||
|
|
152
las.go
152
las.go
|
@ -1,5 +1,6 @@
|
|||
// (c) softland 2020
|
||||
// softlandia@gmail.com
|
||||
// main file
|
||||
|
||||
package glasio
|
||||
|
||||
|
@ -21,58 +22,6 @@ import (
|
|||
"github.com/softlandia/xlib"
|
||||
)
|
||||
|
||||
///format strings represent structure of LAS file
|
||||
const (
|
||||
_LasFirstLine = "~Version information\n"
|
||||
_LasVersion = "VERS. %3.1f : glas (c) softlandia@gmail.com\n"
|
||||
_LasWrap = "WRAP. NO : ONE LINE PER DEPTH STEP\n"
|
||||
_LasWellInfoSec = "~Well information\n"
|
||||
_LasMnemonicFormat = "#MNEM.UNIT DATA :DESCRIPTION\n"
|
||||
_LasStrt = " STRT.M %8.3f :START DEPTH\n"
|
||||
_LasStop = " STOP.M %8.3f :STOP DEPTH\n"
|
||||
_LasStep = " STEP.M %8.3f :STEP\n"
|
||||
_LasNull = " NULL. %9.3f :NULL VALUE\n"
|
||||
_LasRkb = " RKB.M %8.3f :KB or GL\n"
|
||||
_LasXcoord = " XWELL.M %8.3f :Well head X coordinate\n"
|
||||
_LasYcoord = " YWELL.M %8.3f :Well head Y coordinate\n"
|
||||
_LasOilComp = " COMP. %-43.43s:OIL COMPANY\n"
|
||||
_LasWell = " WELL. %-43.43s:WELL\n"
|
||||
_LasField = " FLD . %-43.43s:FIELD\n"
|
||||
_LasLoc = " LOC . %-43.43s:LOCATION\n"
|
||||
_LasCountry = " CTRY. %-43.43s:COUNTRY\n"
|
||||
_LasServiceComp = " SRVC. %-43.43s:SERVICE COMPANY\n"
|
||||
_LasDate = " DATE. %-43.43s:DATE\n"
|
||||
_LasAPI = " API . %-43.43s:API NUMBER\n"
|
||||
_LasUwi = " UWI . %-43.43s:UNIVERSAL WELL INDEX\n"
|
||||
_LasCurvSec = "~Curve Information Section\n"
|
||||
_LasCurvFormat = "#MNEM.UNIT :DESCRIPTION\n"
|
||||
_LasCurvDept = " DEPT.M :\n"
|
||||
_LasCurvLine = " %s.%s :\n"
|
||||
_LasDataSec = "~ASCII Log Data\n"
|
||||
|
||||
//secName: 0 - empty, 1 - Version, 2 - Well info, 3 - Curve info, 4 - dAta
|
||||
lasSecIgnore = 0
|
||||
lasSecVersion = 1
|
||||
lasSecWellInfo = 2
|
||||
lasSecCurInfo = 3
|
||||
lasSecData = 4
|
||||
)
|
||||
|
||||
// HeaderParam - any parameter of LAS
|
||||
type HeaderParam struct {
|
||||
lineNo int // number of line in source file
|
||||
source, // text line from source file contain this parameter
|
||||
name, // name of parameter: STOP, WELL, SP - curve name also
|
||||
Val, // parameter value
|
||||
Unit, // unit of parameter
|
||||
Description string // descrioption of parameter
|
||||
}
|
||||
|
||||
// HeaderSection - contain parameters of Well section
|
||||
type HeaderSection map[string]HeaderParam
|
||||
|
||||
//type TLasNull float64
|
||||
|
||||
// Las - class to store las file
|
||||
// input code page autodetect
|
||||
// at read file always code page converted to UTF
|
||||
|
@ -104,7 +53,7 @@ type Las struct {
|
|||
maxWarningCount int // default maximum warning count
|
||||
stdNull float64 // default null value
|
||||
VerSec,
|
||||
WellSec,
|
||||
WelSec,
|
||||
CurSec,
|
||||
ParSec,
|
||||
OthSec HeaderSection
|
||||
|
@ -128,17 +77,14 @@ func NewLas(outputCP ...cpd.IDCodePage) *Las {
|
|||
las := &Las{} //new(Las)
|
||||
las.Ver = 2.0
|
||||
las.Wrap = "NO"
|
||||
// до того как прочитаем данные мы не можем знать сколько их фактически, предполагаем что 1000, достаточно большой буфер
|
||||
// избавит от необходимости довыделять память при чтении
|
||||
//las.ePoints = ExpPoints
|
||||
las.nRows = ExpPoints
|
||||
las.rows = make([]string, 0, las.nRows)
|
||||
las.Logs = make([]LasCurve, 0)
|
||||
las.VerSec = make(HeaderSection)
|
||||
las.WellSec = make(HeaderSection)
|
||||
las.CurSec = make(HeaderSection)
|
||||
las.ParSec = make(HeaderSection)
|
||||
las.OthSec = make(HeaderSection)
|
||||
las.VerSec = NewVerSection()
|
||||
las.WelSec = NewWelSection()
|
||||
las.CurSec = NewCurSection()
|
||||
las.ParSec = NewParSection()
|
||||
las.OthSec = NewOthSection()
|
||||
las.maxWarningCount = MaxWarningCount
|
||||
las.stdNull = StdNull
|
||||
las.Strt = StdNull
|
||||
|
@ -165,21 +111,13 @@ func NewLas(outputCP ...cpd.IDCodePage) *Las {
|
|||
// ~A - data section
|
||||
func (las *Las) selectSection(r rune) int {
|
||||
switch r {
|
||||
case 86: //V
|
||||
case 0x76, 0x56: //86, 118: //V, v
|
||||
return lasSecVersion //version section
|
||||
case 118: //v
|
||||
return lasSecVersion //version section
|
||||
case 87: //W
|
||||
case 0x77, 0x57: //W, w
|
||||
return lasSecWellInfo //well info section
|
||||
case 119: //w
|
||||
return lasSecWellInfo //well info section
|
||||
case 67: //C
|
||||
case 0x43, 0x63: //C, c
|
||||
return lasSecCurInfo //curve section
|
||||
case 99: //c
|
||||
return lasSecCurInfo //curve section
|
||||
case 65: //A
|
||||
return lasSecData //data section
|
||||
case 97: //a
|
||||
case 0x41, 0x61: //A, a
|
||||
return lasSecData //data section
|
||||
default:
|
||||
return lasSecIgnore
|
||||
|
@ -188,7 +126,7 @@ func (las *Las) selectSection(r rune) int {
|
|||
|
||||
// IsWraped - return true if WRAP == YES
|
||||
func (las *Las) IsWraped() bool {
|
||||
return strings.Contains(strings.ToUpper(las.Wrap), "Y") //(strings.Index(strings.ToUpper(o.Wrap), "Y") >= 0)
|
||||
return strings.Contains(strings.ToUpper(las.Wrap), "Y")
|
||||
}
|
||||
|
||||
// SaveWarning - save to file all warning
|
||||
|
@ -331,12 +269,14 @@ func (las *Las) Open(fileName string) (int, error) {
|
|||
5. читаем одну строку (это один параметер из известной нам секции)
|
||||
*/
|
||||
func (las *Las) LoadHeader() (int, error) {
|
||||
s := ""
|
||||
var err error
|
||||
var (
|
||||
err error
|
||||
sec HeaderSection
|
||||
)
|
||||
secNum := 0
|
||||
las.currentLine = 0
|
||||
for i := range las.rows {
|
||||
s = strings.TrimSpace(las.rows[i])
|
||||
for i, s := range las.rows {
|
||||
s = strings.TrimSpace(s)
|
||||
las.currentLine++
|
||||
if isIgnoredLine(s) {
|
||||
continue
|
||||
|
@ -346,17 +286,38 @@ func (las *Las) LoadHeader() (int, error) {
|
|||
if secNum == lasSecData {
|
||||
break // reached the data section, stop load header
|
||||
}
|
||||
} else {
|
||||
//if not comment, not empty and not new section => parameter, read it
|
||||
err = las.ReadParameter(s, secNum)
|
||||
if err != nil {
|
||||
las.addWarning(TWarning{directOnRead, secNum, i, fmt.Sprintf("param: '%s' error: %v", s, err)})
|
||||
}
|
||||
sec = las.section(rune(s[1]))
|
||||
continue
|
||||
}
|
||||
//not comment, not empty and not new section => parameter, read it
|
||||
err = las.ReadParameter(s, secNum)
|
||||
p, _ := sec.parse(s, las.currentLine)
|
||||
sec.params[p.Name] = p
|
||||
if err != nil {
|
||||
las.addWarning(TWarning{directOnRead, secNum, i, fmt.Sprintf("param: '%s' error: %v", s, err)})
|
||||
}
|
||||
}
|
||||
return las.currentLine, nil
|
||||
}
|
||||
|
||||
func (las *Las) section(r rune) HeaderSection {
|
||||
switch r {
|
||||
case 0x56, 0x76: //V, v
|
||||
return las.VerSec //version section
|
||||
case 0x57, 0x77: //W, w
|
||||
if las.Ver < 2.0 {
|
||||
las.WelSec.parse = welParse12 //change parser, by default using parser 2.0
|
||||
}
|
||||
return las.WelSec //well info section
|
||||
case 0x43, 0x63: //C, c
|
||||
return las.CurSec //curve section
|
||||
case 0x50, 0x70: //P, p
|
||||
return las.ParSec //data section
|
||||
default:
|
||||
return las.OthSec
|
||||
}
|
||||
}
|
||||
|
||||
// saveHeaderWarning - забирает и сохраняет варнинги от всех проверок
|
||||
func (las *Las) storeHeaderWarning(chkResults CheckResults) {
|
||||
for _, v := range chkResults {
|
||||
|
@ -379,7 +340,7 @@ func (las *Las) ReadParameter(s string, secNum int) error {
|
|||
|
||||
func (las *Las) readVersionParam(s string) error {
|
||||
var err error
|
||||
p := NewLasParam(s)
|
||||
p := NewHeaderParam(s, 0)
|
||||
switch p.Name {
|
||||
case "VERS":
|
||||
las.Ver, err = strconv.ParseFloat(p.Val, 64)
|
||||
|
@ -392,7 +353,7 @@ func (las *Las) readVersionParam(s string) error {
|
|||
//ReadWellParam - read parameter from WELL section
|
||||
func (las *Las) ReadWellParam(s string) error {
|
||||
var err error
|
||||
p := NewLasParam(s)
|
||||
p := NewHeaderParam(s, 0)
|
||||
switch p.Name {
|
||||
case "STRT":
|
||||
las.Strt, err = strconv.ParseFloat(p.Val, 64)
|
||||
|
@ -415,25 +376,8 @@ func (las *Las) ReadWellParam(s string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
//ChangeDuplicateLogName - return non duplicated name of log
|
||||
//if input name unique, return input name
|
||||
//if input name not unique, return input name + index duplicate
|
||||
//index duplicate - Las field, increase
|
||||
/*
|
||||
func (las *Las) ChangeDuplicateLogName(name string) string {
|
||||
s := ""
|
||||
if _, ok := las.Logs[name]; ok {
|
||||
las.iDuplicate++
|
||||
s = fmt.Sprintf("%v", las.iDuplicate)
|
||||
name += s
|
||||
}
|
||||
return name
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
//Разбор одной строки с мнемоникой каротажа
|
||||
//Разбираем в переменную l а потом сохраняем в map
|
||||
//Разбираем а потом сохраняем в slice
|
||||
//Каждый каротаж характеризуется тремя именами
|
||||
//IName - имя каротажа в исходном файле, может повторятся
|
||||
//Name - ключ в map хранилище, повторятся не может. если в исходном есть повторение, то Name строится добавлением к IName индекса
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// (c) softland 2020
|
||||
// softlandia@gmail.com
|
||||
// constants
|
||||
|
||||
package glasio
|
||||
|
||||
///format strings for output LAS file
|
||||
const (
|
||||
_LasFirstLine = "~Version information\n"
|
||||
_LasVersion = "VERS. %3.1f : glas (c) softlandia@gmail.com\n"
|
||||
_LasWrap = "WRAP. NO : ONE LINE PER DEPTH STEP\n"
|
||||
_LasWellInfoSec = "~Well information\n"
|
||||
_LasMnemonicFormat = "#MNEM.UNIT DATA :DESCRIPTION\n"
|
||||
_LasStrt = " STRT.M %8.3f :START DEPTH\n"
|
||||
_LasStop = " STOP.M %8.3f :STOP DEPTH\n"
|
||||
_LasStep = " STEP.M %8.3f :STEP\n"
|
||||
_LasNull = " NULL. %9.3f :NULL VALUE\n"
|
||||
_LasRkb = " RKB.M %8.3f :KB or GL\n"
|
||||
_LasXcoord = " XWELL.M %8.3f :Well head X coordinate\n"
|
||||
_LasYcoord = " YWELL.M %8.3f :Well head Y coordinate\n"
|
||||
_LasOilComp = " COMP. %-43.43s:OIL COMPANY\n"
|
||||
_LasWell = " WELL. %-43.43s:WELL\n"
|
||||
_LasField = " FLD . %-43.43s:FIELD\n"
|
||||
_LasLoc = " LOC . %-43.43s:LOCATION\n"
|
||||
_LasCountry = " CTRY. %-43.43s:COUNTRY\n"
|
||||
_LasServiceComp = " SRVC. %-43.43s:SERVICE COMPANY\n"
|
||||
_LasDate = " DATE. %-43.43s:DATE\n"
|
||||
_LasAPI = " API . %-43.43s:API NUMBER\n"
|
||||
_LasUwi = " UWI . %-43.43s:UNIVERSAL WELL INDEX\n"
|
||||
_LasCurvSec = "~Curve Information Section\n"
|
||||
_LasCurvFormat = "#MNEM.UNIT :DESCRIPTION\n"
|
||||
_LasCurvDept = " DEPT.M :\n"
|
||||
_LasCurvLine = " %s.%s :\n"
|
||||
_LasDataSec = "~ASCII Log Data\n"
|
||||
|
||||
//secName: 0 - empty, 1 - Version, 2 - Well info, 3 - Curve info, 4 - dAta
|
||||
lasSecIgnore = 0
|
||||
lasSecVersion = 1
|
||||
lasSecWellInfo = 2
|
||||
lasSecCurInfo = 3
|
||||
lasSecData = 4
|
||||
)
|
227
las_param.go
227
las_param.go
|
@ -1,3 +1,7 @@
|
|||
// (c) softland 2020
|
||||
// softlandia@gmail.com
|
||||
// types and functions for header parameters
|
||||
|
||||
package glasio
|
||||
|
||||
import (
|
||||
|
@ -9,14 +13,133 @@ import (
|
|||
"github.com/softlandia/xlib"
|
||||
)
|
||||
|
||||
//LasParam - class to store parameter from any section
|
||||
type LasParam struct {
|
||||
// HeaderParam - class to store parameter from any section
|
||||
// universal type for store any header parameters
|
||||
// use for store parameters from sections
|
||||
// ~V, ~W and other
|
||||
// for curves used inherited type LasCurve
|
||||
type HeaderParam struct {
|
||||
Val string // parameter value
|
||||
Name string // name of parameter: STOP, WELL, SP - curve name also, also matches the key used in storage
|
||||
IName string
|
||||
Name string
|
||||
Unit string // unit of parameter
|
||||
Mnemonic string
|
||||
Unit string
|
||||
Val string
|
||||
Desc string
|
||||
Desc string // description of parameter
|
||||
lineNo int // number of line in source file
|
||||
}
|
||||
|
||||
// HeaderSection - contain parameters of Well section
|
||||
type HeaderSection struct {
|
||||
params map[string]HeaderParam
|
||||
parse ParseHeaderParam // function for parse one line
|
||||
}
|
||||
|
||||
// ParseHeaderParam - function to parse one line of header
|
||||
// return new of added parameter and warning
|
||||
// on success TWarning.Empty() == true
|
||||
type ParseHeaderParam func(s string, i int) (HeaderParam, TWarning)
|
||||
|
||||
// NewVerSection - create section ~V
|
||||
func NewVerSection() HeaderSection {
|
||||
sec := HeaderSection{}
|
||||
sec.params = make(map[string]HeaderParam)
|
||||
sec.parse = defParse
|
||||
return sec
|
||||
}
|
||||
|
||||
// defParse - parse string and create parameter of section ~V
|
||||
func defParse(s string, i int) (HeaderParam, TWarning) {
|
||||
p := NewHeaderParam(s, i)
|
||||
return *p, TWarning{}
|
||||
}
|
||||
|
||||
// NewOthSection - create section ~W
|
||||
func NewOthSection() HeaderSection {
|
||||
sec := HeaderSection{}
|
||||
sec.params = make(map[string]HeaderParam)
|
||||
sec.parse = defParse
|
||||
return sec
|
||||
}
|
||||
|
||||
// NewParSection - create section ~W
|
||||
func NewParSection() HeaderSection {
|
||||
sec := HeaderSection{}
|
||||
sec.params = make(map[string]HeaderParam)
|
||||
sec.parse = defParse
|
||||
return sec
|
||||
}
|
||||
|
||||
// NewCurSection - create section ~C
|
||||
func NewCurSection() HeaderSection {
|
||||
sec := HeaderSection{}
|
||||
sec.params = make(map[string]HeaderParam)
|
||||
sec.parse = curParse // parser for section ~C
|
||||
return sec
|
||||
}
|
||||
|
||||
// curParse - parse string and create parameter of section ~C
|
||||
func curParse(s string, i int) (HeaderParam, TWarning) {
|
||||
p := NewCurveHeaderParam(s, i)
|
||||
return *p, TWarning{}
|
||||
}
|
||||
|
||||
// NewWelSection - create section ~W
|
||||
func NewWelSection() HeaderSection {
|
||||
sec := HeaderSection{}
|
||||
sec.params = make(map[string]HeaderParam)
|
||||
sec.parse = welParse20 // by default using 2.0 version parser
|
||||
return sec
|
||||
}
|
||||
|
||||
// welParse12 - parse string and create parameter of section ~W
|
||||
// this version for las version less then 2.0
|
||||
func welParse12(s string, i int) (HeaderParam, TWarning) {
|
||||
p := NewHeaderParam(s, i)
|
||||
if p.Name == "WELL" {
|
||||
p.wellName12()
|
||||
}
|
||||
return *p, TWarning{}
|
||||
}
|
||||
|
||||
// welParse20 - parse string and create parameter of section ~W
|
||||
// this version for las version 2.0
|
||||
func welParse20(s string, i int) (HeaderParam, TWarning) {
|
||||
p := NewHeaderParam(s, i)
|
||||
if p.Name == "WELL" {
|
||||
p.wellName20()
|
||||
}
|
||||
return *p, TWarning{}
|
||||
}
|
||||
|
||||
func (p *HeaderParam) wellName12() {
|
||||
p.Val, p.Desc = p.Desc, p.Val
|
||||
}
|
||||
|
||||
func (p *HeaderParam) wellName20() {
|
||||
// по умолчанию строка параметра разбирается на 4 составляющие: "имя параметра, ед измерения, значение, коментарий"
|
||||
// между точкой и двоеточием ожидается единица измерения и значение параметра
|
||||
// для параметра WELL пробел после точки также разбивает строку на две: ед измерения и значение
|
||||
// но ТОЛЬКО для этого параметра единица измерения не существует и делать этого не следует
|
||||
// таким образом собираем обратно в одно значение то, что ВОЗМОЖНО разбилось
|
||||
if len(p.Unit) == 0 {
|
||||
return
|
||||
}
|
||||
if len(p.Val) == 0 {
|
||||
p.Val = p.Unit
|
||||
} else {
|
||||
p.Val = p.Unit + " " + p.Val
|
||||
}
|
||||
p.Unit = ""
|
||||
}
|
||||
|
||||
func wellNameFromParam(p *HeaderParam) string {
|
||||
if len(p.Unit) == 0 {
|
||||
return p.Val
|
||||
}
|
||||
if len(p.Val) == 0 {
|
||||
return p.Unit //TODO не тестируется
|
||||
}
|
||||
return p.Unit + " " + p.Val
|
||||
}
|
||||
|
||||
//PrepareParamStr - prepare string to parse, replace many space to one, replace tab to space, replace combination of separator to one
|
||||
|
@ -30,7 +153,7 @@ func PrepareParamStr(s string) string {
|
|||
// ParseParamStr - parse string from las file
|
||||
// return slice with 4 string and error if occure
|
||||
// before process input string 2 or more space replace on 1 space
|
||||
// sample "NULL . -9999.00 : Null value"
|
||||
// sample "NULL . -9999.00 : Null value"
|
||||
// f[0] - name
|
||||
// f[1] - unit
|
||||
// f[2] - value
|
||||
|
@ -104,10 +227,12 @@ func ParseCurveStr(s string) (f [3]string) {
|
|||
return
|
||||
}
|
||||
|
||||
//NewLasParam - create new object LasParam
|
||||
//fill fields from s
|
||||
func NewLasParam(s string) *LasParam {
|
||||
par := new(LasParam)
|
||||
// NewHeaderParam - create new object LasParam
|
||||
// STRT. m 10.0 : start
|
||||
// field[0] field[1] field[2] field[3]
|
||||
func NewHeaderParam(s string, i int) *HeaderParam {
|
||||
par := new(HeaderParam)
|
||||
par.lineNo = i
|
||||
paramFields := ParseParamStr(s)
|
||||
par.Name = paramFields[0]
|
||||
par.Unit = paramFields[1]
|
||||
|
@ -120,36 +245,55 @@ func NewLasParam(s string) *LasParam {
|
|||
return par
|
||||
}
|
||||
|
||||
//NULL . -9999.00 : Null value
|
||||
//WELL . 1 - Вообщевская :
|
||||
// по умолчанию строка параметра разбирается на 4 составляющие: "имя параметра, ед измерения, значение, коментарий"
|
||||
// между точкой и двоеточием ожидается единица измерения и значение параметра
|
||||
// для параметра WELL пробел после точки также разбивает строку на две: ед измерения и значение
|
||||
// но ТОЛЬКО для этого параметра единица измерения не существует и делать этого не следует
|
||||
// таким образом собираем обратно в одно значение то, что ВОЗМОЖНО разбилось
|
||||
func wellNameFromParam(p *LasParam) string {
|
||||
if len(p.Unit) == 0 {
|
||||
return p.Val
|
||||
}
|
||||
if len(p.Val) == 0 {
|
||||
return p.Unit //TODO не тестируется
|
||||
}
|
||||
return p.Unit + " " + p.Val
|
||||
// NewCurveHeaderParam - create new object LasParam
|
||||
// STRT. m 10.0 : start
|
||||
// field[0] field[1] field[2] field[3]
|
||||
func NewCurveHeaderParam(s string, i int) *HeaderParam {
|
||||
par := new(HeaderParam)
|
||||
par.lineNo = i
|
||||
paramFields := ParseCurveStr(s)
|
||||
par.Name = paramFields[0]
|
||||
par.Unit = paramFields[1]
|
||||
par.Desc = paramFields[2]
|
||||
return par
|
||||
}
|
||||
|
||||
//LasCurve - class to store one log in Las
|
||||
type LasCurve struct {
|
||||
LasParam
|
||||
HeaderParam
|
||||
Index int
|
||||
D []float64
|
||||
V []float64
|
||||
}
|
||||
|
||||
// NewLasCurve - create new object LasCurve
|
||||
// s - string from las header
|
||||
// las - pointer to container
|
||||
func NewLasCurve(s string, las *Las) LasCurve {
|
||||
lc := LasCurve{}
|
||||
curveFields := ParseCurveStr(s)
|
||||
lc.IName = curveFields[0]
|
||||
lc.Name = las.Logs.UniqueName(lc.IName)
|
||||
lc.Unit = curveFields[1]
|
||||
lc.Desc = curveFields[2]
|
||||
lc.Index = len(las.Logs) // index of new curve == number of curve already in container
|
||||
lc.Mnemonic = las.GetMnemonic(lc.IName) // мнемонику определяем по входному имени кривой
|
||||
// вместимость слайсов для хранения данных равна количеству строк в исходном файле
|
||||
lc.D = make([]float64, 0, las.NumPoints())
|
||||
lc.V = make([]float64, 0, las.NumPoints())
|
||||
return lc
|
||||
}
|
||||
|
||||
// String - return LasCurve as string
|
||||
func (o LasCurve) String() string {
|
||||
return fmt.Sprintf("[\n{\n\"IName\": \"%s\",\n\"Name\": \"%s\",\n\"Mnemonic\": \"%s\",\n\"Unit\": \"%s\",\"Val\": \"%s\",\n\"Desc\": \"%s\"\n}\n]", o.IName, o.Name, o.Mnemonic, o.Unit, o.Val, o.Desc)
|
||||
}
|
||||
|
||||
// Cmp - compare current curve with another
|
||||
// не сравниваются хранящиеся числовые данные (сам каротаж), только описание кривой, также не сравнивается индекс
|
||||
// for deep comparison with all data points stored in the container use DeepCmp
|
||||
func (o *LasCurve) Cmp(curve LasCurve) (res bool) {
|
||||
res = (o.LasParam == curve.LasParam)
|
||||
res = (o.HeaderParam == curve.HeaderParam)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -167,33 +311,6 @@ func (o *LasCurve) SetLen(n int) {
|
|||
o.V = t
|
||||
}
|
||||
|
||||
// NewLasCurve - create new object LasCurve
|
||||
// s - string from las header
|
||||
// las - pointer to container
|
||||
func NewLasCurve(s string, las *Las) LasCurve {
|
||||
lc := LasCurve{}
|
||||
curveFields := ParseCurveStr(s)
|
||||
lc.IName = curveFields[0]
|
||||
lc.Name = las.Logs.UniqueName(lc.IName)
|
||||
lc.Unit = curveFields[1]
|
||||
lc.Desc = curveFields[2]
|
||||
// index of new curve == number of curve already in container
|
||||
lc.Index = len(las.Logs)
|
||||
// мнемонику определяем по входному имени кривой
|
||||
lc.Mnemonic = las.GetMnemonic(lc.IName)
|
||||
// размер слайсов для хранения данных готовим равными количеству строк в исходном файле
|
||||
// lc.D = make([]float64, 0, las.ePoints /*las.NumPoints()*/)
|
||||
// lc.V = make([]float64, 0, las.ePoints /*las.NumPoints()*/)
|
||||
lc.D = make([]float64, 0, las.NumPoints())
|
||||
lc.V = make([]float64, 0, las.NumPoints())
|
||||
return lc
|
||||
}
|
||||
|
||||
// String - return LasCurve as string
|
||||
func (o LasCurve) String() string {
|
||||
return fmt.Sprintf("[\n{\n\"IName\": \"%s\",\n\"Name\": \"%s\",\n\"Mnemonic\": \"%s\",\n\"Unit\": \"%s\",\"Val\": \"%s\",\n\"Desc\": \"%s\"\n}\n]", o.IName, o.Name, o.Mnemonic, o.Unit, o.Val, o.Desc)
|
||||
}
|
||||
|
||||
// LasCurves - container for store all curves of las file
|
||||
// .Cmp(curves *LasCurves) bool - compare two curves containers
|
||||
type LasCurves []LasCurve
|
||||
|
|
|
@ -38,7 +38,7 @@ func TestReadWellParam(t *testing.T) {
|
|||
las := NewLas()
|
||||
for i, tmp := range dReadWellParamStep {
|
||||
las.ReadWellParam(tmp.s)
|
||||
assert.Equal(t, las.Step, tmp.v, fmt.Sprintf("<ReadWellParam> on test %d return STEP: '%f' expect: '%f'\n", i, las.Step, tmp.v))
|
||||
assert.Equal(t, tmp.v, las.Step, fmt.Sprintf("<ReadWellParam> on test %d return STEP: '%f' expect: '%f'\n", i, las.Step, tmp.v))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,9 +126,9 @@ var dWellInfoStr = []tWellInfoStr{
|
|||
}
|
||||
|
||||
func TestNewLasParamFromString(t *testing.T) {
|
||||
var lp *LasParam
|
||||
var lp *HeaderParam
|
||||
for _, tmp := range dWellInfoStr {
|
||||
lp = NewLasParam(tmp.s)
|
||||
lp = NewHeaderParam(tmp.s, 0)
|
||||
assert.Equal(t, tmp.f1, lp.Name)
|
||||
assert.Equal(t, tmp.f2, lp.Unit)
|
||||
assert.Equal(t, tmp.f3, lp.Val)
|
||||
|
@ -137,6 +137,17 @@ func TestNewLasParamFromString(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestParseWelSecParam(t *testing.T) {
|
||||
ws := NewWelSection()
|
||||
for i, tmp := range dWellInfoStr {
|
||||
par, _ := ws.parse(tmp.s, 0)
|
||||
assert.Equal(t, tmp.f1, par.Name, fmt.Sprintf("t: %d, 1", i))
|
||||
assert.Equal(t, tmp.f2, par.Unit, fmt.Sprintf("t: %d, 2", i))
|
||||
assert.Equal(t, tmp.f3, par.Val, fmt.Sprintf("t: %d, 3", i))
|
||||
assert.Equal(t, tmp.f4, par.Desc, fmt.Sprintf("t: %d, 4", i))
|
||||
}
|
||||
}
|
||||
|
||||
type tParseCurveStr struct {
|
||||
s string
|
||||
f0 string
|
||||
|
@ -163,6 +174,16 @@ var dParseCurveStr = []tParseCurveStr{
|
|||
{" .m v :sp", "-EL-", "m v", "sp"}, //15
|
||||
}
|
||||
|
||||
func TestNewCurveHeaderParam(t *testing.T) {
|
||||
cs := NewCurSection()
|
||||
for _, tmp := range dParseCurveStr {
|
||||
p, _ := cs.parse(tmp.s, 0)
|
||||
assert.Equal(t, tmp.f0, p.Name)
|
||||
assert.Equal(t, tmp.f1, p.Unit)
|
||||
assert.Equal(t, tmp.f2, p.Desc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCurveStr(t *testing.T) {
|
||||
for _, tmp := range dParseCurveStr {
|
||||
f := ParseCurveStr(tmp.s)
|
||||
|
|
54
las_test.go
54
las_test.go
|
@ -127,17 +127,6 @@ func TestGetStepFromData(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
//Тестирование увеличения чоличества точек
|
||||
type tExpandDept struct {
|
||||
fn string
|
||||
n int //количество считанных точек данных
|
||||
nWrn int //количество предупреждений
|
||||
}
|
||||
|
||||
var dExpandDept = []tExpandDept{
|
||||
{fp.Join("data/expand_points_01.las"), 7, 5},
|
||||
}
|
||||
|
||||
func TestLasSetNull(t *testing.T) {
|
||||
las := NewLas()
|
||||
las.Open(fp.Join("data/expand_points_01.las"))
|
||||
|
@ -299,21 +288,30 @@ func BenchmarkSave2(b *testing.B) {
|
|||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
//TODO данный тест больше не нужен, ExpandPoints больше не вызывается
|
||||
func TestExpandPoints(t *testing.T) {
|
||||
// перед тестом установим маленькое количество ожидаемых точек, иначе надо делать огномный тестовый файл
|
||||
// срабатывание добавления выполняется при переполнении буфера 1000
|
||||
ExpPoints = 2
|
||||
for _, tmp := range dExpandDept {
|
||||
las := NewLas()
|
||||
n, err := las.Open(tmp.fn)
|
||||
assert.Nil(t, err, fmt.Sprintf("<TestExpandPoints> on '%s' return error: %v\n", tmp.fn, err))
|
||||
assert.Equal(t, tmp.n, n, fmt.Sprintf("<TestExpandPoints> on '%s' return n: %d expect: %d\n", tmp.fn, n, tmp.n))
|
||||
assert.Equal(t, tmp.n, las.NumPoints())
|
||||
assert.Equal(t, tmp.nWrn, las.Warnings.Count(), fmt.Sprintf("<TestExpandPoints> '%s' return warning count %d, expected %d\n", tmp.fn, las.Warnings.Count(), tmp.nWrn))
|
||||
assert.Contains(t, las.Warnings[2].String(), "line: 25", fmt.Sprintf("<TestExpandPoints> '%s' return: '%s' wrong warning index 2\n", tmp.fn, las.Warnings[2]))
|
||||
assert.Contains(t, las.Warnings[4].String(), "line: 27", fmt.Sprintf("<TestExpandPoints> '%s' return: '%s' wrong warning index 4\n", tmp.fn, las.Warnings[4]))
|
||||
}
|
||||
//Тестирование заполнения секций
|
||||
type tSecFill struct {
|
||||
fn string
|
||||
n int //количество считанных точек данных
|
||||
well,
|
||||
null,
|
||||
ver,
|
||||
wrap string //версия las файла
|
||||
}
|
||||
|
||||
var dSecFill = []tSecFill{
|
||||
{fp.Join("data/expand_points_01.las"), 7, "12-Сплошная", "-9999.00", "1.20", "NO"},
|
||||
}
|
||||
|
||||
func TestSection(t *testing.T) {
|
||||
for _, tmp := range dSecFill {
|
||||
las := NewLas()
|
||||
n, err := las.Open(tmp.fn)
|
||||
assert.Nil(t, err, fmt.Sprintf("<TestExpandPoints> on '%s' return error: %v\n", tmp.fn, err))
|
||||
assert.Equal(t, tmp.n, n, fmt.Sprintf("<TestExpandPoints> on '%s' return n: %d expect: %d\n", tmp.fn, n, tmp.n))
|
||||
assert.Equal(t, tmp.n, las.NumPoints())
|
||||
assert.Equal(t, tmp.ver, las.VerSec.params["VERS"].Val)
|
||||
assert.Equal(t, tmp.wrap, las.VerSec.params["WRAP"].Val)
|
||||
assert.Equal(t, tmp.null, las.WelSec.params["NULL"].Val)
|
||||
assert.Equal(t, tmp.well, las.WelSec.params["WELL"].Val)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -15,7 +15,7 @@ const (
|
|||
directOnWrite = 2
|
||||
)
|
||||
|
||||
//TWarning - class to store warning
|
||||
// TWarning - class to store warning
|
||||
type TWarning struct {
|
||||
direct int // 0 - undefine (warningUNDEF), 1 - on read (directOnRead), 2 - on write (directOnWrite)
|
||||
section int // 0 - undefine (warningUNDEF), lasSecVertion, lasSecWellInfo, lasSecCurInfo, lasSecData
|
||||
|
@ -23,6 +23,11 @@ type TWarning struct {
|
|||
desc string // description of warning
|
||||
}
|
||||
|
||||
// Empty - return true if warning is empty
|
||||
func (w TWarning) Empty() bool {
|
||||
return len(w.desc) == 0
|
||||
}
|
||||
|
||||
//String - return string with warning
|
||||
func (w TWarning) String() string {
|
||||
return fmt.Sprintf("line: %d,\t\"%s\"", w.line+1, w.desc)
|
||||
|
|
2
ver.txt
2
ver.txt
|
@ -1 +1 @@
|
|||
0.2.1
|
||||
0.2.2
|
||||
|
|
Загрузка…
Ссылка в новой задаче