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.
@@ -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
+ }