@webviz/well-log-viewer 0.0.1-alpha.1 → 0.0.1-alpha.3
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.
- package/dist/SyncLogViewer.js +3 -4
- package/dist/SyncLogViewer.js.map +1 -1
- package/dist/components/WellLogView.js +5 -5
- package/dist/components/WellLogView.js.map +1 -1
- package/dist/demo/example-data/welllog_template_2.json +167 -167
- package/dist/demo/example-data/wellpick_colors.json +1 -1
- package/dist/demo/example-data/wellpicks.json +179 -179
- package/package.json +32 -5
- package/dist/Intro.stories.mdx +0 -59
- package/dist/package.json +0 -21
- package/src/Intro.stories.mdx +0 -59
- package/src/MapAndWellLogViewer.stories.jsx +0 -147
- package/src/MapAndWellLogViewer.test.tsx +0 -26
- package/src/MapAndWellLogViewer.tsx +0 -473
- package/src/SyncLogViewer.stories.jsx +0 -361
- package/src/SyncLogViewer.test.tsx +0 -41
- package/src/SyncLogViewer.tsx +0 -1188
- package/src/WellLogViewer.png +0 -0
- package/src/WellLogViewer.stories.jsx +0 -169
- package/src/WellLogViewer.test.tsx +0 -53
- package/src/WellLogViewer.tsx +0 -439
- package/src/WellLogViewer_performance.test.tsx +0 -78
- package/src/__snapshots__/MapAndWellLogViewer.test.tsx.snap +0 -365
- package/src/__snapshots__/SyncLogViewer.test.tsx.snap +0 -510
- package/src/__snapshots__/WellLogViewer.test.tsx.snap +0 -552
- package/src/components/AxisSelector.test.tsx +0 -50
- package/src/components/AxisSelector.tsx +0 -49
- package/src/components/ColorTableTypes.ts +0 -9
- package/src/components/InfoPanel.test.tsx +0 -58
- package/src/components/InfoPanel.tsx +0 -144
- package/src/components/InfoTypes.ts +0 -17
- package/src/components/LocalMenus.tsx +0 -336
- package/src/components/PlotDialog.tsx +0 -419
- package/src/components/Scroller.stories.jsx +0 -80
- package/src/components/Scroller.test.tsx +0 -22
- package/src/components/Scroller.tsx +0 -173
- package/src/components/TrackDialog.tsx +0 -217
- package/src/components/WellLogSpacer.tsx +0 -483
- package/src/components/WellLogTemplateTypes.ts +0 -65
- package/src/components/WellLogTypes.ts +0 -53
- package/src/components/WellLogView.stories.jsx +0 -84
- package/src/components/WellLogView.test.tsx +0 -52
- package/src/components/WellLogView.tsx +0 -2063
- package/src/components/WellLogViewWithScroller.stories.jsx +0 -69
- package/src/components/WellLogViewWithScroller.test.tsx +0 -47
- package/src/components/WellLogViewWithScroller.tsx +0 -179
- package/src/components/ZoomSlider.stories.jsx +0 -52
- package/src/components/ZoomSlider.test.tsx +0 -28
- package/src/components/ZoomSlider.tsx +0 -86
- package/src/components/__snapshots__/AxisSelector.test.tsx.snap +0 -28
- package/src/components/__snapshots__/InfoPanel.test.tsx.snap +0 -103
- package/src/components/__snapshots__/Scroller.test.tsx.snap +0 -13
- package/src/components/__snapshots__/WellLogView.test.tsx.snap +0 -54
- package/src/components/__snapshots__/WellLogViewWithScroller.test.tsx.snap +0 -270
- package/src/components/__snapshots__/ZoomSlider.test.tsx.snap +0 -50
- package/src/components/styles.scss +0 -106
- package/src/custom.d.ts +0 -13
- package/src/demo/example-data/volve_logs.json +0 -689617
- package/src/demo/example-data/welllog_template_2.json +0 -196
- package/src/demo/example-data/wellpick_colors.json +0 -156
- package/src/demo/example-data/wellpicks.json +0 -186
- package/src/index.ts +0 -8
- package/src/utils/axes.ts +0 -26
- package/src/utils/color-table.ts +0 -153
- package/src/utils/deepcopy.ts +0 -3
- package/src/utils/edit-track.tsx +0 -40
- package/src/utils/fill-info.ts +0 -224
- package/src/utils/gradientfill-plot-legend.ts +0 -177
- package/src/utils/gradientfill-plot.ts +0 -203
- package/src/utils/graph/factory.ts +0 -15
- package/src/utils/legend/common.ts +0 -153
- package/src/utils/log-viewer.ts +0 -209
- package/src/utils/minmax.ts +0 -126
- package/src/utils/pattern.tsx +0 -50
- package/src/utils/stack/stack-legend.ts +0 -100
- package/src/utils/tracks.ts +0 -1559
- package/tsconfig.json +0 -8
package/src/SyncLogViewer.tsx
DELETED
|
@@ -1,1188 +0,0 @@
|
|
|
1
|
-
import React, { Component, ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
import PropTypes from "prop-types";
|
|
4
|
-
|
|
5
|
-
import WellLogSpacer from "./components/WellLogSpacer";
|
|
6
|
-
import WellLogViewWithScroller from "./components/WellLogViewWithScroller";
|
|
7
|
-
import InfoPanel from "./components/InfoPanel";
|
|
8
|
-
import AxisSelector from "./components/AxisSelector";
|
|
9
|
-
|
|
10
|
-
import ZoomSlider from "./components/ZoomSlider";
|
|
11
|
-
|
|
12
|
-
import { WellLog } from "./components/WellLogTypes";
|
|
13
|
-
import { Template } from "./components/WellLogTemplateTypes";
|
|
14
|
-
import { ColorTable } from "./components/ColorTableTypes";
|
|
15
|
-
import { PatternsTable } from "./utils/pattern";
|
|
16
|
-
|
|
17
|
-
import { WellLogController, WellPickProps } from "./components/WellLogView";
|
|
18
|
-
|
|
19
|
-
import WellLogView from "./components/WellLogView";
|
|
20
|
-
import { WellLogViewOptions } from "./components/WellLogView";
|
|
21
|
-
import { WellLogSpacerOptions } from "./components/WellLogSpacer";
|
|
22
|
-
import { getWellPicks } from "./components/WellLogView";
|
|
23
|
-
|
|
24
|
-
import { getAvailableAxes } from "./utils/tracks";
|
|
25
|
-
|
|
26
|
-
import { checkMinMax } from "./utils/minmax";
|
|
27
|
-
function isEqDomains(d1: [number, number], d2: [number, number]): boolean {
|
|
28
|
-
const eps: number = Math.abs(d1[1] - d1[0] + (d2[1] - d2[0])) * 0.00001;
|
|
29
|
-
return Math.abs(d1[0] - d2[0]) < eps && Math.abs(d1[1] - d2[1]) < eps;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
import { onTrackMouseEvent } from "./utils/edit-track";
|
|
33
|
-
import { fillInfos } from "./utils/fill-info";
|
|
34
|
-
import { LogViewer } from "@equinor/videx-wellog";
|
|
35
|
-
|
|
36
|
-
import { Info, InfoOptions } from "./components/InfoTypes";
|
|
37
|
-
|
|
38
|
-
import { isEqualRanges } from "./components/WellLogView";
|
|
39
|
-
//import { boolean } from "mathjs";
|
|
40
|
-
|
|
41
|
-
export function isEqualArrays(
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43
|
-
d1: undefined | any[],
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
-
d2: undefined | any[]
|
|
46
|
-
): boolean {
|
|
47
|
-
if (!d1) return !d2;
|
|
48
|
-
if (!d2) return !d1;
|
|
49
|
-
|
|
50
|
-
const n = d1.length;
|
|
51
|
-
if (n !== d2.length) return false;
|
|
52
|
-
|
|
53
|
-
for (let i = 0; i < n; i++) {
|
|
54
|
-
if (d1[i] !== d2[i]) return false;
|
|
55
|
-
}
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
interface Props {
|
|
60
|
-
/**
|
|
61
|
-
* Object from JSON file describing single well log data.
|
|
62
|
-
*/
|
|
63
|
-
welllogs: WellLog[];
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Prop containing track templates data.
|
|
67
|
-
*/
|
|
68
|
-
templates: Template[];
|
|
69
|
-
/**
|
|
70
|
-
* Prop containing color table data.
|
|
71
|
-
*/
|
|
72
|
-
colorTables: ColorTable[];
|
|
73
|
-
/**
|
|
74
|
-
* Set to true for default titles or to array of individial welllog titles
|
|
75
|
-
*/
|
|
76
|
-
viewTitles?: boolean | (boolean | string | JSX.Element)[];
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Well Picks data array
|
|
80
|
-
*/
|
|
81
|
-
wellpicks?: WellPickProps[];
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Patterns table
|
|
85
|
-
*/
|
|
86
|
-
patternsTable?: PatternsTable;
|
|
87
|
-
/**
|
|
88
|
-
* Horizon to pattern index map
|
|
89
|
-
*/
|
|
90
|
-
patterns?: [string, number][];
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Horizon names for wellpick flatting (pan and zoom)
|
|
94
|
-
*/
|
|
95
|
-
wellpickFlatting?: string[]; // For example ["Hor_5", "Hor_3"];
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Set to true or to spacer width or to array of widths if WellLogSpacers should be used
|
|
99
|
-
*/
|
|
100
|
-
spacers?: boolean | number | number[];
|
|
101
|
-
/**
|
|
102
|
-
* Distanses between wells to show on the spacers
|
|
103
|
-
*/
|
|
104
|
-
wellDistances?: {
|
|
105
|
-
units: string;
|
|
106
|
-
distances: (number | undefined)[];
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Orientation of the track plots on the screen.
|
|
111
|
-
*/
|
|
112
|
-
horizontal?: boolean;
|
|
113
|
-
syncTrackPos?: boolean;
|
|
114
|
-
syncContentDomain?: boolean;
|
|
115
|
-
syncContentSelection?: boolean;
|
|
116
|
-
syncTemplate?: boolean;
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Primary axis id: "md", "tvd", "time"... Default is the first available from axisMnemos
|
|
120
|
-
*/
|
|
121
|
-
primaryAxis?: string;
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Log mnemonics for axes
|
|
125
|
-
*/
|
|
126
|
-
axisTitles: Record<string, string>;
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Names for axes
|
|
130
|
-
*/
|
|
131
|
-
axisMnemos: Record<string, string[]>;
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Initial visible range
|
|
135
|
-
*/
|
|
136
|
-
domain?: [number, number];
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Initial selected range
|
|
140
|
-
*/
|
|
141
|
-
selection?: [number | undefined, number | undefined];
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Options for well log views
|
|
145
|
-
*/
|
|
146
|
-
welllogOptions?: WellLogViewOptions;
|
|
147
|
-
/**
|
|
148
|
-
* Options for well log spacers
|
|
149
|
-
*/
|
|
150
|
-
spacerOptions?: WellLogSpacerOptions;
|
|
151
|
-
/**
|
|
152
|
-
* Options for readout
|
|
153
|
-
*/
|
|
154
|
-
readoutOptions?: InfoOptions; // options for readout
|
|
155
|
-
|
|
156
|
-
// callbacks
|
|
157
|
-
onContentRescale?: (iView: number) => void;
|
|
158
|
-
onContentSelection?: (iView: number) => void;
|
|
159
|
-
onTemplateChanged?: (iView: number) => void;
|
|
160
|
-
|
|
161
|
-
onCreateController?: (iView: number, controller: WellLogController) => void;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export const argTypesSyncLogViewerProp = {
|
|
165
|
-
id: {
|
|
166
|
-
description:
|
|
167
|
-
"The ID of this component, used to identify dash components in callbacks. The ID needs to be unique across all of the components in an app.",
|
|
168
|
-
},
|
|
169
|
-
welllogs: {
|
|
170
|
-
description: "Array of JSON objects describing well log data.",
|
|
171
|
-
},
|
|
172
|
-
templates: {
|
|
173
|
-
description: "Array of track template data.",
|
|
174
|
-
},
|
|
175
|
-
colorTables: {
|
|
176
|
-
description: "Prop containing color table data.",
|
|
177
|
-
},
|
|
178
|
-
wellpicks: {
|
|
179
|
-
description: "Well Picks data array",
|
|
180
|
-
},
|
|
181
|
-
patternsTable: {
|
|
182
|
-
description: "Patterns table",
|
|
183
|
-
},
|
|
184
|
-
patterns: {
|
|
185
|
-
description: "Horizon to pattern index map",
|
|
186
|
-
},
|
|
187
|
-
|
|
188
|
-
spacers: {
|
|
189
|
-
description:
|
|
190
|
-
"Set to true or spacer width or to array of widths if WellLogSpacers should be used",
|
|
191
|
-
},
|
|
192
|
-
wellDistances: {
|
|
193
|
-
description: "Distanses between wells to show on the spacers",
|
|
194
|
-
},
|
|
195
|
-
|
|
196
|
-
horizontal: {
|
|
197
|
-
description: "Orientation of the track plots on the screen.",
|
|
198
|
-
},
|
|
199
|
-
syncTrackPos: {
|
|
200
|
-
description: "Synchronize first visible track", // defaultValue: false
|
|
201
|
-
},
|
|
202
|
-
syncContentDomain: {
|
|
203
|
-
description: "Synchronize visible content domain (pan and zoom)", // defaultValue: false
|
|
204
|
-
},
|
|
205
|
-
syncContentSelection: {
|
|
206
|
-
description: "Synchronize content selection", // defaultValue: false
|
|
207
|
-
},
|
|
208
|
-
syncTemplate: {
|
|
209
|
-
description: "Synchronize templates in the views", // defaultValue: false
|
|
210
|
-
},
|
|
211
|
-
welllogOptions: {
|
|
212
|
-
description:
|
|
213
|
-
"Options for well log views:<br/>" +
|
|
214
|
-
"maxContentZoom: The maximum zoom value (default 256)<br/>" +
|
|
215
|
-
"maxVisibleTrackNum: The maximum number of visible tracks<br/>" +
|
|
216
|
-
"checkDatafileSchema: Validate JSON datafile against schema<br/>" +
|
|
217
|
-
"hideTrackTitle: Hide titles on the tracks<br/>" +
|
|
218
|
-
"hideLegend: Hide legends on the tracks.",
|
|
219
|
-
},
|
|
220
|
-
readoutOptions: {
|
|
221
|
-
description:
|
|
222
|
-
"Options for readout panel.<br/>" +
|
|
223
|
-
"allTracks: boolean — Show not only visible tracks,<br/>" +
|
|
224
|
-
"grouping: string — How group values.",
|
|
225
|
-
//defaultValue: {
|
|
226
|
-
// allTracks: false,
|
|
227
|
-
// grouping: "by_track",
|
|
228
|
-
//},
|
|
229
|
-
},
|
|
230
|
-
domain: {
|
|
231
|
-
description: "Initial visible interval of the log data.",
|
|
232
|
-
},
|
|
233
|
-
selection: {
|
|
234
|
-
description: "Initial selected interval of the log data.",
|
|
235
|
-
},
|
|
236
|
-
viewTitles: {
|
|
237
|
-
description:
|
|
238
|
-
"Set to true for default titles or to array of individial welllog titles",
|
|
239
|
-
},
|
|
240
|
-
// callbacks...
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
interface State {
|
|
244
|
-
axes: string[]; // axes available in welllog
|
|
245
|
-
primaryAxis: string;
|
|
246
|
-
infos: Info[][];
|
|
247
|
-
|
|
248
|
-
sliderValue: number; // value for zoom slider
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
class SyncLogViewer extends Component<Props, State> {
|
|
252
|
-
public static propTypes: Record<string, unknown>;
|
|
253
|
-
|
|
254
|
-
controllers: (WellLogController | null)[];
|
|
255
|
-
spacers: (WellLogSpacer | null)[];
|
|
256
|
-
|
|
257
|
-
collapsedTrackIds: (string | number)[];
|
|
258
|
-
|
|
259
|
-
callbacks: {
|
|
260
|
-
onCreateControllerBind: (controller: WellLogController) => void;
|
|
261
|
-
onInfoBind: (
|
|
262
|
-
x: number,
|
|
263
|
-
logController: LogViewer,
|
|
264
|
-
iFrom: number,
|
|
265
|
-
iTo: number
|
|
266
|
-
) => void;
|
|
267
|
-
onTrackScrollBind: () => void;
|
|
268
|
-
onTrackSelectionBind: () => void;
|
|
269
|
-
onContentRescaleBind: () => void;
|
|
270
|
-
onContentSelectionBind: () => void;
|
|
271
|
-
onTemplateChangedBind: () => void;
|
|
272
|
-
}[];
|
|
273
|
-
|
|
274
|
-
constructor(props: Props) {
|
|
275
|
-
super(props);
|
|
276
|
-
|
|
277
|
-
const _axes = this.props.welllogs.map((welllog: WellLog) =>
|
|
278
|
-
getAvailableAxes(welllog, this.props.axisMnemos)
|
|
279
|
-
);
|
|
280
|
-
const axes = _axes[0];
|
|
281
|
-
let primaryAxis = axes?.[0];
|
|
282
|
-
if (this.props.templates[0] && axes) {
|
|
283
|
-
this.props.templates[0].scale.primary = "tvd"; //!!!!!
|
|
284
|
-
if (
|
|
285
|
-
this.props.templates[0] &&
|
|
286
|
-
this.props.templates[0].scale.primary
|
|
287
|
-
) {
|
|
288
|
-
if (axes.indexOf(this.props.templates[0].scale.primary) >= 0)
|
|
289
|
-
primaryAxis = this.props.templates[0].scale.primary;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
if (this.props.primaryAxis) primaryAxis = this.props.primaryAxis;
|
|
293
|
-
this.state = {
|
|
294
|
-
primaryAxis: primaryAxis, //"md"
|
|
295
|
-
axes: axes, //["md", "tvd"]
|
|
296
|
-
infos: [[], []],
|
|
297
|
-
|
|
298
|
-
sliderValue: 4.0, // zoom
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
this.controllers = [null, null];
|
|
302
|
-
this.spacers = [null, null];
|
|
303
|
-
|
|
304
|
-
this.collapsedTrackIds = [];
|
|
305
|
-
|
|
306
|
-
this.onChangePrimaryAxis = this.onChangePrimaryAxis.bind(this);
|
|
307
|
-
|
|
308
|
-
this.callbacks = [];
|
|
309
|
-
this.props.welllogs.map((_welllog: WellLog, index: number) => {
|
|
310
|
-
this.callbacks.push({
|
|
311
|
-
onCreateControllerBind: this.onCreateController.bind(
|
|
312
|
-
this,
|
|
313
|
-
index
|
|
314
|
-
),
|
|
315
|
-
onInfoBind: this.onInfo.bind(this, index),
|
|
316
|
-
onTrackScrollBind: this.onTrackScroll.bind(this, index),
|
|
317
|
-
onTrackSelectionBind: this.onTrackSelection.bind(this, index),
|
|
318
|
-
onContentRescaleBind: this.onContentRescale.bind(this, index),
|
|
319
|
-
onContentSelectionBind: this.onContentSelection.bind(
|
|
320
|
-
this,
|
|
321
|
-
index
|
|
322
|
-
),
|
|
323
|
-
onTemplateChangedBind: this.onTemplateChanged.bind(this, index),
|
|
324
|
-
});
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
this.onZoomSliderChange = this.onZoomSliderChange.bind(this);
|
|
328
|
-
|
|
329
|
-
this.onInfoGroupClick = this.onInfoGroupClick.bind(this);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
componentDidMount(): void {
|
|
333
|
-
this.syncTrackScrollPos(0);
|
|
334
|
-
this.syncContentScrollPos(0);
|
|
335
|
-
this.syncContentSelection(0);
|
|
336
|
-
this.setSliderValue();
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
|
|
340
|
-
//?!
|
|
341
|
-
const ret =
|
|
342
|
-
!Object.is(this.props, nextProps) ||
|
|
343
|
-
!Object.is(this.state, nextState);
|
|
344
|
-
return ret;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
componentDidUpdate(prevProps: Props /*, prevState: State*/): void {
|
|
348
|
-
if (
|
|
349
|
-
this.props.welllogs !== prevProps.welllogs ||
|
|
350
|
-
this.props.templates !== prevProps.templates ||
|
|
351
|
-
this.props.axisMnemos !== prevProps.axisMnemos ||
|
|
352
|
-
this.props.primaryAxis !== prevProps.primaryAxis /*||
|
|
353
|
-
this.props.colorTables !== prevProps.colorTables*/
|
|
354
|
-
) {
|
|
355
|
-
const _axes = this.props.welllogs.map((welllog) =>
|
|
356
|
-
getAvailableAxes(welllog, this.props.axisMnemos)
|
|
357
|
-
);
|
|
358
|
-
const axes = _axes[0];
|
|
359
|
-
let primaryAxis = axes[0];
|
|
360
|
-
if (this.props.templates[0]) {
|
|
361
|
-
this.props.templates[0].scale.primary = "tvd"; //!!!!!
|
|
362
|
-
if (this.props.templates[0].scale.primary) {
|
|
363
|
-
if (
|
|
364
|
-
axes.indexOf(this.props.templates[0].scale.primary) < 0
|
|
365
|
-
) {
|
|
366
|
-
if (this.props.welllogs === prevProps.welllogs) return; // nothing to update
|
|
367
|
-
} else {
|
|
368
|
-
primaryAxis = this.props.templates[0].scale.primary;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
if (this.props.primaryAxis) primaryAxis = this.props.primaryAxis;
|
|
373
|
-
this.setState({
|
|
374
|
-
primaryAxis: primaryAxis,
|
|
375
|
-
axes: axes,
|
|
376
|
-
// will be changed by callback! infos: [],
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
if (isEqualRanges(this.props.domain, prevProps.domain)) {
|
|
381
|
-
this.setControllersZoom();
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
if (
|
|
385
|
-
this.props.wellpicks !== prevProps.wellpicks ||
|
|
386
|
-
!isEqualArrays(
|
|
387
|
-
this.props.wellpickFlatting,
|
|
388
|
-
prevProps.wellpickFlatting
|
|
389
|
-
)
|
|
390
|
-
) {
|
|
391
|
-
this.syncContentScrollPos(0); // force to redraw
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
if (isEqualRanges(this.props.selection, prevProps.selection)) {
|
|
395
|
-
this.setControllersSelection();
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
if (
|
|
399
|
-
this.props.syncContentSelection !== prevProps.syncContentSelection
|
|
400
|
-
) {
|
|
401
|
-
this.syncContentSelection(0); // force to redraw selection
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
if (
|
|
405
|
-
this.props.readoutOptions &&
|
|
406
|
-
(!prevProps.readoutOptions ||
|
|
407
|
-
this.props.readoutOptions.allTracks !==
|
|
408
|
-
prevProps.readoutOptions.allTracks ||
|
|
409
|
-
this.props.readoutOptions.grouping !==
|
|
410
|
-
prevProps.readoutOptions.grouping)
|
|
411
|
-
) {
|
|
412
|
-
this.updateReadoutPanel();
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
updateReadoutPanel(): void {
|
|
417
|
-
for (const controller of this.controllers) {
|
|
418
|
-
if (!controller) continue;
|
|
419
|
-
controller.selectContent(controller.getContentSelection()); // force to update readout panel
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// callback function from WellLogView
|
|
424
|
-
onInfo(
|
|
425
|
-
iView: number,
|
|
426
|
-
x: number,
|
|
427
|
-
logController: LogViewer,
|
|
428
|
-
iFrom: number,
|
|
429
|
-
iTo: number
|
|
430
|
-
): void {
|
|
431
|
-
const infos = fillInfos(
|
|
432
|
-
x,
|
|
433
|
-
logController,
|
|
434
|
-
iFrom,
|
|
435
|
-
iTo,
|
|
436
|
-
this.collapsedTrackIds,
|
|
437
|
-
this.props.readoutOptions
|
|
438
|
-
);
|
|
439
|
-
|
|
440
|
-
this.setState((state: Readonly<State>) => {
|
|
441
|
-
const newState: { infos: Info[][] } = { infos: [] };
|
|
442
|
-
this.props.welllogs.map((_welllog: WellLog, index: number) =>
|
|
443
|
-
newState.infos.push(iView == index ? infos : state.infos[index])
|
|
444
|
-
);
|
|
445
|
-
return newState;
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
|
-
// callback function from WellLogView
|
|
449
|
-
onCreateController(iView: number, controller: WellLogController): void {
|
|
450
|
-
this.controllers[iView] = controller;
|
|
451
|
-
if (this.props.onCreateController)
|
|
452
|
-
// set callback to component's caller
|
|
453
|
-
this.props.onCreateController(iView, controller);
|
|
454
|
-
|
|
455
|
-
this.setControllersZoom();
|
|
456
|
-
this.syncTrackScrollPos(iView);
|
|
457
|
-
this.syncContentScrollPos(iView);
|
|
458
|
-
this.syncContentSelection(iView);
|
|
459
|
-
}
|
|
460
|
-
// callback function from WellLogView
|
|
461
|
-
onTrackScroll(iView: number): void {
|
|
462
|
-
this.syncTrackScrollPos(iView);
|
|
463
|
-
}
|
|
464
|
-
// callback function from WellLogView
|
|
465
|
-
onTrackSelection(iView: number): void {
|
|
466
|
-
this.syncTrackSelection(iView);
|
|
467
|
-
}
|
|
468
|
-
// callback function from WellLogView
|
|
469
|
-
onContentRescale(iView: number): void {
|
|
470
|
-
this.syncTrackScrollPos(iView);
|
|
471
|
-
this.syncContentScrollPos(iView);
|
|
472
|
-
this.syncContentSelection(iView);
|
|
473
|
-
|
|
474
|
-
this.setSliderValue();
|
|
475
|
-
if (this.props.onContentRescale) this.props.onContentRescale(iView);
|
|
476
|
-
}
|
|
477
|
-
// callback function from WellLogView
|
|
478
|
-
onContentSelection(iView: number): void {
|
|
479
|
-
this.syncContentSelection(iView);
|
|
480
|
-
if (this.props.onContentSelection) this.props.onContentSelection(iView);
|
|
481
|
-
}
|
|
482
|
-
// callback function from WellLogView
|
|
483
|
-
onTemplateChanged(iView: number): void {
|
|
484
|
-
this.syncTemplate(iView);
|
|
485
|
-
|
|
486
|
-
if (this.props.onTemplateChanged) {
|
|
487
|
-
if (this.props.onTemplateChanged)
|
|
488
|
-
this.props.onTemplateChanged(iView);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
// callback function from Axis selector
|
|
492
|
-
onChangePrimaryAxis(value: string): void {
|
|
493
|
-
this.setState({ primaryAxis: value });
|
|
494
|
-
}
|
|
495
|
-
// callback function from Zoom slider
|
|
496
|
-
onZoomSliderChange(value: number): void {
|
|
497
|
-
const iView = 0; // master
|
|
498
|
-
const controller = this.controllers[iView];
|
|
499
|
-
if (!controller) return;
|
|
500
|
-
controller.zoomContent(value);
|
|
501
|
-
this.syncContentScrollPos(iView);
|
|
502
|
-
}
|
|
503
|
-
// callback function from Scroller
|
|
504
|
-
onScrollerScroll(iView: number, x: number, y: number): void {
|
|
505
|
-
const controller = this.controllers[iView];
|
|
506
|
-
if (!controller) return;
|
|
507
|
-
|
|
508
|
-
const posMax = controller.getTrackScrollPosMax();
|
|
509
|
-
let posTrack = (this.props.horizontal ? y : x) * posMax;
|
|
510
|
-
posTrack = Math.round(posTrack);
|
|
511
|
-
controller.scrollTrackTo(posTrack);
|
|
512
|
-
|
|
513
|
-
const fContent = this.props.horizontal ? x : y; // fraction
|
|
514
|
-
controller.scrollContentTo(fContent);
|
|
515
|
-
|
|
516
|
-
const domain = controller.getContentDomain();
|
|
517
|
-
for (const _controller of this.controllers) {
|
|
518
|
-
if (!_controller || _controller == controller) continue;
|
|
519
|
-
if (
|
|
520
|
-
!(this.props.wellpickFlatting && this.props.wellpicks) &&
|
|
521
|
-
this.props.syncContentDomain
|
|
522
|
-
) {
|
|
523
|
-
const _domain = _controller.getContentDomain();
|
|
524
|
-
if (!isEqDomains(_domain, domain))
|
|
525
|
-
_controller.zoomContentTo(domain);
|
|
526
|
-
}
|
|
527
|
-
if (this.props.syncTrackPos) _controller.scrollTrackTo(posTrack);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// set zoom value to slider
|
|
532
|
-
setSliderValue(): void {
|
|
533
|
-
this.setState((state: Readonly<State>) => {
|
|
534
|
-
if (!this.controllers[0]) return null;
|
|
535
|
-
const zoom = this.controllers[0].getContentZoom();
|
|
536
|
-
if (Math.abs(Math.log(state.sliderValue / zoom)) < 0.01)
|
|
537
|
-
return null;
|
|
538
|
-
return { sliderValue: zoom };
|
|
539
|
-
});
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
syncTrackScrollPos(iView: number): void {
|
|
543
|
-
const controller = this.controllers[iView];
|
|
544
|
-
if (!controller) return;
|
|
545
|
-
const trackPos = controller.getTrackScrollPos();
|
|
546
|
-
for (const _controller of this.controllers) {
|
|
547
|
-
if (!_controller || _controller == controller) continue;
|
|
548
|
-
if (this.props.syncTrackPos) _controller.scrollTrackTo(trackPos);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
syncTrackSelection(iView: number): void {
|
|
552
|
-
const controller = this.controllers[iView];
|
|
553
|
-
if (!controller) return;
|
|
554
|
-
const trackSelection = controller.getSelectedTrackIndices();
|
|
555
|
-
for (const _controller of this.controllers) {
|
|
556
|
-
if (!_controller || _controller == controller) continue;
|
|
557
|
-
if (this.props.syncTemplate)
|
|
558
|
-
_controller.setSelectedTrackIndices(trackSelection);
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
getCommonContentBaseDomain(): [number, number] {
|
|
563
|
-
const commonBaseDomain: [number, number] = [
|
|
564
|
-
Number.POSITIVE_INFINITY,
|
|
565
|
-
Number.NEGATIVE_INFINITY,
|
|
566
|
-
];
|
|
567
|
-
for (const controller of this.controllers) {
|
|
568
|
-
if (!controller) continue;
|
|
569
|
-
checkMinMax(commonBaseDomain, controller.getContentBaseDomain());
|
|
570
|
-
}
|
|
571
|
-
return commonBaseDomain;
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
syncContentBaseDomain(): boolean {
|
|
575
|
-
let updated = false;
|
|
576
|
-
if (
|
|
577
|
-
!(this.props.wellpickFlatting && this.props.wellpicks) &&
|
|
578
|
-
this.props.syncContentDomain
|
|
579
|
-
) {
|
|
580
|
-
const commonBaseDomain: [number, number] =
|
|
581
|
-
this.getCommonContentBaseDomain();
|
|
582
|
-
for (const controller of this.controllers) {
|
|
583
|
-
if (!controller) continue;
|
|
584
|
-
const baseDomain = controller.getContentBaseDomain();
|
|
585
|
-
if (!isEqDomains(baseDomain, commonBaseDomain)) {
|
|
586
|
-
controller.setContentBaseDomain(commonBaseDomain);
|
|
587
|
-
updated = true;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
return updated;
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
makeFlattingCoeffs(): {
|
|
595
|
-
A: number[][];
|
|
596
|
-
B: number[][];
|
|
597
|
-
newBaseDomain: [number, number][]; // not used
|
|
598
|
-
} {
|
|
599
|
-
const wellpickFlatting = this.props.wellpickFlatting;
|
|
600
|
-
if (!wellpickFlatting) return { A: [], B: [], newBaseDomain: [] };
|
|
601
|
-
|
|
602
|
-
const flattingA: number[][] = [];
|
|
603
|
-
const flattingB: number[][] = [];
|
|
604
|
-
|
|
605
|
-
const nView = this.controllers.length;
|
|
606
|
-
const newBaseDomain: [number, number][] = [];
|
|
607
|
-
for (let i = 0; i < nView; i++) {
|
|
608
|
-
newBaseDomain.push([
|
|
609
|
-
Number.POSITIVE_INFINITY,
|
|
610
|
-
Number.NEGATIVE_INFINITY,
|
|
611
|
-
]);
|
|
612
|
-
}
|
|
613
|
-
for (const controller of this.controllers) {
|
|
614
|
-
const wellLogView = controller as WellLogView;
|
|
615
|
-
const wps = wellLogView ? getWellPicks(wellLogView) : [];
|
|
616
|
-
let wp1: number | undefined = undefined;
|
|
617
|
-
let wp2: number | undefined = undefined;
|
|
618
|
-
for (const wp of wps) {
|
|
619
|
-
if (wellpickFlatting[0] === wp.horizon) wp1 = wp.vPrimary;
|
|
620
|
-
if (wellpickFlatting[1] === wp.horizon) wp2 = wp.vPrimary;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
const _flattingA: number[] = [];
|
|
624
|
-
const _flattingB: number[] = [];
|
|
625
|
-
let j = -1;
|
|
626
|
-
for (const _controller of this.controllers) {
|
|
627
|
-
j++;
|
|
628
|
-
if (!_controller || !controller) {
|
|
629
|
-
_flattingA.push(0.0);
|
|
630
|
-
_flattingB.push(0.0);
|
|
631
|
-
continue;
|
|
632
|
-
}
|
|
633
|
-
const _wellLogView = _controller as WellLogView;
|
|
634
|
-
const _wps = getWellPicks(_wellLogView);
|
|
635
|
-
let _wp1: number | undefined = undefined;
|
|
636
|
-
let _wp2: number | undefined = undefined;
|
|
637
|
-
for (const _wp of _wps) {
|
|
638
|
-
if (wellpickFlatting[0] === _wp.horizon)
|
|
639
|
-
_wp1 = _wp.vPrimary;
|
|
640
|
-
if (wellpickFlatting[1] === _wp.horizon)
|
|
641
|
-
_wp2 = _wp.vPrimary;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
if (
|
|
645
|
-
Number.isFinite(wp1) &&
|
|
646
|
-
Number.isFinite(_wp1) &&
|
|
647
|
-
wp1 !== undefined &&
|
|
648
|
-
_wp1 !== undefined
|
|
649
|
-
) {
|
|
650
|
-
let a: number;
|
|
651
|
-
if (
|
|
652
|
-
Number.isFinite(wp2) &&
|
|
653
|
-
Number.isFinite(_wp2) &&
|
|
654
|
-
wp2 !== undefined &&
|
|
655
|
-
_wp2 !== undefined &&
|
|
656
|
-
wp2 - wp1
|
|
657
|
-
)
|
|
658
|
-
a = (_wp2 - _wp1) / (wp2 - wp1);
|
|
659
|
-
else {
|
|
660
|
-
if (this.props.syncContentDomain) {
|
|
661
|
-
a = 1;
|
|
662
|
-
} else {
|
|
663
|
-
const domain = controller.getContentDomain();
|
|
664
|
-
const _domain = _controller.getContentDomain();
|
|
665
|
-
if (
|
|
666
|
-
_domain[1] - _domain[0] &&
|
|
667
|
-
domain[1] - domain[0]
|
|
668
|
-
)
|
|
669
|
-
a =
|
|
670
|
-
(_domain[1] - _domain[0]) /
|
|
671
|
-
(domain[1] - domain[0]);
|
|
672
|
-
else a = 1;
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
const b = _wp1 - a * wp1;
|
|
676
|
-
_flattingA.push(a);
|
|
677
|
-
_flattingB.push(b);
|
|
678
|
-
|
|
679
|
-
const baseDomain = controller.getContentBaseDomain();
|
|
680
|
-
const baseDomainNew: [number, number] = [
|
|
681
|
-
a * baseDomain[0] + b,
|
|
682
|
-
a * baseDomain[1] + b,
|
|
683
|
-
];
|
|
684
|
-
|
|
685
|
-
checkMinMax(newBaseDomain[j], baseDomainNew);
|
|
686
|
-
} else {
|
|
687
|
-
// The first well pick undefined
|
|
688
|
-
_flattingA.push(controller === _controller ? 1.0 : 0.0);
|
|
689
|
-
_flattingB.push(0.0);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
flattingA.push(_flattingA);
|
|
693
|
-
flattingB.push(_flattingB);
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
return { A: flattingA, B: flattingB, newBaseDomain: newBaseDomain };
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
syncContentScrollPos(iView: number): void {
|
|
700
|
-
const controller = this.controllers[iView];
|
|
701
|
-
if (!controller) return;
|
|
702
|
-
|
|
703
|
-
let updated = false;
|
|
704
|
-
const wellpickFlatting = this.props.wellpickFlatting;
|
|
705
|
-
const syncContentDomain = this.props.syncContentDomain;
|
|
706
|
-
let coeff: {
|
|
707
|
-
A: number[][];
|
|
708
|
-
B: number[][];
|
|
709
|
-
newBaseDomain: [number, number][];
|
|
710
|
-
} | null = null;
|
|
711
|
-
if (this.props.wellpicks && wellpickFlatting) {
|
|
712
|
-
coeff = this.makeFlattingCoeffs();
|
|
713
|
-
}
|
|
714
|
-
// synchronize base domains
|
|
715
|
-
updated = this.syncContentBaseDomain();
|
|
716
|
-
const domain = controller.getContentDomain();
|
|
717
|
-
|
|
718
|
-
let j = -1;
|
|
719
|
-
for (const _controller of this.controllers) {
|
|
720
|
-
j++;
|
|
721
|
-
if (!_controller || _controller == controller) continue;
|
|
722
|
-
if (coeff) {
|
|
723
|
-
// wellpick flatting
|
|
724
|
-
const a = coeff.A[iView][j];
|
|
725
|
-
const b = coeff.B[iView][j];
|
|
726
|
-
|
|
727
|
-
const domainNew: [number, number] = [
|
|
728
|
-
a * domain[0] + b,
|
|
729
|
-
a * domain[1] + b,
|
|
730
|
-
];
|
|
731
|
-
const _domain = _controller.getContentDomain();
|
|
732
|
-
if (
|
|
733
|
-
Number.isFinite(domainNew[0]) &&
|
|
734
|
-
Number.isFinite(domainNew[1])
|
|
735
|
-
) {
|
|
736
|
-
if (!isEqDomains(_domain, domainNew)) {
|
|
737
|
-
_controller.zoomContentTo(domainNew);
|
|
738
|
-
updated = true;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
// sync scroll bar: not work yet
|
|
742
|
-
const baseDomain = _controller.getContentBaseDomain();
|
|
743
|
-
//const newBaseDomain = coeff.newBaseDomain[j];
|
|
744
|
-
const newBaseDomain: [number, number] = [
|
|
745
|
-
domainNew[0],
|
|
746
|
-
domainNew[1],
|
|
747
|
-
];
|
|
748
|
-
if (baseDomain[0] < newBaseDomain[0])
|
|
749
|
-
newBaseDomain[0] = baseDomain[0];
|
|
750
|
-
if (baseDomain[1] > newBaseDomain[1])
|
|
751
|
-
newBaseDomain[1] = baseDomain[1];
|
|
752
|
-
if (
|
|
753
|
-
Number.isFinite(newBaseDomain[0]) &&
|
|
754
|
-
Number.isFinite(newBaseDomain[1])
|
|
755
|
-
)
|
|
756
|
-
if (!isEqDomains(baseDomain, newBaseDomain)) {
|
|
757
|
-
//_controller.setContentBaseDomain(newBaseDomain);
|
|
758
|
-
//updated = true;
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
} else if (syncContentDomain) {
|
|
762
|
-
const _domain = _controller.getContentDomain();
|
|
763
|
-
if (!isEqDomains(_domain, domain)) {
|
|
764
|
-
_controller.zoomContentTo(domain);
|
|
765
|
-
updated = true;
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
if (updated) {
|
|
771
|
-
for (let i = iView - 1; i <= iView; i++) {
|
|
772
|
-
const spacer = this.spacers[i];
|
|
773
|
-
if (!spacer) continue;
|
|
774
|
-
spacer.update();
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
syncContentSelection(iView: number): void {
|
|
780
|
-
const controller = this.controllers[iView];
|
|
781
|
-
if (!controller) return;
|
|
782
|
-
const selection = controller.getContentSelection();
|
|
783
|
-
for (const _controller of this.controllers) {
|
|
784
|
-
if (!_controller || _controller == controller) continue;
|
|
785
|
-
if (this.props.syncContentSelection) {
|
|
786
|
-
const _selection = _controller.getContentSelection();
|
|
787
|
-
if (!isEqualRanges(_selection, selection))
|
|
788
|
-
_controller.selectContent(selection);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
for (const spacer of this.spacers) {
|
|
793
|
-
if (!spacer) continue;
|
|
794
|
-
spacer.forceUpdate();
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
syncTemplate(iView: number): void {
|
|
799
|
-
const controller = this.controllers[iView];
|
|
800
|
-
if (!controller) return;
|
|
801
|
-
const template = controller.getTemplate();
|
|
802
|
-
for (const _controller of this.controllers) {
|
|
803
|
-
if (!_controller || _controller == controller) continue;
|
|
804
|
-
if (this.props.syncTemplate) _controller.setTemplate(template);
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
setControllersZoom(): void {
|
|
809
|
-
for (const controller of this.controllers) {
|
|
810
|
-
if (!controller) continue;
|
|
811
|
-
if (this.props.domain) controller.zoomContentTo(this.props.domain);
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
setControllersSelection(): void {
|
|
815
|
-
if (!this.props.selection) return;
|
|
816
|
-
for (const controller of this.controllers) {
|
|
817
|
-
if (!controller) continue;
|
|
818
|
-
controller.selectContent(this.props.selection);
|
|
819
|
-
}
|
|
820
|
-
for (const spacer of this.spacers) {
|
|
821
|
-
if (!spacer) continue;
|
|
822
|
-
spacer.forceUpdate();
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
onInfoGroupClick(trackId: string | number): void {
|
|
826
|
-
const i = this.collapsedTrackIds.indexOf(trackId);
|
|
827
|
-
if (i < 0) this.collapsedTrackIds.push(trackId);
|
|
828
|
-
else delete this.collapsedTrackIds[i];
|
|
829
|
-
|
|
830
|
-
this.updateReadoutPanel();
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
createView(index: number): ReactNode {
|
|
834
|
-
const callbacks = this.callbacks[index];
|
|
835
|
-
const wellLog = this.props.welllogs[index];
|
|
836
|
-
const templates = this.props.templates;
|
|
837
|
-
const template = templates[index] ? templates[index] : templates[0];
|
|
838
|
-
const viewTitles = this.props.viewTitles;
|
|
839
|
-
const viewTitle =
|
|
840
|
-
viewTitles && (viewTitles === true ? true : viewTitles[index]);
|
|
841
|
-
const options = {
|
|
842
|
-
...this.props.welllogOptions,
|
|
843
|
-
maxVisibleTrackNum:
|
|
844
|
-
this.props.welllogOptions?.maxVisibleTrackNum ||
|
|
845
|
-
(this.props.horizontal ? 2 : 3),
|
|
846
|
-
};
|
|
847
|
-
return (
|
|
848
|
-
<WellLogViewWithScroller
|
|
849
|
-
key={index}
|
|
850
|
-
welllog={wellLog}
|
|
851
|
-
viewTitle={viewTitle}
|
|
852
|
-
template={template}
|
|
853
|
-
colorTables={this.props.colorTables}
|
|
854
|
-
wellpick={this.props.wellpicks?.[index]}
|
|
855
|
-
patternsTable={this.props.patternsTable}
|
|
856
|
-
patterns={this.props.patterns}
|
|
857
|
-
horizontal={this.props.horizontal}
|
|
858
|
-
axisTitles={this.props.axisTitles}
|
|
859
|
-
axisMnemos={this.props.axisMnemos}
|
|
860
|
-
primaryAxis={this.state.primaryAxis}
|
|
861
|
-
options={options}
|
|
862
|
-
onInfo={callbacks.onInfoBind}
|
|
863
|
-
onCreateController={callbacks.onCreateControllerBind}
|
|
864
|
-
onTrackMouseEvent={onTrackMouseEvent}
|
|
865
|
-
onTrackScroll={callbacks.onTrackScrollBind}
|
|
866
|
-
onTrackSelection={callbacks.onTrackSelectionBind}
|
|
867
|
-
onContentRescale={callbacks.onContentRescaleBind}
|
|
868
|
-
onContentSelection={callbacks.onContentSelectionBind}
|
|
869
|
-
onTemplateChanged={callbacks.onTemplateChangedBind}
|
|
870
|
-
/>
|
|
871
|
-
);
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
createSpacer(index: number): ReactNode {
|
|
875
|
-
if (!this.props.spacers) return null;
|
|
876
|
-
const prev = index - 1;
|
|
877
|
-
|
|
878
|
-
let width = 255;
|
|
879
|
-
if (typeof this.props.spacers !== "boolean") {
|
|
880
|
-
width =
|
|
881
|
-
typeof this.props.spacers === "number"
|
|
882
|
-
? this.props.spacers // all widths are equal
|
|
883
|
-
: this.props.spacers[prev]; // individual width
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
if (width === undefined) width = 255; // set some default value
|
|
887
|
-
if (!width) return null;
|
|
888
|
-
|
|
889
|
-
return (
|
|
890
|
-
<div
|
|
891
|
-
style={
|
|
892
|
-
this.props.horizontal
|
|
893
|
-
? { height: width + "px" }
|
|
894
|
-
: { width: width + "px" }
|
|
895
|
-
}
|
|
896
|
-
key={"s" + index}
|
|
897
|
-
>
|
|
898
|
-
<WellLogSpacer
|
|
899
|
-
controllers={
|
|
900
|
-
this.controllers
|
|
901
|
-
? [this.controllers[prev], this.controllers[index]]
|
|
902
|
-
: []
|
|
903
|
-
}
|
|
904
|
-
distance={{
|
|
905
|
-
units: this.props.wellDistances
|
|
906
|
-
? this.props.wellDistances.units
|
|
907
|
-
: "",
|
|
908
|
-
value: this.props.wellDistances?.distances[prev],
|
|
909
|
-
}}
|
|
910
|
-
colorTables={this.props.colorTables}
|
|
911
|
-
wellpicks={
|
|
912
|
-
this.props.wellpicks
|
|
913
|
-
? [
|
|
914
|
-
this.props.wellpicks[prev],
|
|
915
|
-
this.props.wellpicks[index],
|
|
916
|
-
]
|
|
917
|
-
: []
|
|
918
|
-
}
|
|
919
|
-
patternsTable={this.props.patternsTable}
|
|
920
|
-
patterns={this.props.patterns}
|
|
921
|
-
options={this.props.spacerOptions}
|
|
922
|
-
horizontal={this.props.horizontal}
|
|
923
|
-
onCreateSpacer={(spacer: WellLogSpacer): void => {
|
|
924
|
-
this.spacers[index] = spacer;
|
|
925
|
-
}}
|
|
926
|
-
></WellLogSpacer>
|
|
927
|
-
</div>
|
|
928
|
-
);
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
createRightPanel(): ReactNode {
|
|
932
|
-
return (
|
|
933
|
-
<div
|
|
934
|
-
key="rightPanel"
|
|
935
|
-
style={{
|
|
936
|
-
flex: "0, 0",
|
|
937
|
-
display: "flex",
|
|
938
|
-
flexDirection: "column",
|
|
939
|
-
height: "100%",
|
|
940
|
-
width: "255px",
|
|
941
|
-
minWidth: "255px",
|
|
942
|
-
maxWidth: "255px",
|
|
943
|
-
}}
|
|
944
|
-
>
|
|
945
|
-
<AxisSelector
|
|
946
|
-
header="Primary scale"
|
|
947
|
-
axes={this.state.axes}
|
|
948
|
-
axisLabels={this.props.axisTitles}
|
|
949
|
-
value={this.state.primaryAxis}
|
|
950
|
-
onChange={this.onChangePrimaryAxis}
|
|
951
|
-
/>
|
|
952
|
-
{this.props.welllogs.map((_welllog: WellLog, index: number) => (
|
|
953
|
-
<InfoPanel
|
|
954
|
-
key={index}
|
|
955
|
-
header={
|
|
956
|
-
"Readout " + this.props.welllogs[index].header.well
|
|
957
|
-
}
|
|
958
|
-
onGroupClick={this.onInfoGroupClick}
|
|
959
|
-
infos={this.state.infos[index]}
|
|
960
|
-
/>
|
|
961
|
-
))}
|
|
962
|
-
<div style={{ paddingLeft: "10px", display: "flex" }}>
|
|
963
|
-
<span>Zoom:</span>
|
|
964
|
-
<span
|
|
965
|
-
style={{
|
|
966
|
-
flex: "1 1 100px",
|
|
967
|
-
padding: "0 20px 0 10px",
|
|
968
|
-
}}
|
|
969
|
-
>
|
|
970
|
-
<ZoomSlider
|
|
971
|
-
value={this.state.sliderValue}
|
|
972
|
-
max={
|
|
973
|
-
this.props.welllogOptions?.maxContentZoom ||
|
|
974
|
-
256 /*default*/
|
|
975
|
-
}
|
|
976
|
-
onChange={this.onZoomSliderChange}
|
|
977
|
-
/>
|
|
978
|
-
</span>
|
|
979
|
-
</div>
|
|
980
|
-
</div>
|
|
981
|
-
);
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
render(): JSX.Element {
|
|
985
|
-
return (
|
|
986
|
-
<div
|
|
987
|
-
style={{
|
|
988
|
-
height: "100%",
|
|
989
|
-
width: "100%",
|
|
990
|
-
display: "flex",
|
|
991
|
-
flexDirection: "row",
|
|
992
|
-
}}
|
|
993
|
-
>
|
|
994
|
-
<div
|
|
995
|
-
style={{
|
|
996
|
-
height: "100%",
|
|
997
|
-
width: "255px" /*some small value to be grown by flex*/,
|
|
998
|
-
flex: "1 1",
|
|
999
|
-
display: "flex",
|
|
1000
|
-
flexDirection: this.props.horizontal ? "column" : "row",
|
|
1001
|
-
}}
|
|
1002
|
-
>
|
|
1003
|
-
{this.props.welllogs.map(
|
|
1004
|
-
(_welllog: WellLog, index: number) => [
|
|
1005
|
-
index ? this.createSpacer(index) : null,
|
|
1006
|
-
this.createView(index),
|
|
1007
|
-
]
|
|
1008
|
-
)}
|
|
1009
|
-
</div>
|
|
1010
|
-
{this.createRightPanel()}
|
|
1011
|
-
</div>
|
|
1012
|
-
);
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
///
|
|
1017
|
-
const WellLogViewOptions_propTypes = PropTypes.shape({
|
|
1018
|
-
/**
|
|
1019
|
-
* The maximum zoom value
|
|
1020
|
-
*/
|
|
1021
|
-
maxContentZoom: PropTypes.number,
|
|
1022
|
-
/**
|
|
1023
|
-
* The maximum number of visible tracks
|
|
1024
|
-
*/
|
|
1025
|
-
maxVisibleTrackNum: PropTypes.number,
|
|
1026
|
-
/**
|
|
1027
|
-
* Validate JSON datafile against schema
|
|
1028
|
-
*/
|
|
1029
|
-
checkDatafileSchema: PropTypes.bool,
|
|
1030
|
-
/**
|
|
1031
|
-
* Hide titles of the track. Default is false
|
|
1032
|
-
*/
|
|
1033
|
-
hideTrackTitle: PropTypes.bool,
|
|
1034
|
-
/**
|
|
1035
|
-
* Hide legends of the track. Default is false
|
|
1036
|
-
*/
|
|
1037
|
-
hideTrackLegend: PropTypes.bool,
|
|
1038
|
-
});
|
|
1039
|
-
|
|
1040
|
-
const InfoOptions_propTypes = PropTypes.shape({
|
|
1041
|
-
/**
|
|
1042
|
-
* Show not only visible tracks
|
|
1043
|
-
*/
|
|
1044
|
-
allTracks: PropTypes.bool,
|
|
1045
|
-
/**
|
|
1046
|
-
* how group values. "" | "track"
|
|
1047
|
-
*/
|
|
1048
|
-
grouping: PropTypes.string,
|
|
1049
|
-
});
|
|
1050
|
-
|
|
1051
|
-
/*
|
|
1052
|
-
*/
|
|
1053
|
-
SyncLogViewer.propTypes = {
|
|
1054
|
-
/**
|
|
1055
|
-
* The ID of this component, used to identify dash components
|
|
1056
|
-
* in callbacks. The ID needs to be unique across all of the
|
|
1057
|
-
* components in an app.
|
|
1058
|
-
*/
|
|
1059
|
-
id: PropTypes.string.isRequired,
|
|
1060
|
-
|
|
1061
|
-
/**
|
|
1062
|
-
* Array of JSON objects describing well log data
|
|
1063
|
-
*/
|
|
1064
|
-
welllogs: PropTypes.array.isRequired,
|
|
1065
|
-
|
|
1066
|
-
/**
|
|
1067
|
-
* Prop containing track template data
|
|
1068
|
-
*/
|
|
1069
|
-
templates: PropTypes.array.isRequired,
|
|
1070
|
-
|
|
1071
|
-
/**
|
|
1072
|
-
* Prop containing color table data
|
|
1073
|
-
*/
|
|
1074
|
-
colorTables: PropTypes.array.isRequired,
|
|
1075
|
-
|
|
1076
|
-
/**
|
|
1077
|
-
* Well Picks data array
|
|
1078
|
-
*/
|
|
1079
|
-
wellpicks: PropTypes.array,
|
|
1080
|
-
|
|
1081
|
-
/**
|
|
1082
|
-
* Patterns table
|
|
1083
|
-
*/
|
|
1084
|
-
patternsTable: PropTypes.object,
|
|
1085
|
-
/**
|
|
1086
|
-
* Horizon to pattern index map
|
|
1087
|
-
*/
|
|
1088
|
-
patterns: PropTypes.array, // [string, number][];
|
|
1089
|
-
|
|
1090
|
-
/**
|
|
1091
|
-
* Horizon names for wellpick flatting (pan and zoom)
|
|
1092
|
-
*/
|
|
1093
|
-
wellpickFlatting: PropTypes.arrayOf(PropTypes.string),
|
|
1094
|
-
|
|
1095
|
-
/**
|
|
1096
|
-
* Set to true or to array of spaser widths if WellLogSpacers should be used
|
|
1097
|
-
*/
|
|
1098
|
-
spacers: PropTypes.oneOfType([
|
|
1099
|
-
PropTypes.bool,
|
|
1100
|
-
PropTypes.arrayOf(PropTypes.number),
|
|
1101
|
-
]),
|
|
1102
|
-
|
|
1103
|
-
/**
|
|
1104
|
-
* Distanses between wells to show on the spacers
|
|
1105
|
-
*/
|
|
1106
|
-
wellDistances: PropTypes.object,
|
|
1107
|
-
|
|
1108
|
-
/**
|
|
1109
|
-
* Orientation of the track plots on the screen. Default is false
|
|
1110
|
-
*/
|
|
1111
|
-
horizontal: PropTypes.bool,
|
|
1112
|
-
|
|
1113
|
-
/**
|
|
1114
|
-
* Primary axis id: " md", "tvd", "time"...
|
|
1115
|
-
*/
|
|
1116
|
-
primaryAxis: PropTypes.string,
|
|
1117
|
-
|
|
1118
|
-
/**
|
|
1119
|
-
* Log mnemonics for axes
|
|
1120
|
-
*/
|
|
1121
|
-
axisTitles: PropTypes.object,
|
|
1122
|
-
|
|
1123
|
-
/**
|
|
1124
|
-
* Names for axes
|
|
1125
|
-
*/
|
|
1126
|
-
axisMnemos: PropTypes.object,
|
|
1127
|
-
|
|
1128
|
-
/**
|
|
1129
|
-
* The maximum zoom value
|
|
1130
|
-
*/
|
|
1131
|
-
maxContentZoom: PropTypes.number,
|
|
1132
|
-
|
|
1133
|
-
/**
|
|
1134
|
-
* Initial visible interval of the log data
|
|
1135
|
-
*/
|
|
1136
|
-
domain: PropTypes.arrayOf(PropTypes.number),
|
|
1137
|
-
|
|
1138
|
-
/**
|
|
1139
|
-
* Initial selected interval of the log data
|
|
1140
|
-
*/
|
|
1141
|
-
selection: PropTypes.arrayOf(PropTypes.number),
|
|
1142
|
-
|
|
1143
|
-
/**
|
|
1144
|
-
* Set to true for default titles or to array of individial welllog titles
|
|
1145
|
-
*/
|
|
1146
|
-
viewTitles: PropTypes.oneOfType([
|
|
1147
|
-
PropTypes.bool,
|
|
1148
|
-
PropTypes.arrayOf(
|
|
1149
|
-
PropTypes.oneOfType([
|
|
1150
|
-
PropTypes.bool,
|
|
1151
|
-
PropTypes.string,
|
|
1152
|
-
PropTypes.object,
|
|
1153
|
-
])
|
|
1154
|
-
) /* bool, string or react element */,
|
|
1155
|
-
]),
|
|
1156
|
-
|
|
1157
|
-
/**
|
|
1158
|
-
* WellLogView additional options
|
|
1159
|
-
*/
|
|
1160
|
-
welllogOptions: WellLogViewOptions_propTypes /*PropTypes.object,*/,
|
|
1161
|
-
|
|
1162
|
-
/**
|
|
1163
|
-
* Options for readout panel
|
|
1164
|
-
*/
|
|
1165
|
-
readoutOptions: InfoOptions_propTypes /*PropTypes.object,*/,
|
|
1166
|
-
|
|
1167
|
-
/**
|
|
1168
|
-
* Synchronize the first visible track number in views
|
|
1169
|
-
*/
|
|
1170
|
-
syncTrackPos: PropTypes.bool,
|
|
1171
|
-
|
|
1172
|
-
/**
|
|
1173
|
-
* Synchronize the visible area in views
|
|
1174
|
-
*/
|
|
1175
|
-
syncContentDomain: PropTypes.bool,
|
|
1176
|
-
|
|
1177
|
-
/**
|
|
1178
|
-
* Synchronize the selection (current mouse hover) in views
|
|
1179
|
-
*/
|
|
1180
|
-
syncContentSelection: PropTypes.bool,
|
|
1181
|
-
|
|
1182
|
-
/**
|
|
1183
|
-
* Synchronize templates in views
|
|
1184
|
-
*/
|
|
1185
|
-
syncTemplate: PropTypes.bool,
|
|
1186
|
-
};
|
|
1187
|
-
|
|
1188
|
-
export default SyncLogViewer;
|