Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
bruno-pannunzio committed Jul 5, 2024
1 parent 44d6509 commit d026d2c
Show file tree
Hide file tree
Showing 42 changed files with 53,316 additions and 226 deletions.
2 changes: 1 addition & 1 deletion main/.buildinfo
Original file line number Diff line number Diff line change
@@ -1,4 +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: cdee86f95429db0157b438fbe50abede
config: 6a1d0a9c1312d1a5df376d628fa2dfc5
tags: 645f666f9bcd5a90fca523b33c5a78b7
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@
# %%
# Import required modules, functions, and classes:

import matplotlib.animation as animation
import matplotlib.pyplot as plt
import numpy

from phasorpy.components import two_fractions_from_phasor
from phasorpy._utils import line_from_components, mask_segment
from phasorpy.components import (
graphical_component_analysis,
two_fractions_from_phasor,
)
from phasorpy.phasor import phasor_from_lifetime
from phasorpy.plot import PhasorPlot

Expand Down Expand Up @@ -61,7 +66,7 @@
# phasor coordinates:

real, imag = numpy.random.multivariate_normal(
(0.6, 0.35), [[8e-3, 1e-3], [1e-3, 1e-3]], (100, 100)
(0.5, 0.33), [[5e-3, 1e-3], [1e-3, 1e-3]], (100, 100)
).T
plot = PhasorPlot(
frequency=frequency,
Expand Down Expand Up @@ -102,5 +107,122 @@
plt.tight_layout()
plt.show()

# %%
# Graphical solution for the contribution of multiple components
# --------------------------------------------------------------
#
# The :py:func:`graphical_component_analysis` function performs the graphical
# analysis for two or three components and returns the number of phasors
# for each fraction of the components (with respect to other components):
components_real, components_imag = phasor_from_lifetime(
frequency, [1.0, 4.0, 15.0]
)
counts, fractions = graphical_component_analysis(
real, imag, components_real, components_imag
)
fig, ax = plt.subplots()
plot = PhasorPlot(
frequency=frequency,
title='Phasor with contribution of three known components',
ax=ax,
)
plot.hist2d(real, imag, cmap='plasma')
plot.plot(components_real, components_imag, 'o-', color='blue')
plot.plot(
components_real[[0, -1]], components_imag[[0, -1]], fmt='-', color='blue'
)
ax.annotate('A', xy=(0.8, 0.45), fontsize=16, fontweight='bold', color='blue')
ax.annotate('B', xy=(0.13, 0.43), fontsize=16, fontweight='bold', color='blue')
ax.annotate(
'C', xy=(-0.04, 0.12), fontsize=16, fontweight='bold', color='blue'
)
plt.show()

# %%
# The results can be plotted as histograms for each component pair:

fig, ax = plt.subplots()
ax.plot(fractions, counts[0], linestyle='-', label='Component A vs B')
ax.plot(fractions, counts[1], linestyle='-', label='Component A vs C')
ax.plot(fractions, counts[2], linestyle='-', label='Component B vs C')
ax.set_xlabel('Fraction of component')
ax.set_ylabel('Counts')
ax.set_title('Contribution of multiple components')
ax.legend()
plt.show()

# %%
# The graphical method for resolving the contribution of two or
# three components (pairwise) to a phasor coordinate is based on
# the quantification of moving circular cursors along the line
# between the components, demonstrated in the following animation
# which is repeated for the other combinations of components:

grid_x = numpy.linspace(-0.2, 1, int((1 + 0.2) / 0.001) + 1)
grid_y = numpy.linspace(-0.2, 0.6, int((0.6 + 0.2) / 0.001) + 1)
grid_x, grid_y = numpy.meshgrid(grid_x, grid_y)
cursor_diameter = 0.05
number_of_steps = 30
fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, figsize=(5, 8))
real_a, imag_a = [components_real[0], components_imag[0]]
real_b, imag_b = [components_real[1], components_imag[1]]
real_c, imag_c = [components_real[2], components_imag[2]]
component_counts = []
fractions = numpy.asarray(numpy.linspace(0, 1, number_of_steps + 1))
unit_vector, distance = line_from_components(
[real_b, real_a], [imag_b, imag_a]
)
cursor_real, cursor_imag = real_b, imag_b
step_size = distance / number_of_steps
plot = PhasorPlot(frequency=frequency, ax=ax1)
plot.hist2d(real, imag, cmap='plasma')
plot.plot([real_a, real_b], [imag_a, imag_b], fmt='o-', color='blue')
plot.plot(real_c, imag_c, fmt='o', color='blue')
plots = []
for step in range(number_of_steps + 1):
mask_shape = mask_segment(
grid_x,
grid_y,
cursor_real,
cursor_imag,
real_c,
imag_c,
cursor_diameter / 2,
)
plot.plot(grid_x[mask_shape], grid_y[mask_shape], color='red', alpha=0.01)
mask_phasors = mask_segment(
real,
imag,
cursor_real,
cursor_imag,
real_c,
imag_c,
cursor_diameter / 2,
)
fraction_counts = numpy.sum(mask_phasors)
component_counts.append(fraction_counts)
hist_artists = plt.plot(
fractions[: step + 1], component_counts, linestyle='-', color='blue'
)
plots.append(plot._lines + hist_artists)
cursor_real += step_size * unit_vector[0]
cursor_imag += step_size * unit_vector[1]
moving_cursor_animation = animation.ArtistAnimation(
fig, plots, interval=100, blit=True
)
ax2.set_xlim(0, 1)
ax2.set_title('Fraction of component A (respect to B)')
ax2.set_xlabel('Fraction of A')
ax2.set_ylabel('Counts')
ax1.annotate('A', xy=(0.8, 0.45), fontsize=14, fontweight='bold', color='blue')
ax1.annotate(
'B', xy=(0.13, 0.43), fontsize=14, fontweight='bold', color='blue'
)
ax1.annotate(
'C', xy=(-0.04, 0.12), fontsize=14, fontweight='bold', color='blue'
)
plt.tight_layout()
plt.show()

