Skip to content

Commit

Permalink
deploy: 0e48612
Browse files Browse the repository at this point in the history
  • Loading branch information
aramyxt committed Jan 7, 2025
0 parents commit e5c4f0a
Show file tree
Hide file tree
Showing 52 changed files with 36,516 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .buildinfo
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 1d08db85a79bfccf7301ffbec52d7ebe
tags: 645f666f9bcd5a90fca523b33c5a78b7
Binary file added .doctrees/environment.pickle
Binary file not shown.
Binary file added .doctrees/index.doctree
Binary file not shown.
Binary file added .doctrees/install.doctree
Binary file not shown.
Binary file added .doctrees/quickstart.doctree
Binary file not shown.
Empty file added .nojekyll
Empty file.
Binary file added _images/ModEx_Loop_SoilChip.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4,984 changes: 4,984 additions & 0 deletions _images/micromodel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _images/quickstart_figure_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _images/quickstart_figure_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _images/quickstart_figure_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions _sources/index.rst.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
.. Pore2Chip documentation master file, created by
sphinx-quickstart on Thu Jan 2 09:45:53 2025.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Pore2Chip Documentation
=======================
A python package that takes XCT images of porous materials and generates representative digital twin micromodels.

.. figure:: _static/ModEx_Loop_SoilChip.jpg
:width: 636px
:height: 453px
:scale: 100 %
:alt: ModEx Loop for Pore2Chip and Chip2Flow

ModEx Loop for Pore2Chip and Chip2Flow

About 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.

User Guide
----------
.. toctree::
:maxdepth: 1

install
quickstart

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.

PNNL-SA-197910

Disclaimer
----------
This research work was prepared as an account of work sponsored by an agency of the United States Government. Neither the United States Government nor any agency thereof,
nor any of their employees, makes any warranty, express or implied, or assumes any legal liability or responsibility for the accuracy, completeness, or usefulness of any information,
apparatus, product, or process disclosed, or represents that its use would not infringe privately owned rights. Reference herein to any specific commercial product, process,
or service by trade name, trademark, manufacturer, or otherwise does not necessarily constitute or imply its endorsement, recommendation, or favoring by the United States Government or any agency thereof.
The views and opinions of authors expressed herein do not necessarily state or reflect those of the United States Government or any agency thereof.

.. note::

This project is under active development.


62 changes: 62 additions & 0 deletions _sources/install.rst.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@

.. Installation
.. =======================
.. The OpenPNM and PoreSpy libraries are required to analyze XCT images. PoreSpy is used to generate a
.. pore network that is used to extract pore size distribution, pore throat size distribution, and pore coordination numbers.
.. OpenPNM is used to construct a new 2D pore network that will be used to create the micromodel design.
.. Install using PiP:
.. .. code-block:: console
.. $ pip install pore2chip
Installation
============

The OpenPNM and PoreSpy libraries are required to analyze XCT images. PoreSpy is used to generate a
pore network that is used to extract pore size distribution, pore throat size distribution, and pore coordination numbers.
OpenPNM is used to construct a new 2D pore network that will be used to create the micromodel design.

Pip Installation
----------------
Install using PiP:

.. code-block:: bash
pip install pore2chip
Install from source:

.. code-block:: bash
git clone https://github.com/EMSL-Computing/Pore2Chip.git
cd Pore2Chip
python3 -m build
python3 -m pip install pore2chip --no-index --find-links dist/
Conda Environmental
-------------------
Creating a Conda environment:

.. code-block:: bash
conda create -n pore2chip python=3.9
conda activate pore2chip
pip install pore2chip
Docker Image
------------
Building a Docker Image with Jupyter Notebook:

.. code-block:: bash
git clone https://github.com/EMSL-Computing/Pore2Chip.git
cd Pore2Chip
docker build -t pore2chip
docker run -p 8888:8888 pore2chip
.. note::

This project is under active development.
120 changes: 120 additions & 0 deletions _sources/quickstart.rst.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@

Quickstart Guide
=======================

This guide is meant to showcase the basics of micromodel design and file exporting.

Step 1: Importing Libraries
---------------------------
Before starting, we will import Pore2Chip as well as some support libraries for data visualization and modification.

.. literalinclude:: ./examples/quickstart_example.py
:language: python
:start-after: # Step 1 Start
:end-before: # Step 1 End

Step 2: Loading Desired Data
----------------------------
In order to extract data from XCT images, we need to load it into memory as a 3D array of pixel values. This can be done
all in one step using Pore2Chip's built-in function ``read_and_filter_list``. Other parameters such as cropping the image,
custom threshold values, and gray value masking can also be set in the function parameters.

.. literalinclude:: ./examples/quickstart_example.py
:language: python
:start-after: # Step 2 Start
:end-before: # Step 2 End


.. figure:: example_figures/quickstart_figure_1.png
:width: 416px
:height: 416px
:scale: 100 %
:alt: Filtered Image in 3D Image Stack

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`.

First, we will extract the pore and pore throat diameters:

.. literalinclude:: ./examples/quickstart_example.py
:language: python
:start-after: # Step 3.1 Start
:end-before: # Step 3.1 End

Next, we will extract the pore coordination numbers:

.. literalinclude:: ./examples/quickstart_example.py
:language: python
: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`:

