How to set ImageItem colormaps in code

6,017 views
Skip to first unread message

Alex A

unread,
Sep 18, 2013, 4:43:38 PM9/18/13
to pyqt...@googlegroups.com
Hello,
   I'm just starting with pyqtgraph, and somewhat new to Python overall, so apologies if this is something that is addressed somewhere else but I haven't been able to find it.   I'm trying to figure out how to set the colormap for an ImageItem in code rather than via the GradientEditor or other GUI methods. 
   For a trivial example, starting with the ImageItem.py example code I'd like to make it be just a gradient along the red intensity for values 0 to 0.5, then ramp the green from 0.5 to 1.0.  i.e.:
val -> R,G,B
0.0 -> 0,0,0
0.5 -> 255,0,0
1.0 -> 255,255,0

   It seems that the setLookupTable() is the function that should be used, but I can't seem to figure out exactly how to use it.   Could someone post what I'd need to add to the ImageItem.py example to accomplish this?

  Thanks

Luke Campagnola

unread,
Sep 18, 2013, 9:57:29 PM9/18/13
to pyqt...@googlegroups.com
Like this:

import numpy as np
import pyqtgraph as pg

# build lookup table
lut = np.zeros((256,3), dtype=np.ubyte)
lut[:128,0] = np.arange(0,255,2)
lut[128:,0] = 255
lut[:,1] = np.arange(255)

# random image data
img = np.random.normal(size=(100,100))

# GUI
win = pg.GraphicsWindow()
view = win.addViewBox()
view.setAspectLocked(True)
item = pg.ImageItem(img)
view.addItem(item)
item.setLookupTable(lut)
item.setLevels([0,1])

Equivalently, you could use a ColorMap to generate the lookup table:

pos = np.array([0.0, 0.5, 1.0])
color = np.array([[0,0,0,255], [255,128,0,255], [255,255,0,255]], dtype=np.ubyte)
map = pg.ColorMap(pos, color)
lut = map.getLookupTable(0.0, 1.0, 256)



Luke

Alex A

unread,
Sep 19, 2013, 3:47:58 PM9/19/13
to pyqt...@googlegroups.com
Luke,
   Thanks, that got me most of what I needed and I figured out some more on my own.   I case it's helpful for anyone else just starting out, below is what I modified the central part of the ImageItem.py example into for testing out the colormaps.  I realize it's a bit hacked, but it was just to test whether I understood some things.
   I was having some issues understanding how some of the parameters related to each other as well as when to call certain things.   In particular I was having a hard time at first figuring out why my color scale (i.e. the color of the background gradient in my example) kept changing as I added the solid bars before I realized I had to call setLevels() inside the updateData(). 

   Thanks again for the help,
          Alex


## Set initial view bounds
view.setRange(QtCore.QRectF(0, 0, 600, 600))

#create test pattern background, basically a gradient from left to right
gradCen=1000  #midpoint of gradient
data=np.zeros([15, 600, 600], dtype=np.uint16)
for i in range(data.shape[1]):
    data[:,i,:] = gradCen-(data.shape[1]/2)+i    
#add horizontal bars, the same color as the extremes of the gradient
data[5:10,:,200:210] = gradCen-300
data[5:10,:,300:310] = gradCen+300
#add horizontal bars, the color that should be the extremes of the colorscale
data[10:15,:,200:210] = 0
data[10:15,:,300:310] = gradCen*2


#create a color map that goes from full red, to yellow, then to full green
pos = np.array([0.0, 0.5, 1.0])  #absolute scale here relative to the expected data not important I believe
color = np.array([[255,0,0,255], [255,255,0,255], [0,255,0,255]], dtype=np.ubyte)
colmap = pg.ColorMap(pos, color)

#get LUT, first first two params should match the position scale extremes passed to ColorMap(). 
# I believe last one just has to be >= the difference between the min and max level set later
lut = colmap.getLookupTable(0, 1.0, 2000)

img.setLookupTable(lut)
#img.setLevels([0,2048])   #don't do here, it needs to be after each setImage to work properly


