SegmentSignalPy 0.1.3__cp315-cp315-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- C DLL/DLLExport.h +11 -0
- CPP Static Library/NoiseVarianceEstimateMethod.h +17 -0
- CPP Static Library/SegmentSignal.cpp +167 -0
- CPP Static Library/SegmentSignal.h +195 -0
- CPP Static Library/SegmentSignalFunctions.cpp +797 -0
- CPP Static Library/SegmentSignalFunctions.h +52 -0
- CPP Static Library/SegmentationResults.cpp +82 -0
- CPP Static Library/SegmentationResults.h +101 -0
- CPP Unit Tests/InputDataEnum.h +14 -0
- CPP Unit Tests/stdafx.h +13 -0
- CPP Unit Tests/targetver.h +8 -0
- Python Extension/SegmentationResultsPy.cpp +126 -0
- Python Extension/SegmentationResultsPy.h +119 -0
- Python Extension/module.cpp +140 -0
- Python Extension/setup.py +26 -0
- SegmentSignalPy.cp315-win_amd64.pyd +0 -0
- segmentsignalpy-0.1.3.dist-info/METADATA +72 -0
- segmentsignalpy-0.1.3.dist-info/RECORD +21 -0
- segmentsignalpy-0.1.3.dist-info/WHEEL +5 -0
- segmentsignalpy-0.1.3.dist-info/licenses/License.txt +20 -0
- segmentsignalpy-0.1.3.dist-info/top_level.txt +9 -0
|
@@ -0,0 +1,797 @@
|
|
|
1
|
+
#include "SegmentSignalFunctions.h"
|
|
2
|
+
#include <stdlib.h>
|
|
3
|
+
#include <math.h>
|
|
4
|
+
#include <windows.h>
|
|
5
|
+
#include <malloc.h>
|
|
6
|
+
#include <stdexcept>
|
|
7
|
+
|
|
8
|
+
// Original function name: LOGSEG
|
|
9
|
+
void SegmentSignal(double LOG[], int NSAMPS, double F, int ORDER, int ORDER1, int RMODE, int NITER, int Q[], int& NQ, double FLTLOG[], double SEGLOG[], double R[], double& C, double& D, int& NACT, int& IER)
|
|
10
|
+
{
|
|
11
|
+
// Function:
|
|
12
|
+
// Maximum Likelihood Segmentation
|
|
13
|
+
//
|
|
14
|
+
// Input parameters:
|
|
15
|
+
// LOG: Input discretized well log.
|
|
16
|
+
//
|
|
17
|
+
// NSAMPS: Number of samples in array log.
|
|
18
|
+
//
|
|
19
|
+
// F: Segmentation threshold index.
|
|
20
|
+
//
|
|
21
|
+
// ORDER: Length of the moving average window used for smoothing the input well
|
|
22
|
+
// log to arrive at an initial estimate of jump sequence variance, C.
|
|
23
|
+
//
|
|
24
|
+
// ORDER1: Length of the moving average window used for smoothing the noise variances.
|
|
25
|
+
//
|
|
26
|
+
// RMODE: Noise variance estimate option.
|
|
27
|
+
// RMODE = 0 ==> Point estimate of noise variance.
|
|
28
|
+
// RMODE = 1 ==> Noise estimates smoothed within segments.
|
|
29
|
+
//
|
|
30
|
+
// NITER: Upper bound on the number of SingleMostLikelihoodReplacement iterations.
|
|
31
|
+
//
|
|
32
|
+
// Output parameters:
|
|
33
|
+
// Q: Binary event sequence.
|
|
34
|
+
//
|
|
35
|
+
// NQ: Number of binary events found (number of "1"s in Q).
|
|
36
|
+
//
|
|
37
|
+
// FLTLOG: Filtered estimate of the signal. Also used as intermediate work array.
|
|
38
|
+
//
|
|
39
|
+
// SEGLOG: FLTLOG averaged over each segment.
|
|
40
|
+
//
|
|
41
|
+
// R: Estimated noise variance.
|
|
42
|
+
//
|
|
43
|
+
// C: Estimated variance of the jump sequence.
|
|
44
|
+
//
|
|
45
|
+
// D: Estimated segment density.
|
|
46
|
+
//
|
|
47
|
+
// NACT: Actual SingleMostLikelihoodReplacement iteration count.
|
|
48
|
+
//
|
|
49
|
+
// IER: Error flag.
|
|
50
|
+
// IER = 0 ==> No error.
|
|
51
|
+
// IER < 0 ==> Invalid event density estimated after threshold. Reduce/increase F and rerun.
|
|
52
|
+
// IER > 0 ==> Logarithm argument became zero at sample number IER during the calculation of
|
|
53
|
+
// likelihood ratios in SingleMostLikelihoodReplacement. There may be more samples of this type which may give rise
|
|
54
|
+
// to this problem. Edit/rescale data values and rerun.
|
|
55
|
+
|
|
56
|
+
// Check input.
|
|
57
|
+
if (ORDER > NSAMPS || ORDER1 > NSAMPS)
|
|
58
|
+
{
|
|
59
|
+
throw std::runtime_error("SegmentSignal Error: The window sizes cannot exceed the signal length.");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Intermediate work arrays.
|
|
63
|
+
double* WORK1 = (double*)malloc(NSAMPS * sizeof(double));
|
|
64
|
+
double* WORK2 = (double*)malloc(NSAMPS * sizeof(double));
|
|
65
|
+
|
|
66
|
+
int HORDER = ORDER / 2;
|
|
67
|
+
int NORDER = ORDER1 / 2;
|
|
68
|
+
|
|
69
|
+
// Ensure we did not round to 0.
|
|
70
|
+
if (HORDER < 1)
|
|
71
|
+
{
|
|
72
|
+
HORDER = 1;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (NORDER < 1)
|
|
76
|
+
{
|
|
77
|
+
NORDER = 1;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
int VMODE = 0;
|
|
81
|
+
bool CONV = false;
|
|
82
|
+
int ITER = 0;
|
|
83
|
+
|
|
84
|
+
double MEAN = 0.0;
|
|
85
|
+
double LBOUND = 0.1E-04;
|
|
86
|
+
double UBOUND = 0.98;
|
|
87
|
+
|
|
88
|
+
// Smooth input log using an HORDER point moving average (HORDER is number of points).
|
|
89
|
+
MovingAverage(LOG, NSAMPS, HORDER, SEGLOG);
|
|
90
|
+
|
|
91
|
+
// Initial estimate of c the variance of the jump sequence.
|
|
92
|
+
EstimateVarianceOfJumpSequence(SEGLOG, NSAMPS, WORK1, C);
|
|
93
|
+
|
|
94
|
+
// Estimate R, the variance of the noise.
|
|
95
|
+
for (int i = 0; i < NSAMPS; i++)
|
|
96
|
+
{
|
|
97
|
+
SEGLOG[i] = (LOG[i]-SEGLOG[i]) * (LOG[i]-SEGLOG[i]);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Smooth the variance of the noise using an NORDER point moving average.
|
|
101
|
+
MovingAverage(SEGLOG, NSAMPS, NORDER, R);
|
|
102
|
+
|
|
103
|
+
// Bootstrap event sequence.
|
|
104
|
+
for (int i = 0; i < 2; i++)
|
|
105
|
+
{
|
|
106
|
+
// Initialize event sequence Q.
|
|
107
|
+
for (int j = 0; j < NSAMPS; j++)
|
|
108
|
+
{
|
|
109
|
+
Q[j] = 1;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Invoke fixed interval optimal smoother to estimate the jump sequence, residual state, and its variance.
|
|
113
|
+
KalmanFilter(LOG, Q, C, R, NSAMPS, WORK2, WORK1, SEGLOG, FLTLOG);
|
|
114
|
+
|
|
115
|
+
FixedIntervalOptimalSmoother(Q, NSAMPS, C, SEGLOG, WORK1, WORK2);
|
|
116
|
+
|
|
117
|
+
// Re-estimate the variance of the jump sequence C.
|
|
118
|
+
CalculateMeanAndVariance(SEGLOG, NSAMPS, VMODE, MEAN, C);
|
|
119
|
+
|
|
120
|
+
// Invoke threshold detector and update the event sequence.
|
|
121
|
+
Threshold(SEGLOG, C, F, NSAMPS, Q, D);
|
|
122
|
+
|
|
123
|
+
// Deglitch the event sequence Q.
|
|
124
|
+
Deglitch(NSAMPS, Q);
|
|
125
|
+
|
|
126
|
+
// Update d, the event density.
|
|
127
|
+
EstimateEventDensity(Q, NSAMPS, D, NQ);
|
|
128
|
+
C = C / D;
|
|
129
|
+
|
|
130
|
+
// Deglitch and re-estimate R, the variance of noise.
|
|
131
|
+
DeglitchAndEstimateNoiseVariance(LOG, Q, NSAMPS, RMODE, SEGLOG, R);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Trap event density if invalid.
|
|
135
|
+
if (D <= LBOUND || D >= UBOUND)
|
|
136
|
+
{
|
|
137
|
+
IER = -1;
|
|
138
|
+
}
|
|
139
|
+
else
|
|
140
|
+
{
|
|
141
|
+
// Start Single Most Likelihood Replacement iterations.
|
|
142
|
+
do
|
|
143
|
+
{
|
|
144
|
+
// Increment iteration counter.
|
|
145
|
+
ITER++;
|
|
146
|
+
|
|
147
|
+
// Invoke fixed interval optimal smoother to estimate jump sequence, residual state, and its variance.
|
|
148
|
+
KalmanFilter(LOG, Q, C, R, NSAMPS, WORK2, WORK1, SEGLOG, FLTLOG);
|
|
149
|
+
|
|
150
|
+
FixedIntervalOptimalSmoother(Q, NSAMPS, C, SEGLOG, WORK1, WORK2);
|
|
151
|
+
|
|
152
|
+
// Invoke Single Most Likelihood Replacement detector.
|
|
153
|
+
SingleMostLikelihoodReplacement(WORK2, WORK1, C, NSAMPS, D, Q, CONV, IER);
|
|
154
|
+
|
|
155
|
+
// Update event density d.
|
|
156
|
+
EstimateEventDensity(Q, NSAMPS, D, NQ);
|
|
157
|
+
|
|
158
|
+
}
|
|
159
|
+
// Check for SingleMostLikelihoodReplacement termination.
|
|
160
|
+
while (ITER < NITER && !CONV && IER == 0);
|
|
161
|
+
|
|
162
|
+
NACT = ITER;
|
|
163
|
+
|
|
164
|
+
// Re-run KalmanFilter filter to estimate the filtered log if SingleMostLikelihoodReplacement did not converge.
|
|
165
|
+
if (CONV != 1 && IER == 0)
|
|
166
|
+
{
|
|
167
|
+
KalmanFilter(LOG, Q, C, R, NSAMPS, WORK2, WORK1, SEGLOG, FLTLOG);
|
|
168
|
+
}
|
|
169
|
+
// Average filtered log over segments.
|
|
170
|
+
AverageArraySegments(FLTLOG, Q, NSAMPS, SEGLOG);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Free memory.
|
|
174
|
+
free(WORK1);
|
|
175
|
+
free(WORK2);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Original function name: SMLR
|
|
179
|
+
void SingleMostLikelihoodReplacement(double G[], double S[], double C, int NSAMPS, double D, int Q[], bool& CONV, int& IER)
|
|
180
|
+
{
|
|
181
|
+
// Function:
|
|
182
|
+
// Single most likelihood replacement detector for updating an event sequence Q(k).
|
|
183
|
+
//
|
|
184
|
+
// Input parameters:
|
|
185
|
+
// G: Residual state.
|
|
186
|
+
//
|
|
187
|
+
// S: Variance of the residual state.
|
|
188
|
+
//
|
|
189
|
+
// C: Variance of the jump sequence.
|
|
190
|
+
//
|
|
191
|
+
// NSAMPS: Length of the binary event sequence.
|
|
192
|
+
//
|
|
193
|
+
// D: Segment density.
|
|
194
|
+
//
|
|
195
|
+
// Input/output parameters:
|
|
196
|
+
// Q: Binary event sequence. This sequence is updated by SingleMostLikelihoodReplacement.
|
|
197
|
+
//
|
|
198
|
+
// Output parameters:
|
|
199
|
+
// CONV: Convergence flag.
|
|
200
|
+
// CONV = 0 => No convergence.
|
|
201
|
+
// CONV = 1 => SingleMostLikelihoodReplacement convergence.
|
|
202
|
+
//
|
|
203
|
+
// IER: Return error code.
|
|
204
|
+
// IER = 0 => No error.
|
|
205
|
+
// IER = 1 => logarithm argument became zero at sample number IER.
|
|
206
|
+
|
|
207
|
+
// Input initialization.
|
|
208
|
+
IER = 0;
|
|
209
|
+
CONV = 0;
|
|
210
|
+
|
|
211
|
+
// Local variable initialization.
|
|
212
|
+
double LNHOLD = log(D / (1.0-D));
|
|
213
|
+
int INDKNT = 0;
|
|
214
|
+
int INDSTR = 0;
|
|
215
|
+
double GLOBAL = 0;
|
|
216
|
+
|
|
217
|
+
// Calculate log-likelihood ratios.
|
|
218
|
+
for (int i = 0; i < NSAMPS; i++)
|
|
219
|
+
{
|
|
220
|
+
double DHOLD = 1.0 - 2.0 * Q[i];
|
|
221
|
+
double LOGARG = 1.0 + C * DHOLD * S[i];
|
|
222
|
+
|
|
223
|
+
if (LOGARG <= 0)
|
|
224
|
+
{
|
|
225
|
+
IER = i;
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
double HOLD3 = -0.5 * log(LOGARG);
|
|
230
|
+
double HOLD1 = C * G[i] * G[i] * DHOLD / (2.0*LOGARG);
|
|
231
|
+
double STORE = HOLD1 + DHOLD * LNHOLD + HOLD3;
|
|
232
|
+
if (STORE > 0)
|
|
233
|
+
{
|
|
234
|
+
INDKNT++;
|
|
235
|
+
if (STORE > GLOBAL)
|
|
236
|
+
{
|
|
237
|
+
GLOBAL = STORE;
|
|
238
|
+
INDSTR = i;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (INDKNT < 1)
|
|
244
|
+
{
|
|
245
|
+
// In case of convergence, return.
|
|
246
|
+
CONV = true;
|
|
247
|
+
}
|
|
248
|
+
else
|
|
249
|
+
{
|
|
250
|
+
// Reset event.
|
|
251
|
+
Q[INDSTR] = !Q[INDSTR];
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Original function name: THOLD
|
|
256
|
+
void Threshold(double JMPSEQ[], double C, double F, int NSAMPS, int Q[], double& D)
|
|
257
|
+
{
|
|
258
|
+
// Function:
|
|
259
|
+
// Threshold procedure to estimate an initial event sequence.
|
|
260
|
+
//
|
|
261
|
+
// Input parameters:
|
|
262
|
+
// JMPSEQ: Jump sequence estimate obtained with the event sequence Q set to unity for all values.
|
|
263
|
+
//
|
|
264
|
+
// C: Variance of the jump sequence.
|
|
265
|
+
//
|
|
266
|
+
// F: Segmentation threshold index.
|
|
267
|
+
//
|
|
268
|
+
// NSAMPS: Length of the array JMPSEQ.
|
|
269
|
+
//
|
|
270
|
+
// Output parameters:
|
|
271
|
+
// Q: Estimated binary event sequence.
|
|
272
|
+
//
|
|
273
|
+
// D: Estimated segment density.
|
|
274
|
+
|
|
275
|
+
D = 0.0;
|
|
276
|
+
|
|
277
|
+
for (int i = 0; i < NSAMPS; i++)
|
|
278
|
+
{
|
|
279
|
+
if (F*C <= JMPSEQ[i]*JMPSEQ[i])
|
|
280
|
+
{
|
|
281
|
+
Q[i] = 1;
|
|
282
|
+
D = D + 1.0;
|
|
283
|
+
}
|
|
284
|
+
else
|
|
285
|
+
{
|
|
286
|
+
Q[i] = 0;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
D = D / (double)NSAMPS;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Original function name: MOVAVG
|
|
294
|
+
void MovingAverage(double ARR1[], int NSAMPS, int ORDER, double ARR2[])
|
|
295
|
+
{
|
|
296
|
+
// Function:
|
|
297
|
+
// Centered moving average.
|
|
298
|
+
//
|
|
299
|
+
// Input parameters:
|
|
300
|
+
// ARR1: Input data array to be averaged.
|
|
301
|
+
//
|
|
302
|
+
// NSAMPS: Length of the input data array (ARR1).
|
|
303
|
+
//
|
|
304
|
+
// ORDER: One sided length of the moving average window.
|
|
305
|
+
//
|
|
306
|
+
// Output parameters:
|
|
307
|
+
// ARR2: Averaged data array.
|
|
308
|
+
|
|
309
|
+
if (ORDER >= NSAMPS)
|
|
310
|
+
{
|
|
311
|
+
// Auto correct.
|
|
312
|
+
ORDER = NSAMPS-2;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
ARR2[0] = ARR1[0];
|
|
316
|
+
ARR2[NSAMPS-1] = ARR1[NSAMPS-1];
|
|
317
|
+
|
|
318
|
+
// Average build and drop (beginning and end of average array).
|
|
319
|
+
double SUM = ARR1[0];
|
|
320
|
+
double SUM1 = ARR1[NSAMPS-1];
|
|
321
|
+
|
|
322
|
+
int jfront = -1;
|
|
323
|
+
int jback = NSAMPS;
|
|
324
|
+
|
|
325
|
+
for (int i = 1; i < ORDER+1; i++)
|
|
326
|
+
{
|
|
327
|
+
// Building by 2 because this is a "central" moving average.
|
|
328
|
+
jfront = jfront + 2;
|
|
329
|
+
jback = jback - 2;
|
|
330
|
+
SUM = SUM + ARR1[jfront] + ARR1[jfront+1];
|
|
331
|
+
SUM1 = SUM1 + ARR1[jback] + ARR1[jback-1];
|
|
332
|
+
ARR2[i] = SUM / ((double)jfront + 2);
|
|
333
|
+
ARR2[NSAMPS-1-i] = SUM1 / ((double)jfront + 2);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Average stable.
|
|
337
|
+
jfront = jfront + 2;
|
|
338
|
+
jback = 0;
|
|
339
|
+
|
|
340
|
+
for (int i = ORDER+1; i < NSAMPS-ORDER; i++)
|
|
341
|
+
{
|
|
342
|
+
SUM = SUM + ARR1[jfront] - ARR1[jback];
|
|
343
|
+
ARR2[i] = SUM / ((double)ORDER * 2 + 1);
|
|
344
|
+
jfront++;
|
|
345
|
+
jback++;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Original function name: KALMAN
|
|
350
|
+
void KalmanFilter(double LOG[], int Q[], double C, double R[], int NSAMPS, double GAIN[], double ZTLT[], double ETA[], double STATE[])
|
|
351
|
+
{
|
|
352
|
+
// Function:
|
|
353
|
+
// One dimensional KalmanFilter filter.
|
|
354
|
+
//
|
|
355
|
+
// Input parameters:
|
|
356
|
+
// LOG: Input discretized well log.
|
|
357
|
+
//
|
|
358
|
+
// Q: Binary event sequence.
|
|
359
|
+
//
|
|
360
|
+
// C: Variance of the jump sequence.
|
|
361
|
+
//
|
|
362
|
+
// NSAMPS: Length of the input well log.
|
|
363
|
+
//
|
|
364
|
+
// Output parameters:
|
|
365
|
+
// GAIN: KalmanFilter gain array.
|
|
366
|
+
//
|
|
367
|
+
// ZTLT: Innovation sequence.
|
|
368
|
+
//
|
|
369
|
+
// ETA: Variance of the innovation sequence.
|
|
370
|
+
//
|
|
371
|
+
// STATE: Estimated state values (filtered log).
|
|
372
|
+
|
|
373
|
+
// Init state and its variance.
|
|
374
|
+
double VAR = 0.0;
|
|
375
|
+
|
|
376
|
+
if (Q[0])
|
|
377
|
+
{
|
|
378
|
+
VAR = C;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
ZTLT[0] = 0.0;
|
|
382
|
+
ETA[0] = VAR + R[0];
|
|
383
|
+
GAIN[0] = VAR / ETA[0];
|
|
384
|
+
STATE[0] = LOG[0] + GAIN[0] * ZTLT[0];
|
|
385
|
+
VAR = (1.0 - GAIN[0]) * VAR;
|
|
386
|
+
|
|
387
|
+
// Estimate state and its variance (one dim KalmanFilter filter).
|
|
388
|
+
for (int i = 1; i < NSAMPS; i++)
|
|
389
|
+
{
|
|
390
|
+
if (Q[i])
|
|
391
|
+
{
|
|
392
|
+
VAR = VAR + C;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
ZTLT[i] = LOG[i] - STATE[i-1];
|
|
396
|
+
ETA[i] = VAR + R[i];
|
|
397
|
+
GAIN[i] = VAR / ETA[i];
|
|
398
|
+
STATE[i] = STATE[i-1] + GAIN[i] * ZTLT[i];
|
|
399
|
+
VAR = (1.0 - GAIN[i]) * VAR;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Original function name: FIOS
|
|
404
|
+
void FixedIntervalOptimalSmoother(int Q[], int NSAMPS, double C, double ARR1[], double ARR2[], double ARR3[])
|
|
405
|
+
{
|
|
406
|
+
// Function:
|
|
407
|
+
// Fixed interval optimal smoother to estimate the jump sequence, residual state and its variance.
|
|
408
|
+
//
|
|
409
|
+
// Input parameters:
|
|
410
|
+
// Q: Binary event sequence.
|
|
411
|
+
//
|
|
412
|
+
// NSAMPS: Length of the binary event sequence Q.
|
|
413
|
+
//
|
|
414
|
+
// C: Variance of the jump sequence.
|
|
415
|
+
//
|
|
416
|
+
// Input/output parameters:
|
|
417
|
+
// ARR1: Variance of the innovation sequence. On return it contains the product Q*R.
|
|
418
|
+
//
|
|
419
|
+
// ARR2: Innovation sequence. On return it contains S (variance of residual state).
|
|
420
|
+
//
|
|
421
|
+
// ARR3: KalmanFilter gain array. On return it contains G (residual state).
|
|
422
|
+
|
|
423
|
+
int lastindex = NSAMPS - 1;
|
|
424
|
+
|
|
425
|
+
ARR3[lastindex] = ARR2[lastindex] / ARR1[lastindex];
|
|
426
|
+
ARR2[lastindex] = 1.0 / ARR1[lastindex];
|
|
427
|
+
ARR1[lastindex] = C * Q[lastindex] * ARR3[lastindex];
|
|
428
|
+
|
|
429
|
+
for (int i = lastindex-1; i > -1; i--)
|
|
430
|
+
{
|
|
431
|
+
double TEMP = 1.0 - ARR3[i];
|
|
432
|
+
ARR3[i] = TEMP * ARR3[i+1] + ARR2[i] / ARR1[i];
|
|
433
|
+
ARR2[i] = TEMP * TEMP * ARR2[i+1] + 1.0 / ARR1[i];
|
|
434
|
+
ARR1[i] = C * Q[i] * ARR3[i];
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Original function name: DATAVG
|
|
439
|
+
void AverageArraySegments(double ARR[], int Q[], int NSAMPS, double AVGOUT[])
|
|
440
|
+
{
|
|
441
|
+
// Function:
|
|
442
|
+
// Data array to be averaged within segments implied by an event sequence Q.
|
|
443
|
+
//
|
|
444
|
+
// Input parameters:
|
|
445
|
+
// ARR: Input data array to be averaged.
|
|
446
|
+
//
|
|
447
|
+
// Q: Binary event sequence.
|
|
448
|
+
//
|
|
449
|
+
// NSAMPS: Length of the input data array (ARR).
|
|
450
|
+
//
|
|
451
|
+
// Output parameters:
|
|
452
|
+
// AVGOUT: Output data averaged within each segment implied by the event sequence Q.
|
|
453
|
+
|
|
454
|
+
bool endofarray = false;
|
|
455
|
+
int SEGSTR = 0;
|
|
456
|
+
|
|
457
|
+
while (!endofarray)
|
|
458
|
+
{
|
|
459
|
+
int SEGEND;
|
|
460
|
+
int SEGLEN;
|
|
461
|
+
double SEGAVG;
|
|
462
|
+
|
|
463
|
+
GetSegment(ARR, Q, NSAMPS, SEGSTR, SEGEND, SEGLEN, SEGAVG, endofarray);
|
|
464
|
+
|
|
465
|
+
for (int i = SEGSTR; i <= SEGEND; i++)
|
|
466
|
+
{
|
|
467
|
+
AVGOUT[i] = SEGAVG;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
SEGSTR = SEGEND + 1;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Original function name: UPDNSE
|
|
475
|
+
void DeglitchAndEstimateNoiseVariance(double LOG[], int Q[], int NSAMPS, int RMODE, double WORK1[], double R[])
|
|
476
|
+
{
|
|
477
|
+
// Function:
|
|
478
|
+
// Deglitch and re-estimate noise variance.
|
|
479
|
+
//
|
|
480
|
+
// Input parameters:
|
|
481
|
+
// LOG: Input discretized well log to be used for updating noise variance R.
|
|
482
|
+
//
|
|
483
|
+
// Q: Binary event sequence.
|
|
484
|
+
//
|
|
485
|
+
// NSAMPS: Length of the input well log.
|
|
486
|
+
//
|
|
487
|
+
// RMODE: Noise variance estimate option.
|
|
488
|
+
// RMODE = 0 ==> Point estimate of noise variance.
|
|
489
|
+
// RMODE = 1 ==> Noise estimates smoothed within segments.
|
|
490
|
+
//
|
|
491
|
+
// Output parameters:
|
|
492
|
+
// R: Estimated noise variance.
|
|
493
|
+
|
|
494
|
+
// Average the log within each segment implied by Q.
|
|
495
|
+
AverageArraySegments(LOG, Q, NSAMPS, WORK1);
|
|
496
|
+
|
|
497
|
+
// Calculate the noise variance R.
|
|
498
|
+
for (int i = 0; i < NSAMPS; i++)
|
|
499
|
+
{
|
|
500
|
+
WORK1[i] = (LOG[i] - WORK1[i]) * (LOG[i] - WORK1[i]);
|
|
501
|
+
|
|
502
|
+
if (WORK1[i] <= 0.0)
|
|
503
|
+
{
|
|
504
|
+
WORK1[i] = 1.0;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Point estimate.
|
|
509
|
+
if (RMODE == 0)
|
|
510
|
+
{
|
|
511
|
+
for (int i = 0; i < NSAMPS; i++)
|
|
512
|
+
{
|
|
513
|
+
R[i] = WORK1[i];
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
else
|
|
517
|
+
{
|
|
518
|
+
// Smooth the noise variance R within each segment.
|
|
519
|
+
int SEGSTR = 0;
|
|
520
|
+
bool endofarray = false;
|
|
521
|
+
|
|
522
|
+
while (!endofarray)
|
|
523
|
+
{
|
|
524
|
+
// Outputs from call to "GetSegment".
|
|
525
|
+
int SEGEND;
|
|
526
|
+
int SEGLEN;
|
|
527
|
+
double SEGAVG;
|
|
528
|
+
|
|
529
|
+
GetSegment(LOG, Q, NSAMPS, SEGSTR, SEGEND, SEGLEN, SEGAVG, endofarray);
|
|
530
|
+
|
|
531
|
+
int IOR = SEGLEN/3;
|
|
532
|
+
if (IOR > 0)
|
|
533
|
+
{
|
|
534
|
+
MovingAverage(&(WORK1[SEGSTR]), SEGLEN, IOR, &(R[SEGSTR]));
|
|
535
|
+
}
|
|
536
|
+
else
|
|
537
|
+
{
|
|
538
|
+
for (int i = SEGSTR; i <= SEGEND; i++)
|
|
539
|
+
{
|
|
540
|
+
R[i] = WORK1[i];
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
SEGSTR = SEGEND + 1;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Original function name: GETSEG
|
|
550
|
+
void GetSegment(double LOG[], int Q[], int NSAMPS, int SEGSTR, int& SEGEND, int& SEGLEN, double& SEGAVG, bool& endofarray)
|
|
551
|
+
{
|
|
552
|
+
// Function:
|
|
553
|
+
// Identifies a segment within a given event sequence.
|
|
554
|
+
// A segment is defined by the sequence 1,0,0,...,0,1.
|
|
555
|
+
//
|
|
556
|
+
// Input parameters:
|
|
557
|
+
// LOG: Data array for which the averages are to be computed.
|
|
558
|
+
//
|
|
559
|
+
// Q: Binary event sequence which identifies the segments in the input array log.
|
|
560
|
+
//
|
|
561
|
+
// NSAMPS: Length of the input array log.
|
|
562
|
+
//
|
|
563
|
+
// SEGSTR: Sample number where the segment boundary starts.
|
|
564
|
+
//
|
|
565
|
+
// Output parameters:
|
|
566
|
+
// SEGEND: Sample number where the segment boundary ends.
|
|
567
|
+
//
|
|
568
|
+
// SEGLEN: Length of the segment.
|
|
569
|
+
//
|
|
570
|
+
// SEGAVG: Average value of the input data array log over the segment.
|
|
571
|
+
//
|
|
572
|
+
// endofarray: End of data indicator.
|
|
573
|
+
// true: End of array reached.
|
|
574
|
+
// false: Not at end of the array.
|
|
575
|
+
|
|
576
|
+
endofarray = false;
|
|
577
|
+
SEGEND = SEGSTR;
|
|
578
|
+
SEGAVG = 0;
|
|
579
|
+
|
|
580
|
+
do
|
|
581
|
+
{
|
|
582
|
+
SEGAVG = SEGAVG + LOG[SEGEND];
|
|
583
|
+
SEGEND = SEGEND + 1;
|
|
584
|
+
}
|
|
585
|
+
while (!Q[SEGEND] && SEGEND < NSAMPS);
|
|
586
|
+
|
|
587
|
+
if (SEGEND == NSAMPS)
|
|
588
|
+
{
|
|
589
|
+
// We hit the end of the array without finding an event indicator (a "1" in the "Q" array).
|
|
590
|
+
endofarray = true;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// In the case were we found a "1" in the "Q" array the end of the segment is the previous
|
|
594
|
+
// index before the event ("1"). If we hit the end of the array first, SEGEND == NSAMPS which
|
|
595
|
+
// is past the end of the array so it needs to be de-incremented.
|
|
596
|
+
SEGEND--;
|
|
597
|
+
|
|
598
|
+
SEGLEN = SEGEND - SEGSTR + 1;
|
|
599
|
+
SEGAVG = SEGAVG / SEGLEN;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Original function name: DEGLCH
|
|
603
|
+
void Deglitch(int NSAMPS, int Q[])
|
|
604
|
+
{
|
|
605
|
+
// Function:
|
|
606
|
+
// Deglitches all the spiky zones in the event sequence Q.
|
|
607
|
+
//
|
|
608
|
+
// Input parameters:
|
|
609
|
+
// NSAMPS: Length of the array Q.
|
|
610
|
+
//
|
|
611
|
+
// Input/output parameters:
|
|
612
|
+
// Q: Binary event sequence to be deglitched. On return this contains the updated event
|
|
613
|
+
// sequence. It is of length "NSAMPS."
|
|
614
|
+
|
|
615
|
+
int SEGSTR = 0;
|
|
616
|
+
bool endofarray = false;
|
|
617
|
+
|
|
618
|
+
do
|
|
619
|
+
{
|
|
620
|
+
int SEGEND;
|
|
621
|
+
GetSpikeyZone(Q, NSAMPS, SEGSTR, SEGEND, endofarray);
|
|
622
|
+
|
|
623
|
+
if (SEGSTR == SEGEND)
|
|
624
|
+
{
|
|
625
|
+
SEGSTR++;
|
|
626
|
+
}
|
|
627
|
+
else
|
|
628
|
+
{
|
|
629
|
+
if (SEGEND == SEGSTR+1)
|
|
630
|
+
{
|
|
631
|
+
Q[SEGSTR] = 0;
|
|
632
|
+
}
|
|
633
|
+
else
|
|
634
|
+
{
|
|
635
|
+
for (int i = SEGSTR+1; i < SEGEND; i++)
|
|
636
|
+
{
|
|
637
|
+
Q[i] = 0;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
SEGSTR = SEGEND + 1;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
while (!endofarray);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Original function name: GETSPK
|
|
647
|
+
void GetSpikeyZone(int Q[], int NSAMPS, int SEGSTR, int& SEGEND, bool& endofarray)
|
|
648
|
+
{
|
|
649
|
+
// Function:
|
|
650
|
+
// Identifies a zone of spikes. A spiky zone is defined by 0,1,1,...,1,0.
|
|
651
|
+
//
|
|
652
|
+
// Input parameters:
|
|
653
|
+
// Q: Binary event sequence in which the zone is to be identified.
|
|
654
|
+
//
|
|
655
|
+
// NSAMPS: Length of the array Q.
|
|
656
|
+
//
|
|
657
|
+
// SEGSTR: Sample number where the spiky zone starts.
|
|
658
|
+
//
|
|
659
|
+
// Output parameters:
|
|
660
|
+
// SEGEND: Sample number where the zone ends.
|
|
661
|
+
//
|
|
662
|
+
// endofarray: End of data indicator.
|
|
663
|
+
// true: End of array reached.
|
|
664
|
+
// false: Not at end of the array.
|
|
665
|
+
|
|
666
|
+
SEGEND = SEGSTR;
|
|
667
|
+
if (!Q[SEGEND])
|
|
668
|
+
{
|
|
669
|
+
// Modified from original paper. The "if" statement below was not part of the original algorithm.
|
|
670
|
+
// It seems there can be a case where Q[i] < 0.5 for SEGEND = NSAMPS that causes us to miss flagging the end
|
|
671
|
+
// of the array. Do a check here to ensure we don't overrun the end of the array and over write memory we should
|
|
672
|
+
// not over write.
|
|
673
|
+
if (SEGEND >= NSAMPS)
|
|
674
|
+
{
|
|
675
|
+
endofarray = true;
|
|
676
|
+
SEGEND = NSAMPS - 1;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
do
|
|
683
|
+
{
|
|
684
|
+
SEGEND++;
|
|
685
|
+
}
|
|
686
|
+
while (Q[SEGEND] && (SEGEND < NSAMPS));
|
|
687
|
+
|
|
688
|
+
if (SEGEND >= NSAMPS)
|
|
689
|
+
{
|
|
690
|
+
endofarray = true;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
SEGEND--;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// Original function name: UPDDEN
|
|
697
|
+
void EstimateEventDensity(int Q[], int NSAMPS, double& D, int& NQ)
|
|
698
|
+
{
|
|
699
|
+
// Function:
|
|
700
|
+
// Estimates the event density for a given event sequence.
|
|
701
|
+
//
|
|
702
|
+
// Input parameters:
|
|
703
|
+
// Q: Binary event sequence for which the event density is to be estimated.
|
|
704
|
+
//
|
|
705
|
+
// NSAMPS: Length of the array Q.
|
|
706
|
+
//
|
|
707
|
+
// Output parameters:
|
|
708
|
+
// D: Estimated segment density.
|
|
709
|
+
//
|
|
710
|
+
// NQ: Number of binary events found (number of "1"s in Q).
|
|
711
|
+
|
|
712
|
+
D = 0;
|
|
713
|
+
for (int i = 0; i < NSAMPS; i++)
|
|
714
|
+
{
|
|
715
|
+
D = D + Q[i];
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Store the number of events found, the calculate the event density.
|
|
719
|
+
NQ = (int)D;
|
|
720
|
+
D = D / (double)NSAMPS;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// Original function name: ESTSIG
|
|
724
|
+
void EstimateVarianceOfJumpSequence(double LOG[], int NSAMPS, double WORK1[], double& C)
|
|
725
|
+
{
|
|
726
|
+
// Function:
|
|
727
|
+
// Estimates initially C, the variance of the jump sequence as the variance of unit-step
|
|
728
|
+
// finite difference of input smoothed log.
|
|
729
|
+
//
|
|
730
|
+
// Input parameters:
|
|
731
|
+
// LOG: Smoothed well log.
|
|
732
|
+
//
|
|
733
|
+
// NSAMPS: Length of the array log.
|
|
734
|
+
//
|
|
735
|
+
// Output parameters:
|
|
736
|
+
// C: Estimated variance of the jump sequence.
|
|
737
|
+
|
|
738
|
+
// Estimate jump sequence as the unit-step finite difference of input log.
|
|
739
|
+
WORK1[0] = 0;
|
|
740
|
+
for (int i = 1; i < NSAMPS; i++)
|
|
741
|
+
{
|
|
742
|
+
WORK1[i] = LOG[i] - LOG[i-1];
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// Calculate the variance of the differ log (consider non zero values).
|
|
746
|
+
double MEAN;
|
|
747
|
+
CalculateMeanAndVariance(WORK1, NSAMPS, 1, MEAN, C);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// Original function name: VARNCE
|
|
751
|
+
void CalculateMeanAndVariance(double ARRAY[], int NSAMPS, int MODE, double& MEAN, double& VAR)
|
|
752
|
+
{
|
|
753
|
+
// Function:
|
|
754
|
+
// Calculates mean and variance.
|
|
755
|
+
//
|
|
756
|
+
// Input parameters:
|
|
757
|
+
// ARRAY: Input data array for which the mean and variance is to be calculated.
|
|
758
|
+
//
|
|
759
|
+
// NSAMPS: Length of the input array.
|
|
760
|
+
//
|
|
761
|
+
// MODE: Option to include zero values for calculating mean and variance.
|
|
762
|
+
// MODE == 0 = Consider all values.
|
|
763
|
+
// MODE == 1 = Consider only non zero values.
|
|
764
|
+
//
|
|
765
|
+
// Output parameters:
|
|
766
|
+
// MEAN: Calculated mean of the given data.
|
|
767
|
+
//
|
|
768
|
+
// VAR: Calculated variance of the given data.
|
|
769
|
+
|
|
770
|
+
int NZEKNT = 0;
|
|
771
|
+
MEAN = 0;
|
|
772
|
+
VAR = 0;
|
|
773
|
+
|
|
774
|
+
// Calculate sum and sum of squares.
|
|
775
|
+
for (int i = 0; i < NSAMPS; i++)
|
|
776
|
+
{
|
|
777
|
+
|
|
778
|
+
if (ARRAY[i] != 0)
|
|
779
|
+
{
|
|
780
|
+
NZEKNT++;
|
|
781
|
+
MEAN = MEAN + ARRAY[i];
|
|
782
|
+
VAR = VAR + ARRAY[i]*ARRAY[i];
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// Calculate mean and variance.
|
|
787
|
+
if (MODE == 0)
|
|
788
|
+
{
|
|
789
|
+
MEAN = MEAN / (double)NSAMPS;
|
|
790
|
+
VAR = VAR / (double)NSAMPS - MEAN*MEAN;
|
|
791
|
+
}
|
|
792
|
+
else
|
|
793
|
+
{
|
|
794
|
+
MEAN = MEAN / (double)NZEKNT;
|
|
795
|
+
VAR = VAR / (double)NZEKNT - MEAN*MEAN;
|
|
796
|
+
}
|
|
797
|
+
}
|