python pptx get table width - python

I work with python 2.7 and using python pptx.
I add a table to my slide, and need to get the table overall width.
I found here the _column attribute width, and try to use it, for example with that code
for col in table._column:
yield col.width
and get the following error:
AttributeError: 'Table' object has no attribute '_column'
I need to get the table width (or the columns width and sum it). ideas?
Thanks!

The property you want on Table is .columns, so:
for column in table.columns:
yield column.width
All the properties and a description of each is available in the API section of the documentation, for example this page describing the table object API:
http://python-pptx.readthedocs.io/en/latest/api/table.html

Building off Scanny's code and the pptx documentation we can define a function like this to print the dimensions of an entire existing python-pptx table object:
from pptx import Presentation
from pptx.util import Inches, Cm, Pt
def table_dims(table, measure = 'Inches'):
"""
Returns a dimensions tuple (width, height) of your pptx table
object in Inches, Cm, or Pt.
Defaults to Inches.
This value can then be piped into an Inches, Cm, or Pt call to
generate a new table of the same initial size.
"""
widths = []
heights = []
for column in table.columns:
widths.append(column.width)
for row in table.rows:
heights.append(row.height)
# Because the initial widths/heights are stored in a strange format, we'll convert them
if measure == 'Inches':
total_width = (sum(widths)/Inches(1))
total_height = (sum(heights)/Inches(1))
dims = (total_width, total_height)
return dims
elif measure == 'Cm':
total_width = (sum(widths)/Cm(1))
total_height = (sum(heights)/Cm(1))
dims = (total_width, total_height)
return dims
elif measure == 'Pt':
total_width = (sum(widths)/Pt(1))
total_height = (sum(heights)/Pt(1))
dims = (total_width, total_height)
return dims
else:
Exception('Invalid Measure Argument')
# Initialize the Presentation and Slides objects
prs = Presentation('path_to_existing.pptx')
slides = prs.slides
# Access a given slide's Shape Tree
shape_tree = slides['replace w/ the given slide index'].shapes
# Access a given table
table = shape_tree['replace w/ graphic frame index'].table
# Call our function defined above
slide_table_dims = table_dims(table)
print(slide_table_dims)

Related

How do I filter by area or eccentricity using skimage.measure.regionprops on a binary image in Python

I have a binary image of a road surface and I am trying to isolate the pothole only. Using skimage.measure.regionprops and skimage.measure.label I can produce a table of properties for different labels within the image.
How do I then filter using those values? - for instance using area or axis length or eccentricity to turn off certain labels.
Input, labled Image and properties table
using python 3
I would use pandas together with skimage.measure.regionprops_table to get what you want:
import pandas as pd
import imageio as iio
from skimage.measure import regionprops_table, label
image = np.asarray(iio.imread('path/to/image.png'))
labeled = label(image > 0) # ensure input is binary
data = regionprops_table(
labeled,
properties=('label', 'eccentricity'),
)
table = pd.DataFrame(data)
table_sorted_by_ecc = table.sort_values(
by='eccentricity', ascending=False
)
# print e.g. the 10 most eccentric labels
print(table_sorted.iloc[:10])
If you then want to e.g. produce the label image with only the most eccentric label, you can do:
eccentric_label = table['labels'].iloc[np.argmax(table['eccentricity'])]
labeled_ecc = np.where(labeled == eccentric_label, eccentric_label, 0)
You can also do more sophisticated things, e.g. make a label image with only labels above a certain eccentricity. Below, we use NumPy elementwise multiplication to produce an array that is the original label if that label has high eccentricity, or 0 otherwise. We then use the skimage.util.map_array function to map the original labels to either themselves or 0, again, depending on the eccentricity.
from skimage.util import map_array
ecc_threshold = 0.3
eccentric_labels = table['labels'] * (table['eccentricity'] > ecc_threshold)
new_labels = map_array(
labeled,
np.asarray(table['labels']),
np.asarray(eccentric_labels),
)

editing the position of a shape in PowerPoint

from pptx import Presentation
prs = Presentation(my_file)
print(prs.slides[1].shape[0])
#out:
#<pptx.shapes.picture.Picture at 0x2295816cf98>
I need to loop through my shapes and assign a custom height, width and vertical position :
height = 7002000
width = 12193200
i have my height + width values which I can set via assignment prs.slides[1].shape[0].height = height
with a simple loop.
one thing I can't find is the attribute to set the shape's position on the page, chiefly the Vertical Position
my correct value is set to -0.16cm which I'm trying to replicate.
I thought it might be under left or top but my correct presentation returns a value of 0
Note that you can use the provided convenience measurements like this:
from pptx.util import Cm
shape.left = Cm(5.5)
Which saves you doing the arithmetic to English Metric Units (EMU) yourself.
Found the answer finally - I had to use a combination of top and left on the shape attribute.
in my case I had to set my variables to
top = -57600
left = 0
I then access the shape method
for slide in prs.slides:
for shape in slide.shapes:
shape.left = left
shape.top = top

