Python PPTX workaround to add Transitions to slides - python

I successfully automated the creation of pptx presentations using python-pptx, customising background, inserting text, images, etc.
How can I add custom Transitions to my slides? (E.g. "Transitions" > "Fade" from PowerPoint). As I could not find a function, my idea is to use workaround functions (going deep into xml): where do I start?
python 3.10.4,
PowerPoint v16.54,
MacOS Big Sur 11.6

So, on playing with this, the following worked for me:
xml = '''
<mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<mc:Choice xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" Requires="p14">
<p:transition xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" spd="slow" p14:dur="3400">
<p14:ripple />
</p:transition>
</mc:Choice>
<mc:Fallback>
<p:transition xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" spd="slow">
<p:fade />
</p:transition>
</mc:Fallback>
</mc:AlternateContent>
'''
xmlFragment = parse_xml(xml)
slide.element.insert(-1, xmlFragment)
Where slide is the slide object in python-pptx.
You probably need the following import:
from pptx.oxml import parse_xml
Where I have ripple I first tested with reveal - and that worked as well. I'm sure there are other transitions. Before I attempt to add them to md2pptx I will want to find some more and figure out what kind of UI I want to surface them with.
Hope this helps.
(Edited for grammar.)

Related

Use "Relink to File" button in Photoshop using Python

I would like to relink a Photoshop Smart Object to a new file using Python.
Here's a screenshot of the button that's used in Photoshop to perform this action - "Relink to File":
I've found some solutions in other programming languages but couldn't make them work in Python, here's one for example: Photoshop Scripting: Relink Smart Object
Editing Contents of a Smart Object would also be a good option, but I can't seem to figure that one out either.
Here's a screenshot of the button to Edit Contents of a Smart Object:
So far I have this:
import win32com.client
psApp = win32com.client.Dispatch('Photoshop.Application')
psDoc = psApp.Application.ActiveDocument
for layer in psDoc.layers:
if layer.kind == 17: # layer kind 17 is Smart Object
print(layer.name)
# here it should either "Relink to File" or "Edit Contents" of a Smart Object
I have figured out a workaround! I simply ran JavaScript in Python.
This is the code to Relink to File.... You could do a similar thing for Edit Contents but I haven't tried it yet, as relinking works better for me.
Keep in mind the new_img_path must be a raw string as far as I'm aware, for example:
new_img_path = r"C:\\Users\\miha\\someEpicPic.jpg"
import photoshop.api as ps
def js_relink(new_img_path):
jscode = r"""
var desc = new ActionDescriptor();
desc.putPath(stringIDToTypeID('null'), new File("{}"));
executeAction(stringIDToTypeID('placedLayerRelinkToFile'), desc, DialogModes.NO);
""".format(new_img_path)
JavaScript(jscode)
def JavaScript(js_code):
app = ps.Application()
app.doJavaScript(js_code)

conversion newick to graphml using python

I would like to convert a tree from newick to a format like graphml, that I can open with cytoscape.
So, I have a file "small.newick" that contain:
((raccoon:1,bear:6):0.8,((sea_lion:11.9, seal:12):7,((monkey:100,cat:47):20, weasel:18):2):3,dog:25);
So far, I did that way (Python 3.6.5 |Anaconda):
from Bio import Phylo
import networkx
Tree = Phylo.read("small.newick", 'newick')
G = Phylo.to_networkx(Tree)
networkx.write_graphml(G, 'small.graphml')
There is a problem with the Clade, that I can fix using this code:
from Bio import Phylo
import networkx
def clade_names_fix(tree):
for idx, clade in enumerate(tree.find_clades()):
if not clade.name:
clade.name=str(idx)
Tree = Phylo.read("small.newick", 'newick')
clade_names_fix(Tree)
G = Phylo.to_networkx(Tree)
networkx.write_graphml(G, 'small.graphml')
Giving me something that seem nice enough:
My questions are:
Is that a good way to do it? It seem weird to me that the function does not take care of the internal node names
If you replace one node name with a string long enough, it will be trimmed by the command Phylo.to_networkx(Tree). How to avoid that?
Example: substitution of "dog" by "test_tring_that_create_some_problem_later_on"
Looks like you got pretty far on this already. I can only suggest a few alternatives/extensions to your approach...
Unfortunately, I couldn't find a Cytoscape app that can read this format. I tried searching for PHYLIP, NEWICK and PHYLO. You might have more luck:
http://apps.cytoscape.org/
There is an old Cytoscape 2.x plugin that could read this format, but to run this you would need to install Cytoscape 2.8.3, import the network, then export as xGMML (or save as CYS) and then try to open in Cytoscape 3.7 in order to migrate back into the land of living code. Then again, if 2.8.3 does what you need for this particular case, then maybe you don't need to migrate:
http://apps.cytoscape.org/apps/phylotree
The best approach is programmatic, which you already explored. Finding an R or Python package that turns NEWICK into iGraph or GraphML is a solid strategy. Note that there are updated and slick Cytoscape libs in those languages as well, so you can do all label cleanup, layout, data visualization, analysis, export, etc all within the scripting environment:
https://bioconductor.org/packages/release/bioc/html/RCy3.html
https://py2cytoscape.readthedocs.io/en/latest/
After some research, I actually found a solution that work.
I decided to provide the link here for you, dear reader:
going to github
FYI for anyone coming across this now I think the first issue mentioned here has now been solved in BioPython. Using the same data as above, the networkx graph which is built contains all the internal nodes of the tree as well as the terminal nodes.
import matplotlib.pyplot as plt
import networkx
from Bio import Phylo
Tree = Phylo.read("small.newick", 'newick')
G = Phylo.to_networkx(Tree)
networkx.draw_networkx(G)
plt.savefig("small_graph.png")
Specs:
Python 3.8.10,
Bio 1.78,
networkx 2.5

