Eager to get started? This page gives a good introduction to Flask. It assumes you already have Flask installed. If you do not, head over to the Installation section.
A minimal Flask application looks something like this:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
Just save it as hello.py (or something similar) and run it with your Python interpreter. Make sure to not call your application flask.py because this would conflict with Flask itself.
$ python hello.py
* Running on http://<IP_ADDRESS>:5000/
Now head over to http://<IP_ADDRESS>:5000/, and you should see your hello world greeting.
So what did that code do?
To stop the server, hit control-C.
Externally Visible Server
If you run the server you will notice that the server is only accessible from your own computer, not from any other in the network. This is the default because in debugging mode a user of the application can execute arbitrary Python code on your computer.
If you have debug disabled or trust the users on your network, you can make the server publicly available simply by changing the call of the run() method to look like this:
app.run(host='<IP_ADDRESS>')
This tells your operating system to listen on all public IPs.
The run() method is nice to start a local development server, but you would have to restart it manually after each change to your code. That is not very nice and Flask can do better. If you enable debug support the server will reload itself on code changes, and it will also provide you with a helpful debugger if things go wrong.
There are two ways to enable debugging. Either set that flag on the application object:
app.debug = True
app.run()
Or pass it as a parameter to run:
app.run(debug=True)
Both methods have the exact same effect.
Attention
Even though the interactive debugger does not work in forking environments (which makes it nearly impossible to use on production servers), it still allows the execution of arbitrary code. This makes it a major security risk and therefore it must never be used on production machines.
Screenshot of the debugger in action:
Have another debugger in mind? See Working with Debuggers.
Modern web applications have beautiful URLs. This helps people remember the URLs, which is especially handy for applications that are used from mobile devices with slower network connections. If the user can directly go to the desired page without having to hit the index page it is more likely they will like the page and come back next time.
As you have seen above, the route() decorator is used to bind a function to a URL. Here are some basic examples:
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello World'
But there is more to it! You can make certain parts of the URL dynamic and attach multiple rules to a function.
To add variable parts to a URL you can mark these special sections as <variable_name>. Such a part is then passed as keyword argument to your function. Optionally a converter can be specified by specifying a rule with <converter:variable_name>. Here are some nice examples:
@app.route('/user/<username>')
def show_user_profile(username):
# show the user profile for that user
return 'User %s' % username
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
The following converters exist:
| int | accepts integers |
| float | like int but for floating point values |
| path | like the default but also accepts slashes |
Unique URLs / Redirection Behavior
Flask’s URL rules are based on Werkzeug’s routing module. The idea behind that module is to ensure beautiful and unique URLs based on precedents laid down by Apache and earlier HTTP servers.
Take these two rules:
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
Though they look rather similar, they differ in their use of the trailing slash in the URL definition. In the first case, the canonical URL for the projects endpoint has a trailing slash. In that sense, it is similar to a folder on a file system. Accessing it without a trailing slash will cause Flask to redirect to the canonical URL with the trailing slash.
In the second case, however, the URL is defined without a trailing slash, rather like the pathname of a file on UNIX-like systems. Accessing the URL with a trailing slash will produce a 404 “Not Found” error.
This behavior allows relative URLs to continue working if users access the page when they forget a trailing slash, consistent with how Apache and other servers work. Also, the URLs will stay unique, which helps search engines avoid indexing the same page twice.
If it can match URLs, can Flask also generate them? Of course it can. To build a URL to a specific function you can use the url_for() function. It accepts the name of the function as first argument and a number of keyword arguments, each corresponding to the variable part of the URL rule. Unknown variable parts are appended to the URL as query parameters. Here are some examples:
>>> from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route('/')
... def index(): pass
...
>>> @app.route('/login')
... def login(): pass
...
>>> @app.route('/user/<username>')
... def profile(username): pass
...
>>> with app.test_request_context():
... print url_for('index')
... print url_for('login')
... print url_for('login', next='/')
... print url_for('profile', username='John Doe')
...
/
/login
/login?next=/
/user/John%20Doe
(This also uses the test_request_context() method, explained below. It tells Flask to behave as though it is handling a request, even though we are interacting with it through a Python shell. Have a look at the explanation below. Context Locals).
Why would you want to build URLs instead of hard-coding them into your templates? There are three good reasons for this:
HTTP (the protocol web applications are speaking) knows different methods for accessing URLs. By default, a route only answers to GET requests, but that can be changed by providing the methods argument to the route() decorator. Here are some examples:
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
do_the_login()
else:
show_the_login_form()
If GET is present, HEAD will be added automatically for you. You don’t have to deal with that. It will also make sure that HEAD requests are handled as the HTTP RFC (the document describing the HTTP protocol) demands, so you can completely ignore that part of the HTTP specification. Likewise, as of Flask 0.6, OPTIONS is implemented for you automatically as well.
You have no idea what an HTTP method is? Worry not, here is a quick introduction to HTTP methods and why they matter:
The HTTP method (also often called “the verb”) tells the server what the clients wants to do with the requested page. The following methods are very common:
Now the interesting part is that in HTML4 and XHTML1, the only methods a form can submit to the server are GET and POST. But with JavaScript and future HTML standards you can use the other methods as well. Furthermore HTTP has become quite popular lately and browsers are no longer the only clients that are using HTTP. For instance, many revision control system use it.
Dynamic web applications also need static files. That’s usually where the CSS and JavaScript files are coming from. Ideally your web server is configured to serve them for you, but during development Flask can do that as well. Just create a folder called static in your package or next to your module and it will be available at /static on the application.
To generate URLs for static files, use the special 'static' endpoint name:
url_for('static', filename='style.css')
The file has to be stored on the filesystem as static/style.css.
Generating HTML from within Python is not fun, and actually pretty cumbersome because you have to do the HTML escaping on your own to keep the application secure. Because of that Flask configures the Jinja2 template engine for you automatically.
To render a template you can use the render_template() method. All you have to do is provide the name of the template and the variables you want to pass to the template engine as keyword arguments. Here’s a simple example of how to render a template:
from flask import render_template
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
Flask will look for templates in the templates folder. So if your application is a module, this folder is next to that module, if it’s a package it’s actually inside your package:
Case 1: a module:
/application.py
/templates
/hello.html
Case 2: a package:
/application
/__init__.py
/templates
/hello.html
For templates you can use the full power of Jinja2 templates. Head over to the official Jinja2 Template Documentation for more information.
Here is an example template:
<!doctype html>
<title>Hello from Flask</title>
{% if name %}

Hello {{ name }}!

{% else %}

Hello World!

{% endif %}
Inside templates you also have access to the request, session and g [1] objects as well as the get_flashed_messages() function.
Templates are especially useful if inheritance is used. If you want to know how that works, head over to the Template Inheritance pattern documentation. Basically template inheritance makes it possible to keep certain elements on each page (like header, navigation and footer).
Automatic escaping is enabled, so if name contains HTML it will be escaped automatically. If you can trust a variable and you know that it will be safe HTML (for example because it came from a module that converts wiki markup to HTML) you can mark it as safe by using the Markup class or by using the |safe filter in the template. Head over to the Jinja 2 documentation for more examples.
Here is a basic introduction to how the Markup class works:
>>> from flask import Markup
>>> Markup('Hello %s!') % '<blink>hacker</blink>'
Markup(u'Hello <blink>hacker</blink>!')
>>> Markup.escape('<blink>hacker</blink>')
Markup(u'<blink>hacker</blink>')
>>> Markup('Marked up » HTML').striptags()
u'Marked up \xbb HTML'
Changed in version 0.5.
| [1] | Unsure what that g object is? It’s something in which you can store information for your own needs, check the documentation of that object (g) and the Using SQLite 3 with Flask for more information. |
For web applications it’s crucial to react to the data a client sent to the server. In Flask this information is provided by the global request object. If you have some experience with Python you might be wondering how that object can be global and how Flask manages to still be threadsafe. The answer is context locals:
Insider Information
If you want to understand how that works and how you can implement tests with context locals, read this section, otherwise just skip it.
Certain objects in Flask are global objects, but not of the usual kind. These objects are actually proxies to objects that are local to a specific context. What a mouthful. But that is actually quite easy to understand.
Imagine the context being the handling thread. A request comes in and the web server decides to spawn a new thread (or something else, the underlying object is capable of dealing with concurrency systems other than threads). When Flask starts its internal request handling it figures out that the current thread is the active context and binds the current application and the WSGI environments to that context (thread). It does that in an intelligent way so that one application can invoke another application without breaking.
So what does this mean to you? Basically you can completely ignore that this is the case unless you are doing something like unit testing. You will notice that code which depends on a request object will suddenly break because there is no request object. The solution is creating a request object yourself and binding it to the context. The easiest solution for unit testing is to use the test_request_context() context manager. In combination with the with statement it will bind a test request so that you can interact with it. Here is an example:
from flask import request
with app.test_request_context('/hello', method='POST'):
# now you can do something with the request until the
# end of the with block, such as basic assertions:
assert request.path == '/hello'
assert request.method == 'POST'
The other possibility is passing a whole WSGI environment to the request_context() method:
from flask import request
with app.request_context(environ):
assert request.method == 'POST'
The request object is documented in the API section and we will not cover it here in detail (see request). Here is a broad overview of some of the most common operations. First of all you have to import it from the flask module:
from flask import request
The current request method is available by using the method attribute. To access form data (data transmitted in a POST or PUT request) you can use the form attribute. Here is a full example of the two attributes mentioned above:
@app.route('/login', methods=['POST', 'GET'])
def login():
error = None
if request.method == 'POST':
if valid_login(request.form['username'],
request.form['password']):
return log_the_user_in(request.form['username'])
else:
error = 'Invalid username/password'
# the code below this is executed if the request method
# was GET or the credentials were invalid
return render_template('login.html', error=error)
What happens if the key does not exist in the form attribute? In that case a special KeyError is raised. You can catch it like a standard KeyError but if you don’t do that, a HTTP 400 Bad Request error page is shown instead. So for many situations you don’t have to deal with that problem.
To access parameters submitted in the URL (?key=value) you can use the args attribute:
searchword = request.args.get('key', '')
We recommend accessing URL parameters with get or by catching the KeyError because users might change the URL and presenting them a 400 bad request page in that case is not user friendly.
For a full list of methods and attributes of the request object, head over to the request documentation.
You can handle uploaded files with Flask easily. Just make sure not to forget to set the enctype="multipart/form-data" attribute on your HTML form, otherwise the browser will not transmit your files at all.
Uploaded files are stored in memory or at a temporary location on the filesystem. You can access those files by looking at the files attribute on the request object. Each uploaded file is stored in that dictionary. It behaves just like a standard Python file object, but it also has a save() method that allows you to store that file on the filesystem of the server. Here is a simple example showing how that works:
from flask import request
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/uploaded_file.txt')
...
If you want to know how the file was named on the client before it was uploaded to your application, you can access the filename attribute. However please keep in mind that this value can be forged so never ever trust that value. If you want to use the filename of the client to store the file on the server, pass it through the secure_filename() function that Werkzeug provides for you:
from flask import request
from werkzeug import secure_filename
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/' + secure_filename(f.filename))
...
For some better examples, checkout the Uploading Files pattern.
To access cookies you can use the cookies attribute. To set cookies you can use the set_cookie method of response objects. The cookies attribute of request objects is a dictionary with all the cookies the client transmits. If you want to use sessions, do not use the cookies directly but instead use the Sessions in Flask that add some security on top of cookies for you.
Reading cookies:
from flask import request
@app.route('/')
def index():
username = request.cookies.get('username')
# use cookies.get(key) instead of cookies[key] to not get a
# KeyError if the cookie is missing.
Storing cookies:
from flask import make_response
@app.route('/')
def index():
resp = make_response(render_template(...))
resp.set_cookie('username', 'the username')
return resp
Note that cookies are set on response objects. Since you normally just return strings from the view functions Flask will convert them into response objects for you. If you explicitly want to do that you can use the make_response() function and then modify it.
Sometimes you might want to set a cookie at a point where the response object does not exist yet. This is possible by utilizing the Deferred Request Callbacks pattern.
For this also see About Responses.
To redirect a user to another endpoint, use the redirect() function; to abort a request early with an error code, use the abort() function:
from flask import abort, redirect, url_for
@app.route('/')
def index():
return redirect(url_for('login'))
@app.route('/login')
def login():
abort(401)
this_is_never_executed()
This is a rather pointless example because a user will be redirected from the index to a page they cannot access (401 means access denied) but it shows how that works.
By default a black and white error page is shown for each error code. If you want to customize the error page, you can use the errorhandler() decorator:
from flask import render_template
@app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'), 404
Note the 404 after the render_template() call. This tells Flask that the status code of that page should be 404 which means not found. By default 200 is assumed which translates to: all went well.
The return value from a view function is automatically converted into a response object for you. If the return value is a string it’s converted into a response object with the string as response body, an 200 OK error code and a text/html mimetype. The logic that Flask applies to converting return values into response objects is as follows:
If you want to get hold of the resulting response object inside the view you can use the make_response() function.
Imagine you have a view like this:
@app.errorhandler(404)
def not_found(error):
return render_template('error.html'), 404
You just need to wrap the return expression with make_response() and get the result object to modify it, then return it:
@app.errorhandler(404)
def not_found(error):
resp = make_response(render_template('error.html'), 404)
resp.headers['X-Something'] = 'A value'
return resp
In addition to the request object there is also a second object called session which allows you to store information specific to a user from one request to the next. This is implemented on top of cookies for you and signs the cookies cryptographically. What this means is that the user could look at the contents of your cookie but not modify it, unless they know the secret key used for signing.
In order to use sessions you have to set a secret key. Here is how sessions work:
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
@app.route('/')
def index():
if 'username' in session:
return 'Logged in as %s' % escape(session['username'])
return 'You are not logged in'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form action="" method="post">