.. literalinclude:: ./examples/quickstart_example.py
:language: python
:start-after: # Step 3.3 Start
:end-before: # Step 3.3 End

.. figure:: example_figures/quickstart_figure_2.png
:width: 1165px
:height: 400px
:scale: 100 %
:alt: Histogram of Pore Data Values

.. note::

Keep in mind that the data that is extracted is measured in the number of pixels in the segmented image. If you know the resolution
size of the original XCT scan, you can scale the pixel values by the voxel size from the XCT metadata. Alternatively, you can keep note
of the voxel/volume scale and adjust scaling on the final micromodel design.

Step 4: Micromodel Network Generation
-------------------------------------
Once all the necessary data is extracted (pore diameters, throat diameters, and coordination numbers), we can move on to designing the micromodel.
Pore2Chip creates micromodels by constructing a 2D pore network (backed by `OpenPNM`) that has the overall pore properties that we extracted
in step 2. Then, the network is converted from a digital representation to a shape representation using `drawsvg`.

To construct the 2D `OpenPNM` network, we will use the ``generate_network()`` function in the ``generate`` module:

.. literalinclude:: ./examples/quickstart_example.py
:language: python
:start-after: # Step 4 Start
:end-before: # Step 4 End

.. figure:: example_figures/quickstart_figure_3.png
:width: 630px
:height: 470px
:scale: 100 %
:alt: Visualization of OpenPNM network generated by Pore2Chip

The code above generates a network that is a diamond lattice of 6 x 18 pores. The ``generate_network()`` function has parameters for the number of
pores on the X and Y axis, diameters, coordination numbers, and other optional arguments such as ``center_channel``, which was used above. The
argument or 3 designates a column of pores (3-wide) than the micromodel must connect from top to bottom, ensuring connectivity throughout the
entire network (more info on the generation algorithm in the modules page WIP).

Step 5: Micromodel Exporting
-------------------------------------
Once we have our desired network, we will export it as a micromodel that can be used in simulations or fabrication for microfluidic experiments. This
is done with the ``export`` module. We will use ``network2svg()`` to export our micromodel as a scalable vector graphic:

.. literalinclude:: ./examples/quickstart_example.py
:language: python
:start-after: # Step 5 Start
:end-before: # Step 5 End

This is what the exported SVG based on the `OpenPNM` network looks like:

.. figure:: example_figures/micromodel.svg
:scale: 100 %
:alt: Micromodel Exported by Pore2Chip

This vector image can be used as is for fabrication, or imported into other software such as InkScape for further modification and exported as a
DWG file compatible with most CAD software. There is also a function in ``export`` called ``network2dxf()``, which can export a network to a DXF
file that most CAD software understands, but is currently still being refined (WIP).

.. note::

This project is under active development.
Binary file added _static/ModEx_Loop_SoilChip.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
134 changes: 134 additions & 0 deletions _static/_sphinx_javascript_frameworks_compat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* _sphinx_javascript_frameworks_compat.js
* ~~~~~~~~~~
*
* Compatability shim for jQuery and underscores.js.
*
* WILL BE REMOVED IN Sphinx 6.0
* xref RemovedInSphinx60Warning
*
*/

/**
* select a different prefix for underscore
*/
$u = _.noConflict();


/**
* small helper function to urldecode strings
*
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
*/
jQuery.urldecode = function(x) {
if (!x) {
return x
}
return decodeURIComponent(x.replace(/\+/g, ' '));
};

/**
* small helper function to urlencode strings
*/
jQuery.urlencode = encodeURIComponent;

/**
* This function returns the parsed url parameters of the
* current request. Multiple values per key are supported,
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s === 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
for (var i = 0; i < parts.length; i++) {
var tmp = parts[i].split('=', 2);
var key = jQuery.urldecode(tmp[0]);
var value = jQuery.urldecode(tmp[1]);
if (key in result)
result[key].push(value);
else
result[key] = [value];
}
return result;
};

/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node, addItems) {
if (node.nodeType === 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 &&
!jQuery(node.parentNode).hasClass(className) &&
!jQuery(node.parentNode).hasClass("nohighlight")) {
var span;
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
if (isInSVG) {
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
} else {
span = document.createElement("span");
span.className = className;
}
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
if (isInSVG) {
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
var bbox = node.parentElement.getBBox();
rect.x.baseVal.value = bbox.x;
rect.y.baseVal.value = bbox.y;
rect.width.baseVal.value = bbox.width;
rect.height.baseVal.value = bbox.height;
rect.setAttribute('class', className);
addItems.push({
"parent": node.parentNode,
"target": rect});
}
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this, addItems);
});
}
}
var addItems = [];
var result = this.each(function() {
highlight(this, addItems);
});
for (var i = 0; i < addItems.length; ++i) {
jQuery(addItems[i].parent).before(addItems[i].target);
}
return result;
};

/*
* backward compatibility for jQuery.browser
* This will be supported until firefox bug is fixed.
*/
if (!jQuery.browser) {
jQuery.uaMatch = function(ua) {
ua = ua.toLowerCase();

var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
/(msie) ([\w.]+)/.exec(ua) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[];

return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
};
jQuery.browser = {};
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
}
Loading

0 comments on commit e5c4f0a

Please sign in to comment.