зеркало из https://github.com/softlandia/glasio.git
v0.1.7 add Checker
This commit is contained in:
Родитель
b0000b80c7
Коммит
775d60b031
6
HIST.md
6
HIST.md
|
@ -1,4 +1,8 @@
|
||||||
## ver 0.1.6 // 2020.04.13 ##
|
## ver 0.1.7 // 2020.04.28 ##
|
||||||
|
|
||||||
|
- внедрена первая версия модуля Checker, пока на слайсах, ожидается переделка на map
|
||||||
|
|
||||||
|
## ver 0.1.6 // 2020.04.13 ##
|
||||||
|
|
||||||
- мелкие улучшения
|
- мелкие улучшения
|
||||||
|
|
||||||
|
|
13
data/dic.ini
13
data/dic.ini
|
@ -86,6 +86,8 @@ Kavernomer= CALI
|
||||||
КАВ-9_10 = CALI
|
КАВ-9_10 = CALI
|
||||||
КАВ26 = CALI
|
КАВ26 = CALI
|
||||||
КАВ268 = CALI
|
КАВ268 = CALI
|
||||||
|
CAL = CALI
|
||||||
|
CALvh = CALI
|
||||||
|
|
||||||
DN = BIN
|
DN = BIN
|
||||||
DN_ = BIN
|
DN_ = BIN
|
||||||
|
@ -94,6 +96,7 @@ Dnom = BIN
|
||||||
ДСн = BIN
|
ДСн = BIN
|
||||||
ДСном = BIN
|
ДСном = BIN
|
||||||
Дн = BIN
|
Дн = BIN
|
||||||
|
CAL_nom = BIN
|
||||||
|
|
||||||
ДТП = DTP
|
ДТП = DTP
|
||||||
DТ = DTP
|
DТ = DTP
|
||||||
|
@ -211,6 +214,7 @@ A1M0 = GZ2
|
||||||
A125M01N= GZ2
|
A125M01N= GZ2
|
||||||
À2Ì05N = GZ2
|
À2Ì05N = GZ2
|
||||||
|
|
||||||
|
GZ = GZ3
|
||||||
A2* = GZ3
|
A2* = GZ3
|
||||||
A2*_O = GZ3
|
A2*_O = GZ3
|
||||||
A2*_O_O = GZ3
|
A2*_O_O = GZ3
|
||||||
|
@ -361,6 +365,7 @@ IK Omm = 6F1I
|
||||||
IKOmm = 6F1I
|
IKOmm = 6F1I
|
||||||
ИКомм = 6F1I
|
ИКомм = 6F1I
|
||||||
ИКомм24 = 6F1I
|
ИКомм24 = 6F1I
|
||||||
|
RILD = 6F1I
|
||||||
|
|
||||||
BK = LL3
|
BK = LL3
|
||||||
BK14 = LL3
|
BK14 = LL3
|
||||||
|
@ -383,6 +388,7 @@ BK_Р = LL3
|
||||||
ВК_Р = LL3
|
ВК_Р = LL3
|
||||||
бк = LL3
|
бк = LL3
|
||||||
LLD = LL3
|
LLD = LL3
|
||||||
|
LL8 = LL3
|
||||||
|
|
||||||
MBK = MLL
|
MBK = MLL
|
||||||
BMK = MLL
|
BMK = MLL
|
||||||
|
@ -543,6 +549,8 @@ GGP_Р = RHOB
|
||||||
ГГКПсем = RHOB
|
ГГКПсем = RHOB
|
||||||
ГГКР = RHOB
|
ГГКР = RHOB
|
||||||
ПЛ_ГГ = RHOB
|
ПЛ_ГГ = RHOB
|
||||||
|
DEN = RHOB
|
||||||
|
DENkz = RHOB
|
||||||
|
|
||||||
GGK-bz = GGKbz
|
GGK-bz = GGKbz
|
||||||
ГГКбз = GGKbz
|
ГГКбз = GGKbz
|
||||||
|
@ -571,5 +579,6 @@ Rez = RM
|
||||||
ннкбз = RFEN
|
ннкбз = RFEN
|
||||||
ннкмз = RNEN
|
ннкмз = RNEN
|
||||||
|
|
||||||
Кгл = VCL
|
Кгл = VCL
|
||||||
КП = POR
|
КП = POR
|
||||||
|
So = SOIL
|
||||||
|
|
|
@ -36,3 +36,9 @@ GGKmz = ГГКп бз
|
||||||
OGZ = ГЗ обр
|
OGZ = ГЗ обр
|
||||||
RFEN = ННК бз
|
RFEN = ННК бз
|
||||||
RNEN = ННК мз
|
RNEN = ННК мз
|
||||||
|
COLL = Признак коллектора
|
||||||
|
ZONELOG = номер пласта
|
||||||
|
POR = пористость
|
||||||
|
SOIL = насыщенность
|
||||||
|
VCL = глинистость
|
||||||
|
SAT = признак насыщения
|
|
@ -1,46 +1,42 @@
|
||||||
**file: data\more_20_warnings.las**
|
**file: data\more_20_warnings.las**
|
||||||
0, line: -1, desc: STEP parameter equal 0, replace to 0.000
|
0, line: -1, desc: STEP parameter equal 0, replace to 0.000
|
||||||
1, line: -1, desc: invalid STRT: 0.000 or STOP: 0.000, will be replace to actually
|
1, line: 24, desc: can't convert string: '6.2.2' to number, set to NULL
|
||||||
2, line: 24, desc: can't convert string: '6.2.2' to number, set to NULL
|
2, line: 25, desc: not all column readed, set log value to NULL
|
||||||
3, line: 25, desc: not all column readed, set log value to NULL
|
3, line: 25, desc: not all column readed, set log value to NULL
|
||||||
4, line: 25, desc: not all column readed, set log value to NULL
|
4, line: 26, desc: actual number of data lines more than expected, check: STRT, STOP, STEP
|
||||||
5, line: 27, desc: actual step 1.00 ≠ global STEP 0.00
|
5, line: 26, desc: expand number of points
|
||||||
6, line: 27, desc: can't convert string: '6.2.2' to number, set to NULL
|
6, line: 27, desc: can't convert string: '6.2.2' to number, set to NULL
|
||||||
7, line: 29, desc: actual step 1.00 ≠ global STEP 0.00
|
7, line: 29, desc: can't convert string: '5.97.' to number, set to NULL
|
||||||
8, line: 29, desc: can't convert string: '5.97.' to number, set to NULL
|
8, line: 30, desc: actual number of data lines more than expected, check: STRT, STOP, STEP
|
||||||
9, line: 31, desc: actual step 1.00 ≠ global STEP 0.00
|
9, line: 30, desc: expand number of points
|
||||||
10, line: 31, desc: can't convert string: '6.47.' to number, set to NULL
|
10, line: 31, desc: can't convert string: '6.47.' to number, set to NULL
|
||||||
11, line: 33, desc: actual step 64.00 ≠ global STEP 0.00
|
11, line: 33, desc: actual step 64.00 ≠ global STEP 1.00
|
||||||
12, line: 33, desc: step 64.00 ≠ previously step 1.00
|
12, line: 33, desc: step 64.00 ≠ previously step 1.00
|
||||||
13, line: 33, desc: can't convert string: '5.97.' to number, set to NULL
|
13, line: 33, desc: can't convert string: '5.97.' to number, set to NULL
|
||||||
14, line: 35, desc: actual step 47.00 ≠ global STEP 0.00
|
14, line: 35, desc: actual step 47.00 ≠ global STEP 1.00
|
||||||
15, line: 35, desc: step 47.00 ≠ previously step 64.00
|
15, line: 35, desc: step 47.00 ≠ previously step 64.00
|
||||||
16, line: 35, desc: can't convert string: '5.47.' to number, set to NULL
|
16, line: 35, desc: can't convert string: '5.47.' to number, set to NULL
|
||||||
17, line: 37, desc: actual step 1.00 ≠ global STEP 0.00
|
17, line: 37, desc: step 1.00 ≠ previously step 47.00
|
||||||
18, line: 37, desc: step 1.00 ≠ previously step 47.00
|
18, line: 37, desc: can't convert string: '4.7.' to number, set to NULL
|
||||||
19, line: 37, desc: can't convert string: '4.7.' to number, set to NULL
|
19, line: 38, desc: actual number of data lines more than expected, check: STRT, STOP, STEP
|
||||||
20, line: 38, desc: actual step 1.00 ≠ global STEP 0.00
|
20, line: 38, desc: expand number of points
|
||||||
21, line: 38, desc: can't convert string: '4.7.' to number, set to NULL
|
21, line: 38, desc: can't convert string: '4.7.' to number, set to NULL
|
||||||
22, line: 40, desc: line: 40 is empty, ignore
|
22, line: 40, desc: line: 40 is empty, ignore
|
||||||
23, line: 41, desc: actual step -117.20 ≠ global STEP 0.00
|
23, line: 41, desc: actual step -117.20 ≠ global STEP 1.00
|
||||||
24, line: 41, desc: step -117.20 ≠ previously step 1.00
|
24, line: 41, desc: step -117.20 ≠ previously step 1.00
|
||||||
25, line: 41, desc: not all column readed, set log value to NULL
|
25, line: 41, desc: not all column readed, set log value to NULL
|
||||||
26, line: 42, desc: actual step 170.20 ≠ global STEP 0.00
|
26, line: 42, desc: actual step 170.20 ≠ global STEP 1.00
|
||||||
27, line: 42, desc: step 170.20 ≠ previously step -117.20
|
27, line: 42, desc: step 170.20 ≠ previously step -117.20
|
||||||
28, line: 43, desc: actual step 1.00 ≠ global STEP 0.00
|
28, line: 43, desc: step 1.00 ≠ previously step 170.20
|
||||||
29, line: 43, desc: step 1.00 ≠ previously step 170.20
|
29, line: 45, desc: actual step 4.00 ≠ global STEP 1.00
|
||||||
30, line: 44, desc: actual step 1.00 ≠ global STEP 0.00
|
30, line: 45, desc: step 4.00 ≠ previously step 1.00
|
||||||
31, line: 45, desc: actual step 4.00 ≠ global STEP 0.00
|
31, line: 46, desc: step 1.00 ≠ previously step 4.00
|
||||||
32, line: 45, desc: step 4.00 ≠ previously step 1.00
|
32, line: 49, desc: actual number of data lines more than expected, check: STRT, STOP, STEP
|
||||||
33, line: 46, desc: actual step 1.00 ≠ global STEP 0.00
|
33, line: 49, desc: expand number of points
|
||||||
34, line: 46, desc: step 1.00 ≠ previously step 4.00
|
34, line: 49, desc: actual step 3.00 ≠ global STEP 1.00
|
||||||
35, line: 48, desc: actual step 1.00 ≠ global STEP 0.00
|
35, line: 49, desc: step 3.00 ≠ previously step 1.00
|
||||||
36, line: 49, desc: actual step 3.00 ≠ global STEP 0.00
|
36, line: 50, desc: step 1.00 ≠ previously step 3.00
|
||||||
37, line: 49, desc: step 3.00 ≠ previously step 1.00
|
37, line: 54, desc: actual step 0.00 ≠ global STEP 1.00
|
||||||
38, line: 50, desc: actual step 1.00 ≠ global STEP 0.00
|
38, line: 54, desc: step 0.00 ≠ previously step 1.00
|
||||||
39, line: 50, desc: step 1.00 ≠ previously step 3.00
|
39, line: 55, desc: actual step 0.00 ≠ global STEP 1.00
|
||||||
40, line: 51, desc: actual step 1.00 ≠ global STEP 0.00
|
|
||||||
41, line: 52, desc: actual step 1.00 ≠ global STEP 0.00
|
|
||||||
42, line: 53, desc: actual step 1.00 ≠ global STEP 0.00
|
|
||||||
43, line: 54, desc: step 0.00 ≠ previously step 1.00
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ UWI . WELL ID : 100091604920W300
|
||||||
D.M : 1 DEPTH
|
D.M : 1 DEPTH
|
||||||
A.US/M : 2 SONIC TRANSIT TIME
|
A.US/M : 2 SONIC TRANSIT TIME
|
||||||
B.K/M3 : 3 BULK DENSITY
|
B.K/M3 : 3 BULK DENSITY
|
||||||
C.V/V : 4 NEUTRON POROSITY
|
SP.V/V : 4 SP
|
||||||
-EL- . :
|
-EL- . :
|
||||||
-EL-1.m :
|
-EL-1.m :
|
||||||
-EL-2.v/v :
|
-EL-2.v/v :
|
||||||
|
|
|
@ -18,7 +18,7 @@ UWI . WELL ID : 100091604920W300
|
||||||
D.M : 1 DEPTH
|
D.M : 1 DEPTH
|
||||||
A.US/M : 2 SONIC TRANSIT TIME
|
A.US/M : 2 SONIC TRANSIT TIME
|
||||||
B.K/M3 : 3 BULK DENSITY
|
B.K/M3 : 3 BULK DENSITY
|
||||||
C.V/V : 4 NEUTRON POROSITY
|
SP.V/V : 4 NEUTRON POROSITY
|
||||||
. :
|
. :
|
||||||
.m :
|
.m :
|
||||||
.v/v :
|
.v/v :
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
**file: data\more_20_warnings.las**
|
**file: data\more_20_warnings.las**
|
||||||
0, line: -1, desc: STEP parameter equal 0, replace to 0.000
|
0, line: -1, desc: invalid STRT: 0.000 == STOP: 0.000, will be replace to actually
|
||||||
1, line: -1, desc: invalid STRT: 0.000 or STOP: 0.000, will be replace to actually
|
1, line: -1, desc: STEP parameter equal 0, replace to 0.000
|
||||||
2, line: 24, desc: can't convert string: '6.2.2' to number, set to NULL
|
2, line: 24, desc: can't convert string: '6.2.2' to number, set to NULL
|
||||||
3, line: 25, desc: not all column readed, set log value to NULL
|
3, line: 25, desc: not all column readed, set log value to NULL
|
||||||
4, line: 25, desc: not all column readed, set log value to NULL
|
4, line: 25, desc: not all column readed, set log value to NULL
|
||||||
|
|
406
las.go
406
las.go
|
@ -1,3 +1,6 @@
|
||||||
|
// (c) softland 2020
|
||||||
|
// softlandia@gmail.com
|
||||||
|
|
||||||
package glasio
|
package glasio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -72,6 +75,7 @@ type LasWellInfo struct {
|
||||||
// at read file always code page converted to UTF
|
// at read file always code page converted to UTF
|
||||||
// at save file code page converted to specifyed in Las.toCodePage
|
// at save file code page converted to specifyed in Las.toCodePage
|
||||||
//TODO add pointer to cfg
|
//TODO add pointer to cfg
|
||||||
|
//TODO при создании объекта las есть возможность указать кодировку записи, нужна возможность указать явно кодировку чтения
|
||||||
type Las struct {
|
type Las struct {
|
||||||
FileName string //file name from load
|
FileName string //file name from load
|
||||||
File *os.File //the file from which we are reading
|
File *os.File //the file from which we are reading
|
||||||
|
@ -96,24 +100,23 @@ type Las struct {
|
||||||
currentLine int //index of current line in readed file
|
currentLine int //index of current line in readed file
|
||||||
maxWarningCount int //default maximum warning count
|
maxWarningCount int //default maximum warning count
|
||||||
stdNull float64 //default null value
|
stdNull float64 //default null value
|
||||||
//iCodepage cpd.IDCodePage //codepage input file - autodetected
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStepFromData - return step from data section
|
// GetStepFromData - return step from data section
|
||||||
// read 2 line from section ~A and determine step
|
// read 2 line from section ~A and determine step
|
||||||
// close file
|
// close file
|
||||||
// return o.Null if error occure
|
// return Null if error occure
|
||||||
// если делать функцией, не методом, то придётся NULL передавать. а оно надо вообще
|
// если делать функцией, не методом, то придётся NULL передавать. а оно надо вообще
|
||||||
func (o *Las) GetStepFromData() float64 {
|
func (las *Las) GetStepFromData() float64 {
|
||||||
iFile, err := os.Open(o.FileName)
|
iFile, err := os.Open(las.FileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return o.Null
|
return las.Null
|
||||||
}
|
}
|
||||||
defer iFile.Close()
|
defer iFile.Close()
|
||||||
|
|
||||||
_, iScanner, err := xlib.SeekFileStop(o.FileName, "~A")
|
_, iScanner, err := xlib.SeekFileStop(las.FileName, "~A")
|
||||||
if (err != nil) || (iScanner == nil) {
|
if (err != nil) || (iScanner == nil) {
|
||||||
return o.Null
|
return las.Null
|
||||||
}
|
}
|
||||||
|
|
||||||
s := ""
|
s := ""
|
||||||
|
@ -131,7 +134,7 @@ func (o *Las) GetStepFromData() float64 {
|
||||||
}
|
}
|
||||||
dept1, err = strconv.ParseFloat(s[:k], 64)
|
dept1, err = strconv.ParseFloat(s[:k], 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return o.Null
|
return las.Null
|
||||||
}
|
}
|
||||||
j++
|
j++
|
||||||
if j == 2 {
|
if j == 2 {
|
||||||
|
@ -140,30 +143,30 @@ func (o *Las) GetStepFromData() float64 {
|
||||||
dept2 = dept1
|
dept2 = dept1
|
||||||
}
|
}
|
||||||
//если мы попали сюда, то всё грусно, в файле после ~A не нашлось двух строчек с данными... или пустые строчки или комменты
|
//если мы попали сюда, то всё грусно, в файле после ~A не нашлось двух строчек с данными... или пустые строчки или комменты
|
||||||
// TODO последняя строка "return o.Null" не обрабатывается в тесте
|
// TODO последняя строка "return las.Null" не обрабатывается в тесте
|
||||||
return o.Null
|
return las.Null
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Las) setStep(h float64) {
|
func (las *Las) setStep(h float64) {
|
||||||
o.Step = h
|
las.Step = h
|
||||||
}
|
}
|
||||||
|
|
||||||
//SetNull - change parameter NULL in WELL INFO section and in all logs
|
//SetNull - change parameter NULL in WELL INFO section and in all logs
|
||||||
func (o *Las) SetNull(aNull float64) error {
|
func (las *Las) SetNull(aNull float64) error {
|
||||||
for _, l := range o.Logs { //loop by logs
|
for _, l := range las.Logs { //loop by logs
|
||||||
for i := range l.log { //loop by dept step
|
for i := range l.log { //loop by dept step
|
||||||
if l.log[i] == o.Null {
|
if l.log[i] == las.Null {
|
||||||
l.log[i] = aNull
|
l.log[i] = aNull
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
o.Null = aNull
|
las.Null = aNull
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//logByIndex - return log from map by Index
|
//logByIndex - return log from map by Index
|
||||||
func (o *Las) logByIndex(i int) (*LasCurve, error) {
|
func (las *Las) logByIndex(i int) (*LasCurve, error) {
|
||||||
for _, v := range o.Logs {
|
for _, v := range las.Logs {
|
||||||
if v.Index == i {
|
if v.Index == i {
|
||||||
return &v, nil
|
return &v, nil
|
||||||
}
|
}
|
||||||
|
@ -205,6 +208,7 @@ func NewLas(outputCP ...cpd.IDCodePage) *Las {
|
||||||
return las
|
return las
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// NewLasPar - create new object with parameters
|
// NewLasPar - create new object with parameters
|
||||||
func NewLasPar(lasInfo LasWellInfo) *Las {
|
func NewLasPar(lasInfo LasWellInfo) *Las {
|
||||||
las := new(Las)
|
las := new(Las)
|
||||||
|
@ -225,13 +229,14 @@ func NewLasPar(lasInfo LasWellInfo) *Las {
|
||||||
las.iDuplicate = 0
|
las.iDuplicate = 0
|
||||||
return las
|
return las
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//analize first char after ~
|
// selectSection - analize first char after ~
|
||||||
//~V - section vertion
|
// ~V - section vertion
|
||||||
//~W - well info section
|
// ~W - well info section
|
||||||
//~C - curve info section
|
// ~C - curve info section
|
||||||
//~A - data section
|
// ~A - data section
|
||||||
func (o *Las) selectSection(r rune) int {
|
func (las *Las) selectSection(r rune) int {
|
||||||
switch r {
|
switch r {
|
||||||
case 86: //V
|
case 86: //V
|
||||||
return lasSecVertion //version section
|
return lasSecVertion //version section
|
||||||
|
@ -302,56 +307,56 @@ func (hc *HeaderCheckRes) addNullWarning() {
|
||||||
// - double error on STEP parameter
|
// - double error on STEP parameter
|
||||||
// - las file is WRAP == ON
|
// - las file is WRAP == ON
|
||||||
// - Curve section not exist
|
// - Curve section not exist
|
||||||
func (o *Las) checkHeader() (HeaderCheckRes, error) {
|
func (las *Las) checkHeader() (HeaderCheckRes, error) {
|
||||||
res := make(HeaderCheckRes, 0)
|
res := make(HeaderCheckRes, 0)
|
||||||
if o.Null == 0.0 {
|
if las.Null == 0.0 {
|
||||||
res.addNullWarning()
|
res.addNullWarning()
|
||||||
o.addWarning(TWarning{directOnRead, lasSecWellInfo, -1, fmt.Sprintf("NULL parameter equal 0, replace to %4.3f", o.Null)})
|
las.addWarning(TWarning{directOnRead, lasSecWellInfo, -1, fmt.Sprintf("NULL parameter equal 0, replace to %4.3f", las.Null)})
|
||||||
}
|
}
|
||||||
if o.Step == 0.0 {
|
if las.Step == 0.0 {
|
||||||
res.addStepWarning()
|
res.addStepWarning()
|
||||||
o.addWarning(TWarning{directOnRead, lasSecWellInfo, -1, fmt.Sprintf("STEP parameter equal 0, replace to %4.3f", o.Step)})
|
las.addWarning(TWarning{directOnRead, lasSecWellInfo, -1, fmt.Sprintf("STEP parameter equal 0, replace to %4.3f", las.Step)})
|
||||||
}
|
}
|
||||||
if math.Abs(o.Stop-o.Strt) < 0.1 {
|
if math.Abs(las.Stop-las.Strt) < 0.1 {
|
||||||
o.addWarning(TWarning{directOnRead, lasSecWellInfo, -1, fmt.Sprintf("invalid STRT: %4.3f or STOP: %4.3f, will be replace to actually", o.Strt, o.Stop)})
|
las.addWarning(TWarning{directOnRead, lasSecWellInfo, -1, fmt.Sprintf("invalid STRT: %4.3f or STOP: %4.3f, will be replace to actually", las.Strt, las.Stop)})
|
||||||
}
|
}
|
||||||
if o.IsWraped() {
|
if las.IsWraped() {
|
||||||
o.addWarning(TWarning{directOnRead, lasSecData, -1, "WRAP = YES, file ignored"})
|
las.addWarning(TWarning{directOnRead, lasSecData, -1, "WRAP = YES, file ignored"})
|
||||||
return res, fmt.Errorf("Wrapped files not support") //return 0, nil
|
return res, fmt.Errorf("Wrapped files not support") //return 0, nil
|
||||||
}
|
}
|
||||||
if len(o.Logs) <= 0 {
|
if len(las.Logs) <= 0 {
|
||||||
o.addWarning(TWarning{directOnRead, lasSecData, -1, "section ~Curve not exist, file ignored"})
|
las.addWarning(TWarning{directOnRead, lasSecData, -1, "section ~Curve not exist, file ignored"})
|
||||||
return res, fmt.Errorf("Curve section not exist") //return 0, nil
|
return res, fmt.Errorf("Curve section not exist") //return 0, nil
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsWraped - return true if WRAP == YES
|
// IsWraped - return true if WRAP == YES
|
||||||
func (o *Las) IsWraped() bool {
|
func (las *Las) IsWraped() bool {
|
||||||
return strings.Contains(strings.ToUpper(o.Wrap), "Y") //(strings.Index(strings.ToUpper(o.Wrap), "Y") >= 0)
|
return strings.Contains(strings.ToUpper(las.Wrap), "Y") //(strings.Index(strings.ToUpper(o.Wrap), "Y") >= 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveWarning - save to file all warning
|
// SaveWarning - save to file all warning
|
||||||
func (o *Las) SaveWarning(fileName string) error {
|
func (las *Las) SaveWarning(fileName string) error {
|
||||||
if o.Warnings.Count() == 0 {
|
if las.Warnings.Count() == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
oFile, err := os.Create(fileName)
|
oFile, err := os.Create(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
o.SaveWarningToFile(oFile)
|
las.SaveWarningToFile(oFile)
|
||||||
oFile.Close()
|
oFile.Close()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveWarningToWriter - store all warning to writer, return count lines writed to
|
// SaveWarningToWriter - store all warning to writer, return count lines writed to
|
||||||
func (o *Las) SaveWarningToWriter(writer *bufio.Writer) int {
|
func (las *Las) SaveWarningToWriter(writer *bufio.Writer) int {
|
||||||
n := o.Warnings.Count()
|
n := las.Warnings.Count()
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
for _, w := range o.Warnings {
|
for _, w := range las.Warnings {
|
||||||
writer.WriteString(w.String())
|
writer.WriteString(w.String())
|
||||||
writer.WriteString("\n")
|
writer.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
@ -359,24 +364,24 @@ func (o *Las) SaveWarningToWriter(writer *bufio.Writer) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveWarningToFile - store all warning to file, file not close. return count warning writed
|
// SaveWarningToFile - store all warning to file, file not close. return count warning writed
|
||||||
func (o *Las) SaveWarningToFile(oFile *os.File) int {
|
func (las *Las) SaveWarningToFile(oFile *os.File) int {
|
||||||
if oFile == nil {
|
if oFile == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if o.Warnings.Count() == 0 {
|
if las.Warnings.Count() == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
oFile.WriteString("**file: " + o.FileName + "**\n")
|
oFile.WriteString("**file: " + las.FileName + "**\n")
|
||||||
n := o.Warnings.SaveWarningToFile(oFile)
|
n := las.Warnings.SaveWarningToFile(oFile)
|
||||||
oFile.WriteString("\n")
|
oFile.WriteString("\n")
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Las) addWarning(w TWarning) {
|
func (las *Las) addWarning(w TWarning) {
|
||||||
if o.Warnings.Count() < o.maxWarningCount {
|
if las.Warnings.Count() < las.maxWarningCount {
|
||||||
o.Warnings = append(o.Warnings, w)
|
las.Warnings = append(las.Warnings, w)
|
||||||
if o.Warnings.Count() == o.maxWarningCount {
|
if las.Warnings.Count() == las.maxWarningCount {
|
||||||
o.Warnings = append(o.Warnings, TWarning{0, 0, 0, "*maximum count* of warning reached, change parameter 'maxWarningCount' in 'glas.ini'"})
|
las.Warnings = append(las.Warnings, TWarning{0, 0, 0, "*maximum count* of warning reached, change parameter 'maxWarningCount' in 'glas.ini'"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,15 +389,15 @@ func (o *Las) addWarning(w TWarning) {
|
||||||
// GetMnemonic - return Mnemonic from dictionary by Log Name,
|
// GetMnemonic - return Mnemonic from dictionary by Log Name,
|
||||||
// if Mnemonic not found return ""
|
// if Mnemonic not found return ""
|
||||||
// if Dictionary is nil, then return ""
|
// if Dictionary is nil, then return ""
|
||||||
func (o *Las) GetMnemonic(logName string) string {
|
func (las *Las) GetMnemonic(logName string) string {
|
||||||
if (o.LogDic == nil) || (o.VocDic == nil) {
|
if (las.LogDic == nil) || (las.VocDic == nil) {
|
||||||
return "" //"-"
|
return "" //"-"
|
||||||
}
|
}
|
||||||
_, ok := (*o.LogDic)[logName]
|
_, ok := (*las.LogDic)[logName]
|
||||||
if ok { //GOOD - название каротажа равно мнемонике
|
if ok { //GOOD - название каротажа равно мнемонике
|
||||||
return logName
|
return logName
|
||||||
}
|
}
|
||||||
v, ok := (*o.VocDic)[logName]
|
v, ok := (*las.VocDic)[logName]
|
||||||
if ok { //POOR - название загружаемого каротажа найдено в словаре подстановок, мнемоника найдена
|
if ok { //POOR - название загружаемого каротажа найдено в словаре подстановок, мнемоника найдена
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
@ -405,8 +410,58 @@ func (o *Las) GetMnemonic(logName string) string {
|
||||||
// - file cannot be decoded to UTF-8
|
// - file cannot be decoded to UTF-8
|
||||||
// - las is wrapped
|
// - las is wrapped
|
||||||
// - las file not contain Curve section
|
// - las file not contain Curve section
|
||||||
func (o *Las) Open(fileName string) (int, error) {
|
func (las *Las) Open(fileName string) (int, error) {
|
||||||
//TODO при создании объекта las есть возможность указать кодировку записи, нужна возможность указать явно кодировку чтения
|
var err error
|
||||||
|
las.File, err = os.Open(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer las.File.Close()
|
||||||
|
las.FileName = fileName
|
||||||
|
//create and store Reader, this reader decode to UTF-8
|
||||||
|
las.Reader, err = cpd.NewReader(las.File)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
las.scanner = bufio.NewScanner(las.Reader)
|
||||||
|
las.currentLine = 0
|
||||||
|
las.LoadHeader()
|
||||||
|
// проверки на фатальные ошибки
|
||||||
|
wrongChecker := NewWrongChecker()
|
||||||
|
r := wrongChecker.check(las)
|
||||||
|
if r.wrapWrong() {
|
||||||
|
las.addWarning(TWarning{directOnRead, lasSecData, -1, "WRAP = YES, file ignored"})
|
||||||
|
return 0, fmt.Errorf("Wrapped files not support")
|
||||||
|
}
|
||||||
|
if r.curvesWrong() {
|
||||||
|
las.addWarning(TWarning{directOnRead, lasSecData, -1, "section ~Curve not exist, file ignored"})
|
||||||
|
return 0, fmt.Errorf("Curve section not exist")
|
||||||
|
}
|
||||||
|
// фатальные ошибки в заголовке исключены
|
||||||
|
// делаем стандартные проверки заголовка
|
||||||
|
stdChecker := NewStdChecker()
|
||||||
|
r = stdChecker.check(las)
|
||||||
|
if r.nullWrong() {
|
||||||
|
las.addWarning(TWarning{directOnRead, lasSecWellInfo, -1, fmt.Sprintf("NULL parameter equal 0, replace to %4.3f", las.Null)})
|
||||||
|
las.SetNull(las.stdNull)
|
||||||
|
}
|
||||||
|
if r.strtStopWrong() {
|
||||||
|
las.addWarning(TWarning{directOnRead, lasSecWellInfo, -1, fmt.Sprintf("invalid STRT: %4.3f == STOP: %4.3f, will be replace to actually", las.Strt, las.Stop)})
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.stepWrong() {
|
||||||
|
las.addWarning(TWarning{directOnRead, lasSecWellInfo, -1, fmt.Sprintf("STEP parameter equal 0, replace to %4.3f", las.Step)})
|
||||||
|
h := las.GetStepFromData() // return o.Null if cannot calculate step from data
|
||||||
|
if h == las.Null {
|
||||||
|
return 0, errors.New("invalid STEP parameter and invalid step in data")
|
||||||
|
}
|
||||||
|
las.setStep(h)
|
||||||
|
}
|
||||||
|
return las.ReadDataSec(fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func (o *Las) open1(fileName string) (int, error) {
|
||||||
var err error
|
var err error
|
||||||
o.File, err = os.Open(fileName)
|
o.File, err = os.Open(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -422,12 +477,12 @@ func (o *Las) Open(fileName string) (int, error) {
|
||||||
o.scanner = bufio.NewScanner(o.Reader)
|
o.scanner = bufio.NewScanner(o.Reader)
|
||||||
o.currentLine = 0
|
o.currentLine = 0
|
||||||
o.LoadHeader()
|
o.LoadHeader()
|
||||||
|
|
||||||
// проверка корректности данных секции WELL INFO перез загрузкой данных
|
// проверка корректности данных секции WELL INFO перез загрузкой данных
|
||||||
res, err := o.checkHeader() // res содержит несколько сообщений связанных с корректностью заголовка las файла
|
res, err := o.checkHeader() // res содержит несколько сообщений связанных с корректностью заголовка las файла
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err // дальше читать файл смысла нет, или с файл переносами или нет секции Curve ...
|
return 0, err // дальше читать файл смысла нет, или файл с переносами или нет секции Curve ...
|
||||||
}
|
}
|
||||||
err = nil
|
|
||||||
// обрабатываем изменение параметров las файла по результатам чтения заголовка
|
// обрабатываем изменение параметров las файла по результатам чтения заголовка
|
||||||
if res.needUpdateNull() {
|
if res.needUpdateNull() {
|
||||||
o.SetNull(o.stdNull)
|
o.SetNull(o.stdNull)
|
||||||
|
@ -441,6 +496,7 @@ func (o *Las) Open(fileName string) (int, error) {
|
||||||
}
|
}
|
||||||
return o.ReadDataSec(fileName)
|
return o.ReadDataSec(fileName)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*LoadHeader - read las file and load all section before ~A
|
/*LoadHeader - read las file and load all section before ~A
|
||||||
secName: 0 - empty, 1 - Version, 2 - Well info, 3 - Curve info, 4 - A data
|
secName: 0 - empty, 1 - Version, 2 - Well info, 3 - Curve info, 4 - A data
|
||||||
|
@ -451,25 +507,25 @@ func (o *Las) Open(fileName string) (int, error) {
|
||||||
5. читаем одну строку (это один параметер из известной нам секции)
|
5. читаем одну строку (это один параметер из известной нам секции)
|
||||||
Пока ошибку всегда возвращает nil, причин возвращать другое значение пока нет.
|
Пока ошибку всегда возвращает nil, причин возвращать другое значение пока нет.
|
||||||
*/
|
*/
|
||||||
func (o *Las) LoadHeader() error {
|
func (las *Las) LoadHeader() error {
|
||||||
s := ""
|
s := ""
|
||||||
var err error
|
var err error
|
||||||
secNum := 0
|
secNum := 0
|
||||||
for i := 0; o.scanner.Scan(); i++ {
|
for i := 0; las.scanner.Scan(); i++ {
|
||||||
s = strings.TrimSpace(o.scanner.Text())
|
s = strings.TrimSpace(las.scanner.Text())
|
||||||
o.currentLine++
|
las.currentLine++
|
||||||
if isIgnoredLine(s) {
|
if isIgnoredLine(s) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if s[0] == '~' { //start new section
|
if s[0] == '~' { //start new section
|
||||||
secNum = o.selectSection(rune(s[1]))
|
secNum = las.selectSection(rune(s[1]))
|
||||||
if secNum == lasSecData {
|
if secNum == lasSecData {
|
||||||
break // dAta section read after //exit from for
|
break // dAta section read after //exit from for
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = o.ReadParameter(s, secNum) //if not comment, not empty and not new section => parameter, read it
|
err = las.ReadParameter(s, secNum) //if not comment, not empty and not new section => parameter, read it
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.addWarning(TWarning{directOnRead, secNum, -1, fmt.Sprintf("while process parameter: '%s' occure error: %v", s, err)})
|
las.addWarning(TWarning{directOnRead, secNum, -1, fmt.Sprintf("while process parameter: '%s' occure error: %v", s, err)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,53 +533,53 @@ func (o *Las) LoadHeader() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadParameter - read one parameter
|
// ReadParameter - read one parameter
|
||||||
func (o *Las) ReadParameter(s string, secNum int) error {
|
func (las *Las) ReadParameter(s string, secNum int) error {
|
||||||
switch secNum {
|
switch secNum {
|
||||||
case lasSecVertion:
|
case lasSecVertion:
|
||||||
return o.readVersionParam(s)
|
return las.readVersionParam(s)
|
||||||
case lasSecWellInfo:
|
case lasSecWellInfo:
|
||||||
return o.ReadWellParam(s)
|
return las.ReadWellParam(s)
|
||||||
case lasSecCurInfo:
|
case lasSecCurInfo:
|
||||||
return o.readCurveParam(s)
|
return las.readCurveParam(s)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Las) readVersionParam(s string) error {
|
func (las *Las) readVersionParam(s string) error {
|
||||||
var err error
|
var err error
|
||||||
p := NewLasParam(s)
|
p := NewLasParam(s)
|
||||||
switch p.Name {
|
switch p.Name {
|
||||||
case "VERS":
|
case "VERS":
|
||||||
o.Ver, err = strconv.ParseFloat(p.Val, 64)
|
las.Ver, err = strconv.ParseFloat(p.Val, 64)
|
||||||
case "WRAP":
|
case "WRAP":
|
||||||
o.Wrap = p.Val
|
las.Wrap = p.Val
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReadWellParam - read parameter from WELL section
|
//ReadWellParam - read parameter from WELL section
|
||||||
func (o *Las) ReadWellParam(s string) error {
|
func (las *Las) ReadWellParam(s string) error {
|
||||||
var err error
|
var err error
|
||||||
p := NewLasParam(s)
|
p := NewLasParam(s)
|
||||||
switch p.Name {
|
switch p.Name {
|
||||||
case "STRT":
|
case "STRT":
|
||||||
o.Strt, err = strconv.ParseFloat(p.Val, 64)
|
las.Strt, err = strconv.ParseFloat(p.Val, 64)
|
||||||
case "STOP":
|
case "STOP":
|
||||||
o.Stop, err = strconv.ParseFloat(p.Val, 64)
|
las.Stop, err = strconv.ParseFloat(p.Val, 64)
|
||||||
case "STEP":
|
case "STEP":
|
||||||
o.Step, err = strconv.ParseFloat(p.Val, 64)
|
las.Step, err = strconv.ParseFloat(p.Val, 64)
|
||||||
case "NULL":
|
case "NULL":
|
||||||
o.Null, err = strconv.ParseFloat(p.Val, 64)
|
las.Null, err = strconv.ParseFloat(p.Val, 64)
|
||||||
case "WELL":
|
case "WELL":
|
||||||
if o.Ver < 2.0 {
|
if las.Ver < 2.0 {
|
||||||
o.Well = p.Desc
|
las.Well = p.Desc
|
||||||
} else {
|
} else {
|
||||||
//o.Well = p.Val
|
//las.Well = p.Val
|
||||||
o.Well = wellNameFromParam(p)
|
las.Well = wellNameFromParam(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.addWarning(TWarning{directOnRead, lasSecWellInfo, -1, fmt.Sprintf("detected param: %v, unit:%v, value: %v\n", p.Name, p.Unit, p.Val)})
|
las.addWarning(TWarning{directOnRead, lasSecWellInfo, -1, fmt.Sprintf("detected param: %v, unit:%v, value: %v\n", p.Name, p.Unit, p.Val)})
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -532,11 +588,11 @@ func (o *Las) ReadWellParam(s string) error {
|
||||||
//if input name unique, return input name
|
//if input name unique, return input name
|
||||||
//if input name not unique, return input name + index duplicate
|
//if input name not unique, return input name + index duplicate
|
||||||
//index duplicate - Las field, increase
|
//index duplicate - Las field, increase
|
||||||
func (o *Las) ChangeDuplicateLogName(name string) string {
|
func (las *Las) ChangeDuplicateLogName(name string) string {
|
||||||
s := ""
|
s := ""
|
||||||
if _, ok := o.Logs[name]; ok {
|
if _, ok := las.Logs[name]; ok {
|
||||||
o.iDuplicate++
|
las.iDuplicate++
|
||||||
s = fmt.Sprintf("%v", o.iDuplicate)
|
s = fmt.Sprintf("%v", las.iDuplicate)
|
||||||
name += s
|
name += s
|
||||||
}
|
}
|
||||||
return name
|
return name
|
||||||
|
@ -548,69 +604,69 @@ func (o *Las) ChangeDuplicateLogName(name string) string {
|
||||||
//IName - имя каротажа в исходном файле, может повторятся
|
//IName - имя каротажа в исходном файле, может повторятся
|
||||||
//Name - ключ в map хранилище, повторятся не может. если в исходном есть повторение, то Name строится добавлением к IName индекса
|
//Name - ключ в map хранилище, повторятся не может. если в исходном есть повторение, то Name строится добавлением к IName индекса
|
||||||
//Mnemonic - мнемоника, берётся из словаря, если в словаре не найдено, то ""
|
//Mnemonic - мнемоника, берётся из словаря, если в словаре не найдено, то ""
|
||||||
func (o *Las) readCurveParam(s string) error {
|
func (las *Las) readCurveParam(s string) error {
|
||||||
l := NewLasCurve(s)
|
l := NewLasCurve(s)
|
||||||
l.Init(len(o.Logs), o.GetMnemonic(l.Name), o.ChangeDuplicateLogName(l.Name), o.GetExpectedPointsCount())
|
l.Init(len(las.Logs), las.GetMnemonic(l.Name), las.ChangeDuplicateLogName(l.Name), las.GetExpectedPointsCount())
|
||||||
o.Logs[l.Name] = l //добавление в хранилище кривой каротажа с колонкой глубин
|
las.Logs[l.Name] = l //добавление в хранилище кривой каротажа с колонкой глубин
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetExpectedPointsCount - оценка количества точек по параметрам STEP, STRT, STOP
|
//GetExpectedPointsCount - оценка количества точек по параметрам STEP, STRT, STOP
|
||||||
func (o *Las) GetExpectedPointsCount() int {
|
func (las *Las) GetExpectedPointsCount() int {
|
||||||
var m int
|
var m int
|
||||||
//TODO нужно обработать все случаи
|
//TODO нужно обработать все случаи
|
||||||
if o.Step == 0.0 {
|
if las.Step == 0.0 {
|
||||||
return o.ePoints
|
return las.ePoints
|
||||||
}
|
}
|
||||||
if math.Abs(o.Stop) > math.Abs(o.Strt) {
|
if math.Abs(las.Stop) > math.Abs(las.Strt) {
|
||||||
m = int((o.Stop-o.Strt)/o.Step) + 2
|
m = int((las.Stop-las.Strt)/las.Step) + 2
|
||||||
} else {
|
} else {
|
||||||
m = int((o.Strt-o.Stop)/o.Step) + 2
|
m = int((las.Strt-las.Stop)/las.Step) + 2
|
||||||
}
|
}
|
||||||
if m < 0 {
|
if m < 0 {
|
||||||
m = -m
|
m = -m
|
||||||
}
|
}
|
||||||
if m == 0 {
|
if m == 0 {
|
||||||
return o.ePoints
|
return las.ePoints
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
//expandDept - if actually data points exceeds
|
//expandDept - if actually data points exceeds
|
||||||
func (o *Las) expandDept(d *LasCurve) {
|
func (las *Las) expandDept(d *LasCurve) {
|
||||||
//actual number of points more then expected
|
//actual number of points more then expected
|
||||||
o.addWarning(TWarning{directOnRead, lasSecData, o.currentLine, "actual number of data lines more than expected, check: STRT, STOP, STEP"})
|
las.addWarning(TWarning{directOnRead, lasSecData, las.currentLine, "actual number of data lines more than expected, check: STRT, STOP, STEP"})
|
||||||
o.addWarning(TWarning{directOnRead, lasSecData, o.currentLine, "expand number of points"})
|
las.addWarning(TWarning{directOnRead, lasSecData, las.currentLine, "expand number of points"})
|
||||||
//ожидаем удвоения данных
|
//ожидаем удвоения данных
|
||||||
o.ePoints *= 2
|
las.ePoints *= 2
|
||||||
//expand first log - dept
|
//expand first log - dept
|
||||||
newDept := make([]float64, o.ePoints)
|
newDept := make([]float64, las.ePoints)
|
||||||
copy(newDept, d.dept)
|
copy(newDept, d.dept)
|
||||||
d.dept = newDept
|
d.dept = newDept
|
||||||
|
|
||||||
newLog := make([]float64, o.ePoints)
|
newLog := make([]float64, las.ePoints)
|
||||||
copy(newLog, d.dept)
|
copy(newLog, d.dept)
|
||||||
d.log = newLog
|
d.log = newLog
|
||||||
o.Logs[d.Name] = *d
|
las.Logs[d.Name] = *d
|
||||||
|
|
||||||
//loop over other logs
|
//loop over other logs
|
||||||
n := len(o.Logs)
|
n := len(las.Logs)
|
||||||
var l *LasCurve
|
var l *LasCurve
|
||||||
for j := 1; j < n; j++ {
|
for j := 1; j < n; j++ {
|
||||||
l, _ = o.logByIndex(j)
|
l, _ = las.logByIndex(j)
|
||||||
newDept := make([]float64, o.ePoints)
|
newDept := make([]float64, las.ePoints)
|
||||||
copy(newDept, l.dept)
|
copy(newDept, l.dept)
|
||||||
l.dept = newDept
|
l.dept = newDept
|
||||||
|
|
||||||
newLog := make([]float64, o.ePoints)
|
newLog := make([]float64, las.ePoints)
|
||||||
copy(newLog, l.log)
|
copy(newLog, l.log)
|
||||||
l.log = newLog
|
l.log = newLog
|
||||||
o.Logs[l.Name] = *l
|
las.Logs[l.Name] = *l
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadDataSec - read section of data
|
// ReadDataSec - read section of data
|
||||||
func (o *Las) ReadDataSec(fileName string) (int, error) {
|
func (las *Las) ReadDataSec(fileName string) (int, error) {
|
||||||
var (
|
var (
|
||||||
v float64
|
v float64
|
||||||
err error
|
err error
|
||||||
|
@ -621,45 +677,49 @@ func (o *Las) ReadDataSec(fileName string) (int, error) {
|
||||||
)
|
)
|
||||||
|
|
||||||
//исходя из параметров STRT, STOP и STEP определяем ожидаемое количество строк данных
|
//исходя из параметров STRT, STOP и STEP определяем ожидаемое количество строк данных
|
||||||
o.ePoints = o.GetExpectedPointsCount()
|
las.ePoints = las.GetExpectedPointsCount()
|
||||||
//o.currentLine++
|
//o.currentLine++
|
||||||
n := len(o.Logs) //количество каротажей, столько колонок данных ожидаем
|
n := len(las.Logs) //количество каротажей, столько колонок данных ожидаем
|
||||||
d, _ = o.logByIndex(0) //dept log
|
d, _ = las.logByIndex(0) //dept log
|
||||||
s := ""
|
s := ""
|
||||||
for i = 0; o.scanner.Scan(); i++ {
|
for i = 0; las.scanner.Scan(); i++ {
|
||||||
o.currentLine++
|
las.currentLine++
|
||||||
if i == o.ePoints {
|
if i == las.ePoints {
|
||||||
o.expandDept(d)
|
las.expandDept(d)
|
||||||
}
|
}
|
||||||
s = strings.TrimSpace(o.scanner.Text())
|
s = strings.TrimSpace(las.scanner.Text())
|
||||||
|
// i счётчик не строк, а фактически считанных данных - счётчик добавлений в слайсы данных
|
||||||
|
//TODO возможно следует завести отдельный счётчик и оставить в покое счётчик цикла
|
||||||
if isIgnoredLine(s) {
|
if isIgnoredLine(s) {
|
||||||
i--
|
i--
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
//first column is DEPT
|
//first column is DEPT
|
||||||
k := strings.IndexRune(s, ' ')
|
k := strings.IndexRune(s, ' ') //TODO вероятно получим ошибку если данные будут разделены не пробелом а табуляцией или ещё чем-то
|
||||||
if k < 0 { //line must have n+1 column and n separated spaces block (+1 becouse first column DEPT)
|
if k < 0 { //line must have n+1 column and n separated spaces block (+1 becouse first column DEPT)
|
||||||
o.addWarning(TWarning{directOnRead, lasSecData, o.currentLine, fmt.Sprintf("line: %d is empty, ignore", o.currentLine)})
|
las.addWarning(TWarning{directOnRead, lasSecData, las.currentLine, fmt.Sprintf("line: %d is empty, ignore", las.currentLine)})
|
||||||
i--
|
i--
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dept, err = strconv.ParseFloat(s[:k], 64)
|
dept, err = strconv.ParseFloat(s[:k], 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.addWarning(TWarning{directOnRead, lasSecData, o.currentLine, fmt.Sprintf("first column '%s' not numeric, ignore", s[:k])})
|
las.addWarning(TWarning{directOnRead, lasSecData, las.currentLine, fmt.Sprintf("first column '%s' not numeric, ignore", s[:k])})
|
||||||
i--
|
i--
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
d.dept[i] = dept
|
d.dept[i] = dept
|
||||||
|
// проверка шага у первых двух точек данных и сравнение с параметром step
|
||||||
|
//TODO данную проверку следует делать через Checker
|
||||||
if i > 1 {
|
if i > 1 {
|
||||||
if math.Pow(((dept-d.dept[i-1])-o.Step), 2) > 0.1 {
|
if math.Pow(((dept-d.dept[i-1])-las.Step), 2) > 0.1 {
|
||||||
o.addWarning(TWarning{directOnRead, lasSecData, o.currentLine, fmt.Sprintf("actual step %5.2f ≠ global STEP %5.2f", (dept - d.dept[i-1]), o.Step)})
|
las.addWarning(TWarning{directOnRead, lasSecData, las.currentLine, fmt.Sprintf("actual step %5.2f ≠ global STEP %5.2f", (dept - d.dept[i-1]), las.Step)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// проверка шага между точками [i-1, i] и точками [i-2, i-1] обнаружение немонотонности колонки глубин
|
||||||
if i > 2 {
|
if i > 2 {
|
||||||
if math.Pow(((dept-d.dept[i-1])-(d.dept[i-1]-d.dept[i-2])), 2) > 0.1 {
|
if math.Pow(((dept-d.dept[i-1])-(d.dept[i-1]-d.dept[i-2])), 2) > 0.1 {
|
||||||
o.addWarning(TWarning{directOnRead, lasSecData, o.currentLine, fmt.Sprintf("step %5.2f ≠ previously step %5.2f", (dept - d.dept[i-1]), (d.dept[i-1] - d.dept[i-2]))})
|
las.addWarning(TWarning{directOnRead, lasSecData, las.currentLine, fmt.Sprintf("step %5.2f ≠ previously step %5.2f", (dept - d.dept[i-1]), (d.dept[i-1] - d.dept[i-2]))})
|
||||||
dept = d.dept[i-1] + o.Step
|
dept = d.dept[i-1] + las.Step
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,22 +729,22 @@ func (o *Las) ReadDataSec(fileName string) (int, error) {
|
||||||
iSpace := strings.IndexRune(s, ' ')
|
iSpace := strings.IndexRune(s, ' ')
|
||||||
switch iSpace {
|
switch iSpace {
|
||||||
case -1: //не все колонки прочитаны, а пробелов уже нет... пробуем игнорировать сроку заполняя оставшиеся каротажи NULLами
|
case -1: //не все колонки прочитаны, а пробелов уже нет... пробуем игнорировать сроку заполняя оставшиеся каротажи NULLами
|
||||||
o.addWarning(TWarning{directOnRead, lasSecData, o.currentLine, "not all column readed, set log value to NULL"})
|
las.addWarning(TWarning{directOnRead, lasSecData, las.currentLine, "not all column readed, set log value to NULL"})
|
||||||
case 0:
|
case 0:
|
||||||
v = o.Null
|
v = las.Null
|
||||||
case 1:
|
case 1:
|
||||||
v, err = strconv.ParseFloat(s[:1], 64)
|
v, err = strconv.ParseFloat(s[:1], 64)
|
||||||
default:
|
default:
|
||||||
v, err = strconv.ParseFloat(s[:iSpace], 64) //strconv.ParseFloat(s[:iSpace-1], 64)
|
v, err = strconv.ParseFloat(s[:iSpace], 64) //strconv.ParseFloat(s[:iSpace-1], 64)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.addWarning(TWarning{directOnRead, lasSecData, o.currentLine, fmt.Sprintf("can't convert string: '%s' to number, set to NULL", s[:iSpace-1])})
|
las.addWarning(TWarning{directOnRead, lasSecData, las.currentLine, fmt.Sprintf("can't convert string: '%s' to number, set to NULL", s[:iSpace-1])})
|
||||||
v = o.Null
|
v = las.Null
|
||||||
}
|
}
|
||||||
l, err = o.logByIndex(j)
|
l, err = las.logByIndex(j)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.nPoints = i
|
las.nPoints = i
|
||||||
return i, errors.New("internal ERROR, func (o *Las) readDataSec()::o.logByIndex(j) return error")
|
return i, errors.New("internal ERROR, func (las *Las) readDataSec()::las.logByIndex(j) return error")
|
||||||
}
|
}
|
||||||
l.dept[i] = dept
|
l.dept[i] = dept
|
||||||
l.log[i] = v
|
l.log[i] = v
|
||||||
|
@ -693,20 +753,21 @@ func (o *Las) ReadDataSec(fileName string) (int, error) {
|
||||||
//остаток - последняя колонка
|
//остаток - последняя колонка
|
||||||
v, err = strconv.ParseFloat(s, 64)
|
v, err = strconv.ParseFloat(s, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.addWarning(TWarning{directOnRead, lasSecData, o.currentLine, "not all column readed, set log value to NULL"})
|
las.addWarning(TWarning{directOnRead, lasSecData, las.currentLine, "not all column readed, set log value to NULL"})
|
||||||
v = o.Null
|
v = las.Null
|
||||||
}
|
}
|
||||||
l, err = o.logByIndex(n - 1)
|
l, err = las.logByIndex(n - 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.nPoints = i
|
las.nPoints = i
|
||||||
return i, errors.New("internal ERROR, func (o *Las) readDataSec()::o.logByIndex(j) return error on last column")
|
return i, errors.New("internal ERROR, func (las *Las) readDataSec()::las.logByIndex(j) return error on last column")
|
||||||
}
|
}
|
||||||
l.dept[i] = dept
|
l.dept[i] = dept
|
||||||
l.log[i] = v
|
l.log[i] = v
|
||||||
}
|
}
|
||||||
//i - actually readed lines and add (.) to data array
|
//i - actually readed lines and add (.) to data array
|
||||||
//crop logs to actually len
|
//crop logs to actually len
|
||||||
err = o.setActuallyNumberPoints(i)
|
//TODO перенести в Open()
|
||||||
|
err = las.setActuallyNumberPoints(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -714,32 +775,32 @@ func (o *Las) ReadDataSec(fileName string) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumPoints - return actually number of points in data
|
// NumPoints - return actually number of points in data
|
||||||
func (o *Las) NumPoints() int {
|
func (las *Las) NumPoints() int {
|
||||||
return o.nPoints
|
return las.nPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
//Dept - return slice of DEPT curve (first column)
|
//Dept - return slice of DEPT curve (first column)
|
||||||
func (o *Las) Dept() []float64 {
|
func (las *Las) Dept() []float64 {
|
||||||
d, err := o.logByIndex(0)
|
d, err := las.logByIndex(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return d.dept
|
return d.dept
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Las) setActuallyNumberPoints(numPoints int) error {
|
func (las *Las) setActuallyNumberPoints(numPoints int) error {
|
||||||
if numPoints <= 0 {
|
if numPoints <= 0 {
|
||||||
o.nPoints = 0
|
las.nPoints = 0
|
||||||
return errors.New("internal ERROR, func (o *Las) setActuallyNumberPoints(), actually number of points <= 0")
|
return errors.New("internal ERROR, func (las *Las) setActuallyNumberPoints(), actually number of points <= 0")
|
||||||
}
|
}
|
||||||
if numPoints > len(o.Dept()) {
|
if numPoints > len(las.Dept()) {
|
||||||
o.nPoints = 0
|
las.nPoints = 0
|
||||||
return errors.New("internal ERROR, func (o *Las) setActuallyNumberPoints(), actually number of points > then exist data")
|
return errors.New("internal ERROR, func (las *Las) setActuallyNumberPoints(), actually number of points > then exist data")
|
||||||
}
|
}
|
||||||
for _, l := range o.Logs {
|
for _, l := range las.Logs {
|
||||||
l.SetLen(numPoints)
|
l.SetLen(numPoints)
|
||||||
}
|
}
|
||||||
o.nPoints = numPoints
|
las.nPoints = numPoints
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,15 +882,15 @@ func (o *Las) SaveToFile(fileName string, useMnemonic ...bool) error {
|
||||||
//rewrite if file exist
|
//rewrite if file exist
|
||||||
//if useMnemonic == true then on save using std mnemonic on ~Curve section
|
//if useMnemonic == true then on save using std mnemonic on ~Curve section
|
||||||
//TODO las have field filename of readed las file, after save filename must update or not? warning occure on write for what file?
|
//TODO las have field filename of readed las file, after save filename must update or not? warning occure on write for what file?
|
||||||
func (o *Las) Save(fileName string, useMnemonic ...bool) error {
|
func (las *Las) Save(fileName string, useMnemonic ...bool) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
bufToSave []byte
|
bufToSave []byte
|
||||||
)
|
)
|
||||||
if len(useMnemonic) > 0 {
|
if len(useMnemonic) > 0 {
|
||||||
bufToSave, err = o.SaveToBuf(true)
|
bufToSave, err = las.SaveToBuf(true)
|
||||||
} else {
|
} else {
|
||||||
bufToSave, err = o.SaveToBuf(false)
|
bufToSave, err = las.SaveToBuf(false)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -851,22 +912,22 @@ func (o *Las) Save(fileName string, useMnemonic ...bool) error {
|
||||||
// rewrite if file exist
|
// rewrite if file exist
|
||||||
// if useMnemonic == true then on save using std mnemonic on ~Curve section
|
// if useMnemonic == true then on save using std mnemonic on ~Curve section
|
||||||
// ir return err != nil then fatal error, returned slice is not full corrected
|
// ir return err != nil then fatal error, returned slice is not full corrected
|
||||||
func (o *Las) SaveToBuf(useMnemonic bool) ([]byte, error) {
|
func (las *Las) SaveToBuf(useMnemonic bool) ([]byte, error) {
|
||||||
n := len(o.Logs) //log count
|
n := len(las.Logs) //log count
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
return nil, errors.New("logs not exist")
|
return nil, errors.New("logs not exist")
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
fmt.Fprint(&b, _LasFirstLine)
|
fmt.Fprint(&b, _LasFirstLine)
|
||||||
fmt.Fprintf(&b, _LasVersion, o.Ver)
|
fmt.Fprintf(&b, _LasVersion, las.Ver)
|
||||||
fmt.Fprint(&b, _LasWrap)
|
fmt.Fprint(&b, _LasWrap)
|
||||||
fmt.Fprint(&b, _LasWellInfoSec)
|
fmt.Fprint(&b, _LasWellInfoSec)
|
||||||
fmt.Fprintf(&b, _LasStrt, o.Strt)
|
fmt.Fprintf(&b, _LasStrt, las.Strt)
|
||||||
fmt.Fprintf(&b, _LasStop, o.Stop)
|
fmt.Fprintf(&b, _LasStop, las.Stop)
|
||||||
fmt.Fprintf(&b, _LasStep, o.Step)
|
fmt.Fprintf(&b, _LasStep, las.Step)
|
||||||
fmt.Fprintf(&b, _LasNull, o.Null)
|
fmt.Fprintf(&b, _LasNull, las.Null)
|
||||||
fmt.Fprintf(&b, _LasWell, o.Well)
|
fmt.Fprintf(&b, _LasWell, las.Well)
|
||||||
fmt.Fprint(&b, _LasCurvSec)
|
fmt.Fprint(&b, _LasCurvSec)
|
||||||
fmt.Fprint(&b, _LasCurvDept)
|
fmt.Fprint(&b, _LasCurvDept)
|
||||||
|
|
||||||
|
@ -874,7 +935,7 @@ func (o *Las) SaveToBuf(useMnemonic bool) ([]byte, error) {
|
||||||
sb.WriteString("# DEPT |") //готовим строчку с названиями каротажей глубина всегда присутствует
|
sb.WriteString("# DEPT |") //готовим строчку с названиями каротажей глубина всегда присутствует
|
||||||
var l *LasCurve
|
var l *LasCurve
|
||||||
for i := 1; i < n; i++ { //Пишем названия каротажей
|
for i := 1; i < n; i++ { //Пишем названия каротажей
|
||||||
l, _ := o.logByIndex(i)
|
l, _ := las.logByIndex(i)
|
||||||
if useMnemonic {
|
if useMnemonic {
|
||||||
if len(l.Mnemonic) > 0 {
|
if len(l.Mnemonic) > 0 {
|
||||||
l.Name = l.Mnemonic
|
l.Name = l.Mnemonic
|
||||||
|
@ -888,20 +949,25 @@ func (o *Las) SaveToBuf(useMnemonic bool) ([]byte, error) {
|
||||||
fmt.Fprint(&b, _LasDataSec)
|
fmt.Fprint(&b, _LasDataSec)
|
||||||
//write data
|
//write data
|
||||||
fmt.Fprintf(&b, "%s\n", sb.String())
|
fmt.Fprintf(&b, "%s\n", sb.String())
|
||||||
dept, _ := o.logByIndex(0)
|
dept, _ := las.logByIndex(0)
|
||||||
for i := 0; i < o.nPoints; i++ { //loop by dept (.)
|
for i := 0; i < las.nPoints; i++ { //loop by dept (.)
|
||||||
fmt.Fprintf(&b, "%-9.3f ", dept.dept[i])
|
fmt.Fprintf(&b, "%-9.3f ", dept.dept[i])
|
||||||
for j := 1; j < n; j++ { //loop by logs
|
for j := 1; j < n; j++ { //loop by logs
|
||||||
l, err = o.logByIndex(j)
|
l, err = las.logByIndex(j)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.addWarning(TWarning{directOnWrite, lasSecData, i, "logByIndex() return error, log not found, panic"})
|
las.addWarning(TWarning{directOnWrite, lasSecData, i, "logByIndex() return error, log not found, panic"})
|
||||||
return nil, errors.New("logByIndex() return error, log not found, panic")
|
return nil, errors.New("logByIndex() return error, log not found, panic")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(&b, "%-9.3f ", l.log[i])
|
fmt.Fprintf(&b, "%-9.3f ", l.log[i])
|
||||||
}
|
}
|
||||||
fmt.Fprintln(&b)
|
fmt.Fprintln(&b)
|
||||||
}
|
}
|
||||||
r, _ := cpd.NewReaderTo(io.Reader(&b), o.oCodepage.String()) //ошибку не обрабатываем, допустимость oCodepage проверяем раньше, других причин нет
|
r, _ := cpd.NewReaderTo(io.Reader(&b), las.oCodepage.String()) //ошибку не обрабатываем, допустимость oCodepage проверяем раньше, других причин нет
|
||||||
bufToSave, _ := ioutil.ReadAll(r)
|
bufToSave, _ := ioutil.ReadAll(r)
|
||||||
return bufToSave, nil
|
return bufToSave, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsEmpty - test to not initialize object
|
||||||
|
func (las *Las) IsEmpty() bool {
|
||||||
|
return (las.Logs == nil)
|
||||||
|
}
|
||||||
|
|
190
las_checker.go
190
las_checker.go
|
@ -1,6 +1,192 @@
|
||||||
|
//(c) softland 2020
|
||||||
|
//softlandia@gmail.com
|
||||||
|
|
||||||
package glasio
|
package glasio
|
||||||
|
|
||||||
// Check -
|
import "fmt"
|
||||||
func Check() {
|
|
||||||
|
|
||||||
|
// CheckRes - результаты проверки, получааем из функции doCheck()
|
||||||
|
type CheckRes struct {
|
||||||
|
name string
|
||||||
|
section string
|
||||||
|
message string
|
||||||
|
err error
|
||||||
|
res bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cr CheckRes) String() string {
|
||||||
|
return fmt.Sprintf("check name: %s, section: %s, desc: %s, result: %v", cr.name, cr.section, cr.message, cr.res)
|
||||||
|
}
|
||||||
|
|
||||||
|
type doCheck func(chk Check, las *Las) CheckRes
|
||||||
|
|
||||||
|
// Check - отдельная проверка, обязан реализовать функцию doCheck()
|
||||||
|
type Check struct {
|
||||||
|
name string
|
||||||
|
section string
|
||||||
|
message string
|
||||||
|
do doCheck
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkResults - слайс с результатами всех проверок
|
||||||
|
type checkResults []CheckRes
|
||||||
|
|
||||||
|
func (crs checkResults) nullWrong() bool {
|
||||||
|
for _, r := range crs {
|
||||||
|
if r.name == "NullNot0" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crs checkResults) stepWrong() bool {
|
||||||
|
for _, r := range crs {
|
||||||
|
if r.name == "StepNot0" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crs checkResults) wrapWrong() bool {
|
||||||
|
for _, r := range crs {
|
||||||
|
if r.name == "WrapIsOn" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crs checkResults) curvesWrong() bool {
|
||||||
|
for _, r := range crs {
|
||||||
|
if r.name == "CurvesNotPresent" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (crs checkResults) strtStopWrong() bool {
|
||||||
|
for _, r := range crs {
|
||||||
|
if r.name == "StrtStop" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checker - ПРОВЕРЩИК, содержит в себе всех отдельных проверщиков,
|
||||||
|
// методом check() вызавает последовательно всех своих проверщиков,
|
||||||
|
// результаты отправляет в Logger
|
||||||
|
type Checker []Check
|
||||||
|
|
||||||
|
func (c Checker) check(las *Las) checkResults {
|
||||||
|
res := make([]CheckRes, 0)
|
||||||
|
for _, chk := range c {
|
||||||
|
r := chk.do(chk, las)
|
||||||
|
if !r.res {
|
||||||
|
res = append(res, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************/
|
||||||
|
|
||||||
|
// NewEmptyChecker - создание нового примитивного объекта ПРОВЕРЩИКА
|
||||||
|
// проверяет только на не пустоту объекта las
|
||||||
|
func NewEmptyChecker() Checker {
|
||||||
|
return Checker{
|
||||||
|
{chkEmptyName, chkEmptySection, "", emptyCheck},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
chkEmptyName = "LasNotNil"
|
||||||
|
chkEmptySection = "NoN"
|
||||||
|
)
|
||||||
|
|
||||||
|
// simpleCheck - return true if las not empty
|
||||||
|
func emptyCheck(chk Check, las *Las) CheckRes {
|
||||||
|
return CheckRes{chk.name, chk.section, chk.message, nil, !las.IsEmpty()}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************/
|
||||||
|
|
||||||
|
// NewWrongChecker - создание нового ПРОВЕРЩИКА на ошибочность las файла.
|
||||||
|
// WRAP = ON
|
||||||
|
// section ~Curve is empty
|
||||||
|
func NewWrongChecker() Checker {
|
||||||
|
return Checker{
|
||||||
|
newWrapCheck(),
|
||||||
|
newNotPresentCurvesCheck(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newWrapCheck() Check {
|
||||||
|
return Check{"WrapIsOn", "~V", "WRAP = ON", wrapOn}
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrapOn(chk Check, las *Las) CheckRes {
|
||||||
|
return CheckRes{chk.name, chk.section, chk.message, fmt.Errorf("Wrapped files not support"), !las.IsWraped()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newNotPresentCurvesCheck() Check {
|
||||||
|
return Check{"CurvesNotPresent", "~C", "Curve section is eptry", curvesIsEmpty}
|
||||||
|
}
|
||||||
|
|
||||||
|
func curvesIsEmpty(chk Check, las *Las) CheckRes {
|
||||||
|
return CheckRes{chk.name, chk.section, chk.message, fmt.Errorf("Curve section not exist"), len(las.Logs) > 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStdChecker - создание нового стандартного ПРОВЕРЩИКА
|
||||||
|
// проверяет las
|
||||||
|
// STEP == 0
|
||||||
|
// NULL == 0
|
||||||
|
// STRT == STOP
|
||||||
|
// WELL is empty
|
||||||
|
func NewStdChecker() Checker {
|
||||||
|
return Checker{
|
||||||
|
newStepCheck(),
|
||||||
|
newNullCheck(),
|
||||||
|
newStrtStopCheck(),
|
||||||
|
newWellIsEmptyCheck(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step Check
|
||||||
|
func newStepCheck() Check {
|
||||||
|
return Check{"StepNot0", "~W", "STEP == 0", stepCheck}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stepCheck(chk Check, las *Las) CheckRes {
|
||||||
|
return CheckRes{chk.name, chk.section, chk.message, nil, las.Step != 0.0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Null Check
|
||||||
|
func newNullCheck() Check {
|
||||||
|
return Check{"NullNot0", "~W", "NULL == 0", nullCheck}
|
||||||
|
}
|
||||||
|
|
||||||
|
func nullCheck(chk Check, las *Las) CheckRes {
|
||||||
|
return CheckRes{chk.name, chk.section, chk.message, nil, las.Null != 0.0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// STRT == STOP Check
|
||||||
|
func newStrtStopCheck() Check {
|
||||||
|
return Check{"StrtStop", "~W", "STRT == STOP", strtStopCheck}
|
||||||
|
}
|
||||||
|
|
||||||
|
func strtStopCheck(chk Check, las *Las) CheckRes {
|
||||||
|
return CheckRes{chk.name, chk.section, chk.message, nil, las.Strt != las.Stop}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WELL == "" Check
|
||||||
|
func newWellIsEmptyCheck() Check {
|
||||||
|
return Check{"WellNotEmpty", "~W", "WELL == ''", wellIsEmptyCheck}
|
||||||
|
}
|
||||||
|
|
||||||
|
func wellIsEmptyCheck(chk Check, las *Las) CheckRes {
|
||||||
|
return CheckRes{chk.name, chk.section, chk.message, nil, len(las.Well) != 0}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,50 @@
|
||||||
|
//(c) softland 2020
|
||||||
|
//softlandia@gmail.com
|
||||||
|
|
||||||
package glasio
|
package glasio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LasLog - store log info about the one las, fills up info from las.open() and las.check()
|
// Logger - store log info about the one las, fills up info from las.open() and las.check()
|
||||||
type LasLog struct {
|
type Logger struct {
|
||||||
las *Las // object from message collected
|
las *Las // object from message collected
|
||||||
filename string // file to read, used for reporting // имя файла по которому формируется отчёт, используется для оформления сообщений
|
filename string // file to read, used for reporting // имя файла по которому формируется отчёт, используется для оформления сообщений
|
||||||
readedNumPoints int // number points readed from file get from las.Open()
|
readedNumPoints int // number points readed from file get from las.Open()
|
||||||
errorOnOpen error // status from las.Open()
|
errorOnOpen error // status from las.Open()
|
||||||
msgOpen TLasWarnings // сообщения формируемые в процессе открытия las файла
|
msgOpen TLasWarnings // сообщения формируемые в процессе открытия las файла
|
||||||
msgCheck tCheckMsg // информация об особых случаях, получаем из LasChecker
|
msgCheck tCheckMsg // информация об особых проверках, получаем из LasChecker
|
||||||
msgCurve tCurvRprt // информация о кривых хранящихся в LAS файле, записывается в "log.info.md"
|
msgCurve tCurvRprt // информация о кривых хранящихся в LAS файле, записывается в "log.info.md"
|
||||||
missMnemonic tMMnemonic // мнемоники найденные в файле и не найденные в словаре
|
missMnemonic tMMnemonic // мнемоники найденные в файле и не найденные в словаре
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLasLog - constructor
|
// NewLogger - constructor
|
||||||
func NewLasLog(las *Las) LasLog {
|
func NewLogger(las *Las) *Logger {
|
||||||
var lasLog LasLog
|
logger := new(Logger)
|
||||||
lasLog.las = las
|
logger.las = las
|
||||||
lasLog.filename = las.FileName
|
logger.filename = las.FileName
|
||||||
lasLog.msgOpen = nil
|
logger.msgOpen = nil
|
||||||
lasLog.msgCheck = make(tCheckMsg, 0, 10)
|
logger.msgCheck = make(tCheckMsg, 0, 10)
|
||||||
lasLog.msgCurve = make(tCurvRprt, 0, 10)
|
logger.msgCurve = make(tCurvRprt, 0, 10)
|
||||||
lasLog.missMnemonic = make(tMMnemonic)
|
logger.missMnemonic = make(tMMnemonic)
|
||||||
return lasLog
|
return logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tCheckMsg - хранит все сообщения о специальных проверках las файла
|
||||||
type tCheckMsg []string
|
type tCheckMsg []string
|
||||||
|
|
||||||
|
func (m tCheckMsg) String() string {
|
||||||
|
var sb strings.Builder
|
||||||
|
for _, msg := range m {
|
||||||
|
sb.WriteString(msg)
|
||||||
|
}
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
func (m *tCheckMsg) save(f *os.File) {
|
func (m *tCheckMsg) save(f *os.File) {
|
||||||
for _, msg := range *m {
|
for _, msg := range *m {
|
||||||
f.WriteString(msg)
|
f.WriteString(msg)
|
||||||
|
@ -52,9 +65,20 @@ func (m *tCheckMsg) msgFileOpenWarning(fn string, err error) string {
|
||||||
|
|
||||||
type tCurvRprt []string
|
type tCurvRprt []string
|
||||||
|
|
||||||
func (ir *tCurvRprt) save(f *os.File, filename string) {
|
func (cr tCurvRprt) String(filename string) string {
|
||||||
|
var sb strings.Builder
|
||||||
|
sb.WriteString(fmt.Sprintf("##logs in file: '%s'##\n", filename))
|
||||||
|
for _, s := range cr {
|
||||||
|
sb.WriteString(s)
|
||||||
|
sb.WriteString("\n")
|
||||||
|
}
|
||||||
|
sb.WriteString("\n")
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cr *tCurvRprt) save(f *os.File, filename string) {
|
||||||
fmt.Fprintf(f, "##logs in file: '%s'##\n", filename)
|
fmt.Fprintf(f, "##logs in file: '%s'##\n", filename)
|
||||||
for _, s := range *ir {
|
for _, s := range *cr {
|
||||||
f.WriteString(s)
|
f.WriteString(s)
|
||||||
}
|
}
|
||||||
f.WriteString("\n")
|
f.WriteString("\n")
|
||||||
|
@ -62,6 +86,19 @@ func (ir *tCurvRprt) save(f *os.File, filename string) {
|
||||||
|
|
||||||
type tMMnemonic map[string]string
|
type tMMnemonic map[string]string
|
||||||
|
|
||||||
|
func (mm tMMnemonic) String() string {
|
||||||
|
keys := make([]string, 0, len(mm))
|
||||||
|
for k := range mm {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
var sb strings.Builder
|
||||||
|
for _, k := range keys {
|
||||||
|
sb.WriteString(mm[k] + "\n")
|
||||||
|
}
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
func (mm *tMMnemonic) save(f *os.File) {
|
func (mm *tMMnemonic) save(f *os.File) {
|
||||||
keys := make([]string, 0, len(*mm))
|
keys := make([]string, 0, len(*mm))
|
||||||
for k := range *mm {
|
for k := range *mm {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//(c) softland 2020
|
// (c) softland 2020
|
||||||
//softlandia@gmail.com
|
// softlandia@gmail.com
|
||||||
package glasio
|
package glasio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -50,7 +50,7 @@ var dSummaryCheck = []tSummaryCheck{
|
||||||
{fp.Join("data/missing_vers.las"), 2.0, "NO", 1670, 1660, -0.125, -999.25, "WELL", 8, 3, false},
|
{fp.Join("data/missing_vers.las"), 2.0, "NO", 1670, 1660, -0.125, -999.25, "WELL", 8, 3, false},
|
||||||
{fp.Join("data/missing_wrap.las"), 1.2, "NO", 1670, 1660, -0.125, -999.25, "ANY ET AL OIL WELL #12", 8, 3, false},
|
{fp.Join("data/missing_wrap.las"), 1.2, "NO", 1670, 1660, -0.125, -999.25, "ANY ET AL OIL WELL #12", 8, 3, false},
|
||||||
{fp.Join("data/more_20_warnings.las"), 1.2, "NO", 0.0, 0.0, 1.0, -32768.0, "6", 6, 23, true}, //in las file STEP=0.0 but this incorrect, LoadHeader replace STEP to actual from data
|
{fp.Join("data/more_20_warnings.las"), 1.2, "NO", 0.0, 0.0, 1.0, -32768.0, "6", 6, 23, true}, //in las file STEP=0.0 but this incorrect, LoadHeader replace STEP to actual from data
|
||||||
{fp.Join("data/no-data-section.las"), 1.2, "NO", 0.0, 0.0, -32768, -32768.0, "6", 31, 0, true},
|
{fp.Join("data/no-data-section.las"), 1.2, "NO", 0.0, 0.0, 0.0, -32768.0, "6", 31, 0, true}, //in las file STEP=0.0 but this incorrect, data section contain incorrect step too, result step equal from input
|
||||||
{fp.Join("data/sample_bracketed_units.las"), 1.2, "NO", 1670, 1660, -0.125, -999.25, "ANY ET AL OIL WELL #12", 8, 3, true},
|
{fp.Join("data/sample_bracketed_units.las"), 1.2, "NO", 1670, 1660, -0.125, -999.25, "ANY ET AL OIL WELL #12", 8, 3, true},
|
||||||
{fp.Join("data/test-curve-sec-empty-mnemonic.las"), 1.2, "NO", 1670, 1669.75, -0.125, -999.25, "ANY ET AL OIL WELL #12", 8, 3, true},
|
{fp.Join("data/test-curve-sec-empty-mnemonic.las"), 1.2, "NO", 1670, 1669.75, -0.125, -999.25, "ANY ET AL OIL WELL #12", 8, 3, true},
|
||||||
{fp.Join("data/UWI_API_leading_zero.las"), 1.2, "NO", 1670, 1660, -0.125, -999.25, "ANY ET AL OIL WELL #12", 8, 3, true},
|
{fp.Join("data/UWI_API_leading_zero.las"), 1.2, "NO", 1670, 1660, -0.125, -999.25, "ANY ET AL OIL WELL #12", 8, 3, true},
|
||||||
|
@ -91,3 +91,56 @@ func TestCurveSec2(t *testing.T) {
|
||||||
assert.False(t, cmpLas(correct, las))
|
assert.False(t, cmpLas(correct, las))
|
||||||
assert.False(t, correct.Logs.Cmp(las.Logs))
|
assert.False(t, correct.Logs.Cmp(las.Logs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLasCheck(t *testing.T) {
|
||||||
|
lasLog := LasCheck(fp.Join("data/test-curve-sec-empty-mnemonic+.las"))
|
||||||
|
assert.NotNil(t, lasLog)
|
||||||
|
s := lasLog.msgOpen.ToString()
|
||||||
|
assert.Empty(t, s)
|
||||||
|
s = lasLog.msgCheck.String()
|
||||||
|
assert.Empty(t, s)
|
||||||
|
s = lasLog.msgCurve.String(fp.Join("data/test-curve-sec-empty-mnemonic+.las"))
|
||||||
|
assert.Contains(t, s, "test-curve-sec-empty-mnemonic+.las'##")
|
||||||
|
|
||||||
|
// проверка на возврат nil
|
||||||
|
lasLog, err := LasDeepCheck(fp.Join("data/test-curve-sec-empty-mnemonic+.las"), fp.Join("data/mnemonic.-"), fp.Join("data/dic.ini"))
|
||||||
|
assert.Nil(t, lasLog)
|
||||||
|
lasLog, err = LasDeepCheck(fp.Join("data/test-curve-sec-empty-mnemonic+.las"), fp.Join("data/mnemonic.ini"), fp.Join("data/dic.-"))
|
||||||
|
assert.Nil(t, lasLog)
|
||||||
|
|
||||||
|
lasLog, err = LasDeepCheck(fp.Join("data/test-curve-sec-empty-mnemonic+.las"), fp.Join("data/mnemonic.ini"), fp.Join("data/dic.ini"))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
s = lasLog.msgCurve.String(fp.Join("data/test-curve-sec-empty-mnemonic+.las"))
|
||||||
|
assert.Contains(t, s, "*input log: B internal: B mnemonic:*")
|
||||||
|
assert.Contains(t, s, "input log: SP internal: SP mnemonic: SP")
|
||||||
|
assert.Contains(t, s, "*input log: -EL-2 internal: -EL-2 mnemonic:*")
|
||||||
|
s = lasLog.missMnemonic.String()
|
||||||
|
assert.Contains(t, s, "-EL-1")
|
||||||
|
assert.NotContains(t, s, "SP")
|
||||||
|
|
||||||
|
lasLog, err = LasDeepCheck(fp.Join("data/more_20_warnings.las"), fp.Join("data/mnemonic.ini"), fp.Join("data/dic.ini"))
|
||||||
|
assert.NotNil(t, lasLog)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
s = lasLog.msgOpen.ToString()
|
||||||
|
assert.Contains(t, s, "STEP parameter equal 0")
|
||||||
|
assert.Contains(t, s, "invalid STRT: 0.000 == STOP: 0.000, will be replace to actually")
|
||||||
|
s = lasLog.msgCheck.String()
|
||||||
|
assert.Empty(t, s)
|
||||||
|
s = lasLog.msgCurve.String(fp.Join("data/more_20_warnings.las"))
|
||||||
|
assert.Contains(t, s, "*input log: второй каротаж internal: второй каротаж mnemonic:*")
|
||||||
|
assert.Contains(t, s, "input log: GK internal: GK mnemonic: GR")
|
||||||
|
assert.Contains(t, s, "*input log: первый internal: первый mnemonic:*")
|
||||||
|
s = lasLog.missMnemonic.String()
|
||||||
|
assert.Contains(t, s, "NNB")
|
||||||
|
assert.Contains(t, s, "второй каротаж")
|
||||||
|
assert.NotContains(t, s, "GR")
|
||||||
|
|
||||||
|
// случай если файла нет
|
||||||
|
lasLog, err = LasDeepCheck(fp.Join("data/-test-curve-sec-empty-mnemonic+.las"), fp.Join("data/mnemonic.ini"), fp.Join("data/dic.ini"))
|
||||||
|
assert.NotNil(t, lasLog)
|
||||||
|
assert.NotNil(t, lasLog.errorOnOpen)
|
||||||
|
|
||||||
|
// случай las файл WRAP
|
||||||
|
lasLog = LasCheck(fp.Join("data/1.2/sample_wrapped.las"))
|
||||||
|
assert.Contains(t, lasLog.msgCheck.String(), "WRAP=YES")
|
||||||
|
}
|
||||||
|
|
100
las_test.go
100
las_test.go
|
@ -131,33 +131,6 @@ func TestLoadLasHeader(t *testing.T) {
|
||||||
assert.Nil(t, las)
|
assert.Nil(t, las)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
func TestLoadHeaderUtf(t *testing.T) {
|
|
||||||
las := NewLas()
|
|
||||||
las.iCodepage, _ = cpd.FileCodePageDetect(fp.Join("data/encodings_utf8wbom.las"))
|
|
||||||
las.LoadHeader(fp.Join("data/encodings_utf8wbom.las"))
|
|
||||||
assert.Equal(t, 1.2, las.Ver, fmt.Sprintf("<LoadHeader> file 'encodings_utf8wbom.las' readed VER: %f, expected %f", las.Ver, 1.2))
|
|
||||||
assert.Equal(t, "NO", las.Wrap, fmt.Sprintf("<LoadHeader> file 'encodings_utf8wbom.las' readed WRAP: %s, expected %s", las.Wrap, "NO"))
|
|
||||||
assert.Equal(t, 1670.0, las.Strt, fmt.Sprintf("<LoadHeader> file 'encodings_utf8wbom.las' readed STRT: %f, expected %f", las.Strt, 1670.0))
|
|
||||||
assert.Equal(t, 1660.0, las.Stop, fmt.Sprintf("<LoadHeader> file 'encodings_utf8wbom.las' readed STOP: %f, expected %f", las.Stop, 1660.0))
|
|
||||||
assert.Equal(t, -0.1250, las.Step, fmt.Sprintf("<LoadHeader> file 'encodings_utf8wbom.las' readed STEP: %f, expected %f", las.Step, -0.1250))
|
|
||||||
assert.Equal(t, -999.250, las.Null, fmt.Sprintf("<LoadHeader> file 'encodings_utf8wbom.las' readed NULL: %f, expected %f", las.Null, -999.250))
|
|
||||||
assert.Equal(t, "Скважина ºᶟᵌᴬń #12", las.Well, fmt.Sprintf("<LoadHeader> file 'encodings_utf8wbom.las' readed WELL: %s, expected %s", las.Well, "Скважина ºᶟᵌᴬń #12"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestLoadHeaderUtf16le(t *testing.T) {
|
|
||||||
las := NewLas()
|
|
||||||
las.iCodepage, _ = cpd.FileCodePageDetect(fp.Join("data/encodings_utf16lebom.las"))
|
|
||||||
las.LoadHeader(fp.Join("data/encodings_utf16lebom.las"))
|
|
||||||
assert.Equal(t, 1.2, las.Ver, fmt.Sprintf("file 'encodings_utf16lebom.las' readed VER: %f, expected %f", las.Ver, 1.2))
|
|
||||||
assert.Equal(t, "NO", las.Wrap, fmt.Sprintf("file 'encodings_utf16lebom.las' readed WRAP: %s, expected %s", las.Wrap, "NO"))
|
|
||||||
assert.Equal(t, 1670.0, las.Strt, fmt.Sprintf("file 'encodings_utf16lebom.las' readed STRT: %f, expected %f", las.Strt, 1670.0))
|
|
||||||
assert.Equal(t, 1660.0, las.Stop, fmt.Sprintf("file 'encodings_utf16lebom.las' readed STOP: %f, expected %f", las.Stop, 1660.0))
|
|
||||||
assert.Equal(t, -0.1250, las.Step, fmt.Sprintf("file 'encodings_utf16lebom.las' readed STEP: %f, expected %f", las.Step, -0.1250))
|
|
||||||
assert.Equal(t, -999.25, las.Null, fmt.Sprintf("file 'encodings_utf16lebom.las' readed NULL: %f, expected %f", las.Null, -999.25))
|
|
||||||
assert.Equal(t, "ºᶟᵌᴬń BLOCK", las.Well, fmt.Sprintf("file 'encodings_utf16lebom.las' readed WELL: %s, expected %s", las.Well, "ºᶟᵌᴬń BLOCK"))
|
|
||||||
}*/
|
|
||||||
|
|
||||||
func TestLasSaveWarning(t *testing.T) {
|
func TestLasSaveWarning(t *testing.T) {
|
||||||
las := NewLas()
|
las := NewLas()
|
||||||
las.Open(fp.Join("data/more_20_warnings.las"))
|
las.Open(fp.Join("data/more_20_warnings.las"))
|
||||||
|
@ -176,9 +149,9 @@ type tGetDataStep struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var dGetDataStep = []tGetDataStep{
|
var dGetDataStep = []tGetDataStep{
|
||||||
{fp.Join("data/step-2-data-without-step-case1.las"), -32768.000},
|
{fp.Join("data/step-2-data-without-step-case1.las"), 0.0},
|
||||||
{fp.Join("data/step-2-data-without-step-case2.las"), -32768.000},
|
{fp.Join("data/step-2-data-without-step-case2.las"), 0.0},
|
||||||
{fp.Join("data/no-data-section.las"), -32768.000},
|
{fp.Join("data/no-data-section.las"), 0.0},
|
||||||
{fp.Join("data/step-1-normal-case.las"), 1.0},
|
{fp.Join("data/step-1-normal-case.las"), 1.0},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,8 +215,8 @@ type tSaveLas struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var dSaveLas = []tSaveLas{
|
var dSaveLas = []tSaveLas{
|
||||||
{fp.Join("test_files/~1251.las"), cpd.CP1251, -99.99, 0.201, 10.01, 0.01, "Примерная-101 / бис", -0.1},
|
|
||||||
// filename codepage null strt stop step well name new null
|
// filename codepage null strt stop step well name new null
|
||||||
|
{fp.Join("test_files/~1251.las"), cpd.CP1251, -99.99, 0.201, 10.01, 0.01, "Примерная-101 / бис", -0.1},
|
||||||
{fp.Join("test_files/~koi8.las"), cpd.KOI8R, -99.0, 0.2, 2.0, -0.1, "Примерная-1001 /\"бис\"", -55.55},
|
{fp.Join("test_files/~koi8.las"), cpd.KOI8R, -99.0, 0.2, 2.0, -0.1, "Примерная-1001 /\"бис\"", -55.55},
|
||||||
{fp.Join("test_files/~866.las"), cpd.CP866, -909.0, 2.21, 12.1, -0.1, "Примерная-101 /\"бис\"", 5555.55},
|
{fp.Join("test_files/~866.las"), cpd.CP866, -909.0, 2.21, 12.1, -0.1, "Примерная-101 /\"бис\"", 5555.55},
|
||||||
{fp.Join("test_files/~utf-8.las"), cpd.UTF8, -999.99, 20.21, 1.0, -0.01, "Примерная-101А / бис", -999.25},
|
{fp.Join("test_files/~utf-8.las"), cpd.UTF8, -999.99, 20.21, 1.0, -0.01, "Примерная-101А / бис", -999.25},
|
||||||
|
@ -277,6 +250,71 @@ func TestSetNullOnEmptyLas(t *testing.T) {
|
||||||
assert.Equal(t, -1000.0, las.Null)
|
assert.Equal(t, -1000.0, las.Null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLasIsEmpty(t *testing.T) {
|
||||||
|
las := Las{}
|
||||||
|
assert.True(t, las.IsEmpty())
|
||||||
|
las = *NewLas()
|
||||||
|
assert.False(t, las.IsEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
type tStdCheckLas struct {
|
||||||
|
cp cpd.IDCodePage
|
||||||
|
null float64
|
||||||
|
strt float64
|
||||||
|
stop float64
|
||||||
|
step float64
|
||||||
|
well string
|
||||||
|
testsRes [4]bool // stdCheck contain 4 test
|
||||||
|
}
|
||||||
|
|
||||||
|
var dCheckLas = []tStdCheckLas{
|
||||||
|
//codepage null strt stop step well name проверки step null strt well
|
||||||
|
{cpd.CP1251, 0.0, 0.201, 10.01, 0.01, "Примерная-101 / бис", [4]bool{true, false, true, true}},
|
||||||
|
{cpd.CP1251, -99.99, 0.201, 10.01, 0.0, "Примерная-101 / бис", [4]bool{false, true, true, true}},
|
||||||
|
{cpd.KOI8R, 0.0, 0.2, 2.0, 0.0, "Примерная-1001 /\"бис\"", [4]bool{false, false, true, true}},
|
||||||
|
{cpd.CP866, 0.0, 0.21, 0.21, 0.1, "Примерная-101 /\"бис\"", [4]bool{true, false, false, true}},
|
||||||
|
{cpd.UTF8, 0.0, 0.2, 0.2, 0.0, "", [4]bool{false, false, false, false}},
|
||||||
|
{cpd.UTF16LE, 0.0, 20.2, 1.0, -0.0, "", [4]bool{false, false, true, false}},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLasChecker(t *testing.T) {
|
||||||
|
chkr := NewEmptyChecker()
|
||||||
|
assert.NotEqual(t, 0, len(chkr))
|
||||||
|
chkr = NewStdChecker() //стандартная проверка на step=0, null=0, strt=stop, well=""
|
||||||
|
for _, tmp := range dCheckLas {
|
||||||
|
las := makeSampleLas(tmp.cp, tmp.null, tmp.strt, tmp.stop, tmp.step, tmp.well)
|
||||||
|
assert.NotEqual(t, 0, len(chkr))
|
||||||
|
for i, chk := range chkr {
|
||||||
|
checkRes := chk.do(chk, las)
|
||||||
|
assert.Equal(t, tmp.testsRes[i], checkRes.res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLasChecker2(t *testing.T) {
|
||||||
|
stdChecker := NewStdChecker()
|
||||||
|
|
||||||
|
tmp := dCheckLas[0] // в данных одна ошиба, NULL=0
|
||||||
|
las := makeSampleLas(tmp.cp, tmp.null, tmp.strt, tmp.stop, tmp.step, tmp.well)
|
||||||
|
res := stdChecker.check(las)
|
||||||
|
assert.Equal(t, 1, len(res))
|
||||||
|
assert.Equal(t, res[0].name, "NullNot0")
|
||||||
|
assert.True(t, res.nullWrong())
|
||||||
|
assert.False(t, res.stepWrong())
|
||||||
|
|
||||||
|
tmp = dCheckLas[4] // все 4 ошибки
|
||||||
|
las = makeSampleLas(tmp.cp, tmp.null, tmp.strt, tmp.stop, tmp.step, tmp.well)
|
||||||
|
res = stdChecker.check(las)
|
||||||
|
assert.Equal(t, 4, len(res))
|
||||||
|
assert.Equal(t, res[0].name, "StepNot0")
|
||||||
|
assert.Equal(t, res[3].message, "WELL == ''")
|
||||||
|
assert.True(t, res.stepWrong())
|
||||||
|
|
||||||
|
las = makeSampleLas(cpd.CP866, -999.25, 0, 100, 0.2, "well") //правильные данные
|
||||||
|
res = stdChecker.check(las) //StdChecker должен вернуть пустой слайс
|
||||||
|
assert.Equal(t, 0, len(res))
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkSave1(b *testing.B) {
|
func BenchmarkSave1(b *testing.B) {
|
||||||
for _, tmp := range dSaveLas {
|
for _, tmp := range dSaveLas {
|
||||||
las := makeSampleLas(tmp.cp, tmp.null, tmp.strt, tmp.stop, tmp.step, tmp.well)
|
las := makeSampleLas(tmp.cp, tmp.null, tmp.strt, tmp.stop, tmp.step, tmp.well)
|
||||||
|
|
62
las_util.go
62
las_util.go
|
@ -5,6 +5,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
fp "path/filepath"
|
||||||
|
|
||||||
"github.com/softlandia/cpd"
|
"github.com/softlandia/cpd"
|
||||||
)
|
)
|
||||||
|
@ -82,39 +83,56 @@ func LoadLasHeader(fileName string) (*Las, error) {
|
||||||
return las, nil
|
return las, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LasCheck - read and check las file, return object with all warnings
|
||||||
// считывает файл и собирает все сообщения в один объект
|
// считывает файл и собирает все сообщения в один объект
|
||||||
func lasOpenCheck(filename string) LasLog {
|
// это базовая проверка las файла, прелесть в том что здесь собираются сообщения от прочтения файла
|
||||||
|
func LasCheck(filename string) *Logger {
|
||||||
las := NewLas() // TODO make special constructor to initialize with global Mnemonic and Dic
|
las := NewLas()
|
||||||
//las.LogDic = &Mnemonic // global var
|
n, err := las.Open(filename)
|
||||||
//las.VocDic = &Dic // global var
|
lasLog := NewLogger(las)
|
||||||
|
lasLog.readedNumPoints = n
|
||||||
LasLog := NewLasLog(las)
|
lasLog.errorOnOpen = err
|
||||||
|
lasLog.msgOpen = las.Warnings
|
||||||
LasLog.readedNumPoints, LasLog.errorOnOpen = las.Open(filename)
|
|
||||||
LasLog.msgOpen = las.Warnings
|
|
||||||
|
|
||||||
if las.IsWraped() {
|
if las.IsWraped() {
|
||||||
LasLog.msgCheck = append(LasLog.msgCheck, LasLog.msgCheck.msgFileIsWraped(filename))
|
lasLog.msgCheck = append(lasLog.msgCheck, lasLog.msgCheck.msgFileIsWraped(filename))
|
||||||
//return statLasCheck_WRAP
|
|
||||||
}
|
}
|
||||||
if las.NumPoints() == 0 {
|
if las.NumPoints() == 0 {
|
||||||
LasLog.msgCheck = append(LasLog.msgCheck, LasLog.msgCheck.msgFileNoData(filename))
|
lasLog.msgCheck = append(lasLog.msgCheck, lasLog.msgCheck.msgFileNoData(filename))
|
||||||
//return statLasCheck_DATA
|
|
||||||
}
|
}
|
||||||
if LasLog.errorOnOpen != nil {
|
if lasLog.errorOnOpen != nil {
|
||||||
LasLog.msgCheck = append(LasLog.msgCheck, LasLog.msgCheck.msgFileOpenWarning(filename, LasLog.errorOnOpen))
|
lasLog.msgCheck = append(lasLog.msgCheck, lasLog.msgCheck.msgFileOpenWarning(filename, lasLog.errorOnOpen))
|
||||||
}
|
}
|
||||||
|
las = nil //TODO уверен это грубая ошибка, Logger хранит в себе las НАФИГА мы его тут убиваем...
|
||||||
|
return lasLog
|
||||||
|
}
|
||||||
|
|
||||||
|
// LasDeepCheck - read and check las file, curve name checked to mnemonic, return object with all warnings
|
||||||
|
// считывает файл и собирает все сообщения в один объект
|
||||||
|
func LasDeepCheck(filename, mnemonicFile, vocdicFile string) (*Logger, error) {
|
||||||
|
lasLog := LasCheck(filename)
|
||||||
|
//TODO здесь засада, LasCheck сам создаёт и читает las, более того он вообще-то его в себе хранит,
|
||||||
|
// НО в данном случае нам СТОИТ??? или НЕ СТОИТ??? об этом забывать
|
||||||
|
// мы ведь вынуждены всё равно прочитать ещё раз las файл
|
||||||
|
las := NewLas()
|
||||||
|
Mnemonic, err := LoadStdMnemonicDic(fp.Join(mnemonicFile))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
VocDic, err := LoadStdVocabularyDictionary(fp.Join(vocdicFile))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
las.LogDic = &Mnemonic
|
||||||
|
las.VocDic = &VocDic
|
||||||
|
las.Open(filename) //читаем второй раз, когда подключены словари, то чтение идёт иначе )))
|
||||||
for k, v := range las.Logs {
|
for k, v := range las.Logs {
|
||||||
if len(v.Mnemonic) == 0 { //v.Mnemonic содержит автоопределённую стандартную мнемонику, если она пустая, значит пропущена, помечаем **
|
if len(v.Mnemonic) == 0 { //v.Mnemonic содержит автоопределённую стандартную мнемонику, если она пустая, значит пропущена, помечаем **
|
||||||
LasLog.msgCurve = append(LasLog.msgCurve, fmt.Sprintf("*input log: %s \t internal: %s \t mnemonic:%s*\n", v.IName, k, v.Mnemonic))
|
lasLog.msgCurve = append(lasLog.msgCurve, fmt.Sprintf("*input log: %s \t internal: %s \t mnemonic:%s*\n", v.IName, k, v.Mnemonic))
|
||||||
LasLog.missMnemonic[v.IName] = v.IName
|
lasLog.missMnemonic[v.IName] = v.IName
|
||||||
} else {
|
} else {
|
||||||
LasLog.msgCurve = append(LasLog.msgCurve, fmt.Sprintf("input log: %s \t internal: %s \t mnemonic: %s\n", v.IName, k, v.Mnemonic))
|
lasLog.msgCurve = append(lasLog.msgCurve, fmt.Sprintf("input log: %s \t internal: %s \t mnemonic: %s\n", v.IName, k, v.Mnemonic))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
las = nil
|
las = nil
|
||||||
return LasLog
|
return lasLog, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ func (o TLasWarnings) Count() int {
|
||||||
// ToString - make one string from all elements
|
// ToString - make one string from all elements
|
||||||
// sep[0] - record separator разделитель записей
|
// sep[0] - record separator разделитель записей
|
||||||
// sep[1] - field separator разделитель полей
|
// sep[1] - field separator разделитель полей
|
||||||
// default separator between field ";" between record "\n"
|
// default separator between field "," between record "\n"
|
||||||
// on empty container return ""
|
// on empty container return ""
|
||||||
func (o *TLasWarnings) ToString(sep ...string) string {
|
func (o *TLasWarnings) ToString(sep ...string) string {
|
||||||
if o.Count() == 0 {
|
if o.Count() == 0 {
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
//(c) softland 2020
|
||||||
|
//softlandia@gmail.com
|
||||||
|
package glasio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCheckMeaasges(t *testing.T) {
|
||||||
|
chMsg := make(tCheckMsg, 2)
|
||||||
|
chMsg[0] = "message 1"
|
||||||
|
chMsg[1] = "message 2"
|
||||||
|
assert.Contains(t, chMsg.String(), "1")
|
||||||
|
assert.NotContains(t, chMsg.String(), "0")
|
||||||
|
}
|
2
ver.txt
2
ver.txt
|
@ -1 +1 @@
|
||||||
0.1.6
|
0.1.7
|
||||||
|
|
Загрузка…
Ссылка в новой задаче