How to create a new dicom image with annotations from other?

I would like to create two pydicom file from one. But I can't save file in *.dcm format with annotations.
import pydicom
from pydicom.data import get_testdata_files
# read the dicom file
ds = pydicom.dcmread(test_image_fps[0])
# find the shape of your pixel data
shape = ds.pixel_array.shape
# get the half of the x dimension. For the y dimension use shape[0]
half_x = int(shape[1] / 2)
# slice the halves
# [first_axis, second_axis] so [:,:half_x] means slice all from first axis, slice 0 to half_x from second axis
data = ds.pixel_array[:, :half_x]
print('The image has {} x {}'.format(data.shape[0],
data.shape[1]))
# print the image information given in the dataset
print(data)
data.save_as("/my/path/after.dcm")
'numpy.ndarray' object has no attribute 'save_as
Info on this can be foud in the pydicom documentation.
Remark on "your" ;) code: data = ds.pixel_array[:, :half_x] assigns a view of the numpy.ndarray that is ds.pixel_array to data. Calling data.save_as() expectedly fails because that is an attribute of ds not data. As per the documentation you need to write to the ds.PixelData attribute like so:
ds.PixelData = data.tobytes() # where data is a numpy.ndarray or a view of an numpy.ndarray
# if the shape of your pixel data changes ds.Rows and ds.Columns must be updated,
# otherwise calls to ds.pixel_array.shape will fail
ds.Rows = 512 # update with correct number of rows
ds.Columns = 512 # update with the correct number of columns
ds.save_as("/my/path/after.dcm")

Passing variables in and out of functions

I've written a small program to do the following:
inspect an image
pick a row at random from the image
plot the pixel values along that row
make a list of the local minima in that row
and I'm trying to make it into a function, so that I do the same thing to, say 10 rows, so that I can plot the pixel values of all of those rows without haveing to run the program 10 times.
The code looks like this:
from astropy.io import fits
import matplotlib.pyplot as plt
import numpy as np
hdulist = fits.open('xbulge-w1.fits') # Open FITS file as image
w1data = hdulist[0].data
height = w1data.shape[0] # Inspect height of image
width = w1data.shape[1]
def plot_envelope(image, image_height):
index = np.random.randint(0, height/2) # Select random number in upper half
row = w1data[index] # Look at row number
local_minima = []
# Find local minimum, and add to list of minimum-valued pixels
for i in range(1, width-1):
if w1data[index][i-1] > w1data[index][i]:
if w1data[index][i+1] > w1data[index][i]:
local_minima.append(w1data[index][i])
else:
continue
return (local_minima, row, index)
plot_envelope(w1data, height)
x1 = range(width)
plt.plot(x1, row, color = 'r', linewidth = 0.5)
plt.title('Local envelope for row ' + str(index))
plt.xlabel('Position')
plt.ylabel('Pixel value')
plt.show()
It works fine if I don't use a function definition (i.e. if the declarations of index, row, and local_minima and the nested for loops are in the main part of the program). With the function definition as shown, it returns a NameError: name 'local_minima' is not defined error.
Since I'm passing those variables out of the function, shouldn't I be able to use them in the rest of the program?
Am I missing something about local and global variables?
When you call plot_envelope(w1data, height) you are telling the function to assign w1data and height to image and image_heigth respectivelly. Inside the function you should manipulate the w1data with the image dummy variable (change w1data for image inside the function) , which scope is only inside the function. Next thing is that you should get the result of the function (return) in a variable: envelope = plot_envelope(w1data, height) Then local_minima = envelope[0], row = envelope[1], index = envelope[2].

VTK/numpy for 3D image rendering and visualization