updateTime = ptime.time()
fps = 0
i = 0
def updateData():
    global img, data, i, updateTime, fps

    ## Display the data
    img.setImage(data[i])
    #set the levels to the min and max we desire on our scale
    img.setLevels([0,2000]) 
   
    i = (i+1) % data.shape[0]

    QtCore.QTimer.singleShot(200, updateData)
    now = ptime.time()
    fps2 = 1.0 / (now-updateTime)
    updateTime = now
    fps = fps * 0.9 + fps2 * 0.1
   
    #print "%0.1f fps" % fps

Federico Barabas

unread,
Jan 29, 2015, 12:12:28 PM1/29/15
to pyqt...@googlegroups.com
Is there a way to convert matplotlib colormaps to use them with pyqtgraph?

I'm specially interested in cubehelix:  matplotlib._cm.cubehelix

dyadkin

unread,
Apr 30, 2015, 8:57:01 AM4/30/15
to pyqt...@googlegroups.com
Here it is:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import numpy as np


# taken from https://www.mrao.cam.ac.uk/~dag/CUBEHELIX/cubehelix.py
lut_cubehelix = np.array((
(0.00000, 0.00000, 0.00000),
(2.04510, 0.34680, 1.68810),
(4.02390, 0.71145, 3.45015),
(5.93385, 1.10160, 5.28360),
(7.76730, 1.51470, 7.18335),
(9.52935, 1.95585, 9.14685),
(11.20980, 2.42505, 11.16645),
(12.80865, 2.92485, 13.23960),
(14.32590, 3.46035, 15.36120),
(15.75645, 4.02900, 17.52615),
(17.10030, 4.63590, 19.73190),
(18.35490, 5.27850, 21.97080),
(19.52025, 5.96445, 24.23775),
(20.59635, 6.68865, 26.53020),
(21.57810, 7.45875, 28.84305),
(22.47060, 8.26965, 31.16865),
(23.26875, 9.12900, 33.50445),
(23.97510, 10.03170, 35.84280),
(24.59220, 10.98030, 38.18115),
(25.11750, 11.97735, 40.51185),
(25.55100, 13.02030, 42.83235),
(25.89780, 14.11425, 45.13755),
(26.15535, 15.25410, 47.41980),
(26.32620, 16.44240, 49.67655),
(26.41545, 17.67915, 51.90270),
(26.42055, 18.96180, 54.09060),
(26.34660, 20.29545, 56.24025),
(26.19615, 21.67500, 58.34655),
(25.96920, 23.10045, 60.40185),
(25.67085, 24.57180, 62.40360),
(25.30620, 26.08905, 64.34670),
(24.87525, 27.65220, 66.22860),
(24.38055, 29.25615, 68.04675),
(23.82975, 30.90090, 69.79350),
(23.22540, 32.58900, 71.46885),
(22.57005, 34.31535, 73.07025),
(21.86880, 36.07995, 74.59005),
(21.12420, 37.88025, 76.02825),
(20.34390, 39.71370, 77.38485),
(19.53045, 41.58030, 78.65220),
(18.68895, 43.47750, 79.83030),
(17.82195, 45.40530, 80.91660),
(16.93710, 47.35860, 81.91110),
(16.03695, 49.33485, 82.81125),
(15.12915, 51.33660, 83.61450),
(14.21625, 53.35620, 84.32085),
(13.30335, 55.39365, 84.93030),
(12.39555, 57.44640, 85.44030),
(11.50050, 59.51190, 85.85085),
(10.61820, 61.58760, 86.16450),
(9.75630, 63.67095, 86.37615),
(8.92245, 65.75940, 86.49090),
(8.11665, 67.85040, 86.50620),
(7.34655, 69.94140, 86.42460),
(6.61470, 72.03240, 86.24865),
(5.92875, 74.11575, 85.97580),
(5.29380, 76.19145, 85.60860),
(4.70985, 78.25695, 85.15215),
(4.18455, 80.31225, 84.60390),
(3.72300, 82.34970, 83.96895),
(3.32775, 84.36930, 83.24985),
(3.00135, 86.36595, 82.44660),
(2.75145, 88.34220, 81.56430),
(2.58060, 90.29295, 80.60550),
(2.49135, 92.21565, 79.57275),
(2.48625, 94.10520, 78.46860),
(2.57040, 95.96415, 77.30070),
(2.74890, 97.78995, 76.06650),
(3.01920, 99.57495, 74.77620),
(3.38895, 101.32425, 73.42980),
(3.85815, 103.03020, 72.03240),
(4.43190, 104.69280, 70.58910),
(5.10765, 106.30950, 69.10500),
(5.89050, 107.88030, 67.58265),
(6.78300, 109.40265, 66.02715),
(7.78260, 110.87655, 64.44360),
(8.89440, 112.29690, 62.83710),
(10.11840, 113.66370, 61.21275),
(11.45205, 114.97695, 59.57310),
(12.90300, 116.23410, 57.92835),
(14.46360, 117.43260, 56.27850),
(16.13895, 118.57755, 54.63120),
(17.92650, 119.66130, 52.99155),
(19.82880, 120.68640, 51.36465),
(21.84075, 121.65285, 49.75305),
(23.96490, 122.55810, 48.16695),
(26.19870, 123.40470, 46.60635),
(28.54215, 124.18755, 45.07890),
(30.99015, 124.91175, 43.58970),
(33.54525, 125.57475, 42.14385),
(36.20235, 126.17400, 40.74390),
(38.96145, 126.71715, 39.39750),
(41.81745, 127.19655, 38.10720),
(44.76780, 127.61985, 36.88065),
(47.81250, 127.98195, 35.72040),
(50.94645, 128.28795, 34.62900),
(54.16710, 128.53530, 33.61410),
(57.46935, 128.72655, 32.67825),
(60.85320, 128.86170, 31.82400),
(64.30845, 128.94330, 31.05900),
(67.83765, 128.97390, 30.38325),
(71.43315, 128.95095, 29.80185),
(75.09240, 128.87955, 29.31735),
(78.80775, 128.76225, 28.93485),
(82.57920, 128.59650, 28.65690),
(86.39655, 128.38740, 28.48350),
(90.25980, 128.13495, 28.42230),
(94.16385, 127.84425, 28.46820),
(98.10105, 127.51275, 28.63140),
(102.06885, 127.14810, 28.90935),
(106.05960, 126.74775, 29.30205),
(110.07075, 126.31680, 29.81460),
(114.09465, 125.85525, 30.44955),
(118.12620, 125.37075, 31.20435),
(122.16285, 124.85820, 32.07900),
(126.19695, 124.32780, 33.07605),
(130.22340, 123.77700, 34.19805),
(134.23710, 123.21090, 35.44245),
(138.23295, 122.62950, 36.80670),
(142.20585, 122.04045, 38.29590),
(146.15070, 121.44120, 39.90495),
(150.06240, 120.83685, 41.63640),
(153.93585, 120.22995, 43.48770),
(157.76340, 119.62560, 45.45630),
(161.54250, 119.02380, 47.53965),
(165.27060, 118.42710, 49.74030),
(168.93750, 117.84060, 52.05315),
(172.54320, 117.26430, 54.47565),
(176.08005, 116.70330, 57.00780),
(179.54550, 116.15760, 59.64450),
(182.93700, 115.63230, 62.38320),
(186.24435, 115.12995, 65.22390),
(189.47010, 114.65310, 68.15895),
(192.60660, 114.20175, 71.18580),
(195.65385, 113.78100, 74.30445),
(198.60420, 113.39340, 77.50725),
(201.45510, 113.04150, 80.79165),
(204.20655, 112.72530, 84.15510),
(206.85090, 112.44735, 87.58995),
(209.39070, 112.21275, 91.09365),
(211.82085, 112.02150, 94.66365),
(214.13880, 111.87615, 98.29230),
(216.34455, 111.77670, 101.97450),
(218.43300, 111.72570, 105.70770),
(220.40670, 111.72570, 109.48680),
(222.26055, 111.77925, 113.30415),
(223.99455, 111.88635, 117.15975),
(225.60870, 112.04955, 121.04340),
(227.10045, 112.26885, 124.95255),
(228.47235, 112.54680, 128.87955),
(229.72440, 112.88085, 132.82185),
(230.85150, 113.27610, 136.77435),
(231.86130, 113.73255, 140.72940),
(232.74870, 114.24765, 144.68445),
(233.51625, 114.82650, 148.63185),
(234.16395, 115.46655, 152.56650),
(234.69690, 116.17035, 156.48585),
(235.11255, 116.93535, 160.38225),
(235.41345, 117.76410, 164.25060),
(235.60215, 118.65405, 168.08580),
(235.68120, 119.60775, 171.88530),
(235.65315, 120.62265, 175.64400),
(235.51800, 121.69875, 179.35425),
(235.28340, 122.83605, 183.01350),
(234.94680, 124.03455, 186.61665),
(234.51585, 125.29425, 190.16115),
(233.99055, 126.61005, 193.63935),
(233.37600, 127.98450, 197.05125),
(232.67730, 129.41505, 200.38920),
(231.89445, 130.90170, 203.65065),
(231.03510, 132.44190, 206.83305),
(230.10180, 134.03310, 209.93130),
(229.09965, 135.67785, 212.94540),
(228.03120, 137.37105, 215.86770),
(226.90155, 139.11015, 218.70075),
(225.71835, 140.89515, 221.43690),
(224.48160, 142.72350, 224.07615),
(223.20150, 144.59520, 226.61595),
(221.87805, 146.50515, 229.05375),
(220.51635, 148.45335, 231.38955),
(219.12660, 150.43470, 233.61825),
(217.70880, 152.45175, 235.74240),
(216.26805, 154.49685, 237.76200),
(214.81200, 156.57255, 239.66940),
(213.34575, 158.67120, 241.47225),
(211.87185, 160.79280, 243.16290),
(210.39540, 162.93735, 244.74645),
(208.92660, 165.09720, 246.22290),
(207.46290, 167.27235, 247.58715),
(206.01705, 169.46280, 248.84685),
(204.58650, 171.66090, 249.99690),
(203.18145, 173.86920, 251.04240),
(201.80445, 176.08005, 251.98335),
(200.46060, 178.29345, 252.82230),
(199.15500, 180.50430, 253.55925),
(197.89020, 182.71515, 254.19420),
(196.67385, 184.91835, 254.73480),
(195.50595, 187.11390, 255.00000),
(194.39415, 189.29925, 255.00000),
(193.34100, 191.47185, 255.00000),
(192.34905, 193.62660, 255.00000),
(191.42595, 195.76605, 255.00000),
(190.56915, 197.88255, 255.00000),
(189.78885, 199.97610, 255.00000),
(189.08250, 202.04670, 255.00000),
(188.45265, 204.08925, 255.00000),
(187.90695, 206.10120, 255.00000),
(187.44540, 208.08255, 255.00000),
(187.06800, 210.03075, 254.69145),
(186.77985, 211.94580, 254.25285),
(186.58095, 213.82260, 253.76580),
(186.47385, 215.66115, 253.23795),
(186.46110, 217.45890, 252.66930),
(186.54015, 219.21840, 252.06750),
(186.71610, 220.93200, 251.43765),
(186.98385, 222.60480, 250.78485),
(187.35105, 224.22915, 250.11165),
(187.81260, 225.81015, 249.42315),
(188.36850, 227.34525, 248.72700),
(189.02130, 228.83190, 248.02575),
(189.76845, 230.27010, 247.32705),
(190.60995, 231.65985, 246.63090),
(191.54325, 233.00115, 245.94750),
(192.57090, 234.29400, 245.27940),
(193.68525, 235.53585, 244.63170),
(194.88885, 236.72925, 244.00695),
(196.17915, 237.87420, 243.41535),
(197.55105, 238.97325, 242.85435),
(199.00710, 240.02130, 242.33415),
(200.53965, 241.02090, 241.85730),
(202.14870, 241.97460, 241.42635),
(203.82915, 242.88495, 241.04640),
(205.57845, 243.74685, 240.72510),
(207.39660, 244.56540, 240.45990),
(209.27340, 245.34315, 240.26100),
(211.20885, 246.07755, 240.12585),
(213.20040, 246.77115, 240.06210),
(215.24040, 247.42650, 240.06975),
(217.32375, 248.04615, 240.15645),
(219.45045, 248.63010, 240.31965),
(221.61285, 249.18090, 240.56445),
(223.80840, 249.70110, 240.89340),
(226.02945, 250.19325, 241.30905),
(228.27090, 250.65480, 241.81140),
(230.53020, 251.09340, 242.40300),
(232.80225, 251.51160, 243.08385),
(235.07940, 251.90685, 243.85650),
(237.35655, 252.28680, 244.72350),
(239.63115, 252.64890, 245.68230),
(241.89810, 253.00080, 246.73545),
(244.14975, 253.34250, 247.88295),
(246.37845, 253.67655, 249.12225),
(248.58420, 254.00805, 250.45335),
(250.76190, 254.33700, 251.87880),
(252.90135, 254.66595, 253.39350),
(255.00000, 255.00000, 255.00000)),
dtype=np.ubyte
)

