Spaces:
Running on Zero
Running on Zero
Wells outlined exactly: thin lines just outside the well cell on the map and the well column in the sections, so every cell of the well shows in full.
Browse files- app.py +2 -2
- backend.py +26 -18
app.py
CHANGED
|
@@ -396,10 +396,10 @@ with gr.Blocks(title='ResFlow: 3D reservoir generation', theme=THEME, css=CSS, j
|
|
| 396 |
img_xy = gr.Image(FIRST['xy'], **image)
|
| 397 |
z_s = gr.Slider(0, B.Z - 1, value=B.Z // 2, step=1, label='Depth z (0 = base)')
|
| 398 |
with gr.Column(scale=1, min_width=360):
|
| 399 |
-
gr.Markdown('Section along x (XZ) at the y below; a
|
| 400 |
img_xz = gr.Image(FIRST['xz'], **image)
|
| 401 |
y_s = gr.Slider(0, FIRST['y']['maximum'], value=FIRST['y']['value'], step=1, label='y of the XZ section')
|
| 402 |
-
gr.Markdown('Section along y (YZ) at the x below; a
|
| 403 |
img_yz = gr.Image(FIRST['yz'], **image)
|
| 404 |
x_s = gr.Slider(0, FIRST['x']['maximum'], value=FIRST['x']['value'], step=1, label='x of the YZ section')
|
| 405 |
download = gr.File(FIRST['path'], label='Download (.npz: facies 1 = sand, active = inside the outline)')
|
|
|
|
| 396 |
img_xy = gr.Image(FIRST['xy'], **image)
|
| 397 |
z_s = gr.Slider(0, B.Z - 1, value=B.Z // 2, step=1, label='Depth z (0 = base)')
|
| 398 |
with gr.Column(scale=1, min_width=360):
|
| 399 |
+
gr.Markdown('Section along x (XZ) at the y below; a well is the column between two dark lines.', elem_classes='cap')
|
| 400 |
img_xz = gr.Image(FIRST['xz'], **image)
|
| 401 |
y_s = gr.Slider(0, FIRST['y']['maximum'], value=FIRST['y']['value'], step=1, label='y of the XZ section')
|
| 402 |
+
gr.Markdown('Section along y (YZ) at the x below; a well is the column between two dark lines.', elem_classes='cap')
|
| 403 |
img_yz = gr.Image(FIRST['yz'], **image)
|
| 404 |
x_s = gr.Slider(0, FIRST['x']['maximum'], value=FIRST['x']['value'], step=1, label='x of the YZ section')
|
| 405 |
download = gr.File(FIRST['path'], label='Download (.npz: facies 1 = sand, active = inside the outline)')
|
backend.py
CHANGED
|
@@ -139,38 +139,46 @@ def _rgb(sl, active):
|
|
| 139 |
return np.where(active[..., None], img, OUTSIDE_RGB).astype(np.uint8)
|
| 140 |
|
| 141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
def slice_image(field, active, axis, index, wells=(), scale=None):
|
| 143 |
"""RGB image of one section: axis 'z' gives a map view (x right, y up), 'y' an XZ and 'x' a
|
| 144 |
-
YZ section (depth up). Cells outside the reservoir are white
|
| 145 |
-
|
| 146 |
-
|
|
|
|
| 147 |
nx, ny, nz = field.shape
|
| 148 |
if axis == 'z':
|
| 149 |
img = _rgb(field[:, :, index], active)[:, ::-1].transpose(1, 0, 2)
|
| 150 |
k = scale or max(1, 512 // max(img.shape[:2]))
|
| 151 |
img = np.kron(img, np.ones((k, k, 1), np.uint8))
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
img[
|
| 158 |
-
|
| 159 |
-
return _number_wells(img, [((ny - 1 - int(y)) * k + k // 2, int(x) * k + k // 2, (r + 0.5) * k)
|
| 160 |
for x, y, _ in wells]) if len(wells) else img
|
| 161 |
elif axis == 'y':
|
| 162 |
img = _rgb(field[:, index, :], np.repeat(active[:, index, None], nz, 1))[:, ::-1].transpose(1, 0, 2)
|
| 163 |
-
for x, y, _ in wells
|
| 164 |
-
if int(y) == index:
|
| 165 |
-
img[:, int(x)] = (0.55 * img[:, int(x)] + 0.45 * WELL_RGB).astype(np.uint8)
|
| 166 |
else:
|
| 167 |
img = _rgb(field[index, :, :], np.repeat(active[index, :, None], nz, 1))[:, ::-1].transpose(1, 0, 2)
|
| 168 |
-
for x, y, _ in wells
|
| 169 |
-
if int(x) == index:
|
| 170 |
-
img[:, int(y)] = (0.55 * img[:, int(y)] + 0.45 * WELL_RGB).astype(np.uint8)
|
| 171 |
kx = max(1, 1536 // img.shape[1]) # sections: about 1536 x 256 px (6:1) at any length
|
| 172 |
kz = max(1, round(img.shape[1] * kx / 6 / img.shape[0]))
|
| 173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
|
| 175 |
|
| 176 |
MAP_INSIDE_RGB = np.array([217, 217, 217], np.uint8)
|
|
|
|
| 139 |
return np.where(active[..., None], img, OUTSIDE_RGB).astype(np.uint8)
|
| 140 |
|
| 141 |
|
| 142 |
+
def _beside(lo, hi, w, n):
|
| 143 |
+
"""Two slices, ``w`` pixels wide, just outside the pixel span [lo, hi) of an image ``n`` pixels across; at the
|
| 144 |
+
image edge the slice moves inside the span."""
|
| 145 |
+
return (slice(lo - w, lo) if lo >= w else slice(lo, lo + w),
|
| 146 |
+
slice(hi, hi + w) if hi + w <= n else slice(hi - w, hi))
|
| 147 |
+
|
| 148 |
+
|
| 149 |
def slice_image(field, active, axis, index, wells=(), scale=None):
|
| 150 |
"""RGB image of one section: axis 'z' gives a map view (x right, y up), 'y' an XZ and 'x' a
|
| 151 |
+
YZ section (depth up). Cells outside the reservoir are white. A well is outlined by thin dark lines drawn
|
| 152 |
+
just outside the cells it conditions, and only those: a one-pixel ring around its cell on the map, a line
|
| 153 |
+
down each side of its column in a section, so every cell of the well shows in full. ``scale`` sets the
|
| 154 |
+
pixels per cell of the map view."""
|
| 155 |
nx, ny, nz = field.shape
|
| 156 |
if axis == 'z':
|
| 157 |
img = _rgb(field[:, :, index], active)[:, ::-1].transpose(1, 0, 2)
|
| 158 |
k = scale or max(1, 512 // max(img.shape[:2]))
|
| 159 |
img = np.kron(img, np.ones((k, k, 1), np.uint8))
|
| 160 |
+
for x, y, _ in wells:
|
| 161 |
+
row, col = (ny - 1 - int(y)) * k, int(x) * k
|
| 162 |
+
top, bottom = _beside(row, row + k, 1, img.shape[0])
|
| 163 |
+
left, right = _beside(col, col + k, 1, img.shape[1])
|
| 164 |
+
rows, cols = slice(top.start, bottom.stop), slice(left.start, right.stop)
|
| 165 |
+
img[top, cols] = img[bottom, cols] = img[rows, left] = img[rows, right] = WELL_RGB
|
| 166 |
+
return _number_wells(img, [((ny - 1 - int(y)) * k + k // 2, int(x) * k + k // 2, k / 2 + 1)
|
|
|
|
| 167 |
for x, y, _ in wells]) if len(wells) else img
|
| 168 |
elif axis == 'y':
|
| 169 |
img = _rgb(field[:, index, :], np.repeat(active[:, index, None], nz, 1))[:, ::-1].transpose(1, 0, 2)
|
| 170 |
+
marks = [int(x) for x, y, _ in wells if int(y) == index]
|
|
|
|
|
|
|
| 171 |
else:
|
| 172 |
img = _rgb(field[index, :, :], np.repeat(active[index, :, None], nz, 1))[:, ::-1].transpose(1, 0, 2)
|
| 173 |
+
marks = [int(y) for x, y, _ in wells if int(x) == index]
|
|
|
|
|
|
|
| 174 |
kx = max(1, 1536 // img.shape[1]) # sections: about 1536 x 256 px (6:1) at any length
|
| 175 |
kz = max(1, round(img.shape[1] * kx / 6 / img.shape[0]))
|
| 176 |
+
img = np.kron(img, np.ones((kz, kx, 1), np.uint8))
|
| 177 |
+
w = 1 if kx < 4 else 2 # the lines must survive the browser scaling the image down
|
| 178 |
+
for c in marks:
|
| 179 |
+
left, right = _beside(c * kx, (c + 1) * kx, w, img.shape[1])
|
| 180 |
+
img[:, left] = img[:, right] = WELL_RGB
|
| 181 |
+
return img
|
| 182 |
|
| 183 |
|
| 184 |
MAP_INSIDE_RGB = np.array([217, 217, 217], np.uint8)
|