I am trying to display images obtained with a CT-scan using numpy/vtk. To do so, I followed this sample code and the answer to this question, but I do not get good results and I do not know the reason.
I have checked it out that I load the data correctly so it seems I am doing something wrong when rendering. Any type of help is highly appreciated. This is my result until now:
Thanks in advance.
This is my code :
import os
import sys
import pylab
import glob
import vtk
import numpy as np
#We order all the directories by name
path="data/Images/"
tulip_files = [t for t in os.listdir(path)]
tulip_files.sort() #the os.listdir function do not give the files in the right order so we need to sort them
#Function that open all the images of a folder and save them in a images list
def imageread(filePath):
filenames = [img for img in glob.glob(filePath)]
filenames.sort()
temp = pylab.imread(filenames[0])
d, w = temp.shape
h = len(filenames)
print 'width, depth, height : ',w,d,h
volume = np.zeros((w, d, h), dtype=np.uint16)
k=0
for img in filenames: #assuming tif
im=pylab.imread(img)
assert im.shape == (500,500), 'Image with an unexpected size'
volume[:,:,k] = im
k+=1
return volume
#We create the data we want to render. We create a 3D-image by a X-ray CT-scan made to an object. We store the values of each
#slice and we complete the volume with them in the z axis
matrix_full = imageread(path+'Image15/raw/reconstruction/*.tif')
# For VTK to be able to use the data, it must be stored as a VTK-image. This can be done by the vtkImageImport-class which
# imports raw data and stores it.
dataImporter = vtk.vtkImageImport()
# The previously created array is converted to a string of chars and imported.
data_string = matrix_full.tostring()
dataImporter.CopyImportVoidPointer(data_string, len(data_string))
# The type of the newly imported data is set to unsigned short (uint16)
dataImporter.SetDataScalarTypeToUnsignedShort()
# Because the data that is imported only contains an intensity value (it isnt RGB-coded or someting similar), the importer
# must be told this is the case.
dataImporter.SetNumberOfScalarComponents(1)
# The following two functions describe how the data is stored and the dimensions of the array it is stored in.
w, h, d = tulip_matrix_full.shape
dataImporter.SetDataExtent(0, h-1, 0, d-1, 0, w-1)
dataImporter.SetWholeExtent(0, h-1, 0, d-1, 0, w-1)
# This class stores color data and can create color tables from a few color points.
colorFunc = vtk.vtkPiecewiseFunction()
colorFunc.AddPoint(0, 0.0);
colorFunc.AddPoint(65536, 1);
# The following class is used to store transparency-values for later retrieval.
alphaChannelFunc = vtk.vtkPiecewiseFunction()
#Create transfer mapping scalar value to opacity
alphaChannelFunc.AddPoint(0, 0.0);
alphaChannelFunc.AddPoint(65536, 1);
# The previous two classes stored properties. Because we want to apply these properties to the volume we want to render,
# we have to store them in a class that stores volume properties.
volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(colorFunc)
volumeProperty.SetScalarOpacity(alphaChannelFunc)
#volumeProperty.ShadeOn();
# This class describes how the volume is rendered (through ray tracing).
compositeFunction = vtk.vtkVolumeRayCastCompositeFunction()
# We can finally create our volume. We also have to specify the data for it, as well as how the data will be rendered.
volumeMapper = vtk.vtkVolumeRayCastMapper()
volumeMapper.SetMaximumImageSampleDistance(0.01) # function to reduce the spacing between each image
volumeMapper.SetVolumeRayCastFunction(compositeFunction)
volumeMapper.SetInputConnection(dataImporter.GetOutputPort())
# The class vtkVolume is used to pair the previously declared volume as well as the properties to be used when rendering that volume.
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty)
# With almost everything else ready, its time to initialize the renderer and window, as well as creating a method for exiting the application
renderer = vtk.vtkRenderer()
renderWin = vtk.vtkRenderWindow()
renderWin.AddRenderer(renderer)
renderInteractor = vtk.vtkRenderWindowInteractor()
renderInteractor.SetRenderWindow(renderWin)
# We add the volume to the renderer ...
renderer.AddVolume(volume)
# ... set background color to white ...
renderer.SetBackground(1,1,1)
# ... and set window size.
renderWin.SetSize(550, 550)
renderWin.SetMultiSamples(4)
# A simple function to be called when the user decides to quit the application.
def exitCheck(obj, event):
if obj.GetEventPending() != 0:
obj.SetAbortRender(1)
# Tell the application to use the function as an exit check.
renderWin.AddObserver("AbortCheckEvent", exitCheck)
renderInteractor.Initialize()
# Because nothing will be rendered without any input, we order the first render manually before control is handed over to the main-loop.
renderWin.Render()
renderInteractor.Start()
Finally I found a solution. I made two important changes:
Change opacity values. I have a lot of near-to-black voxels so I modify the opacity to consider them as black (0.0).
alphaChannelFunc.AddPoint(15000, 0.0);
alphaChannelFunc.AddPoint(65536, 1);
Change array order. It seems that the array order in VTK is Fortran order, so I changed the next functions to define the axis correctly:
dataImporter.SetDataExtent(0, h-1, 0, d-1, 0, w-1)
dataImporter.SetWholeExtent(0, h-1, 0, d-1, 0, w-1)
And now it works!

Categories