Federico Barabas

unread,
May 2, 2015, 10:43:23 PM5/2/15
to pyqt...@googlegroups.com
thanks a lot!

--
You received this message because you are subscribed to a topic in the Google Groups "pyqtgraph" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pyqtgraph/gEjC08Vb8NQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pyqtgraph+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyqtgraph/3f2fbe52-000d-43c2-8318-b66d435c2281%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Federico Barabas

unread,
May 13, 2015, 1:08:48 PM5/13/15
to pyqt...@googlegroups.com
For some reason it's not really working. Here's what I'm trying:

self.img = pg.ImageItem()

self.vb.addItem(self.img)

self.hist = pg.HistogramLUTItem()

self.hist.setImageItem(self.img)

self.img.setLookupTable(cubehelix())


where cubehelix is just a function that returns the lut_cubehelix array


what am I doing wrong?

dyadkin

unread,
May 15, 2015, 11:27:42 AM5/15/15
to pyqt...@googlegroups.com
I do not really know. I use ImageView widget and it works fine, I just had to subclass, otherwise if you resize the window, LUT drops to the default one. Now it works fine.

class ImageView(pg.ImageView):
def __init__(self, *args, **kwargs):
super(ImageView, self).__init__(*args, **kwargs)
self.lut = None

def updateImage(self, autoHistogramRange=True):
super(ImageView, self).updateImage(autoHistogramRange)
self.getImageItem().setLookupTable(self.lut)

