diff --git a/CITATION.cff b/CITATION.cff index 075cb08..94745aa 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -38,7 +38,7 @@ authors: given-names: "Satish" orcid: "https://orcid.org/0000-0001-7847-6293" affiliation: "EMSL" -version: "0.1.0" +version: "0.2.0" date-released: "2024-7-15" repository-code: "https://github.com/EMSL-Computing/Pore2Chip/" license: "MIT" diff --git a/README.md b/README.md index 5f84544..7021de6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Pore2Chip: All-in-One Python Tool for Soil Microstructure Analysis and Micromodel Design ## What is Pore2Chip? -Pore2Chip is a Python module designed to streamline the process of analyzing X-ray computed tomography (XCT) images of soil and creating 2D micromodel designs based on that analysis. It leverages the power of open-source libraries like OpenPNM, PoreSpy, and drawsvg to extract key information about the soil's porous structure and translate it into a blueprint for microfluidic simulations or physical "lab-on-a-chip" devices developed using additive manufacturing. +Pore2Chip is a Python module designed to streamline the process of analyzing X-ray computed tomography (XCT) images of soil and creating 2D micromodel designs based on that analysis. It leverages the power of open-source libraries like OpenPNM, PoreSpy, and drawsvg to extract key information about the soil's porous structure and translate it into a blueprint for microfluidic simulations or physical `lab-on-a-chip` devices developed using additive manufacturing. ### A workflow for model-data-experiment (ModEx) design: @@ -15,7 +15,7 @@ Below is a conceptual figure, workflow, and vision for this all-in-one Python to (3) **Transform 3D Pore Network into 2D Rendering (Pore2Chip):** The complex 3D network is simplified into a 2D rendering for easier analysis and visualization. -(4) **Build Micromodels for Environmental Experiments (Pore2Chip):** Micromodels replicate environmental conditions, enabling controlled experiments to observe fluid flow and chemical species degradation. +(4) **Build Micromodels for Experiments (Pore2Chip):** Micromodels replicate environmental conditions, enabling controlled experiments to observe fluid flow and chemical species degradation. (5) **Microscale Experimental Data on Chemical Hotspots (Chip2Flow):** Detailed experiments using techniques like ToF-SIMS and SEM-EDS provide data on chemical hotspots within the porous media. @@ -23,7 +23,7 @@ Below is a conceptual figure, workflow, and vision for this all-in-one Python to (6b) **Calibration and Validation (Chip2Flow):** Predictive AI/ML-enabled models are calibrated and validated using experimental data for accuracy and reliability. -(7a) **Understanding Fluid Flow and Species Degradation in Soil Core Experiments (Chip2Flow):** Experiments on soil cores provide vital information on fluid flow and chemical species degradation, connecting back to micromodel generation. +(7a) **Understanding Fluid Flow and Reactive-Transport in Soil Core Experiments (Chip2Flow):** Experiments on soil cores provide vital information on fluid flow and chemical species degradation, connecting back to micromodel generation. (7b) **Upscaled Properties (Chip2Flow):** Properties and behaviors observed at smaller scales are upscaled to larger scales (mm to cm) for real-world application. @@ -345,7 +345,7 @@ Additionally, your contributions can be as simple as: ``` ## Acknowledgements -This research was performed on a project award (Award DOIs: 10.46936/ltds.proj.2024.61069/60012423; 10.46936/intm.proj.2023.60674/60008777; 10.46936/intm.proj.2023.60904/60008965) from the Environmental Molecular Sciences Laboratory, a DOE Office of Science User Facility sponsored by the Biological and Environmental Research program under contract no. DE-AC05-76RL01830. The authors acknowledge the contributions of Michael Perkins at PNNL’s Creative Services, who developed the conceptual graphics in this paper. +This research was performed on a project award (Award DOIs: 10.46936/ltds.proj.2024.61069/60012423; 10.46936/intm.proj.2023.60674/60008777; 10.46936/intm.proj.2023.60904/60008965) from the Environmental Molecular Sciences Laboratory, a DOE Office of Science User Facility sponsored by the Biological and Environmental Research program under contract no. DE-AC05-76RL01830. The authors acknowledge the contributions of Michael Perkins and Ben Watson at PNNL’s Creative Services, who developed the conceptual graphics in this paper. PNNL-SA-197910 diff --git a/docs/source/conf.py b/docs/source/conf.py index 0366b77..cdc117c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -9,7 +9,7 @@ project = 'Pore2Chip' copyright = '2025, Aramy Truong, Maruti Mudunuru, Md Lal Mamud' author = 'Aramy Truong, Maruti Mudunuru, Md Lal Mamud' -release = '0.1.1' +release = '0.2.0' # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/docs/source/coordination_api.rst b/docs/source/coordination_api.rst index 2ba8de6..004c94f 100644 --- a/docs/source/coordination_api.rst +++ b/docs/source/coordination_api.rst @@ -69,4 +69,8 @@ Functionality: .. - This function assumes the `porespy` and `openpnm` libraries are installed and imported. - - The specific implementation of `ps.networks.snow2` might require further investigation depending on the exact functionality of the PoresPy library. \ No newline at end of file + - The specific implementation of `ps.networks.snow2` might require further investigation depending on the exact functionality of the PoresPy library. + +.. note:: + + This project is under active development. diff --git a/docs/source/export_api.rst b/docs/source/export_api.rst index 2457f8b..ce04a5f 100644 --- a/docs/source/export_api.rst +++ b/docs/source/export_api.rst @@ -1,5 +1,24 @@ -export -====== +**export** +========== -(WIP) \ No newline at end of file +The ``export`` module contains functions to draw a visual micromodel mask from an OpenPNM network generated +from the ``generate`` module (see ``generate`` for more info on generating a network). + + +network2svg() +------------- + +.. autofunction:: pore2chip.export.network2svg + +---- + +network2dxf() +------------- + +.. autofunction:: pore2chip.export.network2dxf + + +.. note:: + + This project is under active development. diff --git a/docs/source/generate_api.rst b/docs/source/generate_api.rst index 252e476..6a5fbba 100644 --- a/docs/source/generate_api.rst +++ b/docs/source/generate_api.rst @@ -10,4 +10,9 @@ contains a 2D network based on input pore data (see ``metrics`` for more info on generate_network() ------------------ -.. autofunction:: pore2chip.generate.generate_network \ No newline at end of file +.. autofunction:: pore2chip.generate.generate_network + + +.. note:: + + This project is under active development. diff --git a/docs/source/index.rst b/docs/source/index.rst index 09a9f60..abe5862 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -5,7 +5,7 @@ Pore2Chip Documentation ======================= -A python package that takes XCT images of porous materials and generates representative digital twin micromodels. +A python package that takes XCT images of porous materials and generates representative reduced complexity micromodels. .. figure:: _static/ModEx_Loop_SoilChip.jpg :width: 636px @@ -35,7 +35,7 @@ Acknowledgements ---------------- This research was performed on a project award (Award DOIs: 10.46936/ltds.proj.2024.61069/60012423; 10.46936/intm.proj.2023.60674/60008777; 10.46936/intm.proj.2023.60904/60008965) from the Environmental Molecular Sciences Laboratory, a DOE Office of Science User Facility sponsored by the Biological and Environmental Research program under contract no. DE-AC05-76RL01830. -The authors acknowledge the contributions of Michael Perkins at PNNL’s Creative Services, who developed the conceptual graphics in this paper. +The authors acknowledge the contributions of Michael Perkins and Ben Watson at PNNL’s Creative Services, who developed the conceptual graphics in this paper. PNNL-SA-197910 diff --git a/docs/source/io_api.rst b/docs/source/io_api.rst index 7867336..0fc8fa8 100644 --- a/docs/source/io_api.rst +++ b/docs/source/io_api.rst @@ -1,5 +1,17 @@ -io -== +**io** +====== -(WIP) \ No newline at end of file +The ``io`` module contain a function that writes a 2D image array to a VTK format file. + +---- + +img2vtk() +--------- + +.. autofunction:: pore2chip.io.img2vtk + + +.. note:: + + This project is under active development. diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 4a23fa1..d9d6ea4 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -33,9 +33,8 @@ custom threshold values, and gray value masking can also be set in the function Step 3: Pore Data Extraction ---------------------------- -Now that the segmented data is loaded into memory, we will use the ``metrics`` module to extract the necessary information needed to -cunstruct the micromodel design. This extraction is based on pore network extraction via watershed segmentation and the SNOW -algorithm provided by `Porespy`. +Now that the segmented data is loaded into memory, we will use the ``metrics`` module to extract the necessary information needed to construct the micromodel design. +This extraction is based on pore network extraction via watershed segmentation and the SNOW algorithm provided by `Porespy`. First, we will extract the pore and pore throat diameters: @@ -51,8 +50,7 @@ Next, we will extract the pore coordination numbers: :start-after: # Step 3.2 Start :end-before: # Step 3.2 End -The variables we extracted are arrays that contain all of the pore diameters, throat diameters, and coordination numbers for all the -extracted pores in the pore network. We can visualize the distribution of the data using `matplotlib`: +The variables we extracted are arrays that contain all of the pore diameters, throat diameters, and coordination numbers for all the extracted pores in the pore network. We can visualize the distribution of the data using `matplotlib`: .. literalinclude:: ./examples/quickstart_example.py :language: python diff --git a/example_outputs/ModEx_Loop_SoilChip.jpg b/example_outputs/ModEx_Loop_SoilChip.jpg index 5e370e4..40cb0bc 100644 Binary files a/example_outputs/ModEx_Loop_SoilChip.jpg and b/example_outputs/ModEx_Loop_SoilChip.jpg differ diff --git a/paper/figures/1_AI4SoilChip.jpg b/paper/figures/1_AI4SoilChip.jpg index 7160dfc..450271f 100644 Binary files a/paper/figures/1_AI4SoilChip.jpg and b/paper/figures/1_AI4SoilChip.jpg differ diff --git a/paper/figures/2_ModEx_Loop_SoilChip.jpg b/paper/figures/2_ModEx_Loop_SoilChip.jpg index 5e370e4..40cb0bc 100644 Binary files a/paper/figures/2_ModEx_Loop_SoilChip.jpg and b/paper/figures/2_ModEx_Loop_SoilChip.jpg differ diff --git a/paper/paper.md b/paper/paper.md index 89abda8..e366fe5 100644 --- a/paper/paper.md +++ b/paper/paper.md @@ -53,58 +53,53 @@ bibliography: paper.bib # Summary The `Pore2Chip` Python package is designed to create 2D micromodels using extracted data from 3D X-ray computed tomography -(XCT) images. This package helps analyze soil structure and function, allowing for the investigation of environmentally significant biogeochemical processes -that impact soil organic matter (SOM) decomposition and loss, oxygen concentrations, and nutrient availability in disturbed or managed soils. Key metrics encompass pore size -distributions, pore throat size distributions, and connectivity (pore coordination numbers). The final output is a 2D scalable SVG -design representing a core or aggregate. Designs can be fabricated with methods such as laser etching, 3D printing, and photolithography. +(XCT) images. +This package helps analyze soil structure and function, allowing for the investigation of hydro-biogeochemical processes +that impact mineral extraction and reactivity, oxygen concentrations, and nutrient availability in disturbed or managed soils. +Key metrics encompass pore size distributions, pore throat size distributions, and connectivity (pore coordination numbers). +The final output is a 2D scalable SVG design representing a core or aggregate. +Designs can be fabricated with methods such as laser etching, 3D printing, and photolithography. # Statement of need -The resilience of agricultural and natural landscapes is intrinsically connected to soil structure. Land management (e.g., tillage, grazing, and fire) and -associated impacts (e.g., compaction and pore-clogging) along with climate disturbances (e.g., freeze-thaw, flooding, and sea level rise) can transform soil -microstructure [@Stoof2016; @Liu2018; @Feng2020; @deOliveira2022; @Rooney2022]. These changes in the soil microstructure -determine the flow of water, solutes, and gasses as well as SOM retention, transport, and distribution -[@hamamoto2010excluded; @bailey2017differences; @Waring2020]. Simplified, homogeneous pore networks provide innovative -demonstrations of how water, solutes, and microbes interact [@Bhattacharjee2022] but need more accurate representations of soil properties. +The resilience of agricultural and natural landscapes is intrinsically connected to soil structure. +Land management (e.g., tillage, grazing, and fire) and associated impacts (e.g., compaction, pore-clogging) can transform soil microstructure [@Stoof2016; @Liu2018; @Feng2020; @deOliveira2022; @Rooney2022]. +These changes in the soil microstructure determine the flow of water, solutes, and gasses as well as mineral retention, transport, and distribution [@hamamoto2010excluded; @bailey2017differences; @Waring2020]. +Simplified, homogeneous pore networks provide innovative demonstrations of how water, solutes, and microbes interact [@Bhattacharjee2022] but need more accurate representations of soil properties. Creating realistic heterogeneous habitats is time-consuming and does not include pore network characteristics, such as pore -connectivity. Incorporating pore dynamics into soil models such as SOM degradation enables dynamic predictions for soil +connectivity. +Incorporating pore dynamics into soil models such as chemical species degradation enables dynamic predictions for soil responses under changing pore networks [@davidson2012d; @moyano2018diffusion]. -The need for software that can generate various micromodel designs that researchers can test and validate with minimal computational -cost [@Dentz2023; @Oostrom2014] is increasing. `Pore2Chip` allows this functionality by providing the intended users, such as earth scientists and -lab-on-chip instrument specialists, with easy-to-use research software for lab-on-chip designs. Specifically, the Pore2Chip-based data worth analysis allows researchers to -fill this experimental design gap by enabling the ability to build a representative quasi-2D pore network along with -first-order, fast, and reasonably accurate flow models that can be linked with experiments. These flow models are built using recent advances in -physics-informed neural networks [@New2024], laying the foundation to accelerate numerical simulations and improve the fidelity of predictions in -microscale environments. Moreover, `Pore2Chip` allows one to assess the impact of various system parameters, such as pore structures, fluid properties, and -flow conditions, needed to develop optimal micromodel experiments. Such a capability can guide model-experiment-data (ModEx) integration at the microscale, -allowing for upscaling microscale processes and predictions of dynamic soil properties and functions (see \autoref{fig:fig1}). +The need for software that can generate various micromodel designs that researchers can test and validate with minimal computational cost [@Dentz2023; @Oostrom2014] is increasing. +`Pore2Chip` allows this functionality by providing the intended users, such as earth scientists and lab-on-chip instrument specialists, with easy-to-use research software for lab-on-chip designs. +Specifically, the Pore2Chip-based information analysis of XCT images allows researchers to fill this experimental design gap by enabling the ability to build a representative quasi-2D pore network along with first-order, fast, and reasonably accurate flow models that can be linked with experiments. +These flow models are built using recent advances in physics-informed neural networks [@New2024], laying the foundation to accelerate numerical simulations and improve the fidelity of predictions in microscale environments. +Moreover, `Pore2Chip` allows one to assess the impact of various system parameters, such as pore structures, fluid properties, and flow conditions, needed to develop optimal micromodel experiments. +Such a capability can guide model-experiment-data (ModEx) integration at the microscale, allowing for upscaling microscale processes and predictions of dynamic soil properties and functions (see \autoref{fig:fig1}). ## Main features and differences with other tools `Pore2Chip` addresses complex pore structures by representing pore networks as connected shapes, unlike older sphere packing algorithms. -This enables users to easily create and control pore networks representing various real-world conditions. `Pore2Chip` offers experimental design capabilities that -cannot be achieved by existing software such as epyc [@Dobson2022]. -`Pore2Chip` provides support and reproducibility for developing lab-on-chip experimental designs uniformly across different soil datasets with fast, reasonably -accurate, first-order flow modeling capabilities. Microscale experiments using `Pore2Chip` micromodels may target both abiotic and biotic -processes and be integrated into modeling efforts such as water flow modeling, reactive transport modeling, and microbial activity simulations. +This enables users to easily create and control pore networks representing various real-world conditions. `Pore2Chip` offers experimental design capabilities that cannot be achieved by existing software such as epyc [@Dobson2022]. +`Pore2Chip` provides support and reproducibility for developing lab-on-chip experimental designs uniformly across different soil datasets with fast, reasonably accurate, first-order flow modeling capabilities. +Microscale experiments using `Pore2Chip` micromodels may target both abiotic and biotic processes and be integrated into modeling efforts such as water flow modeling, reactive transport modeling, and microbial activity simulations. ## Implementation details and support libraries Using `Porespy` [@Gostick2016], `OpenPNM` [@Gostick2016] and various graphics rendering libraries (e.g., drawsvg, ezdxf, svglib, cairosvg, reportlab), -`Pore2Chip` renders SVG or DXF micromodel designs of the generated network. Output designs are scalable and adjustable based -on the target porosity of the micromodel. It can also be exported as micromodel data in VTK formats for -visualization in Paraview or microfluidic simulations with open-source software such as `PFLOTRAN` (https://www.pflotran.org), `OpenFOAM` (https://www.openfoam.com), -and other physics-informed neural network modules. If the user wants to extract data from XCT images, `Pore2Chip` has image filtering and network extraction -modules utilizing Otsu thresholding and `PoreSpy`. The generation function can also work with data extracted by other means if it is an array of values that -Python can read. +`Pore2Chip` renders SVG or DXF micromodel designs of the generated network. +Output designs are scalable and adjustable based on the target porosity of the micromodel. +It can also be exported as micromodel data in VTK formats for visualization in Paraview or microfluidic simulations with open-source software such as `PFLOTRAN` (https://www.pflotran.org), `OpenFOAM` (https://www.openfoam.com), +and other physics-informed neural network modules. +If the user wants to extract data from XCT images, `Pore2Chip` has image filtering and network extraction modules utilizing Otsu thresholding and `PoreSpy`. Though, generation function can also work with data extracted by other software as long as it is an array of values that Python can read. \autoref{fig:fig2} provides a high-level overview of the repository structure and example use cases (\autoref{fig:fig1}) within the `Pore2Chip` repository. # Figures -![A high-level overview of essential steps in Pore2Chip-based micromodel designs informed by soil dataset. The iterative ModEx loop continuously improves multi-physics process models by integrating experimental data, leading to more accurate predictions for soil carbon cycling and rhizosphere function applications.\label{fig:fig1}](figures/2_ModEx_Loop_SoilChip.jpg) +![A high-level overview of essential steps in Pore2Chip-based micromodel designs informed by soil dataset. The iterative ModEx loop continuously improves multi-physics process models by integrating experimental data, leading to more accurate predictions for fluid flow, reactive-transport, and rhizosphere function applications.\label{fig:fig1}](figures/2_ModEx_Loop_SoilChip.jpg) ![An overview of the Pore2Chip repository structure, detailed example notebooks, and built distributions.\label{fig:fig2}](figures/3_Workflow.png) diff --git a/pyproject.toml b/pyproject.toml index a9069e6..44bdd4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "pore2chip" -version = "0.1.1" +version = "0.2.0" authors = [ { name="Aramy Truong", email="aramy.truong@pnnl.gov" }, { name="Maruti Mudunuru", email="maruti@pnnl.gov" }, diff --git a/src/pore2chip/export.py b/src/pore2chip/export.py index 1a251cf..5deb5bf 100644 --- a/src/pore2chip/export.py +++ b/src/pore2chip/export.py @@ -23,44 +23,34 @@ def network2svg( middle_pores=None, disconnected=None, throat_vector_thres=None): # Boolean to draw perp. lines for throat placement (debugging) + r""" - Create an SVG file from an OpenPNM network. - The network2svg function converts an OpenPNM network into an SVG image. - It represents pores as either blobs or circles, and throats as either simple lines - or a series of connected circles to form a more complex shape - - Parameters: - generated_network : dict - The OpenPNM network containing pore and throat information. - n1 : int - Number of pores on the x-axis of the model grid - n2 : int - Number of pores on the y-axis of the model grid - d1 : int - The x length of the SVG image (in pixels). - d2 : int - The y length of the SVG image (in pixels). - pore_shape : str, optional - Shape of the pore bodies, can be 'blob' or 'circle'. Default is 'blob'. - throat_random : int, optional - Multiplier that decides how random the throat shape will be. Default is 1. + + Create an SVG file from an OpenPNM network. + The network2svg function converts an OpenPNM network into an SVG image. + It represents pores as either blobs or circles, and throats as either simple lines + or a series of connected circles to form a more complex shape + + Args: + generated_network (dict): The OpenPNM network containing pore and throat information. + n1 (int): Number of pores on the x-axis of the model grid + n2 (int): Number of pores on the y-axis of the model grid + d1 (int): The x length of the SVG image (in pixels). + d2 (int): The y length of the SVG image (in pixels). + pore_shape (str): Shape of the pore bodies, can be 'blob' or 'circle'. Default is 'blob'. + throat_random (int): Multiplier that decides how random the throat shape will be. Default is 1. A value of 0 makes the throats straight. - pore_debug : bool, optional - If True, draws pore bodies as blue and draws pore index number next + pore_debug (boolean): If True, draws pore bodies as blue and draws pore index number next to the pore. Default is False. - throat_debug : bool, optional - If True, draws lines where throats connect. Default is False. - throat_random_debug : bool, optional - If True, draws lines perpendicular to throat directions used to randomize + throat_debug (boolean): If True, draws lines where throats connect. Default is False. + throat_random_debug (boolean): If True, draws lines perpendicular to throat directions used to randomize throat shape. `throat_debug` must be True. Default is False. - middle_pores : array-like - Array or pore indices that indicate the center channel for debugging + middle_pores (array): Array or pore indices that indicate the center channel for debugging Renders the middle pores in green. Also writes pore index number next to dot. Default is None. - Returns: - dr.Drawing - A drawSvg drawing object representing the network. + Returns: + dr.Drawing: A drawSvg drawing object representing the network. """ # Initialize the drawing with the specified size and origin at the bottom left @@ -351,22 +341,19 @@ def network2dxf( no_throats=False, ): r""" - Create a DXF file from an OpenPNM network. - The network2dxf function generates a DXF file from an OpenPNM network. - It represents pores as circles and throats as a series of connected circles - to form irregular shapes, with an optional parameter to introduce randomness - in the throat shapes. - - Parameters: - generated_network : dict - The OpenPNM network containing pore and throat information. - throat_random : int, optional - Multiplier that decides how random the throat shape will be. Default is 1. + Create a DXF file from an OpenPNM network. (deprecated) + The network2dxf function generates a DXF file from an OpenPNM network. + It represents pores as circles and throats as a series of connected circles + to form irregular shapes, with an optional parameter to introduce randomness + in the throat shapes. + + Args: + generated_network (dict): The OpenPNM network containing pore and throat information. + throat_random (int): Multiplier that decides how random the throat shape will be. Default is 1. A value of 0 makes the throats straight. - Returns: - ezdxf.document - An ezdxf document object representing the network. + Returns: + ezdxf.document: An ezdxf document object representing the network. """ # Create a new DXF document with DXF version R2000 diff --git a/src/pore2chip/io.py b/src/pore2chip/io.py index 01ae84f..c63be6c 100644 --- a/src/pore2chip/io.py +++ b/src/pore2chip/io.py @@ -69,16 +69,23 @@ def _write_vtk(vtk_fl_name, num_nodes, num_elements, nodes_per_element, \ def img2vtk(image, vtk_fl_name, dims, **kwargs): r""" - Converts 2D image array to 3D vtk model + Converts 2D image array to 3D vtk model - Parameters: - image : 2D image array - vtk_fl_name : Filename/filepath - dims : Size 3 Array-like for x, y, and z dimentions respectively + Args: + image (2D array): 2D image array + vtk_fl_name (str): Filename/filepath + dims (array): Size 3 Array-like for x, y, and z dimentions respectively **kwargs : Extra arguements to write to VTK file. - Examples: Permeability = perm_matrix - ...where perm_matrix is an array defining permeability - values for each pixel + Examples: Permeability = perm_matrix ... + where perm_matrix is an array defining permeability + values for each pixel + + generated_network (dict): The OpenPNM network containing pore and throat information. + throat_random (int): Multiplier that decides how random the throat shape will be. Default is 1. + A value of 0 makes the throats straight. + + Returns: + None """ xseed = image.shape[0] yseed = image.shape[1]