Skip to content

Commit fa913c7

Browse files
Merge branch 'master' into feature/add_step_5.1
2 parents e037bea + 80bbcfe commit fa913c7

File tree

9 files changed

+230
-0
lines changed

9 files changed

+230
-0
lines changed

docs/ets_tutorial_slides.pdf

-284 KB
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__version__ = "0.0.1"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# General imports
2+
import PIL.Image
3+
from PIL.ExifTags import TAGS
4+
import numpy as np
5+
6+
# ETS imports
7+
from traits.api import cached_property, Dict, File, HasStrictTraits, Property
8+
9+
10+
class ImageFile(HasStrictTraits):
11+
""" Model to hold an image file.
12+
"""
13+
filepath = File
14+
15+
metadata = Property(Dict, depends_on="filepath")
16+
17+
def to_array(self):
18+
if not self.filepath:
19+
return np.array([])
20+
21+
with PIL.Image.open(self.filepath) as img:
22+
return np.asarray(img)
23+
24+
@cached_property
25+
def _get_metadata(self):
26+
if not self.filepath:
27+
return {}
28+
29+
with PIL.Image.open(self.filepath) as img:
30+
exif = img._getexif()
31+
32+
if exif:
33+
return {TAGS[k]: v for k, v in exif.items()
34+
if k in TAGS}
35+
else:
36+
return {}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import glob
2+
from os.path import expanduser, split
3+
4+
import pandas as pd
5+
6+
from traits.api import (
7+
Directory, HasStrictTraits, Instance, List, observe,
8+
)
9+
10+
from pycasa.model.image_file import ImageFile
11+
12+
SUPPORTED_FORMATS = [".png", ".jpg", ".jpeg", ".PNG", ".JPG", ".JPEG"]
13+
14+
15+
class ImageFolder(HasStrictTraits):
16+
""" Model for a folder of images.
17+
"""
18+
directory = Directory(expanduser("~"))
19+
20+
images = List(Instance(ImageFile))
21+
22+
@observe("directory")
23+
def _get_images(self, event):
24+
self.images = [
25+
ImageFile(filepath=file)
26+
for fmt in SUPPORTED_FORMATS
27+
for file in glob.glob(f"{self.directory}/*{fmt}")
28+
]
29+
30+
def create_metadata_df(self):
31+
return pd.DataFrame(
32+
[img.metadata for img in self.images],
33+
index=[split(img.filepath)[1] for img in self.images]
34+
)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from os.path import dirname, join, split
2+
import unittest
3+
4+
from image_folder import ImageFolder
5+
6+
import ets_tutorial
7+
8+
TUTORIAL_DIR = dirname(ets_tutorial.__file__)
9+
SAMPLE_IMG_DIR = join(TUTORIAL_DIR, "..", "sample_images")
10+
11+
12+
class TestImageFolder(unittest.TestCase):
13+
def setUp(self):
14+
self.filenames = ["IMG-0311_xmas_2020.JPG", "owls.jpg"]
15+
self.img_folder = ImageFolder(directory=SAMPLE_IMG_DIR)
16+
17+
def test_filters_images(self):
18+
self.assertEqual(
19+
{split(img.filepath)[1] for img in self.img_folder.images},
20+
set(self.filenames)
21+
)
22+
23+
def test_create_metadata_df(self):
24+
df = self.img_folder.create_metadata_df()
25+
self.assertEqual(set(df.index), set(self.filenames))
26+
self.assertIn("ExifVersion", df)
27+
self.assertIn("ApertureValue", df)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# General imports
2+
from matplotlib.figure import Figure
3+
4+
# ETS imports
5+
from traits.api import Instance, observe
6+
from traitsui.api import Item, ModelView, View
7+
8+
# Local imports
9+
from ets_tutorial.util.mpl_figure_editor import MplFigureEditor
10+
from pycasa.model.image_file import ImageFile
11+
12+
13+
class ImageFileView(ModelView):
14+
""" ModelView for an image file object.
15+
"""
16+
model = Instance(ImageFile)
17+
18+
figure = Instance(Figure)
19+
20+
view = View(
21+
Item("model.filepath", style="readonly", show_label=False),
22+
Item("figure", editor=MplFigureEditor(), show_label=False)
23+
)
24+
25+
@observe("model.filepath")
26+
def build_mpl_figure(self, event):
27+
figure = Figure()
28+
axes = figure.add_subplot(111)
29+
axes.imshow(self.model.to_array())
30+
self.figure = figure
31+
32+
33+
if __name__ == '__main__':
34+
from os.path import dirname, join
35+
import ets_tutorial
36+
37+
TUTORIAL_DIR = dirname(ets_tutorial.__file__)
38+
SAMPLE_IMG_DIR = join(TUTORIAL_DIR, "..", "sample_images")
39+
SAMPLE_IMG1 = join(SAMPLE_IMG_DIR, "IMG-0311_xmas_2020.JPG")
40+
41+
image_file = ImageFile(filepath=SAMPLE_IMG1)
42+
view = ImageFileView(model=image_file)
43+
view.configure_traits()
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from traits.api import cached_property, Instance, Property
2+
from traitsui.api import Item, ModelView, View
3+
from traitsui.ui_editors.data_frame_editor import DataFrameEditor
4+
5+
from pycasa.model.image_folder import ImageFolder
6+
7+
DISPLAYED_COLUMNS = [
8+
'ApertureValue', 'ExifVersion', 'Model', 'Make', 'LensModel', 'DateTime',
9+
'ShutterSpeedValue', 'XResolution', 'YResolution'
10+
]
11+
12+
13+
class ImageFolderView(ModelView):
14+
""" ModelView for a folder of images.
15+
"""
16+
model = Instance(ImageFolder)
17+
18+
metadata_df = Property(depends_on="model.images.items")
19+
20+
view = View(
21+
Item('model.directory', style="readonly", show_label=False),
22+
Item(
23+
'metadata_df',
24+
editor=DataFrameEditor(columns=DISPLAYED_COLUMNS),
25+
show_label=False,
26+
width=1200,
27+
),
28+
resizable=True
29+
)
30+
31+
@cached_property
32+
def _get_metadata_df(self):
33+
return self.model.create_metadata_df()
34+
35+
36+
if __name__ == '__main__':
37+
from os.path import dirname, join
38+
import ets_tutorial
39+
40+
TUTORIAL_DIR = dirname(ets_tutorial.__file__)
41+
SAMPLE_IMG_DIR = join(TUTORIAL_DIR, "..", "sample_images")
42+
43+
image_file = ImageFolder(directory=SAMPLE_IMG_DIR)
44+
view = ImageFolderView(model=image_file)
45+
view.configure_traits()
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import unittest
2+
from os.path import dirname, join
3+
4+
from traitsui.testing.api import UITester, IsVisible
5+
6+
import ets_tutorial
7+
from pycasa.model.image_folder import ImageFolder
8+
from image_folder_view import ImageFolderView
9+
10+
TUTORIAL_DIR = dirname(ets_tutorial.__file__)
11+
SAMPLE_IMG_DIR = join(TUTORIAL_DIR, "..", "sample_images")
12+
13+
14+
class TestImageFolderView(unittest.TestCase):
15+
def test_image_folder_view(self):
16+
# A smoke test.
17+
view = ImageFolderView(model=ImageFolder(directory=SAMPLE_IMG_DIR))
18+
tester = UITester()
19+
with tester.create_ui(view) as ui:
20+
df = tester.find_by_name(ui, "metadata_df")
21+
df.inspect(IsVisible())

stage3.0_first_views/setup.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from os.path import abspath, dirname, join
2+
from setuptools import setup, find_packages
3+
4+
HERE = dirname(abspath(__file__))
5+
6+
PKG_NAME = "pycasa"
7+
8+
info = {}
9+
init_file = join(HERE, PKG_NAME, "__init__.py")
10+
11+
with open(init_file) as fp:
12+
exec(fp.read(), globals(), info)
13+
14+
setup(
15+
name=PKG_NAME,
16+
version=info["__version__"],
17+
description='Introduction to TraitsUI views',
18+
ext_modules=[],
19+
packages=find_packages(),
20+
data_files=[
21+
(".", ["README.md"]),
22+
],
23+
)

0 commit comments

Comments
 (0)