How can I display an empty staff using music21?

I am trying to produce a quick reworking of some educational materials on music showing how it may be able to create the associated media assets (images, audio files) from "code" in a Jupyter notebook using the Python music21 package.
It seems the simplest steps are the hardest. For example, how do I create an empty staff:
or a staff populated by notes but without a clef at the start?
If I do something like:
from music21 import *
s = stream.Stream()
s.append(note.Note('G4', type='whole'))
s.append(note.Note('A4', type='whole'))
s.append(note.Note('B4', type='whole'))
s.append(note.Note('C5', type='whole'))
s.show()
I get the following?
Try creating a stream.Measure object, so that barlines before the notes don't appear.
Music21 puts barlines and clefs, etc., in by default. You can manually put in a time signature of 4/1 and a treble clef and set them with ".style.hideObjectOnPrint" (or just ".hideObjectOnPrint" on older m21 versions). You will probably need to also set .rightBarline = bar.Barline('none') or something like that for the end.
It is possible, but I haven't ever fully tried all the parts of it.

Can python-pptx module insert video?

according to the documentation, python-pptx can insert videos, however, the documentation does not give very good examples. Anybody have any code snippets to add video1.avi to my pptx?
from pptx import Presentation
pptx1 = Presentation()
slide = pptx1.slides.add_slide(blank_slide_layout)
not sure what inputs I need
slide.placeholders.element.add_placeholder(id_,name,ph_type, orient, sz,idx)
thanks
UPDATE: python-pptx now supports inserting videos (and probably audio in many cases using the same method).
I'm not sure where in the documentation it says it can insert videos, but if you can cite a particular location I'll fix it.
We've looked at this feature, but it turns out to be quite complex as different video formats require a substantial amount of undocumented customization to the metadata inserted into the XML surrounding the embedded video object. Also as I recall one needs a way to get a still image (first frame maybe) from the video to insert in it's place while it's not running, and libraries for this sort of thing are not readily available in Python last time we looked.
Anyway, the short answer is no, it's not supported yet. And it's not likely to come soon unless there's a motivated contributor or sponsor. Sorry I didn't have happier news for you :(
I ended up converting my avi video to an animated gif, and that successfully inserted into the pptx
aviname = 'vid1.avi'
from moviepy.editor import VideoFileClip
aviname = 'vid1.avi'
clip = VideoFileClip(aviname)
clip.write_gif(os.path.splitext(aviname)[0]+'.gif')
The library now has a function for adding videos to slides:
slide.shapes.add_movie(video_file, x_pos, y_pos, width, height, poster_frame_image=thumbnail_image_file)
this video could help you:
https://www.youtube.com/watch?v=5a1kH996DJM&t=315s
he speaks arabic. Here is the code:
import pptx
from pptx.utils import Cm
from pptx.enum.shapes import PP_MEDIA_TYPE
pres = pptx.Presentation()
blank_slide = pres.slides.add_slide(pres.slide_layouts[6])
movie_path = "path"
movie_shape = blank_slide.shapes.add_movie(left = Cm(5), top = Cm(5), width = Cm(10), height = Cm(10), poster_frame_image = "image_path", mime_type = "video/mp4")
movie_shape.media_type = PP_MEDIA_TYPE.MOVIE
pres.save("pres.pptx")

Read binary data off Windows clipboard, in Blender (python)

EDIT: Figured THIS part out, but see 2nd post below for another question.
(a little backstory here, skip ahead for the TLDR :) )
I'm currently trying to write a few scripts for Blender to help improve the level creation workflow for a game that I play (Natural Selection 2). Currently, to move geometry from the level editor to Blender, I have to 1) Save a file from the editor as an .obj 2) import obj into blender, and make my changes. Then I 3) export to the game's level format using an exporter script I wrote, and 4) re-open the file in a new instance of the editor. 5) copy the level data from the new instance. 6) paste into the main level file. This is quite a pain to do, and quite clearly discourages even using the tool at all but for major edits. My idea for an improved workflow: 1) Copy data to clipboard in editor 2) Run importer script in Blender to load data. 3) Run exporter script in blender to save data. 4) Paste back into original file. This not only cuts out two whole steps in the tedious process, but also eliminates the need for extra files cluttering up my desktop. Currently though, I haven't found a way to read in clipboard data from the Windows clipboard into Blender... at least not without having to go through some really elaborate installation steps (eg install python 3.1, install pywin32, move x,y,z to the blender directory, uninstall python 3.1... etc...)
TLDR
I need help finding a way to write/read BINARY data to/from the clipboard in Blender. I'm not concerned about cross-platform capability -- the game tools are Windows only.
Ideally -- though obviously beggars can't be choosers here -- the solution would not make it too difficult to install the script for the layman. I'm (hopefully) not the only person who is going to be using this, so I'd like to keep the installation instructions as simple as possible. If there's a solution available in the python standard library, that'd be awesome!
Things I've looked at already/am looking at now
Pyperclip -- plaintext ONLY. I need to be able to read BINARY data off the clipboard.
pywin32 -- Kept getting missing DLL file errors, so I'm sure I'm doing something wrong. Need to take another stab at this, but the steps I had to take were pretty involved (see last sentence above TLDR section :) )
TKinter -- didn't read too far into this one as it seemed to only read plain-text.
ctypes -- actually just discovered this in the process of writing this post. Looks scary as hell, but I'll give it a shot.
Okay I finally got this working. Here's the code for those interested:
from ctypes import *
from binascii import hexlify
kernel32 = windll.kernel32
user32 = windll.user32
user32.OpenClipboard(0)
CF_SPARK = user32.RegisterClipboardFormatW("application/spark editor")
if user32.IsClipboardFormatAvailable(CF_SPARK):
data = user32.GetClipboardData(CF_SPARK)
size = kernel32.GlobalSize(data)
data_locked = kernel32.GlobalLock(data)
text = string_at(data_locked,size)
kernel32.GlobalUnlock(data)
else:
print('No spark data in clipboard!')
user32.CloseClipboard()
Welp... this is a new record for me (posting a question and almost immediately finding an answer).
For those interested, I found this: How do I read text from the (windows) clipboard from python?
It's exactly what I'm after... sort of. I used that code as a jumping-off point.
Instead of CF_TEXT = 1
I used CF_SPARK = user32.RegisterClipboardFormatW("application/spark editor")
Here's where I got that function name from: http://msdn.microsoft.com/en-us/library/windows/desktop/ms649049(v=vs.85).aspx
The 'W' is there because for whatever reason, Blender doesn't see the plain-old "RegisterClipboardFormat" function, you have to use "...FormatW" or "...FormatA". Not sure why that is. If somebody knows, I'd love to hear about it! :)
Anyways, haven't gotten it actually working yet: still need to find a way to break this "data" object up into bytes so I can actually work with it, but that shouldn't be too hard.
Scratch that, it's giving me quite a bit of difficulty.
Here's my code
from ctypes import *
from binascii import hexlify
kernel32 = windll.kernel32
user32 = windll.user32
user32.OpenClipboard(0)
CF_SPARK = user32.RegisterClipboardFormatW("application/spark editor")
if user32.IsClipboardFormatAvailable(CF_SPARK):
data = user32.GetClipboardData(CF_SPARK)
data_locked = kernel32.GlobalLock(data)
print(data_locked)
text = c_char_p(data_locked)
print(text)
print(hexlify(text))
kernel32.GlobalUnlock(data_locked)
else:
print('No spark data in clipboard!')
user32.CloseClipboard()
There aren't any errors, but the output is wrong. The line print(hexlify(text)) yields b'e0cb0c1100000000', when I should be getting something that's 946 bytes long, the first 4 of which should be 01 00 00 00. (Here's the clipboard data, saved out from InsideClipboard as a .bin file: https://www.dropbox.com/s/bf8yhi1h5z5xvzv/testLevel.bin?dl=1 )

Categories