Last active
March 3, 2023 12:43
-
-
Save GenevieveBuckley/4ad4282038a9ec49e548898c78d3b590 to your computer and use it in GitHub Desktop.
ITK + Dask notebooks (August 2022)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 29, | |
"id": "2876057e", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import itk\n", | |
"import numpy as np\n", | |
"import skimage.restoration" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 30, | |
"id": "89e50023", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"(200, 200, 200)\n", | |
"(101, 64, 64)\n" | |
] | |
} | |
], | |
"source": [ | |
"img_size = (200, 200, 200)\n", | |
"psf_size = (101, 64, 64) #(12, 100, 100)\n", | |
"\n", | |
"img = np.random.random(img_size)\n", | |
"psf = np.ones(psf_size) / np.prod(psf_size).astype('uint16')\n", | |
"\n", | |
"print(img.shape)\n", | |
"print(psf.shape)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 34, | |
"id": "383fd3f4", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"float64\n", | |
"float64\n" | |
] | |
} | |
], | |
"source": [ | |
"print(psf.dtype)\n", | |
"print(img.dtype)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 32, | |
"id": "90733602", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"done\n" | |
] | |
} | |
], | |
"source": [ | |
"# itk richardson-lucy deconvolution\n", | |
"\n", | |
"image = itk.image_view_from_array(img) # Convert to ITK object\n", | |
"kernel = itk.image_view_from_array(psf) # Convert to ITK object\n", | |
"iterations = 1\n", | |
"\n", | |
"deconvolved = itk.richardson_lucy_deconvolution_image_filter(\n", | |
" image,\n", | |
" kernel_image=kernel,\n", | |
" number_of_iterations=iterations\n", | |
")\n", | |
"\n", | |
"result = itk.array_from_image(deconvolved) # Convert back to Numpy array\n", | |
"print('done')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 33, | |
"id": "c5f601d6", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"(200, 200, 200)\n" | |
] | |
} | |
], | |
"source": [ | |
"print(result.shape)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 26, | |
"id": "0bdcd30a", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<table>\n", | |
" <tr>\n", | |
" <td>\n", | |
" <table>\n", | |
" <thead>\n", | |
" <tr>\n", | |
" <td> </td>\n", | |
" <th> Array </th>\n", | |
" <th> Chunk </th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" \n", | |
" <tr>\n", | |
" <th> Bytes </th>\n", | |
" <td> 61.04 MiB </td>\n", | |
" <td> 3.81 MiB </td>\n", | |
" </tr>\n", | |
" \n", | |
" <tr>\n", | |
" <th> Shape </th>\n", | |
" <td> (200, 200, 200) </td>\n", | |
" <td> (50, 100, 100) </td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th> Count </th>\n", | |
" <td> 16 Tasks </td>\n", | |
" <td> 16 Chunks </td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th> Type </th>\n", | |
" <td> float64 </td>\n", | |
" <td> numpy.ndarray </td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
" </table>\n", | |
" </td>\n", | |
" <td>\n", | |
" <svg width=\"250\" height=\"240\" style=\"stroke:rgb(0,0,0);stroke-width:1\" >\n", | |
"\n", | |
" <!-- Horizontal lines -->\n", | |
" <line x1=\"10\" y1=\"0\" x2=\"80\" y2=\"70\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"10\" y1=\"60\" x2=\"80\" y2=\"130\" />\n", | |
" <line x1=\"10\" y1=\"120\" x2=\"80\" y2=\"190\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Vertical lines -->\n", | |
" <line x1=\"10\" y1=\"0\" x2=\"10\" y2=\"120\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"27\" y1=\"17\" x2=\"27\" y2=\"137\" />\n", | |
" <line x1=\"45\" y1=\"35\" x2=\"45\" y2=\"155\" />\n", | |
" <line x1=\"62\" y1=\"52\" x2=\"62\" y2=\"172\" />\n", | |
" <line x1=\"80\" y1=\"70\" x2=\"80\" y2=\"190\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Colored Rectangle -->\n", | |
" <polygon points=\"10.0,0.0 80.58823529411765,70.58823529411765 80.58823529411765,190.58823529411765 10.0,120.0\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n", | |
"\n", | |
" <!-- Horizontal lines -->\n", | |
" <line x1=\"10\" y1=\"0\" x2=\"130\" y2=\"0\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"27\" y1=\"17\" x2=\"147\" y2=\"17\" />\n", | |
" <line x1=\"45\" y1=\"35\" x2=\"165\" y2=\"35\" />\n", | |
" <line x1=\"62\" y1=\"52\" x2=\"182\" y2=\"52\" />\n", | |
" <line x1=\"80\" y1=\"70\" x2=\"200\" y2=\"70\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Vertical lines -->\n", | |
" <line x1=\"10\" y1=\"0\" x2=\"80\" y2=\"70\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"70\" y1=\"0\" x2=\"140\" y2=\"70\" />\n", | |
" <line x1=\"130\" y1=\"0\" x2=\"200\" y2=\"70\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Colored Rectangle -->\n", | |
" <polygon points=\"10.0,0.0 130.0,0.0 200.58823529411765,70.58823529411765 80.58823529411765,70.58823529411765\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n", | |
"\n", | |
" <!-- Horizontal lines -->\n", | |
" <line x1=\"80\" y1=\"70\" x2=\"200\" y2=\"70\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"80\" y1=\"130\" x2=\"200\" y2=\"130\" />\n", | |
" <line x1=\"80\" y1=\"190\" x2=\"200\" y2=\"190\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Vertical lines -->\n", | |
" <line x1=\"80\" y1=\"70\" x2=\"80\" y2=\"190\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"140\" y1=\"70\" x2=\"140\" y2=\"190\" />\n", | |
" <line x1=\"200\" y1=\"70\" x2=\"200\" y2=\"190\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Colored Rectangle -->\n", | |
" <polygon points=\"80.58823529411765,70.58823529411765 200.58823529411765,70.58823529411765 200.58823529411765,190.58823529411765 80.58823529411765,190.58823529411765\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n", | |
"\n", | |
" <!-- Text -->\n", | |
" <text x=\"140.588235\" y=\"210.588235\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" >200</text>\n", | |
" <text x=\"220.588235\" y=\"130.588235\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" transform=\"rotate(-90,220.588235,130.588235)\">200</text>\n", | |
" <text x=\"35.294118\" y=\"175.294118\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" transform=\"rotate(45,35.294118,175.294118)\">200</text>\n", | |
"</svg>\n", | |
" </td>\n", | |
" </tr>\n", | |
"</table>" | |
], | |
"text/plain": [ | |
"dask.array<array, shape=(200, 200, 200), dtype=float64, chunksize=(50, 100, 100), chunktype=numpy.ndarray>" | |
] | |
}, | |
"execution_count": 26, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"import dask.array as da\n", | |
"\n", | |
"imgs = da.from_array(img, chunks=(50,100,100))\n", | |
"imgs" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 27, | |
"id": "1836c22a", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<table>\n", | |
" <tr>\n", | |
" <td>\n", | |
" <table>\n", | |
" <thead>\n", | |
" <tr>\n", | |
" <td> </td>\n", | |
" <th> Array </th>\n", | |
" <th> Chunk </th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" \n", | |
" <tr>\n", | |
" <th> Bytes </th>\n", | |
" <td> 30.52 MiB </td>\n", | |
" <td> 1.91 MiB </td>\n", | |
" </tr>\n", | |
" \n", | |
" <tr>\n", | |
" <th> Shape </th>\n", | |
" <td> (200, 200, 200) </td>\n", | |
" <td> (50, 100, 100) </td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th> Count </th>\n", | |
" <td> 32 Tasks </td>\n", | |
" <td> 16 Chunks </td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th> Type </th>\n", | |
" <td> float32 </td>\n", | |
" <td> numpy.ndarray </td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
" </table>\n", | |
" </td>\n", | |
" <td>\n", | |
" <svg width=\"250\" height=\"240\" style=\"stroke:rgb(0,0,0);stroke-width:1\" >\n", | |
"\n", | |
" <!-- Horizontal lines -->\n", | |
" <line x1=\"10\" y1=\"0\" x2=\"80\" y2=\"70\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"10\" y1=\"60\" x2=\"80\" y2=\"130\" />\n", | |
" <line x1=\"10\" y1=\"120\" x2=\"80\" y2=\"190\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Vertical lines -->\n", | |
" <line x1=\"10\" y1=\"0\" x2=\"10\" y2=\"120\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"27\" y1=\"17\" x2=\"27\" y2=\"137\" />\n", | |
" <line x1=\"45\" y1=\"35\" x2=\"45\" y2=\"155\" />\n", | |
" <line x1=\"62\" y1=\"52\" x2=\"62\" y2=\"172\" />\n", | |
" <line x1=\"80\" y1=\"70\" x2=\"80\" y2=\"190\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Colored Rectangle -->\n", | |
" <polygon points=\"10.0,0.0 80.58823529411765,70.58823529411765 80.58823529411765,190.58823529411765 10.0,120.0\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n", | |
"\n", | |
" <!-- Horizontal lines -->\n", | |
" <line x1=\"10\" y1=\"0\" x2=\"130\" y2=\"0\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"27\" y1=\"17\" x2=\"147\" y2=\"17\" />\n", | |
" <line x1=\"45\" y1=\"35\" x2=\"165\" y2=\"35\" />\n", | |
" <line x1=\"62\" y1=\"52\" x2=\"182\" y2=\"52\" />\n", | |
" <line x1=\"80\" y1=\"70\" x2=\"200\" y2=\"70\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Vertical lines -->\n", | |
" <line x1=\"10\" y1=\"0\" x2=\"80\" y2=\"70\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"70\" y1=\"0\" x2=\"140\" y2=\"70\" />\n", | |
" <line x1=\"130\" y1=\"0\" x2=\"200\" y2=\"70\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Colored Rectangle -->\n", | |
" <polygon points=\"10.0,0.0 130.0,0.0 200.58823529411765,70.58823529411765 80.58823529411765,70.58823529411765\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n", | |
"\n", | |
" <!-- Horizontal lines -->\n", | |
" <line x1=\"80\" y1=\"70\" x2=\"200\" y2=\"70\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"80\" y1=\"130\" x2=\"200\" y2=\"130\" />\n", | |
" <line x1=\"80\" y1=\"190\" x2=\"200\" y2=\"190\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Vertical lines -->\n", | |
" <line x1=\"80\" y1=\"70\" x2=\"80\" y2=\"190\" style=\"stroke-width:2\" />\n", | |
" <line x1=\"140\" y1=\"70\" x2=\"140\" y2=\"190\" />\n", | |
" <line x1=\"200\" y1=\"70\" x2=\"200\" y2=\"190\" style=\"stroke-width:2\" />\n", | |
"\n", | |
" <!-- Colored Rectangle -->\n", | |
" <polygon points=\"80.58823529411765,70.58823529411765 200.58823529411765,70.58823529411765 200.58823529411765,190.58823529411765 80.58823529411765,190.58823529411765\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n", | |
"\n", | |
" <!-- Text -->\n", | |
" <text x=\"140.588235\" y=\"210.588235\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" >200</text>\n", | |
" <text x=\"220.588235\" y=\"130.588235\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" transform=\"rotate(-90,220.588235,130.588235)\">200</text>\n", | |
" <text x=\"35.294118\" y=\"175.294118\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" transform=\"rotate(45,35.294118,175.294118)\">200</text>\n", | |
"</svg>\n", | |
" </td>\n", | |
" </tr>\n", | |
"</table>" | |
], | |
"text/plain": [ | |
"dask.array<richardson_lucy_deconvolution_image_filter, shape=(200, 200, 200), dtype=float32, chunksize=(50, 100, 100), chunktype=numpy.ndarray>" | |
] | |
}, | |
"execution_count": 27, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"deconvolved = da.map_blocks(\n", | |
" itk.richardson_lucy_deconvolution_image_filter,\n", | |
" imgs, \n", | |
" kernel_image=kernel,\n", | |
" number_of_iterations=1,\n", | |
" dtype=np.float32\n", | |
")\n", | |
"deconvolved" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 28, | |
"id": "5a46cdfb", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"deonvolved_result = deconvolved.compute()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"id": "5bbae81c", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"(200, 200, 200)\n" | |
] | |
} | |
], | |
"source": [ | |
"print(deonvolved_result.shape)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"id": "d500e9ad", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"Validation errors in config file(s).\n", | |
"The following fields have been reset to the default value:\n", | |
"\n", | |
"schema_version\n", | |
" value is not a valid tuple (type=type_error.tuple)\n", | |
"\n", | |
"\n", | |
"\n", | |
"napari was tested with QT library `>=5.12.3`.\n", | |
"The version installed is 5.9.7. Please report any issues with\n", | |
"this specific QT version at https://github.com/Napari/napari/issues.\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"<Image layer 'result' at 0x7f1a4fb0cbb0>" | |
] | |
}, | |
"execution_count": 8, | |
"metadata": {}, | |
"output_type": "execute_result" | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"Traceback (most recent call last):\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 489, in mouseMoveEvent\n", | |
" modifiers=self._modifiers(ev),\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 582, in _modifiers\n", | |
" if q & qtmod:\n", | |
"TypeError: unsupported operand type(s) for &: 'KeyboardModifier' and 'KeyboardModifiers'\n", | |
"Traceback (most recent call last):\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 489, in mouseMoveEvent\n", | |
" modifiers=self._modifiers(ev),\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 582, in _modifiers\n", | |
" if q & qtmod:\n", | |
"TypeError: unsupported operand type(s) for &: 'KeyboardModifier' and 'KeyboardModifiers'\n", | |
"Traceback (most recent call last):\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 489, in mouseMoveEvent\n", | |
" modifiers=self._modifiers(ev),\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 582, in _modifiers\n", | |
" if q & qtmod:\n", | |
"TypeError: unsupported operand type(s) for &: 'KeyboardModifier' and 'KeyboardModifiers'\n", | |
"Traceback (most recent call last):\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 489, in mouseMoveEvent\n", | |
" modifiers=self._modifiers(ev),\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 582, in _modifiers\n", | |
" if q & qtmod:\n", | |
"TypeError: unsupported operand type(s) for &: 'KeyboardModifier' and 'KeyboardModifiers'\n", | |
"Traceback (most recent call last):\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 489, in mouseMoveEvent\n", | |
" modifiers=self._modifiers(ev),\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 582, in _modifiers\n", | |
" if q & qtmod:\n", | |
"TypeError: unsupported operand type(s) for &: 'KeyboardModifier' and 'KeyboardModifiers'\n", | |
"Traceback (most recent call last):\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 489, in mouseMoveEvent\n", | |
" modifiers=self._modifiers(ev),\n", | |
" File \"/home/genevieb/em95/miniconda/conda/envs/itk-dask/lib/python3.10/site-packages/vispy/app/backends/_qt.py\", line 582, in _modifiers\n", | |
" if q & qtmod:\n", | |
"TypeError: unsupported operand type(s) for &: 'KeyboardModifier' and 'KeyboardModifiers'\n" | |
] | |
} | |
], | |
"source": [ | |
"import napari\n", | |
"\n", | |
"viewer = napari.Viewer()\n", | |
"viewer.add_image(result)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "7320ab30", | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "be4e635f", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# itk richardson-lucy deconvolution\n", | |
"deconvolved = itk.RichardsonLucyDeconvolutionImageFilter(img, kernel_image=psf, number_of_iterations=1)\n", | |
"print(deconvolved.shape)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"id": "367b6db1", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"(200, 200, 200)\n" | |
] | |
} | |
], | |
"source": [ | |
"# scikit-image richardson-lucy deconvolution\n", | |
"deconvolved_RL = skimage.restoration.richardson_lucy(img, psf, num_iter=30)\n", | |
"print(deconvolved_RL.shape)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"id": "6f00a0ce", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"del deconvolved_RL" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "621c6f24", | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3 (ipykernel)", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.10.4" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 5 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment