 Let's do the next talk. So I think it's a good job. I have a few software consultant for talk on here. This is it for a few big web development projects. And I'm going to give the next talk a practical introduction to the QT binding to Python and the OpenGL binding to Python. It's going to be a little session of extreme programming. We are peer programming. You are my peers. I'm behind the keyboard. So we are going to develop a little toy application and see how it goes. OK. So first thing that I want to do is not to use too much time. So I'm going to make sure that I have time for questions. Yeah. Good. OK. And next, first thing, I want to show you a little Python application that uses OpenGL. See what can be done. It should appeal to some people in here since it's a bioinformatics application. So here it is. It's a viewer for multiple alignments. There we go. So what we see here is the quality of the alignment for hate species. Yes, hate species. So this is the genome of the reference species. And here we have the quality of the alignment. When we have a dot, it means that we have a match. And when we have a mismatch, we show the layer where the mismatch is. We developed this for a group of bioinformatics researchers as you can. Why we developed this and why we use Python? We use Python because the problem was not well developed. They wanted something, but they didn't really know what they wanted. And all the other systems to see multiple alignments were not like it. I'm going to show you what you typically get. Yes? Very, very quickly, it's a problem set of alignment. Yes, yes, sure. Just enough that we have context. Yes. Yes. You're right. It's a gene. I'm not going to get that far. So OK, so I don't want to dive too deep into diamonds, but so you probably know that we can express the genome as a series of the four base pairs. They are AC, G, and T. And we express the genome as a big word. The problem of the alignment is to see how closely related genome is to another. So to do that, we basically write one genome under the other. The best that we can do, so we have the longest substrings matching under the reference genome. And the multiple alignment is just the problem of aligning multiple species with a reference genome. Do you think that it's close to the cap? Part of us is. Yes. So you're comparing DNA of different species. Yes. And we just want to see what are the big regions that are conserved that all the genomes that we selected keep this part of the word the same. And what is moving fast and stuff like that. And so typically what you get when you are looking at the multiple alignment is a really broad view of the alignment and where it's good and where it's not good. And you get a small window for a big 20k words long. And then you have 80 pages of stuff like that. So when you want to look at just a small part of it, and you say, oh, this is a really small part that is really well conserved, what it is. And then you go into databases to see where you find this part elsewhere. So this representation is really not good for that. So we developed this little application to look at, and this little application that is frozen. Yeah. To have a good view of the whole alignment with different resolutions. So I can have a more compressed view. I can see that here we have something that is moving really, really fast. But here we have a really conserved region. And we can instantly see what it is. And then we can select it as a probe and then export all the probes to do a search on the database. So this is basically just a few days of work with something with Python and OpenGL. Why OpenGL? Well, OpenGL has a really, really good set of graphic primitives. So we can draw multiple representation because we were not sure what was the best graphical representation for the conservation. It ended up that most people look at the color. So the bar plot is not really good. We still added this one for people who are colorblind. And yeah, that's it. This is an example application. Sorry, I have to leave. I have a train to catch. See you next time. See you next time. Thank you. Enjoy the stickers. All right. So next thing, Qt is most of you probably know Qt. So Qt is a multi-platform toolkit to develop graphical applications. Here, this is a typical pipeline. When you develop, you start to sketch your application. Here, we'll add a few buttons, loop your buttons so they keep well proportional. This is a really dumb window, but we can still have a quick prototype of our application. So let's add a few more things to it. Sorry? Do you have a specific goal for this window yet? I have an idea of what I want, but I'm open to suggestions. More or less, it's going to be kind of basic because I don't want to have a too broad scope. And I don't want to develop everything from scratch, but if you have suggestions, go ahead. So the basic version of the app that you showed us already? Well, we are not going to go into something like that, but we are going to do some 3D graphical programming. Good, so QT, the message passing with QT works with signals and slots. So basically every Q object can emit signals and receive signals into its slots. So and when you want to know the signals of an object, use the excellent QT documentation. So here I have a button. I have something that is called the Q slider and here a Q LCD number. So OK, let's see. For a Q slider, I have a few signals, like value change. Interesting. And right into the designer, I can connect a signal, value change, into a slot, like a display to change. Here, all changes on the slider are directly reflected on the LCD number. We still have a problem with those buttons. Yes, yes. Can you generate this kind of interface using a XNL or something like that? Yes, yes, it is XNL. Yeah, but instead of naming it in the designer, I have the data model that you want to generate the interface automatically. Yes. Yeah, you can. Yes, definitely. If I save that, and that was my plan, I'm just going to give it a name. This is not what I wanted to name. So yeah, let me show you. Name my file and save here in my, so it looks like that. It's a really simple XNL, not much in it. So it would be really trivial to generate from a data model. Yes. So it would work on a map. Oh yeah, definitely. Well, it's arguable if you have a script that reads your data model, it won't ask the question. Oh yeah. You might just create a GUI dynamically, right? Yeah, yeah, you can do it. You can create a GUI from Python too. You don't need to have a resource file. You could programmatically create buttons and fit them right into your window. Is there a way once you have an application built to actually dump the XNL file? That's harder. If you programmatically build the GUI, you create a... I don't know. You know that GUI files are programmable. Yes, and what did you do? Yeah, yeah, they do have that. You already generated XNL or other GUI. You didn't want to write it? No, I think GUI is a rejected tool for GUI. Yeah, but I don't think it's built in. You would need to write some code. OK, so here we have something and we fixed the button. I fixed them while we were talking, but you get the idea. And how do we bind this interface to Python code? That's where it gets interesting, where we call Python functions to react to events. There is something called... So if you were to do this in C++, the native framework for QT, you would call UIC that would generate C++ code for this GUI. But here we use IUIC on this LCD GUI. And it generates Python code. And then we have to use this Python code somehow. So let's add another button. This is the code generated in the interface? Sorry? This is the code generated in the interface? Yes. So yeah, so I call... Can you please turn on your computer? Oh. Yes, I can. Yes, I didn't plan for that enlarge. Like this? Yeah, I'm going there. Good. OK, because we still need to look at good chunk of code. So yeah, do you see in the back down there? Almost. Almost? So when I call PyUIC on this, it dumps the base class for this dialog. And it's the object-oriented way to program. We derive from this class and overload the methods that we are interested in. So... What actually happened? Has the source code 4 actually, in correct degree, in the GUI gadget, generated out of the XML file? Yes, yes. You need the XML file for the runtime? OK. So what happened? OK, with this little interface, I generate an XML file? Yeah, that's right. Let's look at it. OK, so if we take this button, let's call it OKDTM. Something wrong just happened. I'm sorry, if some of you have problems with the flashes, I usually use the visual belt. So this OK button is a Q push button. So when I ask PyUIC to compile this user interface to Python code, it says, OK, right here, I have a widget. It's a Q push button. So I need to create an object that is a Q push button. Let's save this generated interface into a file. And I lost my Python node. It's quite simple. We have some OKDTM somewhere here. So that's it. It's just direct translation from the XML. There is no. So XML is just a step in the process, really, right? Yes, yes. So you need to be in format to represent the GUI you designed. Yes, yes. Then you compile this to make the actual running GUI that's OK. This means you can use QT to make GUIs another language? Yeah, well, originally QT is made to do GUIs in C++. So yeah, they just hijacked there. Yeah? It's a separate tool. The QT designer is a tool. It's built on QT, generates the XML file. You have a tool that converts that into a C file. Or there's another tool that you I compiled that generates a Python file. But I think even better than that, you can just load the XML file dynamically. This way, you don't even have to restart your program. You can actually, sorry, keep your program running. And if it loads the file every time, it can be in one window in the designer. You change stuff, and then you just invoke the function that just dynamically reloads your. OK. Yeah. If you look at dynamically changing the tool. I realized just an example about a searcher who encourages doing the wrong thing, that in Turkey, a format that you use to design your GUI, and then you generate code. And then you know, modifying files like that by hand. People will do that when you shop, but you don't style it. But it's sort of, yeah, but loading is runtime. These angles are set right there. So it just demands from people from other countries in the South. All right. Thank you. Can you create the Q button from the string and dynamically? What do you mean? And if you have a string, a Python string with the name of the class, then the object? Yes, yes, yes. Yes? Yes, definitely. OK. So is it something you can do in Python that you cannot do in C++? Oh, yeah, the Python binding to QT is a lot more dynamic than the C++1. I'm going to show you an example a little around. Yeah, well, in Python, with eval, you can do pretty much anything. But even without resorting to eval, the reflection in Python is just so great that you can do pretty much everything you want. Because, first, we don't have access to the names of the class. Yeah. So yeah, that's why I don't want to get into that. That's cool. OK, so we have here this toy application. And we want to call some Python code to respond to an action. So I'm going to add a new button that I'm going to call foo, btn, here it's. Layout is usually quite tolerant. You just need to roughly group your stuff. So I have a new button. Doesn't do anything yet. And I want to call Python code in response to this button action. So again, I save my file. I compile it to Python code. And then I just need a little stub to load this file and run my application. So let's do that. Still problems with the, sorry? You do version four and so much better. Yeah, I should. I know, but my examples were ready with version three. So like I said, I just derived from this. So I think you are most familiar with Python, but this is the syntax to derive a class. So I create a new class, lcd win, that derives from lcd win. This is a mistake. That derives from lcd ui. I just create this. This is the constructor in Python. I'm not really sure what the constructor receives. And I'm not really interested by that either. So I just skip. Suppose that I am not sure. So you can just forward everything that you receive through some other method. And I just call my parent constructor. And then I do the interesting stuff. So what we just did in the ui thing with the connector to connect signals to stuff, we can do that with the connect function that receives an object, a signal, and then a receiver object and the slot. In Python, it's more dynamic. You can connect a signal to any callable function. So I'm going to connect from my full BTN, the signal that we need the correct syntax. Well, I pretty much know it. But QBTN, it's a Q push button. Yeah. As a signal, it has no signal. Clicked. Where? Where? Lower. Lower. Lower. Oh, it's in the aspect class. It's one out. Yeah. It's in QButton, right? It's like click to find it. Yeah. So you see that peer programming works. OK, so this is really the QT way of. Actually, this is gone in the new version. It's in the chip version. So yeah, in C++, they do it that way because they cannot introspect. So they use a preprocessor for the C++ files that uses the string. And this is a macro that can easily be parsed. So I need to pass the signal name and then to map it to some function that I don't know yet. Let's write a function that will respond to our button. Or less. Right now, I'm writing the response for the button. So this part is mostly boilerplate code. No, definitely not. So if you was using the XML file dynamically, instead of importing LCD Google, you would have a line of code somewhere that says load this file. And then you could get the class of the window created and some other class. And then you can just instantiate that. It doesn't make sense. It wouldn't be important. You'd be loading that and you get the class object and then you would create it. Yeah, there's a lot of things that you can do. So I just created a new function. I connected this function to the clicked signal of the foo button. And right now, I just need another bit of boilerplate code. I'm going to reuse. Let's say you didn't see that. LCD. OK. So we need an application that will load everything and launch the main window. So it's always a Q application. It receives the command line argument. We set the main window to this application. It can have more than one window. And then we show the window and we give the execution control to the application. Very simple. So now we have this button that prints, prints, prints, Python. So this is basically the way to bind events from the user interface to Python code. In the new version, you don't have to do connect. You can just name, instead of saying foo, you say on foo clicked. And it will automatically bind it for you. Yeah, yeah. So the three lines go with a connect call. You don't need it alone. In Qt4, there's a binding for Python and Qt4. So this is using Qt3. So with Qt4, you can do away with those. That's the same way. That's how it connects. I think the Python's binding is that way. Yeah, actually, there's a C++ function in version 4 that does it too. But Python has it. And the C++ functions that were limited, it will bind only on the same object. So basically, it takes your class, and then it looks for methods that would match patterns that correspond to on widget name, signal name. And then, so what you can have a function, and if anybody wants to, I can be happy to share it, you can say, bind all the signals from this object from, so all the, can you give it an object that has attributes, and then you give it another object that you want to connect the signals to. And just by searching the names, you can have it automatically, just one way. Well, in C++, this is some preprocessing data, right? So you need more of a static code. Yeah, it's the mock preprocessor. So yeah, yeah, there's a step. You need to transform the. So there are problems that you can only start as a proper class, and here, you can take an instance and bind the needs. Yeah, so let's say we want to pop a window when the button is clicked, we look for the documentation of message box, and the QT binding is really a clean translation. The Python binding to QT is really a clean translation. You can just use a QT assistant, the documentation for the C++ version of QT, and it translates directly to Python code. So QMessageBox, to have an information dialogue, I just need to pass the parent, a QWidget, and a caption and a text. Let's use that. So it's a static method from the QMessageBox class. I pass self, that is a QWidget. No need to recompile, we are in Python. Just close this guy and we run a little. So this is basically what we do, we just bind and connect events to Python code. So yeah, let's jump right into OpenGL. So I wanted to start the OpenGL thing from scratch, but while I was doing it to get to something interesting, it required quite a bit of boilerplate code, so I'm going to get to something pre-done. This doesn't exist, you've not seen it. Okay, so what we have here, there are a few things that are always there or mostly. In an OpenGL application, you need to somehow initialize your view pane, whether you want an orthographic view or a projection that will do the perspective. And every time you redraw, you need to update your position in the view pane, so okay. This is where I do this. Well, I won't get into the boilerplate OpenGL code. So this is how I compute my field of view. This is really simple, drawing with OpenGL. So it's always like that, you start with the GL begin and then something that you want to draw. And you place the vertices for whatever you are drawing. So in this case, a triangle. So I place the three vertices of the triangle and OpenGL will fill this shape with my GL color that is set just over there. So here I have a triangle, I have a quad and a little pyramid with blended vertices. So I'm going to reuse some of this code here. Okay, and this is, so it's a really simple GUI. Here we have, we need to derive from the GL widget. So show you. Here we have, so this stuff with lots of boilerplate code is a subclass of the QT OpenGL widget. We need to overload the initialization method and the paint GL method. So this one we need to do a custom widget that overwrite those methods. And then in QT Designer, we add a new custom widget style. Oh, we are. Okay, I'm speeding up. We add a new custom widget. It's really easy to, and it's a, here this one, a new custom widget. Here we have the view widget that I used in the viewer, the first application that I showed you. This is going to show you here. So you just add your new custom widget. When you edit your, no, your toolbox, no, when you edit your custom widgets, you can just, just say where to get the code for the custom widget. When it's Python code, you just say a Python code. Usually for custom widgets, you pass the header file for C++. So you pass the dot H. And there is a little catch. You need to, in order to use it in Python, I don't want to say that. You need to pass here Python and you can add pretty much anything you want here. So PyUIC will parse this part of the comment and include it in your Python code when you call PyUIC. So here I have this little really, really simple application. I just modified my app and we have a triangle, a square, and a little Pyramid with a really strange perspective. And yes, I didn't show you that. I overloaded the wheel event. So when we receive a wheel event, I take the delta from the event. For some reason, the delta is in a strange unit that each time you send a click of the wheel, it sends 100 or something like that. So I divide that to have a much finer grain resolution. So, and I just update my Z position and Z position is used when I change my position here in the view pane. I use it here, here, reset pass. So I just translate with those two never change and I just change here my Z. So I can zoom in and out and I can rotate these guys. So that's pretty much how you use OpenGL in Python. So this is really boring. We just manually draw the vertices. So what I wanted to do was to import some model that I did with Blender. So I'm going to skip most of the modeling part with Blender, but just show you models that I already have. Okay, so this is a really simple model with Blender. A tutorial on how to use Blender is really beyond the scope of this presentation. The UI is quite efficient once you know it, but there is a really, really steep learning curve to get proficient with Blender. But just for the sake of it, I'm going to hack this cube here. I'm going to select those. So you will know that I'm not cheating. And then like that, select this one. So I just edited some basic editing with my model. Blender is completely scripted in Python. So if I go to export this, most of the export scripts are Python, Python code. And Blender exports a really, really nice Python API. So if you use the Blender gaming engine, you can script everything in Python. Everything that is in Blender you can control from Python. And here I'm going to show you custom import script from Blender. And it's really, really simple to use Blender from Python. So you just need to import the Blender module. And then Blender.mesh.get gives you a list of meshes. So these two are meshes. Meshes are just a bunch of edges and faces. There are other things in Blender, like smooth solids and stuff like that, that are not easy to draw in OpenGL because meshes is really easy. It's just faces and you draw the faces. For the others, it would be more complicated. So I just export the meshes here. So this is really, really simple as an export script. So for all the mesh in my meshes, I just print map, so I map the export face function. And I map this to the list of faces in my mesh. I need to change that a bit because it was optimized to do one mesh. And now I want to do them all. So I'm going to do something. So I'm just going to dump the list of meshes. Look good. Okay, then to call a script, there are a few ways to call a script from Blender. You see if your programming works. Yes? Below? And the end of the faces. What, what? The end of the faces. Yes? And the end of the faces. Yes, yes, yes, it's here. No, no, no, export mesh. Yes? The end of the faces, the reference end of the faces. The end of the faces. Yes. Thank you. Okay, so yeah, there are a few ways to call a script from Blender. We use the quick and easy way. That is called Blender with the name of your model and the name of your script. And we should have a dump. All right, that's right. No object, right. Okay, and I probably mistyped. Yeah, I think it's that. You get dumped. So what is really nice in Python is that you have really great reflection. So instead of digging into the documentation to get the object that you want, its documentation, you can just pick the object because you know really well where to get this object and ask for its documentation. So yes, here it's the object first and the file that I want to dump. So now I should have a dump. Good, so I'm going to load this dump into my, and it's directly from a file. And I need to use that thing that we have just dumped. So I just load the list of meshes. For all the meshes, I loop on all the faces and then I just draw a polygon with all the vertices. Then, oh, we have a problem with the centering of all those meshes, but we didn't record the position. So what we need now would be to add some lighting because without light we don't really get the perspective effect. But I think that I just show you that it's fairly easy to do some 3D programming with Python. We just started mostly from scratch. Yeah, that's it.