def setLookupTable(self, lut):
self.lut = lut
self.updateImage()

def resizeEvent(self, event):
super(ImageView, self).resizeEvent(event)
self.updateImage()

Thus, just:
iv = ImageView()
iv.setLookupTable(cubehelix()) 
should work.

dyadkin

unread,
May 15, 2015, 3:33:20 PM5/15/15
to pyqt...@googlegroups.com
Finally, I have written a generator of lookup table for pyqtgraph.
Cubehelix:

def cubehelix(gamma=1.0, s=0.5, r=-1.5, h=1.0):
def get_color_function(p0, p1):
def color(x):
xg = x ** gamma
a = h * xg * (1 - xg) / 2
phi = 2 * np.pi * (s / 3 + r * x)
return xg + a * (p0 * np.cos(phi) + p1 * np.sin(phi))
return color

array = np.empty((256, 3))
abytes = np.arange(0, 1, 1/256.)
array[:, 0] = get_color_function(-0.14861, 1.78277)(abytes) * 255
array[:, 1] = get_color_function(-0.29227, -0.90649)(abytes) * 255
array[:, 2] = get_color_function(1.97294, 0.0)(abytes) * 255
return array

Rainbow:

def rainbow():
array = np.empty((256, 3))
abytes = np.arange(0, 1, 0.00390625)
array[:, 0] = np.abs(2 * abytes - 0.5) * 255
array[:, 1] = np.sin(abytes * np.pi) * 255
array[:, 2] = np.cos(abytes * np.pi / 2) * 255
return array

