Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1fea4aa
started implementation of ImageWidget, nothing is tested yet
kushalkolar Dec 2, 2022
1bc65a0
basic stuff finished for single plot with a slider, need to test
kushalkolar Dec 2, 2022
6592cc3
basic image widget works
kushalkolar Dec 2, 2022
658f298
docs
kushalkolar Dec 2, 2022
5cc91ae
splitting imagewidget into two classes
kushalkolar Dec 4, 2022
7a6a136
split ImageWidget into ImageWidgetSingle and later ImageWidgetGrid
kushalkolar Dec 4, 2022
7cce91f
combined single and grid ImageWidget into single class
kushalkolar Dec 4, 2022
56a9b1c
simple and grid image widget works, tested with simple args, need to …
kushalkolar Dec 4, 2022
79f4452
catch another user error
kushalkolar Dec 4, 2022
e4f6b12
fix type annotation
kushalkolar Dec 4, 2022
5028ce7
docstrings, started slice_avg implementation
kushalkolar Dec 4, 2022
5ef32eb
slice averaging on single and multiple dimensions works perfectly
kushalkolar Dec 5, 2022
eca6599
is_array() checks for and attr, better error messages
kushalkolar Dec 8, 2022
0e3cf16
rename axis -> dims
kushalkolar Dec 10, 2022
570c076
make most imagewidget methods private, most attributes as read-only p…
kushalkolar Dec 10, 2022
4764b84
quick_min_max() returns pre-computed min max if int or float, imagewi…
kushalkolar Dec 10, 2022
afc0378
vmin vmax for gridplot
kushalkolar Dec 10, 2022
fc3365b
Merge branch 'master' into high-level-widgets
kushalkolar Dec 11, 2022
b1e922c
update Image -> ImageGraphic
kushalkolar Dec 11, 2022
e6c5d3a
refactor, window_funcs now works very well, slow with multiple dims b…
kushalkolar Dec 11, 2022
64faffd
vminmax works, also added names for subplots, everything works
kushalkolar Dec 11, 2022
8fc63b3
proper-ish image widget example
kushalkolar Dec 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
splitting imagewidget into two classes
  • Loading branch information
kushalkolar committed Dec 4, 2022
commit 5cc91ae74aad3deb3ac5fd3b95732ca382b2d33d
97 changes: 97 additions & 0 deletions examples/imagewidget.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "111354d5-36ee-4bd5-9376-aaece6eb5b4e",
"metadata": {},
"outputs": [],
"source": [
"%load_ext autoreload"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "8404aaae-ba87-426c-a3cf-f3968640b8e3",
"metadata": {},
"outputs": [],
"source": [
"%autoreload 2"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "2253ccaa-670c-4c6a-9e81-48963bd1d964",
"metadata": {},
"outputs": [],
"source": [
"from fastplotlib.widgets import ImageWidget\n",
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "9775a1f0-34c3-4583-8dcc-00707095150b",
"metadata": {},
"outputs": [],
"source": [
"a = np.random.rand(1000, 512, 512)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "8b910f06-2cf4-4363-8b58-71c32d6f9c64",
"metadata": {},
"outputs": [
{
"ename": "ValueError",
"evalue": "'t' is not in list",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn [6], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m iw \u001b[38;5;241m=\u001b[39m \u001b[43mImageWidget\u001b[49m\u001b[43m(\u001b[49m\u001b[43ma\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcmap\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mgnuplot2\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n",
"File \u001b[0;32m~/repos/fastplotlib/fastplotlib/widgets/image.py:98\u001b[0m, in \u001b[0;36mImageWidget.__init__\u001b[0;34m(self, data, axes_order, slider_sync, slider_axes, slice_avg, frame_apply, grid_shape, **kwargs)\u001b[0m\n\u001b[1;32m 96\u001b[0m \u001b[38;5;66;03m# make a slider for \"t\", the time dimension, if slider_axes is not provided\u001b[39;00m\n\u001b[1;32m 97\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m slider_axes \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m---> 98\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_slider_axes \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43maxes_order\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mindex\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mt\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 100\u001b[0m \u001b[38;5;66;03m# if a single axes is provided for the slider\u001b[39;00m\n\u001b[1;32m 101\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(slider_axes, (\u001b[38;5;28mint\u001b[39m, \u001b[38;5;28mstr\u001b[39m)):\n",
"\u001b[0;31mValueError\u001b[0m: 't' is not in list"
]
}
],
"source": [
"iw = ImageWidget(a, cmap=\"gnuplot2\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f1be6cd2-9263-4da0-9280-48444dd74c1f",
"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.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
45 changes: 41 additions & 4 deletions fastplotlib/widgets/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
2: "xy",
3: "txy",
4: "tzxy",
5: "tczxy",
# 5: "tczxy", # no 5 dim stuff for now
}


Expand All @@ -30,6 +30,14 @@ def get_indexer(ndim: int, dim_index: int, slice_index: int) -> slice:
return tuple(indexer)


def is_arraylike(obj) -> bool:
"""
Checks if the object is array-like.
For now just checks if obj has `__getitem__()`
"""
return hasattr(obj, "__getitem__")


class ImageWidget:
"""
A high level for displaying n-dimensional image data in conjunction with automatically generated sliders for
Expand All @@ -40,9 +48,10 @@ class ImageWidget:
def __init__(
self,
data: Union[np.ndarray, List[np.ndarray]],
axes_order: str = None,
axes_order: [str, dict] = None,
slider_sync: bool = True,
slider_axes: Union[int, str, dict] = None,
slice_avg: Union[int, dict] = None,
frame_apply: Union[callable, dict] = None,
grid_shape: Tuple[int, int] = None,
**kwargs
Expand Down Expand Up @@ -87,14 +96,14 @@ def __init__(

# default axes order if not passed
if axes_order is None:
self.axes_order: List[str] = [DEFAULT_AXES_ORDER[ndim] for i in range(len(data))]
self.axes_order: str = [DEFAULT_AXES_ORDER[ndim] for i in range(len(data))]

else:
self.axes_order = axes_order

# make a slider for "t", the time dimension, if slider_axes is not provided
if slider_axes is None:
slider_axes = self.axes_order.index("t")
self._slider_axes = self.axes_order.index("t")

# if a single axes is provided for the slider
if isinstance(slider_axes, (int, str)):
Expand Down Expand Up @@ -190,3 +199,31 @@ def slider_changed(self):
def show(self):
self.plot.show()
return self.widget


class _ImageWidget:
"""Single n-dimension image with slider(s)"""
def __init__(
self,
data: np.ndarray,
axes_order: str = None,
slider_axes: Union[str, int, List[Union[str, int]]] = None,
slice_average: Dict[Union[int, str], int] = None,
frame_apply: Union[callable, Dict[Union[int, str], callable]] = None,
**kwargs
):
if not is_arraylike(data):
raise TypeError(
f"`data` must be an array-like object"
)

self.data = data
self.ndim = self.data.ndim

if axes_order is None:
self.axes_order: str = DEFAULT_AXES_ORDER[self.ndim]
else:
if not type(axes_order) is str:
raise TypeError(f"`axes_order` must be a <str>, you have passed a: <{type(axes_order)}>")
self.axes_order = axes_order