<input type=text name=username>

<input type=submit value=Login>
</form>
'''
@app.route('/logout')
def logout():
# remove the username from the session if it's there
session.pop('username', None)
return redirect(url_for('index'))
# set the secret key. keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
The escape() mentioned here does escaping for you if you are not using the template engine (as in this example).
How to generate good secret keys
The problem with random is that it’s hard to judge what is truly random. And a secret key should be as random as possible. Your operating system has ways to generate pretty random stuff based on a cryptographic random generator which can be used to get such a key:
>>> import os
>>> os.urandom(24)
'\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'
Just take that thing and copy/paste it into your code and you’re done.
A note on cookie-based sessions: Flask will take the values you put into the session object and serialize them into a cookie. If you are finding some values do not persist across requests, cookies are indeed enabled, and you are not getting a clear error message, check the size of the cookie in your page responses compared to the size supported by web browsers.
Good applications and user interfaces are all about feedback. If the user does not get enough feedback they will probably end up hating the application. Flask provides a really simple way to give feedback to a user with the flashing system. The flashing system basically makes it possible to record a message at the end of a request and access it on the next (and only the next) request. This is usually combined with a layout template to expose the message.
To flash a message use the flash() method, to get hold of the messages you can use get_flashed_messages() which is also available in the templates. Check out the Message Flashing for a full example.
New in version 0.3.
Sometimes you might be in a situation where you deal with data that should be correct, but actually is not. For example you may have some client-side code that sends an HTTP request to the server but it’s obviously malformed. This might be caused by a user tampering with the data, or the client code failing. Most of the time it’s okay to reply with 400 Bad Request in that situation, but sometimes that won’t do and the code has to continue working.
You may still want to log that something fishy happened. This is where loggers come in handy. As of Flask 0.3 a logger is preconfigured for you to use.
Here are some example log calls:
app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')
The attached logger is a standard logging Logger, so head over to the official logging documentation for more information.
If you want to add a WSGI middleware to your application you can wrap the internal WSGI application. For example if you want to use one of the middlewares from the Werkzeug package to work around bugs in lighttpd, you can do it like this:
from werkzeug.contrib.fixers import LighttpdCGIRootFix
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)
Ready to deploy your new Flask app? To wrap up the quickstart, you can immediately deploy to a hosted platform, all of which offer a free plan for small projects:
Other places where you can host your Flask app:
If you manage your own hosts and would like to host yourself, see the chapter on Deployment Options.


{% extends "base.html" %} {% block title %}Quality metrics help – {{ super() }}{% endblock %} {% block content %}
EEA websites are audited daily and receive a score between 0 and 100 for each of the following metrics:
For more info please visit the quality metrics wiki page.


{% extends "layout.html" %} {% block body_class %}projects{% endblock %} {% block content %}
Is it a cat or dog?
Is it a hotdog or not hotdog?
Bitcoin quant trading model
What will a home cost?


|
SuperLU
5.3.0
|
Improves computed solution to a system of inear equations. More...
Macros | |
| #define | ITMAX 5 |
Functions | |
| void | zgsrfs (trans_t trans, SuperMatrix *A, SuperMatrix *L, SuperMatrix *U, int *perm_c, int *perm_r, char *equed, double *R, double *C, SuperMatrix *B, SuperMatrix *X, double *ferr, double *berr, SuperLUStat_t *stat, int *info) |
Copyright (c) 2003, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from U.S. Dept. of Energy)
All rights reserved.
The source code is distributed under BSD license, see the file License.txt at the top-level directory.
-- SuperLU routine (version 5.1) -- Univ. of California Berkeley, Xerox Palo Alto Research Center, and Lawrence Berkeley National Lab. October 15, 2003
Modified from lapack routine ZGERFS Last modified: December 3, 2015
| #define ITMAX 5 |
| void zgsrfs | ( | trans_t | trans, |
| SuperMatrix * | A, | ||
| SuperMatrix * | L, | ||
| SuperMatrix * | U, | ||
| int * | perm_c, | ||
| int * | perm_r, | ||
| char * | equed, | ||
| double * | R, | ||
| double * | C, | ||
| SuperMatrix * | B, | ||
| SuperMatrix * | X, | ||
| double * | ferr, | ||
| double * | berr, | ||
| SuperLUStat_t * | stat, | ||
| int * | info | ||
| ) |
Purpose =======
ZGSRFS improves the computed solution to a system of linear equations and provides error bounds and backward error estimates for the solution.
If equilibration was performed, the system becomes: (diag(R)*A_original*diag(C)) * X = diag(R)*B_original.
See supermatrix.h for the definition of 'SuperMatrix' structure.
Arguments =========
trans (input) trans_t Specifies the form of the system of equations: = NOTRANS: A * X = B (No transpose) = TRANS: A'* X = B (Transpose) = CONJ: A**H * X = B (Conjugate transpose)
A (input) SuperMatrix* The original matrix A in the system, or the scaled A if equilibration was done. The type of A can be: Stype = SLU_NC, Dtype = SLU_Z, Mtype = SLU_GE.
L (input) SuperMatrix* The factor L from the factorization Pr*A*Pc=L*U. Use compressed row subscripts storage for supernodes, i.e., L has types: Stype = SLU_SC, Dtype = SLU_Z, Mtype = SLU_TRLU.
U (input) SuperMatrix* The factor U from the factorization Pr*A*Pc=L*U as computed by zgstrf(). Use column-wise storage scheme, i.e., U has types: Stype = SLU_NC, Dtype = SLU_Z, Mtype = SLU_TRU.
perm_c (input) int*, dimension (A->ncol) Column permutation vector, which defines the permutation matrix Pc; perm_c[i] = j means column i of A is in position j in A*Pc.
perm_r (input) int*, dimension (A->nrow) Row permutation vector, which defines the permutation matrix Pr; perm_r[i] = j means row i of A is in position j in Pr*A.
equed (input) Specifies the form of equilibration that was done. = 'N': No equilibration. = 'R': Row equilibration, i.e., A was premultiplied by diag(R). = 'C': Column equilibration, i.e., A was postmultiplied by diag(C). = 'B': Both row and column equilibration, i.e., A was replaced by diag(R)*A*diag(C).
R (input) double*, dimension (A->nrow) The row scale factors for A. If equed = 'R' or 'B', A is premultiplied by diag(R). If equed = 'N' or 'C', R is not accessed.
C (input) double*, dimension (A->ncol) The column scale factors for A. If equed = 'C' or 'B', A is postmultiplied by diag(C). If equed = 'N' or 'R', C is not accessed.
B (input) SuperMatrix* B has types: Stype = SLU_DN, Dtype = SLU_Z, Mtype = SLU_GE. The right hand side matrix B. if equed = 'R' or 'B', B is premultiplied by diag(R).
X (input/output) SuperMatrix* X has types: Stype = SLU_DN, Dtype = SLU_Z, Mtype = SLU_GE. On entry, the solution matrix X, as computed by zgstrs(). On exit, the improved solution matrix X. if *equed = 'C' or 'B', X should be premultiplied by diag(C) in order to obtain the solution to the original system.
FERR (output) double*, dimension (B->ncol) The estimated forward error bound for each solution vector X(j) (the j-th column of the solution matrix X). If XTRUE is the true solution corresponding to X(j), FERR(j) is an estimated upper bound for the magnitude of the largest element in (X(j) - XTRUE) divided by the magnitude of the largest element in X(j). The estimate is as reliable as the estimate for RCOND, and is almost always a slight overestimate of the true error.
BERR (output) double*, dimension (B->ncol) The componentwise relative backward error of each solution vector X(j) (i.e., the smallest relative change in any element of A or B that makes X(j) an exact solution).
stat (output) SuperLUStat_t* Record the statistics on runtime and floating-point operation count. See util.h for the definition of 'SuperLUStat_t'.
info (output) int* = 0: successful exit < 0: if INFO = -i, the i-th argument had an illegal value
Internal Parameters ===================
ITMAX is the maximum number of steps of iterative refinement.


|
Cannon Cpp
1.0.0
|
Axis aligned uniform grid broadphase. More...
#include <GridBroadphase.h>
Public Member Functions | |
| void | collisionPairs (World *world, std::vector< Body * > &pairs1, std::vector< Body * > &pairs2) override |
| Get the collision pairs from the world. More... | |
| void | aabbQuery (World *world, const AABB &aabb, std::vector< Body * > &result) override |
| Returns all the bodies within the AABB. More... | |
| void | setWorld (World *world) override |
| Set the physics world. More... | |
| Public Member Functions inherited from Broadphase | |
| bool | needBroadphaseCollision (Body *bodyA, Body *bodyB) |
| Check if a body pair needs to be intersection tested at all. More... | |
| void | intersectionTest (Body *bodyA, Body *bodyB, std::vector< Body * > &pairs1, std::vector< Body * > &pairs2) |
| Check if the bounding volumes of two bodies intersect. More... | |
| void | makePairsUnique (std::vector< Body * > &pairs1, std::vector< Body * > &pairs2) |
| Removes duplicate pairs from the pair arrays. More... | |
| bool | dirty () const |
| void | setDirty (bool value) |
| Public Member Functions inherited from Ref | |
| Ref () | |
| void | retain () |
| Retain a reference, _referenceCount add one. More... | |
| void | release () |
| Release a reference, _referenceCount minus one. More... | |
| int | getReferenceCount () const |
| Get the reference count of this object. More... | |
Static Public Member Functions | |
| static GridBroadphase * | create (Vec3 aabbMin=Vec3(100, 100, 100), Vec3 aabbMax=Vec3(-100,-100,-100), int nx=10, int ny=10, int nz=10) |
| The create function of GridBroadphase. More... | |
Protected Member Functions | |
| GridBroadphase () | |
| The constructor of GridBroadphase. More... | |
| ~GridBroadphase () | |
| virtual bool | init (Vec3 aabbMin=Vec3(100, 100, 100), Vec3 aabbMax=Vec3(-100,-100,-100), int nx=10, int ny=10, int nz=10) |
| Protected Member Functions inherited from Broadphase | |
| void | doBoundingSphereBroadphase (Body *bodyA, Body *bodyB, std::vector< Body * > &pairs1, std::vector< Body * > &pairs2) |
| Check if the bounding spheres of two bodies are intersecting. More... | |
| void | doBoundingBoxBroadphase (Body *bodyA, Body *bodyB, std::vector< Body * > &pairs1, std::vector< Body * > &pairs2) |
| Check if the bounding boxes of two bodies are intersecting. More... | |
| Broadphase () | |
| The constructor. More... | |
| virtual | ~Broadphase () |
| virtual bool | init () |
| Protected Member Functions inherited from Ref | |
| virtual | ~Ref () |
Protected Attributes | |
| Vec3 | _aabbMin = Vec3::ZERO |
| Vec3 | _aabbMax = Vec3::ZERO |
| std::vector< std::vector< Body * > > | _bins |
| std::vector< int > | _binLengths |
| int | _nx = 10 |
| int | _ny = 10 |
| int | _nz = 10 |
| Protected Attributes inherited from Broadphase | |
| World * | _world = nullptr |
| The world to search for collisions in. More... | |
| bool | _useBoundingBoxes = false |
| If set to true, the broadphase uses bounding boxes for intersection test, else it uses bounding spheres. More... | |
| bool | _dirty = true |
| Set to true if the objects in the world moved. More... | |
| Protected Attributes inherited from Ref | |
| int | _referenceCount = 0 |
| count of references More... | |
Axis aligned uniform grid broadphase.
|
protected |
The constructor of GridBroadphase.
|
protected |
|
overridevirtual |
Returns all the bodies within the AABB.
| world | The physics world |
| aabb | The AABB |
| result | An array to store resulting bodies in. |
Reimplemented from Broadphase.
|
overridevirtual |
Get the collision pairs from the world.
| world | The world to search in |
| pairs1 | Empty array to be filled with body objects |
| pairs2 | Empty array to be filled with body objects |
Reimplemented from Broadphase.
|
static |
The create function of GridBroadphase.
|
protectedvirtual |
|
inlineoverridevirtual |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |
|
protected |


pxtextmineR-vignette.Rmd
Welcome to pxtextmineR
’s vignette!
Package pxtextmineR
is an R wrapper for Python’s pxtextmining
library- a pipeline to classify text-based patient experience data. The pipeline uses the state-of-the-art Machine Learning Python library Scikit-learn
(Pedregosa et al., 2011), which offers numerous top-notch models and methods for text classification.
The installation instructions are here. Make sure to take a look at this bit too!
The pipeline consists of four factory_*
functions that implement different stages to build the pipeline:
factory_data_load_and_split_r
splits the data into training and test sets.factory_pipeline_r
prepares and fits a text classification pipeline.factory_model_performance_r
evaluates the performance of a fitted pipeline.factory_predict_unlabelled_text_r
predicts unlabelled text using the fitted pipeline.Function text_classification_pipeline_r
conveniently brings together the first three of the aforementioned factories.
Let’s see how to split data into training and test sets with pxtextmineR
. We will use the package’s dataset text_data
, which is an open dataset with patient feedback text from different NHS (National Health Service) trusts in England, UK.
# Prepare training and test sets
data_splits <- pxtextmineR::factory_data_load_and_split_r(
filename = pxtextmineR::text_data,
target = "label",
predictor = "feedback",
test_size = 0.90) # Make a small training set for a faster run in this example
# Let's take a look at the returned list
str(data_splits)
#> List of 6
#> $ x_train :'data.frame': 1033 obs. of 1 variable:
#> ..$ predictor: chr [1:1033] "Everything, cannot be better. Thank you. " "Super nurses and doctors" "Ward is fantastic. Staff very welcoming and friendly and lays willing to help nothing is ever to much for them." "Bays are too cold, especially at night." ...
#> ..- attr(*, "pandas.index")=Int64Index([ 1521, 7492, 7862, 8066, 790, 10004, 3828, 2899, 1947,
#> 1220,
#> ...
#> 3490, 7788, 2980, 6742, 6705, 3124, 6197, 40, 6643,
#> 6298],
#> dtype='int64', length=1033)
#> $ x_test :'data.frame': 9301 obs. of 1 variable:
#> ..$ predictor: chr [1:9301] "Great all round." "Seeing people get discharged. Supportive and understanding team. Activities on ward." "Huge thank you to Dr Croft and Dr Bohane (sorry if I spelt that wrong). Who have supported my family and I to g"| __truncated__ "The lady who treated me was kind, poilite & courteous" ...
#> ..- attr(*, "pandas.index")=Int64Index([8413, 1865, 1800, 1693, 1904, 7018, 634, 2463, 4823, 3286,
#> ...
#> 4659, 6728, 6477, 7705, 4088, 3552, 725, 2522, 153, 5746],
#> dtype='int64', length=9301)
#> $ y_train : chr [1:1033(1d)] "Miscellaneous" "Staff" "Care received" "Environment/ facilities" ...
#> ..- attr(*, "dimnames")=List of 1
#> .. ..$ : chr [1:1033] "1521" "7492" "7862" "8066" ...
#> $ y_test : chr [1:9301(1d)] "Care received" "Care received" "Staff" "Staff" ...
#> ..- attr(*, "dimnames")=List of 1
#> .. ..$ : chr [1:9301] "8413" "1865" "1800" "1693" ...
#> $ index_training_data: int [1:1033] 1521 7492 7862 8066 790 10004 3828 2899 1947 1220 ...
#> $ index_test_data : int [1:9301] 8413 1865 1800 1693 1904 7018 634 2463 4823 3286 ...
From the printed results we note the following:
Objects x_train
and x_test
contain the predictor with the feedback text, and are data frames. The text column is internally renamed to “predictor”. This is to ensure that the pipeline will not break if the user supplies a dataset with a different name for the text column.
Objects y_train
and y_test
contain the response variable and are 1D arrays.
When Scikit-learn
splits the data, it assigns index values to the them. This is convenient for knowing which of the data records belong to the training set and which to the test set. The indices are available in objects index_training_data
and index_test_data
, but are also conveniently available as (row) names in objects x_train/test
and y_train/test
:
# Each record in the split data is tagged with the row index of the original dataset
head(rownames(data_splits$x_train))
#> [1] "1521" "7492" "7862" "8066" "790" "10004"
head(names(data_splits$y_train))
#> [1] "1521" "7492" "7862" "8066" "790" "10004"
# Note that, in Python, indices start from 0 and go up to number_of_records - 1
all_indices <- data_splits$y_train %>%
names() %>%
c(names(data_splits$y_test)) %>%
as.numeric() %>%
sort()
head(all_indices) # Starts from zero
#> [1] 0 1 2 3 4 5
tail(all_indices) # Ends in nrow(text_data) - 1
#> [1] 10328 10329 10330 10331 10332 10333
length(all_indices) == nrow(text_data)
#> [1] TRUE
Function factory_pipeline_r
can do standard or ordinal classification of text data, with a range of models that perform well in text classification settings (logistic regression, Support Vector Machines, Naive Bayes models, Random Forest). Logistic regression and linear support vector classification are implemented with sklearn.linear_model.SGDClassifier
, which employs the former model using “log” loss and the latter using “hinge” loss (see the User Guide). Both types of loss are set internally in the tuning grid of the pipeline.
The pipeline tries both Bag-of-Words (BoW) and word vectors. Both options are internally set as tunable parameters. For BoW, the default tokenizer is spaCy
, although the option if NLTK
is also available. At the time of development we were experimenting as to which would result in faster and better results. With our data (pxtextmineR::text_data
), spaCy
does a better job, faster. Generally, although we have kept the option of NLTK
, you are probably better off with spaCy
.
Most tunable (hyper)parameters are set internally and cannot be changed by the user. We did this for a very practical reason: you can spend hours if not days trying out more values in the search grid that minimally increase the performance of the pipeline (e.g. from 75% accuracy to 76%). We therefore opted for value ranges that are observed to work well in practice. In any case, if you are expert in a particular model and believe that changing one or more of these values would improve the pipeline, you are more than welcome to make a pull request!
Finally, the best (hyper)parameter values for the pipeline during training with cross-validation (CV) can be determined with a range of metrics, from the standard accuracy score to a few metrics that account for class imbalances. See the documentation.
Let’s fit the pipeline! We will try two classifiers, namely SGDClassifier
and sklearn.naive_bayes.MultinomialNB
, with a two-fold CV and 10 iterations, resulting in 2 X 10 = 20 fits. As mentioned earlier, SGDClassifier
can be either logistic regression or linear SVC. Let’s see which one will win!
(NOTE: If your machine does not have the number of cores specified in n_jobs
, then an error will be returned. For error-free experimentation, try with n_jobs = 1
.)
pipe <- pxtextmineR::factory_pipeline_r(
x = data_splits$x_train,
y = data_splits$y_train,
tknz = "spacy",
ordinal = FALSE,
metric = "accuracy_score",
cv = 2, n_iter = 10, n_jobs = 1, verbose = 3,
learners = c("SGDClassifier", "MultinomialNB")
)
# Mean cross-validated score of the best_estimator
pipe$best_score_
#> [1] 0.5507999
# Best parameters during tuning
pipe$best_params_
#> $sampling__kw_args
#> $sampling__kw_args$up_balancing_counts
#> [1] 800
#>
#>
#> $preprocessor__texttr__text__transformer__use_idf
#> [1] TRUE
#>
#> $preprocessor__texttr__text__transformer__tokenizer
#> <pxtextmining.helpers.tokenization.LemmaTokenizer>
#>
#> $preprocessor__texttr__text__transformer__preprocessor
#> <function text_preprocessor at 0x00000000664484C0>
#>
#> $preprocessor__texttr__text__transformer__norm
#> [1] "l2"
#>
#> $preprocessor__texttr__text__transformer__ngram_range
#> $preprocessor__texttr__text__transformer__ngram_range[[1]]
#> [1] 1
#>
#> $preprocessor__texttr__text__transformer__ngram_range[[2]]
#> [1] 3
#>
#>
#> $preprocessor__texttr__text__transformer__min_df
#> [1] 1
#>
#> $preprocessor__texttr__text__transformer__max_df
#> [1] 0.95
#>
#> $preprocessor__texttr__text__transformer
#> TfidfVectorizer(max_df=0.95, ngram_range=(1, 3),
#> preprocessor=<function text_preprocessor at 0x00000000664484C0>,
#> tokenizer=<pxtextmining.helpers.tokenization.LemmaTokenizer>)
#>
#> $preprocessor__sentimenttr__scaler__scaler__n_bins
#> [1] 4
#>
#> $preprocessor__sentimenttr__scaler__scaler
#> KBinsDiscretizer(n_bins=4, strategy='kmeans')
#>
#> $preprocessor__lengthtr__scaler__scaler
#> KBinsDiscretizer(n_bins=3, strategy='kmeans')
#>
#> $featsel__selector__score_func
#> <function chi2 at 0x000000006642F5E0>
#>
#> $featsel__selector__percentile
#> [1] 70
#>
#> $featsel__selector
#> SelectPercentile(percentile=70,
#> score_func=<function chi2 at 0x000000006642F5E0>)
#>
#> $clf__estimator__penalty
#> [1] "elasticnet"
#>
#> $clf__estimator__max_iter
#> [1] 10000
#>
#> $clf__estimator__loss
#> [1] "log"
#>
#> $clf__estimator__class_weight
#> NULL
#>
#> $clf__estimator
#> SGDClassifier(loss='log', max_iter=10000, penalty='elasticnet')
# Make predictions
preds <- pipe$predict(data_splits$x_test)
head(preds)
#> [1] "Care received" "Staff" "Access"
#> [4] "Staff" "Access" "Couldn't be improved"
# Performance on test set #
# Can be done using the pipe's score() method
pipe$score(data_splits$x_test, data_splits$y_test)
#> [1] 0.5317708
# Or using dplyr
data_splits$y_test %>%
data.frame() %>%
dplyr::rename(true = '.') %>%
dplyr::mutate(
pred = preds,
check = true == preds,
check = sum(check) / nrow(.)
) %>%
dplyr::pull(check) %>%
unique
#> [1] 0.5317708
# We can also use other metrics, such as the Class Balance Accuracy score
pxtextmineR::class_balance_accuracy_score_r(
data_splits$y_test,
preds
)
#> [1] 0.3534209
Let’s pass our fitted pipeline pipe
to factory_model_performance_r
to evaluate how well it did.
# Assess model performance
pipe_performance <- pxtextmineR::factory_model_performance_r(
pipe = pipe,
x_train = data_splits$x_train,
y_train = data_splits$y_train,
x_test = data_splits$x_test,
y_test = data_splits$y_test,
metric = "accuracy_score")
names(pipe_performance)
#> [1] "pipe" "tuning_results" "pred"
#> [4] "accuracy_per_class" "p_compare_models_bar"
# Let's compare pipeline performance for different tunings with a range of
# metrics averaging the cross-validation metrics for each fold.
pipe_performance$
tuning_results %>%
dplyr::select(learner, dplyr::contains("mean_test"))
#> learner mean_test_Accuracy mean_test_Balanced Accuracy
#> 8 Logistic 0.5507999 0.3391156
#> 4 Linear SVM 0.4801760 0.2670942
#> 7 MultinomialNB 0.4743545 0.3213362
#> 6 Logistic 0.4617632 0.2859347
#> 3 Linear SVM 0.4540169 0.2600976
#> 1 Linear SVM 0.4520771 0.2447616
#> 9 Linear SVM 0.4443326 0.2197800
#> 2 Logistic 0.4288756 0.2125337
#> 0 Linear SVM 0.3969495 0.2029141
#> 5 Logistic 0.3824239 0.2103374
#> mean_test_Matthews Correlation Coefficient mean_test_Class Balance Accuracy
#> 8 0.4250879 0.3068169
#> 4 0.3210595 0.2338451
#> 7 0.3436740 0.2647703
#> 6 0.3174870 0.2520342
#> 3 0.2860687 0.2188777
#> 1 0.2846360 0.1963320
#> 9 0.2589440 0.1768461
#> 2 0.2461072 0.1659125
#> 0 0.2249788 0.1743526
#> 5 0.2182756 0.1740442
# A glance at the (hyper)parameters and their tuned values
pipe_performance$
tuning_results %>%
dplyr::select(learner, dplyr::contains("param_")) %>%
str()
#> 'data.frame': 10 obs. of 22 variables:
#> $ learner : chr "Logistic" "Linear SVM" "MultinomialNB" "Logistic" ...
#> $ param_sampling__kw_args : chr "{'up_balancing_counts': 800}" "{'up_balancing_counts': 800}" "{'up_balancing_counts': 300}" "{'up_balancing_counts': 800}" ...
#> $ param_preprocessor__texttr__text__transformer__use_idf :List of 10
#> ..$ : logi TRUE
#> ..$ : logi FALSE
#> ..$ : logi FALSE
#> ..$ : logi FALSE
#> ..$ : logi FALSE
#> ..$ : logi TRUE
#> ..$ : logi FALSE
#> ..$ : logi FALSE
#> ..$ : logi FALSE
#> ..$ : logi FALSE
#> $ param_preprocessor__texttr__text__transformer__tokenizer : chr "<pxtextmining.helpers.tokenization.LemmaTokenizer object at 0x00000000659CE760>" "<pxtextmining.helpers.tokenization.LemmaTokenizer object at 0x00000000659CE760>" "<pxtextmining.helpers.tokenization.LemmaTokenizer object at 0x0000000065C791C0>" "<pxtextmining.helpers.tokenization.LemmaTokenizer object at 0x00000000659CE760>" ...
#> $ param_preprocessor__texttr__text__transformer__preprocessor: chr "<function text_preprocessor at 0x00000000664484C0>" "<function text_preprocessor at 0x00000000664484C0>" "<function text_preprocessor at 0x00000000664484C0>" "<function text_preprocessor at 0x00000000664484C0>" ...
#> $ param_preprocessor__texttr__text__transformer__norm :List of 10
#> ..$ : chr "l2"
#> ..$ : chr "l2"
#> ..$ : chr "l2"
#> ..$ : chr "l2"
#> ..$ : chr "l2"
#> ..$ : chr "l2"
#> ..$ : NULL
#> ..$ : NULL
#> ..$ : chr "l2"
#> ..$ : chr "l2"
#> $ param_preprocessor__texttr__text__transformer__ngram_range : chr "(1, 3)" "(2, 3)" "(1, 3)" "(2, 3)" ...
#> $ param_preprocessor__texttr__text__transformer__min_df :List of 10
#> ..$ : int 1
#> ..$ : int 3
#> ..$ : int 1
#> ..$ : int 1
#> ..$ : int 3
#> ..$ : int 1
#> ..$ : int 3
#> ..$ : int 3
#> ..$ : int 1
#> ..$ : int 3
#> $ param_preprocessor__texttr__text__transformer__max_df :List of 10
#> ..$ : num 0.95
#> ..$ : num 0.7
#> ..$ : num 0.7
#> ..$ : num 0.7
#> ..$ : num 0.7
#> ..$ : num 0.7
#> ..$ : num 0.95
#> ..$ : num 0.7
#> ..$ : num 0.7
#> ..$ : num 0.7
#> $ param_preprocessor__texttr__text__transformer : chr "TfidfVectorizer(max_df=0.95, ngram_range=(1, 3),\n preprocessor=<function text_preprocessor at 0"| __truncated__ "TfidfVectorizer(max_df=0.95, ngram_range=(1, 3),\n preprocessor=<function text_preprocessor at 0"| __truncated__ "TfidfVectorizer()" "TfidfVectorizer(max_df=0.95, ngram_range=(1, 3),\n preprocessor=<function text_preprocessor at 0"| __truncated__ ...
#> $ param_preprocessor__sentimenttr__scaler__scaler__n_bins :List of 10
#> ..$ : int 4
#> ..$ : int 8
#> ..$ : int 8
#> ..$ : int 8
#> ..$ : int 4
#> ..$ : int 4
#> ..$ : int 8
#> ..$ : int 8
#> ..$ : int 8
#> ..$ : int 4
#> $ param_preprocessor__sentimenttr__scaler__scaler : chr "KBinsDiscretizer(n_bins=4, strategy='kmeans')" "KBinsDiscretizer(n_bins=4, strategy='kmeans')" "KBinsDiscretizer(strategy='kmeans')" "KBinsDiscretizer(n_bins=4, strategy='kmeans')" ...
#> $ param_preprocessor__lengthtr__scaler__scaler : chr "KBinsDiscretizer(n_bins=3, strategy='kmeans')" "KBinsDiscretizer(n_bins=3, strategy='kmeans')" "KBinsDiscretizer(n_bins=3, strategy='kmeans')" "KBinsDiscretizer(n_bins=3, strategy='kmeans')" ...
#> $ param_featsel__selector__score_func : chr "<function chi2 at 0x000000006642F5E0>" "<function chi2 at 0x000000006642F5E0>" "<function chi2 at 0x000000006642F5E0>" "<function chi2 at 0x000000006642F5E0>" ...
#> $ param_featsel__selector__percentile :List of 10
#> ..$ : int 70
#> ..$ : int 85
#> ..$ : int 70
#> ..$ : int 100
#> ..$ : int 70
#> ..$ : int 100
#> ..$ : int 70
#> ..$ : int 85
#> ..$ : int 70
#> ..$ : int 85
#> $ param_featsel__selector : chr "SelectPercentile(percentile=70,\n score_func=<function chi2 at 0x000000006642F5E0>)" "SelectPercentile(percentile=70,\n score_func=<function chi2 at 0x000000006642F5E0>)" "SelectPercentile(percentile=70,\n score_func=<function chi2 at 0x000000006642F5E0>)" "SelectPercentile(percentile=70,\n score_func=<function chi2 at 0x000000006642F5E0>)" ...
#> $ param_clf__estimator__penalty :List of 10
#> ..$ : chr "elasticnet"
#> ..$ : chr "l2"
#> ..$ : num NaN
#> ..$ : chr "l2"
#> ..$ : chr "l2"
#> ..$ : chr "l2"
#> ..$ : chr "elasticnet"
#> ..$ : chr "l2"
#> ..$ : chr "l2"
#> ..$ : chr "elasticnet"
#> $ param_clf__estimator__max_iter :List of 10
#> ..$ : int 10000
#> ..$ : int 10000
#> ..$ : num NaN
#> ..$ : int 10000
#> ..$ : int 10000
#> ..$ : int 10000
#> ..$ : int 10000
#> ..$ : int 10000
#> ..$ : int 10000
#> ..$ : int 10000
#> $ param_clf__estimator__loss :List of 10
#> ..$ : chr "log"
#> ..$ : chr "hinge"
#> ..$ : num NaN
#> ..$ : chr "log"
#> ..$ : chr "hinge"
#> ..$ : chr "hinge"
#> ..$ : chr "hinge"
#> ..$ : chr "log"
#> ..$ : chr "hinge"
#> ..$ : chr "log"
#> $ param_clf__estimator__class_weight : chr "None" "balanced" "nan" "balanced" ...
#> $ param_clf__estimator : chr "SGDClassifier(loss='log', max_iter=10000, penalty='elasticnet')" "SGDClassifier(loss='log', max_iter=10000, penalty='elasticnet')" "MultinomialNB()" "SGDClassifier(loss='log', max_iter=10000, penalty='elasticnet')" ...
#> $ param_clf__estimator__alpha :List of 10
#> ..$ : num NaN
#> ..$ : num NaN
#> ..$ : num 0.5
#> ..$ : num NaN
#> ..$ : num NaN
#> ..$ : num NaN
#> ..$ : num NaN
#> ..$ : num NaN
#> ..$ : num NaN
#> ..$ : num NaN
#> - attr(*, "pandas.index")=Int64Index([8, 4, 7, 6, 3, 1, 9, 2, 0, 5], dtype='int64')
The following bar plot reports the performance of the best of each fitted classifier with four different metrics. Thus, if, say, two classifiers were tried out, e.g. Multinomial Naive Bayes and Random Forest, and each one was fit with, say, 10 different tunings, the bar plot would plot the best of the Multinomial Naive Bayes and the best of the Random Forest models; the “best” being defined here according to the specified metric
argument that was used to fit the pipeline (see factory_pipeline_r
and factory_model_performance_r
). The models are ordered in descending order, from left to right, according to the specified metric.
# Learner performance barplot
pipe_performance$p_compare_models_bar
Remember that we tried three models: Logistic regression (SGDClassifier
with “log” loss), linear SVM (SGDClassifier
with “hinge” loss) and MultinomialNB
. Do not be surprised if one of these models does not show on the plot. There are numerous values for the different (hyper)parameters (recall, most of which are set internally) and only n_iter = 10
iterations in this example. As with factory_pipeline_r
the choice of which (hyper)parameter values to try out is random, one or more classifiers may not be chosen. Increasing n_iter
to a larger number would avoid this, at the expense of longer fitting times (but with a possibly more accurate pipeline).
# Predictions on test set
preds <- pipe_performance$pred
head(preds)
#> [1] "Care received" "Care received" "Access"
#> [4] "Staff" "Care received" "Couldn't be improved"
################################################################################
# NOTE!!! #
################################################################################
# After calculating performance metrics on the test set,
# pxtextmineR::factory_model_performance_r fits the pipeline on the WHOLE
# dataset (train + test). Hence, do not be surprised that the pipeline's
# score() method will now return a dramatically improved score on the test
# set- the refitted pipeline has now "seen" the test dataset.
pipe_performance$pipe$score(data_splits$x_test, data_splits$y_test)
#> [1] 0.7208902
pipe$score(data_splits$x_test, data_splits$y_test)
#> [1] 0.7208902
# We can confirm this score by having the re-fitted pipeline predict x_test
# again. The predictions will be better and the new accuracy score will be
# the inflated one.
preds_refitted <- pipe$predict(data_splits$x_test)
score_refitted <- data_splits$y_test %>%
data.frame() %>%
dplyr::rename(true = '.') %>%
dplyr::mutate(
pred = preds_refitted,
check = true == preds_refitted,
check = sum(check) / nrow(.)
) %>%
dplyr::pull(check) %>%
unique()
score_refitted
#> [1] 0.7208902
# Compare this to the ACTUAL performance on the test dataset
preds_actual <- pipe_performance$pred
score_actual <- data_splits$y_test %>%
data.frame() %>%
dplyr::rename(true = '.') %>%
dplyr::mutate(
pred = preds_actual,
check = true == preds_actual,
check = sum(check) / nrow(.)
) %>%
dplyr::pull(check) %>%
unique()
score_actual
#> [1] 0.5554241
score_refitted - score_actual
#> [1] 0.1654661
This is where factory_predict_unlabelled_text_r
comes in handy.
# Make predictions #
# Return data frame with predictions column and all original columns from
# the supplied data frame
preds_all_cols <- pxtextmineR::factory_predict_unlabelled_text_r(
dataset = pxtextmineR::text_data,
predictor = "feedback",
pipe_path_or_object = pipe,
column_names = "all_cols")
str(preds_all_cols)
#> 'data.frame': 10334 obs. of 4 variables:
#> $ feedback_preds: chr "Couldn't be improved" "Care received" "Care received" "Care received" ...
#> $ label : chr "Couldn't be improved" "Environment/ facilities" "Access" "Communication" ...
#> $ criticality : chr "3" "-1" "-2" "-1" ...
#> $ feedback : chr "Nothing." "Temperature in theatre a little low." "Same service available at Bingham Health Centre." "Appointment details given over phone - no physical evidence/reminder which could cause problems. Other than tha"| __truncated__ ...
#> - attr(*, "pandas.index")=RangeIndex(start=0, stop=10334, step=1)
# Return data frame with predictions column only
preds_preds_only <- pxtextmineR::factory_predict_unlabelled_text_r(
dataset = pxtextmineR::text_data,
predictor = "feedback",
pipe_path_or_object = pipe,
column_names = "preds_only")
head(preds_preds_only)
#> feedback_preds
#> 1 Couldn't be improved
#> 2 Care received
#> 3 Care received
#> 4 Care received
#> 5 Care received
#> 6 Transition/coordination
# Return data frame with predictions column and columns label and feedback from
# the supplied data frame
preds_label_text <- pxtextmineR::factory_predict_unlabelled_text_r(
dataset = pxtextmineR::text_data,
predictor = "feedback",
pipe_path_or_object = pipe,
column_names = c("label", "feedback"))
str(preds_label_text)
#> 'data.frame': 10334 obs. of 3 variables:
#> $ feedback_preds: chr "Couldn't be improved" "Care received" "Care received" "Care received" ...
#> $ label : chr "Couldn't be improved" "Environment/ facilities" "Access" "Communication" ...
#> $ feedback : chr "Nothing." "Temperature in theatre a little low." "Same service available at Bingham Health Centre." "Appointment details given over phone - no physical evidence/reminder which could cause problems. Other than tha"| __truncated__ ...
#> - attr(*, "pandas.index")=RangeIndex(start=0, stop=10334, step=1)
# Return data frame with the predictions column name supplied by the user
preds_custom_preds_name <- pxtextmineR::factory_predict_unlabelled_text_r(
dataset = pxtextmineR::text_data,
predictor = "feedback",
pipe_path_or_object = pipe,
column_names = "preds_only",
preds_column = "predictions")
head(preds_custom_preds_name)
#> predictions
#> 1 Couldn't be improved
#> 2 Care received
#> 3 Care received
#> 4 Care received
#> 5 Care received
#> 6 Transition/coordination
Function text_classification_pipeline_r
conveniently runs factory_data_load_and_split_r
, factory_pipeline_r
and factory_model_performance_r
in one go.
# We can prepare the data, build and fit the pipeline, and get performance
# metrics, in two ways. One way is to run the factory_* functions independently
# The commented out script right below would do exactly that.
# Prepare training and test sets
# data_splits <- pxtextmineR::factory_data_load_and_split_r(
# filename = pxtextmineR::text_data,
# target = "label",
# predictor = "feedback",
# test_size = 0.90) # Make a small training set for a faster run in this example
#
# # Fit the pipeline
# pipe <- pxtextmineR::factory_pipeline_r(
# x = data_splits$x_train,
# y = data_splits$y_train,
# tknz = "spacy",
# ordinal = FALSE,
# metric = "accuracy_score",
# cv = 2, n_iter = 10, n_jobs = 1, verbose = 3,
# learners = c("SGDClassifier", "MultinomialNB")
# )
#
# # Assess model performance
# pipe_performance <- pxtextmineR::factory_model_performance_r(
# pipe = pipe,
# x_train = data_splits$x_train,
# y_train = data_splits$y_train,
# x_test = data_splits$x_test,
# y_test = data_splits$y_test,
# metric = "class_balance_accuracy_score")
# Alternatively, we can use text_classification_pipeline_r() to do everything in
# one go.
text_pipe <- pxtextmineR::text_classification_pipeline_r(
filename = pxtextmineR::text_data,
target = 'label',
predictor = 'feedback',
test_size = 0.33,
ordinal = FALSE,
tknz = "spacy",
metric = "class_balance_accuracy_score",
cv = 2, n_iter = 10, n_jobs = 1, verbose = 3,
learners = c("SGDClassifier", "MultinomialNB"),
reduce_criticality = FALSE,
theme = NULL
)
names(text_pipe)
#> [1] "pipe" "tuning_results" "pred"
#> [4] "accuracy_per_class" "p_compare_models_bar" "index_training_data"
#> [7] "index_test_data"
# Let's compare pipeline performance for different tunings with a range of
# metrics averaging the cross-validation metrics for each fold.
text_pipe$
tuning_results %>%
dplyr::select(learner, dplyr::contains("mean_test"))
#> learner mean_test_Accuracy mean_test_Balanced Accuracy
#> 1 Linear SVM 0.6526066 0.4570045
#> 5 Linear SVM 0.6003183 0.3754105
#> 8 Linear SVM 0.5766278 0.3624667
#> 2 MultinomialNB 0.5636296 0.3382470
#> 9 Logistic 0.4805714 0.3197915
#> 6 Logistic 0.5093159 0.2907475
#> 7 Linear SVM 0.4730608 0.2918243
#> 0 Linear SVM 0.5020944 0.2796527
#> 3 MultinomialNB 0.5423962 0.2567648
#> 4 MultinomialNB 0.5174073 0.2223761
#> mean_test_Matthews Correlation Coefficient mean_test_Class Balance Accuracy
#> 1 0.5465140 0.4235396
#> 5 0.4738895 0.3404655
#> 8 0.4446102 0.3167579
#> 2 0.4299264 0.3005711
#> 9 0.3330483 0.2716780
#> 6 0.3548452 0.2401257
#> 7 0.3200443 0.2387569
#> 0 0.3441047 0.2279749
#> 3 0.3882195 0.2005050
#> 4 0.3664081 0.1622427
# A glance at the (hyper)parameters and their tuned values
text_pipe$
tuning_results %>%
dplyr::select(learner, dplyr::contains("param_")) %>%
str()
#> 'data.frame': 10 obs. of 22 variables:
#> $ learner : chr "Linear SVM" "Linear SVM" "Linear SVM" "MultinomialNB" ...
#> $ param_sampling__kw_args : chr "{'up_balancing_counts': 800}" "{'up_balancing_counts': 300}" "{'up_balancing_counts': 300}" "{'up_balancing_counts': 300}" ...
#> $ param_preprocessor__texttr__text__transformer__use_idf :List of 10
#> ..$ : logi FALSE
#> ..$ : logi TRUE
#> ..$ : logi FALSE
#> ..$ : logi FALSE
#> ..$ : logi FALSE
#> ..$ : logi FALSE
#> ..$ : logi FALSE
#> ..$ : logi FALSE
#> ..$ : logi TRUE
#> ..$ : logi FALSE
#> $ param_preprocessor__texttr__text__transformer__tokenizer : chr "<pxtextmining.helpers.tokenization.LemmaTokenizer object at 0x0000000105F14D60>" "<pxtextmining.helpers.tokenization.LemmaTokenizer object at 0x0000000105F14D60>" "<pxtextmining.helpers.tokenization.LemmaTokenizer object at 0x0000000105F14D60>" "<pxtextmining.helpers.tokenization.LemmaTokenizer object at 0x00000000D7B4DA00>" ...
#> $ param_preprocessor__texttr__text__transformer__preprocessor: chr "<function text_preprocessor at 0x00000000664484C0>" "<function text_preprocessor at 0x00000000664484C0>" "<function text_preprocessor at 0x00000000664484C0>" "<function text_preprocessor at 0x00000000664484C0>" ...
#> $ param_preprocessor__texttr__text__transformer__norm : chr "None" "l2" "None" "None" ...
#> $ param_preprocessor__texttr__text__transformer__ngram_range : chr "(1, 3)" "(2, 3)" "(2, 3)" "(2, 3)" ...
#> $ param_preprocessor__texttr__text__transformer__min_df :List of 10
#> ..$ : int 3
#> ..$ : int 1
#> ..$ : int 1
#> ..$ : int 3
#> ..$ : int 1
#> ..$ : int 1
#> ..$ : int 3
#> ..$ : int 1
#> ..$ : int 3
#> ..$ : int 1
#> $ param_preprocessor__texttr__text__transformer__max_df :List of 10
#> ..$ : num 0.95
#> ..$ : num 0.7
#> ..$ : num 0.7
#> ..$ : num 0.95
#> ..$ : num 0.95
#> ..$ : num 0.7
#> ..$ : num 0.95
#> ..$ : num 0.95
#> ..$ : num 0.95
#> ..$ : num 0.7
#> $ param_preprocessor__texttr__text__transformer : chr "TfidfVectorizer(max_df=0.95, min_df=3, ngram_range=(1, 3), norm=None,\n preprocessor=<function t"| __truncated__ "TfidfVectorizer(max_df=0.95, min_df=3, ngram_range=(1, 3), norm=None,\n preprocessor=<function t"| __truncated__ "TfidfVectorizer(max_df=0.95, min_df=3, ngram_range=(1, 3), norm=None,\n preprocessor=<function t"| __truncated__ "TfidfVectorizer()" ...
#> $ param_preprocessor__sentimenttr__scaler__scaler__n_bins :List of 10
#> ..$ : int 8
#> ..$ : int 8
#> ..$ : int 4
#> ..$ : int 4
#> ..$ : int 8
#> ..$ : int 8
#> ..$ : int 4
#> ..$ : int 8
#> ..$ : int 4
#> ..$ : int 4
#> $ param_preprocessor__sentimenttr__scaler__scaler : chr "KBinsDiscretizer(n_bins=8, strategy='kmeans')" "KBinsDiscretizer(n_bins=8, strategy='kmeans')" "KBinsDiscretizer(n_bins=8, strategy='kmeans')" "KBinsDiscretizer(strategy='kmeans')" ...
#> $ param_preprocessor__lengthtr__scaler__scaler : chr "KBinsDiscretizer(n_bins=3, strategy='kmeans')" "KBinsDiscretizer(n_bins=3, strategy='kmeans')" "KBinsDiscretizer(n_bins=3, strategy='kmeans')" "KBinsDiscretizer(n_bins=3, strategy='kmeans')" ...
#> $ param_featsel__selector__score_func : chr "<function chi2 at 0x000000006642F5E0>" "<function chi2 at 0x000000006642F5E0>" "<function chi2 at 0x000000006642F5E0>" "<function chi2 at 0x000000006642F5E0>" ...
#> $ param_featsel__selector__percentile :List of 10
#> ..$ : int 70
#> ..$ : int 100
#> ..$ : int 85
#> ..$ : int 100
#> ..$ : int 85
#> ..$ : int 85
#> ..$ : int 70
#> ..$ : int 70
#> ..$ : int 70
#> ..$ : int 70
#> $ param_featsel__selector : chr "SelectPercentile(percentile=70,\n score_func=<function chi2 at 0x000000006642F5E0>)" "SelectPercentile(percentile=70,\n score_func=<function chi2 at 0x000000006642F5E0>)" "SelectPercentile(percentile=70,\n score_func=<function chi2 at 0x000000006642F5E0>)" "SelectPercentile(percentile=70,\n score_func=<function chi2 at 0x000000006642F5E0>)" ...
#> $ param_clf__estimator__penalty :List of 10
#> ..$ : chr "elasticnet"
#> ..$ : chr "l2"
#> ..$ : chr "elasticnet"
#> ..$ : num NaN
#> ..$ : chr "l2"
#> ..$ : chr "l2"
#> ..$ : chr "l2"
#> ..$ : chr "elasticnet"
#> ..$ : num NaN
#> ..$ : num NaN
#> $ param_clf__estimator__max_iter :List of 10
#> ..$ : int 10000
#> ..$ : int 10000
#> ..$ : int 10000
#> ..$ : num NaN
#> ..$ : int 10000
#> ..$ : int 10000
#> ..$ : int 10000
#> ..$ : int 10000
#> ..$ : num NaN
#> ..$ : num NaN
#> $ param_clf__estimator__loss :List of 10
#> ..$ : chr "hinge"
#> ..$ : chr "hinge"
#> ..$ : chr "hinge"
#> ..$ : num NaN
#> ..$ : chr "log"
#> ..$ : chr "log"
#> ..$ : chr "hinge"
#> ..$ : chr "hinge"
#> ..$ : num NaN
#> ..$ : num NaN
#> $ param_clf__estimator__class_weight : chr "None" "None" "balanced" "nan" ...
#> $ param_clf__estimator : chr "SGDClassifier(max_iter=10000, penalty='elasticnet')" "SGDClassifier(max_iter=10000, penalty='elasticnet')" "SGDClassifier(max_iter=10000, penalty='elasticnet')" "MultinomialNB()" ...
#> $ param_clf__estimator__alpha :List of 10
#> ..$ : num NaN
#> ..$ : num NaN
#> ..$ : num NaN
#> ..$ : num 0.1
#> ..$ : num NaN
#> ..$ : num NaN
#> ..$ : num NaN
#> ..$ : num NaN
#> ..$ : num 0.5
#> ..$ : int 1
#> - attr(*, "pandas.index")=Int64Index([1, 5, 8, 2, 9, 6, 7, 0, 3, 4], dtype='int64')
# Learner performance barplot
text_pipe$p_compare_models_bar
# Predictions on test set
preds <- text_pipe$pred
head(preds)
#> [1] "Care received" "Couldn't be improved" "Couldn't be improved"
#> [4] "Couldn't be improved" "Care received" "Access"
head(sort(text_pipe$index_training_data))
#> [1] 0 1 3 4 7 8
# Let's subset the original data set
text_dataset <- pxtextmineR::text_data
rownames(text_dataset) <- 0:(nrow(text_dataset) - 1)
data_train <- text_dataset[text_pipe$index_training_data, ]
data_test <- text_dataset[text_pipe$index_test_data, ]
str(data_train)
#> 'data.frame': 6922 obs. of 3 variables:
#> $ label : chr "Staff" "Staff" "Staff" "Staff" ...
#> $ criticality: chr "1" "0" "3" "3" ...
#> $ feedback : chr "Staff." "Mrs XXXX is excellent at her job." "Promote Jenna and Olivia because they are great and Kev. \nThey are very good at keeping us all busy (Jenna and"| __truncated__ "Best team of nurses" ...
There are a few helper functions that Python library pxtextmining
and its R wrapper pxtextmineR
use in the background that are worth making available in R:
class_balance_accuracy_score_r
calculates Mosley’s (2013) Class Balance Accuracy score, a metric that is particularly useful when there are class imbalances in the dataset.sentiment_scores_r
calculates sentiment indicators from TextBlob
and vaderSentiment
.According to Mosley (2013, abstract), “[…] models chosen by maximizing the training class balance accuracy consistently yield both high overall accuracy and per class recall on the test sets compared to the models chosen by other criteria.” Our pipeline’s default metric is Class Balance Accuracy, although other metrics are also possible, namely standard accuracy, Balanced Accuracy, and Matthews Correlation Coefficient. See this User Guide.
x <- pxtextmineR::text_data %>%
dplyr::mutate(label_pred = sample(label, size = nrow(.))) # Mock predictions column
pxtextmineR::class_balance_accuracy_score_r(x$label, x$label_pred)
#> [1] 0.1124614
Function sentiment_scores_r
complements existing sentiment analysis packages in R (e.g. tidytext
or quanteda.sentiment
) with the popular Python sentiment analysis libraries TextBlob
and vaderSentiment
.
TextBlob
calculates two indicators, namely polarity and subjectivity. The polarity score is a float within the range [-1, 1]
, where -1 is for very negative sentiment, +1 is for very positive sentiment, and 0 is for neutral sentiment. The subjectivity is a float within the range [0, 1]
, where 0 is very objective and 1 is very subjective.
vaderSentiment
assigns to the given text three sentiment proportions (positive, negative and neutral) whose scores sum to 1. It also calculates a compound score that is a float in [-1, 1]
, similar to TextBlob
’s polarity.
sentiments <- pxtextmineR::text_data %>%
dplyr::select(feedback) %>%
pxtextmineR::sentiment_scores_r()
head(sentiments)
#> text_blob_polarity text_blob_subjectivity vader_neg vader_neu vader_pos
#> 1 0.00000 0.0000000 0.000 1.000 0.000
#> 2 -0.09375 0.4000000 0.265 0.735 0.000
#> 3 0.20000 0.2625000 0.000 1.000 0.000
#> 4 0.23125 0.4669643 0.199 0.625 0.176
#> 5 0.02500 0.3250000 0.029 0.913 0.058
#> 6 -0.27500 0.5750000 0.091 0.813 0.096
#> vader_compound
#> 1 0.0000
#> 2 -0.2040
#> 3 0.0000
#> 4 0.0490
#> 5 0.3400
#> 6 0.2967
apply(sentiments, 2, range)
#> text_blob_polarity text_blob_subjectivity vader_neg vader_neu vader_pos
#> [1,] -1 0 0 0 0
#> [2,] 1 1 1 1 1
#> vader_compound
#> [1,] -0.9916
#> [2,] 0.9971
Mosley L. (2013). A balanced approach to the multi-class imbalance problem. Graduate Theses and Dissertations. 13537. https://lib.dr.iastate.edu/etd/13537.
Pedregosa F., Varoquaux G., Gramfort A., Michel V., Thirion B., Grisel O., Blondel M., Prettenhofer P., Weiss R., Dubourg V., Vanderplas J., Passos A., Cournapeau D., Brucher M., Perrot M. & Duchesnay E. (2011), Scikit-learn: Machine Learning in Python. Journal of Machine Learning Research 12:2825–2830.


{% extends "base.html" %} {% block title %}{{ fondz.name }} - Summary{% endblock %} {% block content %} Below is a list of the bags that are part of this collection. Click on one of them to see details about the bag. Bag Location Files Size {% for bag in fondz.bags %} {{ bag.path }} {{ humanize.intcomma(bag.manifest|count) }} {{ humanize.naturalsize(bag.bytes) }} {% endfor %} {% endblock %}
Below is a list of the bags that are part of this collection. Click on one of them to see details about the bag.


I'm Esther Xuanpei Ouyang, a thrid year Computer Science and Statistics double major student with focus on Artificial Intelligence at UC Berkeley. Go Bears! 🐻
I am interested in Software development, Data Analysis, Machine Learning.
Sep 2016
Sep 2016
Aug 2016
July 2016
May 2016
Sep 2015
Aug 2015
Mar 2015
Oct 2014
Feel free to contact me and check out my resume


Basket Minder is an iOS application for iPhone and iPad that notifies users when baskets are available in their area.


{3}
Just published on {0}
{4}
Keep reading...
You are receiving this email because you are subscribed to {0} Updates. To unsubscribe
click here
.


Class: Sass::Tree::Visitors::Base Abstract
- Inherits:
-
Object
- Object
- Sass::Tree::Visitors::Base
- Defined in:
- /usr/local/google-old/home/code/sass-site/.sass/lib/sass/tree/visitors/base.rb
Overview
The abstract base class for Sass visitors. Visitors should extend this class, then implement visit_*
methods for each node they care about (e.g. visit_rule
for RuleNode or visit_for
for ForNode). These methods take the node in question as argument. They may yield
to visit the child nodes of the current node.
Note: due to the unusual nature of IfNode, special care must be taken to ensure that it is properly handled. In particular, there is no built-in scaffolding for dealing with the return value of @else
nodes.
Direct Known Subclasses
CheckNesting, Convert, Cssize, DeepCopy, Extend, Perform, SetOptions, ToCss
Class Method Summary (collapse)
-
+ (String) node_name(node)
protected
Returns the name of a node as used in the
visit_*
method. -
+ (Object) visit(root)
Runs the visitor on a tree.
Instance Method Summary (collapse)
-
- (Object) visit(node)
protected
Runs the visitor on the given node.
-
- (Array<Object>) visit_children(parent)
protected
Visit the child nodes for a given node.
-
- visit_if(node)
protected
yield
s, then runs the visitor on the@else
clause if the node has one.
Class Method Details
+ (String) node_name(node) (protected)
Returns the name of a node as used in the visit_*
method.
59 60 61 62 |
# File '/usr/local/google-old/home/code/sass-site/.sass/lib/sass/tree/visitors/base.rb', line 59
def self.node_name(node)
Sass::Util.deprecated(self, "Call node.class.node_name instead.")
node.class.node_name
end
|
+ (Object) visit(root)
Runs the visitor on a tree.
23 24 25 |
# File '/usr/local/google-old/home/code/sass-site/.sass/lib/sass/tree/visitors/base.rb', line 23
def self.visit(root)
new.send(:visit, root)
end
|
Instance Method Details
- (Object) visit(node) (protected)
Runs the visitor on the given node. This can be overridden by subclasses that need to do something for each node.
34 35 36 37 38 39 40 |
# File '/usr/local/google-old/home/code/sass-site/.sass/lib/sass/tree/visitors/base.rb', line 34
def visit(node)
if respond_to?(node.class.visit_method, true)
send(node.class.visit_method, node) {visit_children(node)}
else
visit_children(node)
end
end
|
- (Array<Object>) visit_children(parent) (protected)
Visit the child nodes for a given node. This can be overridden by subclasses that need to do something with the child nodes’ return values.
This method is run when visit_*
methods yield
, and its return value is returned from the yield
.
51 52 53 |
# File '/usr/local/google-old/home/code/sass-site/.sass/lib/sass/tree/visitors/base.rb', line 51
def visit_children(parent)
parent.children.map {|c| visit(c)}
end
|
- visit_if(node) (protected)
yield
s, then runs the visitor on the @else
clause if the node has one. This exists to ensure that the contents of the @else
clause get visited.
66 67 68 69 70 |
# File '/usr/local/google-old/home/code/sass-site/.sass/lib/sass/tree/visitors/base.rb', line 66
def visit_if(node)
yield
visit(node.else) if node.else
node
end
|


Start Date : {{ ticket.start.utc | date: 'short' }} End Date : {{ ticket.end.utc | date: 'short' }} Tickets Left : {{ ticket.capacity }}


isomorphic-fetchline umd version test
Open the developer console of your browser to inspect the testing result.
fetchline
fetchline_pkg
isomorphic-fetchline
isomorphic-fetchline_pkg
naivefetchline
naivefetchline_pkg


Andrei Kelin Appointed Russian Ambassador to United Kingdom
MOSCOW (Sputnik) - Russian President Vladimir Putin has appointed Andrey Kelin as Russian ambassador to the United Kingdom, according to a relevant decree published on the portal of legal information.
"To appoint Kelin Andrey Vladimirovich Ambassador Extraordinary and Plenipotentiary of the Russian Federation to the United Kingdom of Great Britain and Northern Ireland," the decree says.
Earlier, Kelin told Sputnik in an interview that no high-level contacts between Moscow and London were being planned for the near future.
Kelin previously served as director of the Department of European Cooperation at the Russian Foreign Ministry and supervised Russia-NATO relations, Russia's work in the OSCE and the Council of Europe.


Sorry, but you must be logged in with a valid account to contact an administrator.
Subject Line:
Message for Admins:
Submit your message


Hey there!
I'm an Engineering Graduate Student studying Computer Science at North Carolina State University. (Go Pack!). Prior to my masters I worked at Samsung Research India. I obtained my Bachelor's in Computer Science from Birla Institute of Technology and Science, Pilani.
I love building new and challenging software, especially in areas that I have little to no prior knowledge. I also love solving puzzles. My interests lie in design and development of large scale software systems and Machine Learning and I am particularly excited to work on applications at the confluence of these two. Let's get started!


WITNESS LIST Jurisprudence Committee March 14, 1997-10:00A Public testimony judicial selection On: Alvarado, Carol (Chair, Sen Dist 6), Houston Boze, U. Lawrence (National Bar Assn.), Houston Christian, George (Txns Jud Election Rfrm), Houston Douglas, Keryl (NAACP Houston), Houston Drayden Charles (Houston Lawyers Assn.), Houston Kelly, Hugh Rice (Txns Jud. Election Rfrm), Houston Kerrigan, Patricia J. (Tx Assn of Def Counsel), Houston Klages, George (Justice For All), Fresno Leal, Al Judge (Self), Houston Luce, Tom (Self), Dallas Polland, Gary (Harris Co Repub Party), Houston Reyes, Frumencia (Self), Houston Wittig, Don Judge (Harris Co Dist. Judges), Houston Registering, but not testifying: On: Fital, Bonnie (Self), Houston Guerrero, Ruben (Self), Houston King, Carl (Pan Energy), Houston Smith, Freeman E. (TX Judicial Elctn Refrm), Houston Wallace, Jim Judge (Self), Houston


UI5
Web Components
Enterprise-flavored sugar on top of native APIs!
Latest version: 1.6.0
Get Started
Easy to consume
Based on web standards - just HTML! Future-proof. Easy to add to your project.Lightweight
Tiny - come with a minimal footprint. Modular - take only the parts you need. Fast - built with performance in mind.Enterprise Ready
Implement the SAP Fiori design language. Feature-rich Secure, accessible, themeable, i18n-ready.Test the UI5 Web Components
<ui5-date-picker></ui5-date-picker>
Try Out the Demo Apps
Framework Compatibility
Browser Compatibility
Testimonials
"I absolutely loved working with the UI5 web components since they are very easy to plug into any application. It made our MDK Web runtime development much easier and more productive so that we were able to smoothly deliver our first Web channel in a short time."
"The UI5 Web Components are well documented and easy to re-use, making for quick and consistent development. The team provided exceptional service."
"UI5 Web Components keep our focus on delivering product features instead of re-implementing UI primitives while staying consistent with Fiori design system and giving us an opportunity to use React as our base framework. Great job!"
"UI5 Web Components are a great set of UI elements that allow you to use the framework you like to easily build SAP Fiori compliant apps and deliver the best user experience for your customers."


Conducts statistical downscaling of daily CMIP5 (Coupled Model Intercomparison Project 5) climate change scenario data at a station level using empirical quantile mapping method by Jaepil Cho et al. (2016) <doi:10.1002/ird.2035>.
| Version: | 1.3.14 |
| Depends: | R (≥ 3.3.0) |
| Imports: | ncdf4, zoo, stringr, EcoHydRology, dplyr, gsubfn, yaml, mise, reshape2, qmap, ggplot2 |
| Suggests: | knitr, rmarkdown, testthat |
| Published: | 2018-01-12 |
| Author: | Jaepil Cho [aut], Wonil Cho [aut, cre], Imgook Jung [aut] |
| Maintainer: | Wonil Cho <climate.service at apcc21.org> |
| License: | GPL-2 | GPL-3 [expanded from: GPL (≥ 2)] |
| NeedsCompilation: | no |
| Materials: | README NEWS |
| CRAN checks: | rSQM results |
| Reference manual: | rSQM.pdf |
| Vignettes: |
rSQM workflow |
| Package source: | rSQM_1.3.14.tar.gz |
| Windows binaries: | r-devel: rSQM_1.3.14.zip, r-release: rSQM_1.3.14.zip, r-oldrel: rSQM_1.3.14.zip |
| OS X binaries: | r-release: rSQM_1.3.14.tgz, r-oldrel: rSQM_1.3.14.tgz |
| Old sources: | rSQM archive |
Please use the canonical form https://CRAN.R-project.org/package=rSQM to link to this page.


Four-Bar Linkages
A planar four-bar linkage consists of four rigid rods in the plane connected by pin joints. We call the rods:
- Ground link $g$: fixed to anchor pivots $A$ and $B$.
- Input link $a$: driven by input angle $\alpha$.
- Output link $b$: gives output angle $\beta$.
- Floating link $f$: connects the two moving pins $C$ and $D$.
We often think of a four-bar linkage as being driven at the input angle $\alpha$, resulting in the output angle $\beta$. We only need one input, because the system has exactly $N_{\rm DOF} = 1$ degree of freedom. We can count the DOF as 9 free variables (three moving rigid bodies with three variables each) minus 8 constraints (four pin joints with two constraints each).
|
Four-bar linkages can be used for many mechanical purposes, including to:
- convert rotational motion to reciprocating motion (e.g., pumpjack examples below)
- convert reciprocating motion to rotational motion (e.g., bicycle examples below)
- constrain motion (e.g., knee joint and suspension examples below)
- magnify force (e.g., parrotfish jaw examples below)
Rotating cranks and reciprocating rockers
Four-bar linkages can convert between different types of motion. We call these:
- Crank rod: rotating motion through a complete circle.
- Rocker rod: reciprocating motion with a total angle less than $360^\circ$.
On the linkage below, adjusting the lengths of the input rod $a$ and the output rod $b$ shows that we can have an input crank and output rocker or the other way around, depending on whether $a < b$ or $a > b$. The case when $a = b$ is special.
|
| Input link length: | \(a = \) cm | |
| Output link length: | \(b = \) cm |
Coupler dynamics
The joints $C$ and $D$ always move in circles or semi-circles. More complex motion can be achieved with a coupler point $P$ attached to the floating link $f$, as shown below where the position of $P$ can be adjusted. Adding a coupler technically makes this a six-bar linkage (four original links plus $CP$ and $DP$).
Here the input and output links are listed as a 0-rocker and π-rocker, as they reciprocate about the angles $\alpha = 0^\circ$ and $\beta = 180^\circ = \pi\rm\ rad$, respectively.
|
| Coupler position: | \(P_{\rm pos} = \) % from DC midpoint towards C | |
| Coupler offset: | \(P_{\rm off} = \) % of DC length |
Limiting the input angle
It is often helpful to limit the input angle in a mechanism, even when the linkage could allow for greater movement. For example, to have a lifting platform the linkage below uses a crank limited to a smaller reciprocating input range. The input center angle $\alpha_{\rm cent}$ and range $\Delta\alpha$ can be adjusted to control the range of movement of the platform.
|
| Input angle center: | \(\alpha_{\rm cent} = \) % from 0° to 360° | |
| Input angle range: | \(\Delta\alpha = \) % of 180° |
Example: Pumpjack (rotary to reciprocal)
In areas where underground oil is not under enough pressure to drive it all the way to the surface, it is necessary for oil wells to actively pump up the oil. One standard method for achieving this is to use a reciprocating piston that pumps the oil up the shaft. As most motors (electrical or internal combustion) provide a rotating drive shaft, some way is needed to convert the rotary engine motion into reciprocating pump motion. A pumpjack is a drive mechanism to achieve this, consisting of a four-bar linkage as shown below. The heavy rotating counterweight is arranged so that it is falling while the pump is performing the up-stroke, and thus lifting the oil against gravity. This allows a smaller engine to be used.
A pumpjack (also known as a nodding donkey) pump in Northeast Colorado. Image credit: Flickr image by Greg Goebel (CC BY-SA 2.0) (full-sized image).
Example: Bicycle pedaling (reciprocal to rotary)
Bicycles are an efficient means of human-powered transportation due to their use of rotary wheel motion. Humans cannot directly produce indefinite rotations, however, so some mechanism is required to translate reciprocating human motion into rotary motion. Bicycles achieve this conversion with two four-bar linkages, each consisting of the two segments of the riders leg, the bicycle frame, and the crank, as shown below.
A man riding a bicycle at the port of Vannes, Brittany, in the north-west of France. Image source: Flickr image by Alexandre Dulaunoy (CC BY 2.0) (full-sized image).
While the four links in the bicycle linkage are approximately rigid rods, only two of the joints are in fact reasonable models of a pin joint (the knee and lower crank). At the pedal and seat, only compression is allowed, as there is no way for the rider to pull up on the pedal or seat. This doesn't normally matter, as the rider's weight serves to maintain the connection at the seat, while the pedal joint only has force exerted during the down-stroke on each side, and the two legs are offset by 180° so one is always pushing down. An alternative approach is used on racing bikes, where the feet are clipped to the pedals and so each foot can pull up as well as push down.
While the current form of the bicycle may seem obvious, with a rotary crank connected by a chain to the rear wheel, it took over 50 years for it to be developed. Before this time, many different systems for bicycle propulsion were tried. The first bicycle, invented by Karl Drais in Mannheim, Germany in 1818, used direct human propulsion along the ground, as shown below. Mannheim was an important location for vehicle invention, as it was also the city where Karl Benz invented the modern automobile in 1885.
Later bicycle propulsion mechanisms used pedals directly attached to the hub of the front wheel (the so-called bone-shaker), which caused difficulties in pedaling while turning. This direct drive also had gearing problems, as a comfortable ratio of pedal frequency to velocity required very large wheels, leading to the penny-farthing. An alternative approach to cranks was to use treadles, allowing the pedals to be positioned away from the wheel hub. This series of inventions finally resulted in the safety bicycle in 1876, which is the modern form we still use today.
Example: Knee joint (constrained motion)
The human knee joint is a type of biological hinge, which allows movement in only one primary angle. The knee connects the femur (the upper leg bone) to the tibia (the larger of the two lower leg bones). These two bones sit next to each other and are free to rotate about a single axis. A mechanism is needed to keep the two legs bones attached to each other, while still allowing rotation. In the case of the human knee this is achieved with a four-bar linkage consisting of the two bones together with the anterior cruciate ligament (ACL) and posterior cruciate ligament (PCL), as shown below.
An MRI image of a sagittal section through a human knee joint, showing the ACL and PCL ligaments. Image credit: Wikimedia Commons image (CC BY-SA 2.0).
The four-bar model of the knee is only approximate, and neglects many important mechanical features. In particular, the ACL and PCL are not rigid rods, and can only provide tensile forces (they act as mechanical ropes). The compressive force is actually provided by the meniscus that separates the femur and tibia bones. In the simple four-bar knee model shown here, the rigid rods include the effects of both the ligaments and the meniscus.
References
- A. B. Zavatsky and J. J. O'Connor. A model of human knee ligaments in the sagittal plane: Part 1: Response to passive flexion. Proceedings of the Institution of Mechanical Engineers, Part H: Journal of Engineering in Medicine, 206(3):125–134, 1992. DOI: 10.1243/PIME_PROC_1992_206_280_02
No joints in the human body have the rotating bone fully constrained by the enclosing socket bone. Instead, like the knee, they have a partial socket or cylinder and the rotating bone is held in place by ligaments. This type of arrangement is typical for most animals, with one rare exception being the European Badger (Meles Meles). In older badgers, the jaw rotates on an entirely enclosed pivot, as shown below. This means that the badger cannot waggle its jaw side-to-side as humans can, and also means that the badger jaw cannot be dislocated or disconnected without breaking the bone.
Example: Suspensions with Watt's linkage (constrained motion)
Apart from being one of the inventors of the steam engine and having an SI unit named after him, James Watt also developed a linkage to produce approximate straight line motion. Watt's linkage consists of two long near-parallel links and a small floating link between them, with the near-linear motion occurring for a coupler point midway along the floating link. This linkage is commonly used in suspension systems, as shown below.
The rear suspension of a 1998 Ford Ranger EV. Image credit: Wikimedia Commons (CC SA 1.0) (full-sized image).
Watt's original hand drawing of the linkage clearly shows the main elements, and also indicates the circular motions of the two moving pivots, as we can see below.
Watt's hand-drawn diagram explaining the concept behind his new linkage design. Image credit: Wikimedia Commons, originally from J. P. Muirhead, The Life of James Watt with Selections from his Correspondence, 1858, p. 294 (public domain) (full-sized image).
The discovery was first revealed in a letter that Watt wrote in 1784:
I have got a glimpse of a method of causing a piston rod to move up and down perpendicularly by only fixing it to a piece of iron upon the beam, without chains or perpendicular guides [...] and one of the most ingenious simple pieces of mechanics I have invented.
While Watt's linkage only produces approximate straight-line motion, the 8-link Peaucellier-Lipkin linkage, shown below, was discovered in 1864 and produces an exactly straight line. In the illustration the links of the same color are equal in length.
Rather than trying to discover special linkages to produce different types of motion, Alfred Kempe proved that any plane algebraic curve (the set of zeros of a polynomial like \(x + 2 x^3 - y^2 - 3\)) can be traced by a sufficiently complicated linkage. See: A. B. Kempe, On a General Method of describing Plane Curves of the nth degree by Linkwork, Proceedings of the London Mathematical Society (1875) s1-7(1): 213-216. doi: 10.1112/plms/s1-7.1.213.
Example: Parrotfish jaw (force multiplication)
Parrotfish live in shallow tropical waters on coral reefs, where they feed on the the algae that live inside the coral. To get to the algae, they eat the coral itself and then grind it up to release the algae-filled coral polyps inside. The name of parrotfish comes from their teeth, which are packed tightly together to form a parrot-like beak and which grow continuously as they are worn down by feeding.
 Image credit: Image reef4416 from NOAA's Coral Kingdom Collection by Julie Bedford. (Public domain, U.S. Federal Government). (full-sized image).
To eat the calcium carbonate coral skeleton, parrotfish need not only extremely strong teeth, but they also need a very powerful biting motion of their jaws. To achieve this, they use a four-bar linkage in their jaws to enable the muscle force to obtain a significant mechanical advantage when the jaws are closing, as shown below. The opening motion is comparatively weak, but this is unimportant for normal feeding.
The skull of a Bleeker's Parrotfish, showing the main components of the jaw. Image credit: BioLab image by Pavel Zuber (CC BY 2.0) (full-sized image).
References
- M. Muller. A Novel Classification of Planar Four-Bar Linkages and its Application to the Mechanical Analysis of Animal Systems. Philosophical Transactions of the Royal Society B, 351(1340):689–720, 1996. DOI: 10.1098/rstb.1996.0065
Parrotfish have two sets of jaws: the regular set of oral jaws that we can see, and a second set of pharyngeal jaws located at the start of their throat (the pharynx). The pharyngeal jaws are used to crush the coral that has been bitten off by the main oral jaws.
Many species of fish have secondary pharyngeal jaws. A particularly striking example is the Moray eel, shown below, which launches its pharyngeal jaws up into the mouth to actively capture prey and drag it back into the throat. This is the basis for the Alien from the film series, which could launch its inner pharyngeal jaws well beyond its body.
Full linkage model
The linkage model below can have its geometry set either by the link lengths ($g$, $a$, $b$, $f$) or by the excess quantities ($T_1$, $T_2$, $T_3$). Whether each of the $T_i$ are positive or negative determines the type of input and output (crank, rocker, etc.). For example, if $T_3$ is negative then $T_3 = f + b - g - a < 0$, which means $g + a > f + b$. This implies that the input angle $\alpha$ cannot rotate around to $180^\circ$, as $D$ would be too far from $B$, and so the input rod can't be a crank and must be some type of rocker.
Two other useful geometric quantities shown below are the Grashof index $G$ and the validity index $V$. If $G \gt 0$ then the shortest link is able to fully rotate through $360^\circ$ (the linkage is “Grashof”), while if $G \lt 0$ then the shortest link only reciprocates (the linkage is “non-Grashof”). If $V \lt 0$ then the linkage is impossible, as the longest link is longer than the total length of the other three links.
|
| Orientation: | ||
| set link lengths | ||
| Ground link length: | \(g = \) cm | |
| Input link length: | \(a = \) cm | |
| Output link length: | \(b = \) cm | |
| Floating link length: | \(f = \) cm | |
| set excess values | ||
| Ground-free excess: | \(T_1 = g + f - b - a = \) cm | |
| Output-ground excess: | \(T_2 = b + g - f - a = \) cm | |
| Free-output excess: | \(T_3 = f + b - g - a = \) cm | |
| Total length: | \(L = g + f + b + a = \) cm | |
| Coupler position: | \(P_{\rm pos} = \) % from DC midpoint towards C | |
| Coupler offset: | \(P_{\rm off} = \) % of DC length | |
| Ground link angle: | \(\theta_{\rm g} = \) ° | |
| Input angle center: | \(\alpha_{\rm cent} = \) % from \(\alpha_{\rm min}\) to \(\alpha_{\rm max}\) from 0° to 360° | |
| Input angle range: | \(\Delta\alpha = \) % from \(\alpha_{\rm cent}\) to nearest \(\alpha_{\rm min}/\alpha_{\rm max}\) of 180° | |
| Grashof index: | \(G = s + l - p - q = \) cm | |
| Validity index: | \(V = l - s - p - q = \) cm |
The variables \(s\) and \(l\) are the shortest and longest side lengths, respectively, while \(p\) and \(q\) are the remaining two side lengths.
The type of input and output links is determined by whether each of $T_1$, $T_2$, and $T_3$ are positive, zero, or negative. The full table of possibilities is given below.
| \(T_1\) | \(T_2\) | \(T_3\) | Input \(\alpha\) | Output \(\beta\) | \(T_1\) | \(T_2\) | \(T_3\) | Input \(\alpha\) | Output \(\beta\) | \(T_1\) | \(T_2\) | \(T_3\) | Input \(\alpha\) | Output \(\beta\) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| + | + | + | crank | rocker | + | + | 0 | crank | π-rocker | + | + | - | 0-rocker | π-rocker |
| 0 | + | + | crank | π-rocker | 0 | + | 0 | crank | π-rocker | 0 | + | - | 0-rocker | π-rocker |
| - | + | + | π-rocker | π-rocker | - | + | 0 | π-rocker | π-rocker | - | + | - | rocker | rocker |
| + | 0 | + | crank | 0-rocker | + | 0 | 0 | crank | crank | + | 0 | - | 0-rocker | crank |
| 0 | 0 | + | crank | crank | 0 | 0 | 0 | crank | crank | 0 | 0 | - | 0-rocker | crank |
| - | 0 | + | crank | crank | - | 0 | 0 | crank | crank | - | 0 | - | 0-rocker | 0-rocker |
| + | - | + | π-rocker | 0-rocker | + | - | 0 | π-rocker | crank | + | - | - | rocker | crank |
| 0 | - | + | crank | crank | 0 | - | 0 | crank | crank | 0 | - | - | 0-rocker | crank |
| - | - | + | crank | crank | - | - | 0 | crank | crank | - | - | - | 0-rocker | 0-rocker |


BuildContext
, BLoC
, and ViewModel
, and supports screen action.Presenter extents Presenter< Bloc, ViewModel, Screen>
to create the Screen, and also manages all user actions on screen.
class ExamplePresenter extends Presenter<ExampleBloc, ExampleViewModel, ExampleScreen> {
@override
Stream<ExampleViewModel> getViewModelStream (ExampleBloc bloc) {...
@override
Widget buildLoadingScreen(BuildContext context) {...
@override
Widget buildErrorScreen(BuildContext context, Object? error) {...
@override
ExampleScreen buildScreen(BuildContext context, ExampleBloc bloc, ExampleViewModel viewModel) {...
}
getViewModelStream
method provide ViewModel
by listening to BLoc
listener.buildLoadingScreen
method return a Widget
to create the loading screen.buildErrorScreen
method return a Widget
to create the error screen.buildScreen
method return a Screen
to create the UI by passing the associated ViewModel
and the action functions. @override
ExampleScreen buildScreen(BuildContext context,
ExampleBloc bloc, ExampleViewModel viewModel) {
return ExampleScreen(
viewModel: viewModel,
pressenterActions: ExamplePressenterActions(),
);
}
BLoC
, is like an application traffic manager that connects Usecase
and Screen
via pipesclass ExampleBloc extends Bloc {
ExampleUseCase? _exampleUseCase;
final exampleViewModelPipe = Pipe<ExampleViewModel>();
final exampleEventPipe = Pipe<ExampleEvent>(canSendDuplicateData: true);
@override
void dispose() {
exampleViewModelPipe.dispose();
exampleEventPipe.dispose();
}
ExampleBloc({ExampleUseCase? exampleUseCase}) {
_exampleUseCase = exampleUseCase ?? ExampleUseCase(exampleEventPipe.send);
exampleViewModelPipe.whenListenedDo(() => _exampleUseCase!.execute());
exampleEventPipe.receive.listen(exampleEventPipeHandler);
}
void exampleEventPipeHandler(ExampleEvent event) {}
}
Presenter and Bloc are connecting the domain layer and presentation layer, to serve Screen data/state with logic that process in Usecase.
ViewModel
through listening to ViewModel
pipes and provide that to screen, or send screen event to domain layer through calling event pipe provided by BloC
.BloC
Listen to events/data from presenter via pipes and invoke the use case by specific business logic. Receive updated ViewModel
from UseCase
via callback, and send the ViewModel
to the presenter via the ViewModel pipe.