Federico Barabas

unread,
May 17, 2015, 12:54:36 PM5/17/15
to pyqt...@googlegroups.com
Awesome!
I didn't want to use an ImageView, so in the update routine I did this:

self.img.setImage(image, autoLevels=False, lut=self.lut)


where self.lut points to the cubehelix


--
You received this message because you are subscribed to a topic in the Google Groups "pyqtgraph" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pyqtgraph/gEjC08Vb8NQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pyqtgraph+...@googlegroups.com.

Federico Barabas

unread,
May 17, 2015, 1:04:47 PM5/17/15
to pyqt...@googlegroups.com
The only (small) thing that bugs me is the fact that the gradient in the HistogramLutItem doesn't reflect the cubehelix gradient

Luke Campagnola

unread,
May 18, 2015, 11:01:18 PM5/18/15
to pyqt...@googlegroups.com
If you are using ImageView, then you can assign a colormap to the gradient editor rather than the image:

    imageview.ui.histogram.gradient.setColorMap(colormap)

This should also make it unnecessary to deal with the widget resize resetting the LUT. 

You received this message because you are subscribed to the Google Groups "pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyqtgraph+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyqtgraph/CAFGKJ92gPN4-%2Br11HvDx6TUnPJyv7tg5kRFWFUi3nat4KkK-9Q%40mail.gmail.com.