# %%
# sphinx_gallery_thumbnail_number = 2
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\nimport numpy\n\nfrom phasorpy.components import two_fractions_from_phasor\nfrom phasorpy.phasor import phasor_from_lifetime\nfrom phasorpy.plot import PhasorPlot\n\nnumpy.random.seed(42)"
"import matplotlib.animation as animation\nimport matplotlib.pyplot as plt\nimport numpy\n\nfrom phasorpy._utils import line_from_components, mask_segment\nfrom phasorpy.components import (\n graphical_component_analysis,\n two_fractions_from_phasor,\n)\nfrom phasorpy.phasor import phasor_from_lifetime\nfrom phasorpy.plot import PhasorPlot\n\nnumpy.random.seed(42)"
]
},
{
Expand Down Expand Up @@ -76,7 +76,7 @@
},
"outputs": [],
"source": [
"real, imag = numpy.random.multivariate_normal(\n (0.6, 0.35), [[8e-3, 1e-3], [1e-3, 1e-3]], (100, 100)\n).T\nplot = PhasorPlot(\n frequency=frequency,\n title='Phasor with contribution of two known components',\n)\nplot.hist2d(real, imag, cmap='plasma')\nplot.plot(*phasor_from_lifetime(frequency, components_lifetimes), fmt='o-')\nplot.show()"
"real, imag = numpy.random.multivariate_normal(\n (0.5, 0.33), [[5e-3, 1e-3], [1e-3, 1e-3]], (100, 100)\n).T\nplot = PhasorPlot(\n frequency=frequency,\n title='Phasor with contribution of two known components',\n)\nplot.hist2d(real, imag, cmap='plasma')\nplot.plot(*phasor_from_lifetime(frequency, components_lifetimes), fmt='o-')\nplot.show()"
]
},
{
Expand All @@ -97,6 +97,60 @@
"(\n fraction_from_first_component,\n fraction_from_second_component,\n) = two_fractions_from_phasor(real, imag, components_real, components_imag)\nfig, ax = plt.subplots()\nax.hist(\n fraction_from_first_component.flatten(),\n range=(0, 1),\n bins=100,\n alpha=0.75,\n label='First',\n)\nax.hist(\n fraction_from_second_component.flatten(),\n range=(0, 1),\n bins=100,\n alpha=0.75,\n label='Second',\n)\nax.set_title('Histograms of fractions of first and second component')\nax.set_xlabel('Fraction')\nax.set_ylabel('Counts')\nax.legend()\nplt.tight_layout()\nplt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Graphical solution for the contribution of multiple components\n\nThe :py:func:`graphical_component_analysis` function performs the graphical\nanalysis for two or three components and returns the number of phasors\nfor each fraction of the components (with respect to other components):\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"components_real, components_imag = phasor_from_lifetime(\n frequency, [1.0, 4.0, 15.0]\n)\ncounts, fractions = graphical_component_analysis(\n real, imag, components_real, components_imag\n)\nfig, ax = plt.subplots()\nplot = PhasorPlot(\n frequency=frequency,\n title='Phasor with contribution of three known components',\n ax=ax,\n)\nplot.hist2d(real, imag, cmap='plasma')\nplot.plot(components_real, components_imag, 'o-', color='blue')\nplot.plot(\n components_real[[0, -1]], components_imag[[0, -1]], fmt='-', color='blue'\n)\nax.annotate('A', xy=(0.8, 0.45), fontsize=16, fontweight='bold', color='blue')\nax.annotate('B', xy=(0.13, 0.43), fontsize=16, fontweight='bold', color='blue')\nax.annotate(\n 'C', xy=(-0.04, 0.12), fontsize=16, fontweight='bold', color='blue'\n)\nplt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The results can be plotted as histograms for each component pair:\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"fig, ax = plt.subplots()\nax.plot(fractions, counts[0], linestyle='-', label='Component A vs B')\nax.plot(fractions, counts[1], linestyle='-', label='Component A vs C')\nax.plot(fractions, counts[2], linestyle='-', label='Component B vs C')\nax.set_xlabel('Fraction of component')\nax.set_ylabel('Counts')\nax.set_title('Contribution of multiple components')\nax.legend()\nplt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The graphical method for resolving the contribution of two or\nthree components (pairwise) to a phasor coordinate is based on\nthe quantification of moving circular cursors along the line\nbetween the components, demonstrated in the following animation\nwhich is repeated for the other combinations of components:\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"grid_x = numpy.linspace(-0.2, 1, int((1 + 0.2) / 0.001) + 1)\ngrid_y = numpy.linspace(-0.2, 0.6, int((0.6 + 0.2) / 0.001) + 1)\ngrid_x, grid_y = numpy.meshgrid(grid_x, grid_y)\ncursor_diameter = 0.05\nnumber_of_steps = 30\nfig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, figsize=(5, 8))\nreal_a, imag_a = [components_real[0], components_imag[0]]\nreal_b, imag_b = [components_real[1], components_imag[1]]\nreal_c, imag_c = [components_real[2], components_imag[2]]\ncomponent_counts = []\nfractions = numpy.asarray(numpy.linspace(0, 1, number_of_steps + 1))\nunit_vector, distance = line_from_components(\n [real_b, real_a], [imag_b, imag_a]\n)\ncursor_real, cursor_imag = real_b, imag_b\nstep_size = distance / number_of_steps\nplot = PhasorPlot(frequency=frequency, ax=ax1)\nplot.hist2d(real, imag, cmap='plasma')\nplot.plot([real_a, real_b], [imag_a, imag_b], fmt='o-', color='blue')\nplot.plot(real_c, imag_c, fmt='o', color='blue')\nplots = []\nfor step in range(number_of_steps + 1):\n mask_shape = mask_segment(\n grid_x,\n grid_y,\n cursor_real,\n cursor_imag,\n real_c,\n imag_c,\n cursor_diameter / 2,\n )\n plot.plot(grid_x[mask_shape], grid_y[mask_shape], color='red', alpha=0.01)\n mask_phasors = mask_segment(\n real,\n imag,\n cursor_real,\n cursor_imag,\n real_c,\n imag_c,\n cursor_diameter / 2,\n )\n fraction_counts = numpy.sum(mask_phasors)\n component_counts.append(fraction_counts)\n hist_artists = plt.plot(\n fractions[: step + 1], component_counts, linestyle='-', color='blue'\n )\n plots.append(plot._lines + hist_artists)\n cursor_real += step_size * unit_vector[0]\n cursor_imag += step_size * unit_vector[1]\nmoving_cursor_animation = animation.ArtistAnimation(\n fig, plots, interval=100, blit=True\n)\nax2.set_xlim(0, 1)\nax2.set_title('Fraction of component A (respect to B)')\nax2.set_xlabel('Fraction of A')\nax2.set_ylabel('Counts')\nax1.annotate('A', xy=(0.8, 0.45), fontsize=14, fontweight='bold', color='blue')\nax1.annotate(\n 'B', xy=(0.13, 0.43), fontsize=14, fontweight='bold', color='blue'\n)\nax1.annotate(\n 'C', xy=(-0.04, 0.12), fontsize=14, fontweight='bold', color='blue'\n)\nplt.tight_layout()\nplt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down
Binary file modified main/_images/sphx_glr_phasorpy_components_002.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 modified main/_images/sphx_glr_phasorpy_components_003.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 main/_images/sphx_glr_phasorpy_components_004.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 main/_images/sphx_glr_phasorpy_components_005.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 modified main/_images/sphx_glr_phasorpy_components_thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit d026d2c

Please sign in to comment.