Federico Barabas

unread,
May 19, 2015, 10:37:26 AM5/19/15
to pyqt...@googlegroups.com
ok, but I think that's not so easy because the cubehelix lut has a continous change in color, so I can't think of a way of creating a colormap with positions

Federico Barabas

unread,
Jul 11, 2016, 7:23:21 PM7/11/16
to pyqtgraph
I went over this thing again and I managed to change the gradient to the cubehelix colormap in this way:

I got the cubehelix RGB array from https://www.mrao.cam.ac.uk/~dag/CUBEHELIX/cubehelix.py. And then these lines made the trick:

        hist = pyqtgraph.HistogramLUTItem()
        cubehelix = cubehelix().astype(int)
        pos, color = np.arange(0, 1, 1/256), cubehelix
        hist.gradient.setColorMap(pyqtgraph.ColorMap(pos, color))

One question remains: is there an easy way of hiding all the ticks next to the gradient? I don't need them and they don't look good because the colormap has a tick for each position between 0 and 255. I tried subclassing TickSliderItem but in the end I failed.


To unsubscribe from this group and all its topics, send an email to pyqtgraph+unsubscribe@googlegroups.com.


--
You received this message because you are subscribed to the Google Groups "pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyqtgraph+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to a topic in the Google Groups "pyqtgraph" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pyqtgraph/gEjC08Vb8NQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pyqtgraph+unsubscribe@googlegroups.com.

Luke Campagnola

unread,
Jul 12, 2016, 2:08:42 AM7/12/16
to pyqt...@googlegroups.com
I would love it if we could move away from using lookup tables and toward a more general colormapping model. The ColorMap class was intended to be a start in this direction, but I think this would take a lot more work to sort out.


On Mon, Jul 11, 2016 at 4:23 PM, Federico Barabas <fede.b...@gmail.com> wrote:

One question remains: is there an easy way of hiding all the ticks next to the gradient? I don't need them and they don't look good because the colormap has a tick for each position between 0 and 255. I tried subclassing TickSliderItem but in the end I failed.

I suppose the easiest way is just to hide the ticks after you set the gradient, and maybe adjust the width of the gradient editor, like:

  for tick in histogramLutItem.gradient.ticks:
      tick.hide()
  histogramLutItem.gradient.setFixedWidth(...)

Federico Barabas

unread,
Jul 12, 2016, 9:25:10 AM7/12/16
to pyqt...@googlegroups.com
Thank you Luke! I'm sorry I missed that simple hide command

--
You received this message because you are subscribed to a topic in the Google Groups "pyqtgraph" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pyqtgraph/gEjC08Vb8NQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pyqtgraph+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyqtgraph/CACZXET8sUPK1OgprTcDC%2BS_Fhxd%2B7TRu7%3DUYt2oEH9SRaseeCA%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages