-
Password
-
-
-
- {{ render_only_errors(register_user_form.password_confirm) }}
-
- {% endif %}
-
-
-
+ {% if register_user_form.password_confirm %}
+
+
Password
+
+
+
+ {{ render_only_errors(register_user_form.password_confirm) }}
-
+ {% endif %}
-
+
-
+
+
+
{% include "security/_scripts.html" %}
--
cgit 1.4.1
From 48ba921c234abb218b14d7f1ae4d5b017ab8d388 Mon Sep 17 00:00:00 2001
From: Sam
Date: Fri, 17 May 2013 20:59:50 +0000
Subject: Added flask_security locally
---
wqflask/flask_security/__init__.py | 23 ++
wqflask/flask_security/changeable.py | 45 +++
wqflask/flask_security/confirmable.py | 83 +++++
wqflask/flask_security/core.py | 381 +++++++++++++++++++++
wqflask/flask_security/datastore.py | 260 ++++++++++++++
wqflask/flask_security/decorators.py | 207 +++++++++++
wqflask/flask_security/forms.py | 277 +++++++++++++++
wqflask/flask_security/passwordless.py | 59 ++++
wqflask/flask_security/recoverable.py | 80 +++++
wqflask/flask_security/registerable.py | 43 +++
wqflask/flask_security/script.py | 130 +++++++
wqflask/flask_security/signals.py | 29 ++
wqflask/flask_security/templates/.DS_Store | Bin 0 -> 6148 bytes
.../flask_security/templates/security/.DS_Store | Bin 0 -> 6148 bytes
.../flask_security/templates/security/_macros.html | 16 +
.../flask_security/templates/security/_menu.html | 15 +
.../templates/security/_messages.html | 9 +
.../templates/security/change_password.html | 11 +
.../templates/security/email/change_notice.html | 4 +
.../templates/security/email/change_notice.txt | 5 +
.../security/email/confirmation_instructions.html | 3 +
.../security/email/confirmation_instructions.txt | 3 +
.../security/email/login_instructions.html | 5 +
.../security/email/login_instructions.txt | 5 +
.../security/email/reset_instructions.html | 1 +
.../security/email/reset_instructions.txt | 3 +
.../templates/security/email/reset_notice.html | 1 +
.../templates/security/email/reset_notice.txt | 1 +
.../templates/security/email/welcome.html | 7 +
.../templates/security/email/welcome.txt | 7 +
.../templates/security/forgot_password.html | 9 +
.../templates/security/login_user.html | 12 +
.../templates/security/register_user.html | 13 +
.../templates/security/reset_password.html | 10 +
.../templates/security/send_confirmation.html | 9 +
.../templates/security/send_login.html | 9 +
wqflask/flask_security/utils.py | 379 ++++++++++++++++++++
wqflask/flask_security/views.py | 359 +++++++++++++++++++
wqflask/wqflask/templates/security/_macros.html | 48 ++-
wqflask/wqflask/templates/security/login_user.html | 7 +-
wqflask/wqflask/views.py | 3 +
41 files changed, 2550 insertions(+), 21 deletions(-)
create mode 100644 wqflask/flask_security/__init__.py
create mode 100644 wqflask/flask_security/changeable.py
create mode 100644 wqflask/flask_security/confirmable.py
create mode 100644 wqflask/flask_security/core.py
create mode 100644 wqflask/flask_security/datastore.py
create mode 100644 wqflask/flask_security/decorators.py
create mode 100644 wqflask/flask_security/forms.py
create mode 100644 wqflask/flask_security/passwordless.py
create mode 100644 wqflask/flask_security/recoverable.py
create mode 100644 wqflask/flask_security/registerable.py
create mode 100644 wqflask/flask_security/script.py
create mode 100644 wqflask/flask_security/signals.py
create mode 100644 wqflask/flask_security/templates/.DS_Store
create mode 100644 wqflask/flask_security/templates/security/.DS_Store
create mode 100644 wqflask/flask_security/templates/security/_macros.html
create mode 100644 wqflask/flask_security/templates/security/_menu.html
create mode 100644 wqflask/flask_security/templates/security/_messages.html
create mode 100644 wqflask/flask_security/templates/security/change_password.html
create mode 100644 wqflask/flask_security/templates/security/email/change_notice.html
create mode 100644 wqflask/flask_security/templates/security/email/change_notice.txt
create mode 100644 wqflask/flask_security/templates/security/email/confirmation_instructions.html
create mode 100644 wqflask/flask_security/templates/security/email/confirmation_instructions.txt
create mode 100644 wqflask/flask_security/templates/security/email/login_instructions.html
create mode 100644 wqflask/flask_security/templates/security/email/login_instructions.txt
create mode 100644 wqflask/flask_security/templates/security/email/reset_instructions.html
create mode 100644 wqflask/flask_security/templates/security/email/reset_instructions.txt
create mode 100644 wqflask/flask_security/templates/security/email/reset_notice.html
create mode 100644 wqflask/flask_security/templates/security/email/reset_notice.txt
create mode 100644 wqflask/flask_security/templates/security/email/welcome.html
create mode 100644 wqflask/flask_security/templates/security/email/welcome.txt
create mode 100644 wqflask/flask_security/templates/security/forgot_password.html
create mode 100644 wqflask/flask_security/templates/security/login_user.html
create mode 100644 wqflask/flask_security/templates/security/register_user.html
create mode 100644 wqflask/flask_security/templates/security/reset_password.html
create mode 100644 wqflask/flask_security/templates/security/send_confirmation.html
create mode 100644 wqflask/flask_security/templates/security/send_login.html
create mode 100644 wqflask/flask_security/utils.py
create mode 100644 wqflask/flask_security/views.py
(limited to 'wqflask')
diff --git a/wqflask/flask_security/__init__.py b/wqflask/flask_security/__init__.py
new file mode 100644
index 00000000..68267cff
--- /dev/null
+++ b/wqflask/flask_security/__init__.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security
+ ~~~~~~~~~~~~~~~~~~
+
+ Flask-Security is a Flask extension that aims to add quick and simple
+ security via Flask-Login, Flask-Principal, Flask-WTF, and passlib.
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+__version__ = '1.6.0'
+
+from .core import Security, RoleMixin, UserMixin, AnonymousUser, current_user
+from .datastore import SQLAlchemyUserDatastore, MongoEngineUserDatastore, PeeweeUserDatastore
+from .decorators import auth_token_required, http_auth_required, \
+ login_required, roles_accepted, roles_required
+from .forms import ForgotPasswordForm, LoginForm, RegisterForm, \
+ ResetPasswordForm, PasswordlessLoginForm, ConfirmRegisterForm
+from .signals import confirm_instructions_sent, password_reset, \
+ reset_password_instructions_sent, user_confirmed, user_registered
+from .utils import login_user, logout_user, url_for_security
diff --git a/wqflask/flask_security/changeable.py b/wqflask/flask_security/changeable.py
new file mode 100644
index 00000000..4447b655
--- /dev/null
+++ b/wqflask/flask_security/changeable.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.changeable
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security recoverable module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :author: Eskil Heyn Olsen
+ :license: MIT, see LICENSE for more details.
+"""
+
+from flask import current_app as app, request
+from werkzeug.local import LocalProxy
+
+from .signals import password_changed
+from .utils import send_mail, encrypt_password, url_for_security, \
+ config_value
+
+
+# Convenient references
+_security = LocalProxy(lambda: app.extensions['security'])
+
+_datastore = LocalProxy(lambda: _security.datastore)
+
+
+def send_password_changed_notice(user):
+ """Sends the password changed notice email for the specified user.
+
+ :param user: The user to send the notice to
+ """
+ send_mail(config_value('EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE'), user.email,
+ 'change_notice', user=user)
+
+
+def change_user_password(user, password):
+ """Change the specified user's password
+
+ :param user: The user to change_password
+ :param password: The unencrypted new password
+ """
+ user.password = encrypt_password(password)
+ _datastore.put(user)
+ send_password_changed_notice(user)
+ password_changed.send(user, app=app._get_current_object())
diff --git a/wqflask/flask_security/confirmable.py b/wqflask/flask_security/confirmable.py
new file mode 100644
index 00000000..a7caf6cd
--- /dev/null
+++ b/wqflask/flask_security/confirmable.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.confirmable
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security confirmable module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+from datetime import datetime
+
+from flask import current_app as app, request
+from werkzeug.local import LocalProxy
+
+from .utils import send_mail, md5, url_for_security, get_token_status,\
+ config_value
+from .signals import user_confirmed, confirm_instructions_sent
+
+
+# Convenient references
+_security = LocalProxy(lambda: app.extensions['security'])
+
+_datastore = LocalProxy(lambda: _security.datastore)
+
+
+def generate_confirmation_link(user):
+ token = generate_confirmation_token(user)
+ url = url_for_security('confirm_email', token=token)
+ return request.url_root[:-1] + url, token
+
+
+def send_confirmation_instructions(user):
+ """Sends the confirmation instructions email for the specified user.
+
+ :param user: The user to send the instructions to
+ :param token: The confirmation token
+ """
+
+ confirmation_link, token = generate_confirmation_link(user)
+
+ send_mail(config_value('EMAIL_SUBJECT_CONFIRM'), user.email,
+ 'confirmation_instructions', user=user,
+ confirmation_link=confirmation_link)
+
+ confirm_instructions_sent.send(user, app=app._get_current_object())
+ return token
+
+
+def generate_confirmation_token(user):
+ """Generates a unique confirmation token for the specified user.
+
+ :param user: The user to work with
+ """
+ data = [str(user.id), md5(user.email)]
+ return _security.confirm_serializer.dumps(data)
+
+
+def requires_confirmation(user):
+ """Returns `True` if the user requires confirmation."""
+ return _security.confirmable and user.confirmed_at == None
+
+
+def confirm_email_token_status(token):
+ """Returns the expired status, invalid status, and user of a confirmation
+ token. For example::
+
+ expired, invalid, user = confirm_email_token_status('...')
+
+ :param token: The confirmation token
+ """
+ return get_token_status(token, 'confirm', 'CONFIRM_EMAIL')
+
+
+def confirm_user(user):
+ """Confirms the specified user
+
+ :param user: The user to confirm
+ """
+ user.confirmed_at = datetime.utcnow()
+ _datastore.put(user)
+ user_confirmed.send(user, app=app._get_current_object())
diff --git a/wqflask/flask_security/core.py b/wqflask/flask_security/core.py
new file mode 100644
index 00000000..d794fad5
--- /dev/null
+++ b/wqflask/flask_security/core.py
@@ -0,0 +1,381 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.core
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security core module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+from flask import current_app
+from flask.ext.login import AnonymousUser as AnonymousUserBase, \
+ UserMixin as BaseUserMixin, LoginManager, current_user
+from flask.ext.principal import Principal, RoleNeed, UserNeed, Identity, \
+ identity_loaded
+from itsdangerous import URLSafeTimedSerializer
+from passlib.context import CryptContext
+from werkzeug.datastructures import ImmutableList
+from werkzeug.local import LocalProxy
+
+from .utils import config_value as cv, get_config, md5, url_for_security
+from .views import create_blueprint
+from .forms import LoginForm, ConfirmRegisterForm, RegisterForm, \
+ ForgotPasswordForm, ChangePasswordForm, ResetPasswordForm, \
+ SendConfirmationForm, PasswordlessLoginForm
+
+# Convenient references
+_security = LocalProxy(lambda: current_app.extensions['security'])
+
+
+#: Default Flask-Security configuration
+_default_config = {
+ 'BLUEPRINT_NAME': 'security',
+ 'URL_PREFIX': None,
+ 'SUBDOMAIN': None,
+ 'FLASH_MESSAGES': True,
+ 'PASSWORD_HASH': 'plaintext',
+ 'PASSWORD_SALT': None,
+ 'LOGIN_URL': '/login',
+ 'LOGOUT_URL': '/logout',
+ 'REGISTER_URL': '/register',
+ 'RESET_URL': '/reset',
+ 'CHANGE_URL': '/change',
+ 'CONFIRM_URL': '/confirm',
+ 'POST_LOGIN_VIEW': '/',
+ 'POST_LOGOUT_VIEW': '/',
+ 'CONFIRM_ERROR_VIEW': None,
+ 'POST_REGISTER_VIEW': None,
+ 'POST_CONFIRM_VIEW': None,
+ 'POST_RESET_VIEW': None,
+ 'POST_CHANGE_VIEW': None,
+ 'UNAUTHORIZED_VIEW': None,
+ 'FORGOT_PASSWORD_TEMPLATE': 'security/forgot_password.html',
+ 'LOGIN_USER_TEMPLATE': 'security/login_user.html',
+ 'REGISTER_USER_TEMPLATE': 'security/register_user.html',
+ 'RESET_PASSWORD_TEMPLATE': 'security/reset_password.html',
+ 'SEND_CONFIRMATION_TEMPLATE': 'security/send_confirmation.html',
+ 'SEND_LOGIN_TEMPLATE': 'security/send_login.html',
+ 'CONFIRMABLE': False,
+ 'REGISTERABLE': False,
+ 'RECOVERABLE': False,
+ 'TRACKABLE': False,
+ 'PASSWORDLESS': False,
+ 'CHANGEABLE': False,
+ 'SEND_REGISTER_EMAIL': True,
+ 'LOGIN_WITHIN': '1 days',
+ 'CONFIRM_EMAIL_WITHIN': '5 days',
+ 'RESET_PASSWORD_WITHIN': '5 days',
+ 'LOGIN_WITHOUT_CONFIRMATION': False,
+ 'EMAIL_SENDER': 'no-reply@localhost',
+ 'TOKEN_AUTHENTICATION_KEY': 'auth_token',
+ 'TOKEN_AUTHENTICATION_HEADER': 'Authentication-Token',
+ 'CONFIRM_SALT': 'confirm-salt',
+ 'RESET_SALT': 'reset-salt',
+ 'LOGIN_SALT': 'login-salt',
+ 'CHANGE_SALT': 'change-salt',
+ 'REMEMBER_SALT': 'remember-salt',
+ 'DEFAULT_HTTP_AUTH_REALM': 'Login Required',
+ 'EMAIL_SUBJECT_REGISTER': 'Welcome',
+ 'EMAIL_SUBJECT_CONFIRM': 'Please confirm your email',
+ 'EMAIL_SUBJECT_PASSWORDLESS': 'Login instructions',
+ 'EMAIL_SUBJECT_PASSWORD_NOTICE': 'Your password has been reset',
+ 'EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE': 'Your password has been changed',
+ 'EMAIL_SUBJECT_PASSWORD_RESET': 'Password reset instructions'
+}
+
+#: Default Flask-Security messages
+_default_messages = {
+ 'UNAUTHORIZED': ('You do not have permission to view this resource.', 'error'),
+ 'CONFIRM_REGISTRATION': ('Thank you. Confirmation instructions have been sent to %(email)s.', 'success'),
+ 'EMAIL_CONFIRMED': ('Thank you. Your email has been confirmed.', 'success'),
+ 'ALREADY_CONFIRMED': ('Your email has already been confirmed.', 'info'),
+ 'INVALID_CONFIRMATION_TOKEN': ('Invalid confirmation token.', 'error'),
+ 'EMAIL_ALREADY_ASSOCIATED': ('%(email)s is already associated with an account.', 'error'),
+ 'PASSWORD_MISMATCH': ('Password does not match', 'error'),
+ 'RETYPE_PASSWORD_MISMATCH': ('Passwords do not match', 'error'),
+ 'INVALID_REDIRECT': ('Redirections outside the domain are forbidden', 'error'),
+ 'PASSWORD_RESET_REQUEST': ('Instructions to reset your password have been sent to %(email)s.', 'info'),
+ 'PASSWORD_RESET_EXPIRED': ('You did not reset your password within %(within)s. New instructions have been sent to %(email)s.', 'error'),
+ 'INVALID_RESET_PASSWORD_TOKEN': ('Invalid reset password token.', 'error'),
+ 'CONFIRMATION_REQUIRED': ('Email requires confirmation.', 'error'),
+ 'CONFIRMATION_REQUEST': ('Confirmation instructions have been sent to %(email)s.', 'info'),
+ 'CONFIRMATION_EXPIRED': ('You did not confirm your email within %(within)s. New instructions to confirm your email have been sent to %(email)s.', 'error'),
+ 'LOGIN_EXPIRED': ('You did not login within %(within)s. New instructions to login have been sent to %(email)s.', 'error'),
+ 'LOGIN_EMAIL_SENT': ('Instructions to login have been sent to %(email)s.', 'success'),
+ 'INVALID_LOGIN_TOKEN': ('Invalid login token.', 'error'),
+ 'DISABLED_ACCOUNT': ('Account is disabled.', 'error'),
+ 'EMAIL_NOT_PROVIDED': ('Email not provided', 'error'),
+ 'INVALID_EMAIL_ADDRESS': ('Invalid email address', 'error'),
+ 'PASSWORD_NOT_PROVIDED': ('Password not provided', 'error'),
+ 'USER_DOES_NOT_EXIST': ('Specified user does not exist', 'error'),
+ 'INVALID_PASSWORD': ('Invalid password', 'error'),
+ 'PASSWORDLESS_LOGIN_SUCCESSFUL': ('You have successfuly logged in.', 'success'),
+ 'PASSWORD_RESET': ('You successfully reset your password and you have been logged in automatically.', 'success'),
+ 'PASSWORD_CHANGE': ('You successfully changed your password.', 'success'),
+ 'LOGIN': ('Please log in to access this page.', 'info'),
+ 'REFRESH': ('Please reauthenticate to access this page.', 'info'),
+}
+
+_allowed_password_hash_schemes = [
+ 'bcrypt',
+ 'des_crypt',
+ 'pbkdf2_sha256',
+ 'pbkdf2_sha512',
+ 'sha256_crypt',
+ 'sha512_crypt',
+ # And always last one...
+ 'plaintext'
+]
+
+_default_forms = {
+ 'login_form': LoginForm,
+ 'confirm_register_form': ConfirmRegisterForm,
+ 'register_form': RegisterForm,
+ 'forgot_password_form': ForgotPasswordForm,
+ 'reset_password_form': ResetPasswordForm,
+ 'change_password_form': ChangePasswordForm,
+ 'send_confirmation_form': SendConfirmationForm,
+ 'passwordless_login_form': PasswordlessLoginForm,
+}
+
+
+def _user_loader(user_id):
+ return _security.datastore.find_user(id=user_id)
+
+
+def _token_loader(token):
+ try:
+ data = _security.remember_token_serializer.loads(token)
+ user = _security.datastore.find_user(id=data[0])
+ if user and md5(user.password) == data[1]:
+ return user
+ except:
+ pass
+
+ return None
+
+
+def _identity_loader():
+ if not isinstance(current_user._get_current_object(), AnonymousUser):
+ identity = Identity(current_user.id)
+ return identity
+
+
+def _on_identity_loaded(sender, identity):
+ if hasattr(current_user, 'id'):
+ identity.provides.add(UserNeed(current_user.id))
+
+ for role in current_user.roles:
+ identity.provides.add(RoleNeed(role.name))
+
+ identity.user = current_user
+
+
+def _get_login_manager(app):
+ lm = LoginManager()
+ lm.anonymous_user = AnonymousUser
+ lm.login_view = '%s.login' % cv('BLUEPRINT_NAME', app=app)
+ lm.user_loader(_user_loader)
+ lm.token_loader(_token_loader)
+ lm.login_message, lm.login_message_category = cv('MSG_LOGIN', app=app)
+ lm.needs_refresh_message, lm.needs_refresh_message_category = cv('MSG_REFRESH', app=app)
+ lm.init_app(app)
+ return lm
+
+
+def _get_principal(app):
+ p = Principal(app, use_sessions=False)
+ p.identity_loader(_identity_loader)
+ return p
+
+
+def _get_pwd_context(app):
+ pw_hash = cv('PASSWORD_HASH', app=app)
+ if pw_hash not in _allowed_password_hash_schemes:
+ allowed = ', '.join(_allowed_password_hash_schemes[:-1]) + ' and ' + _allowed_password_hash_schemes[-1]
+ raise ValueError("Invalid hash scheme %r. Allowed values are %s" % (pw_hash, allowed))
+ return CryptContext(schemes=_allowed_password_hash_schemes, default=pw_hash)
+
+
+def _get_serializer(app, name):
+ secret_key = app.config.get('SECRET_KEY')
+ salt = app.config.get('SECURITY_%s_SALT' % name.upper())
+ return URLSafeTimedSerializer(secret_key=secret_key, salt=salt)
+
+
+def _get_state(app, datastore, **kwargs):
+ for key, value in get_config(app).items():
+ kwargs[key.lower()] = value
+
+ kwargs.update(dict(
+ app=app,
+ datastore=datastore,
+ login_manager=_get_login_manager(app),
+ principal=_get_principal(app),
+ pwd_context=_get_pwd_context(app),
+ remember_token_serializer=_get_serializer(app, 'remember'),
+ login_serializer=_get_serializer(app, 'login'),
+ reset_serializer=_get_serializer(app, 'reset'),
+ confirm_serializer=_get_serializer(app, 'confirm'),
+ _context_processors={},
+ _send_mail_task=None
+ ))
+
+ for key, value in _default_forms.items():
+ if key not in kwargs or not kwargs[key]:
+ kwargs[key] = value
+
+ return _SecurityState(**kwargs)
+
+
+def _context_processor():
+ return dict(url_for_security=url_for_security, security=_security)
+
+
+class RoleMixin(object):
+ """Mixin for `Role` model definitions"""
+ def __eq__(self, other):
+ return (self.name == other or \
+ self.name == getattr(other, 'name', None))
+
+ def __ne__(self, other):
+ return (self.name != other and
+ self.name != getattr(other, 'name', None))
+
+
+class UserMixin(BaseUserMixin):
+ """Mixin for `User` model definitions"""
+
+ def is_active(self):
+ """Returns `True` if the user is active."""
+ return self.active
+
+ def get_auth_token(self):
+ """Returns the user's authentication token."""
+ data = [str(self.id), md5(self.password)]
+ return _security.remember_token_serializer.dumps(data)
+
+ def has_role(self, role):
+ """Returns `True` if the user identifies with the specified role.
+
+ :param role: A role name or `Role` instance"""
+ return role in self.roles
+
+
+class AnonymousUser(AnonymousUserBase):
+ """AnonymousUser definition"""
+
+ def __init__(self):
+ super(AnonymousUser, self).__init__()
+ self.roles = ImmutableList()
+
+ def has_role(self, *args):
+ """Returns `False`"""
+ return False
+
+
+class _SecurityState(object):
+
+ def __init__(self, **kwargs):
+ for key, value in kwargs.items():
+ setattr(self, key.lower(), value)
+
+ def _add_ctx_processor(self, endpoint, fn):
+ group = self._context_processors.setdefault(endpoint, [])
+ fn not in group and group.append(fn)
+
+ def _run_ctx_processor(self, endpoint):
+ rv, fns = {}, []
+ for g in [None, endpoint]:
+ for fn in self._context_processors.setdefault(g, []):
+ rv.update(fn())
+ return rv
+
+ def context_processor(self, fn):
+ self._add_ctx_processor(None, fn)
+
+ def forgot_password_context_processor(self, fn):
+ self._add_ctx_processor('forgot_password', fn)
+
+ def login_context_processor(self, fn):
+ self._add_ctx_processor('login', fn)
+
+ def register_context_processor(self, fn):
+ self._add_ctx_processor('register', fn)
+
+ def reset_password_context_processor(self, fn):
+ self._add_ctx_processor('reset_password', fn)
+
+ def change_password_context_processor(self, fn):
+ self._add_ctx_processor('change_password', fn)
+
+ def send_confirmation_context_processor(self, fn):
+ self._add_ctx_processor('send_confirmation', fn)
+
+ def send_login_context_processor(self, fn):
+ self._add_ctx_processor('send_login', fn)
+
+ def mail_context_processor(self, fn):
+ self._add_ctx_processor('mail', fn)
+
+ def send_mail_task(self, fn):
+ self._send_mail_task = fn
+
+
+class Security(object):
+ """The :class:`Security` class initializes the Flask-Security extension.
+
+ :param app: The application.
+ :param datastore: An instance of a user datastore.
+ """
+ def __init__(self, app=None, datastore=None, **kwargs):
+ self.app = app
+ self.datastore = datastore
+
+ if app is not None and datastore is not None:
+ self._state = self.init_app(app, datastore, **kwargs)
+
+ def init_app(self, app, datastore=None, register_blueprint=True,
+ login_form=None, confirm_register_form=None,
+ register_form=None, forgot_password_form=None,
+ reset_password_form=None, change_password_form=None,
+ send_confirmation_form=None, passwordless_login_form=None):
+ """Initializes the Flask-Security extension for the specified
+ application and datastore implentation.
+
+ :param app: The application.
+ :param datastore: An instance of a user datastore.
+ :param register_blueprint: to register the Security blueprint or not.
+ """
+ datastore = datastore or self.datastore
+
+ for key, value in _default_config.items():
+ app.config.setdefault('SECURITY_' + key, value)
+
+ for key, value in _default_messages.items():
+ app.config.setdefault('SECURITY_MSG_' + key, value)
+
+ identity_loaded.connect_via(app)(_on_identity_loaded)
+
+ state = _get_state(app, datastore,
+ login_form=login_form,
+ confirm_register_form=confirm_register_form,
+ register_form=register_form,
+ forgot_password_form=forgot_password_form,
+ reset_password_form=reset_password_form,
+ change_password_form=change_password_form,
+ send_confirmation_form=send_confirmation_form,
+ passwordless_login_form=passwordless_login_form)
+
+ if register_blueprint:
+ app.register_blueprint(create_blueprint(state, __name__))
+ app.context_processor(_context_processor)
+
+ app.extensions['security'] = state
+
+ return state
+
+ def __getattr__(self, name):
+ return getattr(self._state, name, None)
diff --git a/wqflask/flask_security/datastore.py b/wqflask/flask_security/datastore.py
new file mode 100644
index 00000000..f8c7218d
--- /dev/null
+++ b/wqflask/flask_security/datastore.py
@@ -0,0 +1,260 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.datastore
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This module contains an user datastore classes.
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+class Datastore(object):
+ def __init__(self, db):
+ self.db = db
+
+ def commit(self):
+ pass
+
+ def put(self, model):
+ raise NotImplementedError
+
+ def delete(self, model):
+ raise NotImplementedError
+
+
+class SQLAlchemyDatastore(Datastore):
+ def commit(self):
+ self.db.session.commit()
+
+ def put(self, model):
+ self.db.session.add(model)
+ return model
+
+ def delete(self, model):
+ self.db.session.delete(model)
+
+
+class MongoEngineDatastore(Datastore):
+ def put(self, model):
+ model.save()
+ return model
+
+ def delete(self, model):
+ model.delete()
+
+
+class PeeweeDatastore(Datastore):
+ def put(self, model):
+ model.save()
+ return model
+
+ def delete(self, model):
+ model.delete_instance()
+
+
+class UserDatastore(object):
+ """Abstracted user datastore.
+
+ :param user_model: A user model class definition
+ :param role_model: A role model class definition
+ """
+
+ def __init__(self, user_model, role_model):
+ self.user_model = user_model
+ self.role_model = role_model
+
+ def _prepare_role_modify_args(self, user, role):
+ if isinstance(user, basestring):
+ user = self.find_user(email=user)
+ if isinstance(role, basestring):
+ role = self.find_role(role)
+ return user, role
+
+ def _prepare_create_user_args(self, **kwargs):
+ kwargs.setdefault('active', True)
+ roles = kwargs.get('roles', [])
+ for i, role in enumerate(roles):
+ rn = role.name if isinstance(role, self.role_model) else role
+ # see if the role exists
+ roles[i] = self.find_role(rn)
+ kwargs['roles'] = roles
+ return kwargs
+
+ def find_user(self, *args, **kwargs):
+ """Returns a user matching the provided parameters."""
+ raise NotImplementedError
+
+ def find_role(self, *args, **kwargs):
+ """Returns a role matching the provided name."""
+ raise NotImplementedError
+
+ def add_role_to_user(self, user, role):
+ """Adds a role tp a user
+
+ :param user: The user to manipulate
+ :param role: The role to add to the user
+ """
+ rv = False
+ user, role = self._prepare_role_modify_args(user, role)
+ if role not in user.roles:
+ rv = True
+ user.roles.append(role)
+ return rv
+
+ def remove_role_from_user(self, user, role):
+ """Removes a role from a user
+
+ :param user: The user to manipulate
+ :param role: The role to remove from the user
+ """
+ rv = False
+ user, role = self._prepare_role_modify_args(user, role)
+ if role in user.roles:
+ rv = True
+ user.roles.remove(role)
+ return rv
+
+ def toggle_active(self, user):
+ """Toggles a user's active status. Always returns True."""
+ user.active = not user.active
+ return True
+
+ def deactivate_user(self, user):
+ """Deactivates a specified user. Returns `True` if a change was made.
+
+ :param user: The user to deactivate
+ """
+ if user.active:
+ user.active = False
+ return True
+ return False
+
+ def activate_user(self, user):
+ """Activates a specified user. Returns `True` if a change was made.
+
+ :param user: The user to activate
+ """
+ if not user.active:
+ user.active = True
+ return True
+ return False
+
+ def create_role(self, **kwargs):
+ """Creates and returns a new role from the given parameters."""
+
+ role = self.role_model(**kwargs)
+ return self.put(role)
+
+ def find_or_create_role(self, name, **kwargs):
+ """Returns a role matching the given name or creates it with any
+ additionally provided parameters
+ """
+ kwargs["name"] = name
+ return self.find_role(name) or self.create_role(**kwargs)
+
+ def create_user(self, **kwargs):
+ """Creates and returns a new user from the given parameters."""
+
+ user = self.user_model(**self._prepare_create_user_args(**kwargs))
+ return self.put(user)
+
+ def delete_user(self, user):
+ """Delete the specified user
+
+ :param user: The user to delete
+ """
+ self.delete(user)
+
+
+class SQLAlchemyUserDatastore(SQLAlchemyDatastore, UserDatastore):
+ """A SQLAlchemy datastore implementation for Flask-Security that assumes the
+ use of the Flask-SQLAlchemy extension.
+ """
+ def __init__(self, db, user_model, role_model):
+ SQLAlchemyDatastore.__init__(self, db)
+ UserDatastore.__init__(self, user_model, role_model)
+
+ def find_user(self, **kwargs):
+ return self.user_model.query.filter_by(**kwargs).first()
+
+ def find_role(self, role):
+ return self.role_model.query.filter_by(name=role).first()
+
+
+class MongoEngineUserDatastore(MongoEngineDatastore, UserDatastore):
+ """A MongoEngine datastore implementation for Flask-Security that assumes
+ the use of the Flask-MongoEngine extension.
+ """
+ def __init__(self, db, user_model, role_model):
+ MongoEngineDatastore.__init__(self, db)
+ UserDatastore.__init__(self, user_model, role_model)
+
+ def find_user(self, **kwargs):
+ return self.user_model.objects(**kwargs).first()
+
+ def find_role(self, role):
+ return self.role_model.objects(name=role).first()
+
+
+class PeeweeUserDatastore(PeeweeDatastore, UserDatastore):
+ """A PeeweeD datastore implementation for Flask-Security that assumes
+ the use of the Flask-Peewee extension.
+
+ :param user_model: A user model class definition
+ :param role_model: A role model class definition
+ :param role_link: A model implementing the many-to-many user-role relation
+ """
+ def __init__(self, db, user_model, role_model, role_link):
+ PeeweeDatastore.__init__(self, db)
+ UserDatastore.__init__(self, user_model, role_model)
+ self.UserRole = role_link
+
+ def find_user(self, **kwargs):
+ try:
+ return self.user_model.filter(**kwargs).get()
+ except self.user_model.DoesNotExist:
+ return None
+
+ def find_role(self, role):
+ try:
+ return self.role_model.filter(name=role).get()
+ except self.role_model.DoesNotExist:
+ return None
+
+ def create_user(self, **kwargs):
+ """Creates and returns a new user from the given parameters."""
+ roles = kwargs.pop('roles', [])
+ user = self.user_model(**self._prepare_create_user_args(**kwargs))
+ user = self.put(user)
+ for role in roles:
+ self.add_role_to_user(user, role)
+ return user
+
+
+ def add_role_to_user(self, user, role):
+ """Adds a role tp a user
+
+ :param user: The user to manipulate
+ :param role: The role to add to the user
+ """
+ user, role = self._prepare_role_modify_args(user, role)
+ if self.UserRole.select().where(self.UserRole.user==user, self.UserRole.role==role).count():
+ return False
+ else:
+ self.UserRole.create(user=user, role=role)
+ return True
+
+ def remove_role_from_user(self, user, role):
+ """Removes a role from a user
+
+ :param user: The user to manipulate
+ :param role: The role to remove from the user
+ """
+ user, role = self._prepare_role_modify_args(user, role)
+ if self.UserRole.select().where(self.UserRole.user==user, self.UserRole.role==role).count():
+ self.UserRole.delete().where(self.UserRole.user==user, self.UserRole.role==role)
+ return True
+ else:
+ return False
+
diff --git a/wqflask/flask_security/decorators.py b/wqflask/flask_security/decorators.py
new file mode 100644
index 00000000..0ea1105c
--- /dev/null
+++ b/wqflask/flask_security/decorators.py
@@ -0,0 +1,207 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.decorators
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security decorators module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+from functools import wraps
+
+from flask import current_app, Response, request, redirect, _request_ctx_stack
+from flask.ext.login import current_user, login_required
+from flask.ext.principal import RoleNeed, Permission, Identity, identity_changed
+from werkzeug.local import LocalProxy
+
+from . import utils
+
+
+# Convenient references
+_security = LocalProxy(lambda: current_app.extensions['security'])
+
+
+_default_unauthorized_html = """
+
Unauthorized
+
The server could not verify that you are authorized to access the URL
+ requested. You either supplied the wrong credentials (e.g. a bad password),
+ or your browser doesn't understand how to supply the credentials required.
+ """
+
+
+def _get_unauthorized_response(text=None, headers=None):
+ text = text or _default_unauthorized_html
+ headers = headers or {}
+ return Response(text, 401, headers)
+
+
+def _get_unauthorized_view():
+ cv = utils.get_url(utils.config_value('UNAUTHORIZED_VIEW'))
+ utils.do_flash(*utils.get_message('UNAUTHORIZED'))
+ return redirect(cv or request.referrer or '/')
+
+
+def _check_token():
+ header_key = _security.token_authentication_header
+ args_key = _security.token_authentication_key
+ header_token = request.headers.get(header_key, None)
+ token = request.args.get(args_key, header_token)
+ if request.json:
+ token = request.json.get(args_key, token)
+ serializer = _security.remember_token_serializer
+
+ try:
+ data = serializer.loads(token)
+ except:
+ return False
+
+ user = _security.datastore.find_user(id=data[0])
+
+ if utils.md5(user.password) == data[1]:
+ app = current_app._get_current_object()
+ _request_ctx_stack.top.user = user
+ identity_changed.send(app, identity=Identity(user.id))
+ return True
+
+
+def _check_http_auth():
+ auth = request.authorization or dict(username=None, password=None)
+ user = _security.datastore.find_user(email=auth.username)
+
+ if user and utils.verify_and_update_password(auth.password, user):
+ _security.datastore.commit()
+ app = current_app._get_current_object()
+ _request_ctx_stack.top.user = user
+ identity_changed.send(app, identity=Identity(user.id))
+ return True
+
+ return False
+
+
+def http_auth_required(realm):
+ """Decorator that protects endpoints using Basic HTTP authentication.
+ The username should be set to the user's email address.
+
+ :param realm: optional realm name"""
+
+ def decorator(fn):
+ @wraps(fn)
+ def wrapper(*args, **kwargs):
+ if _check_http_auth():
+ return fn(*args, **kwargs)
+ r = _security.default_http_auth_realm if callable(realm) else realm
+ h = {'WWW-Authenticate': 'Basic realm="%s"' % r}
+ return _get_unauthorized_response(headers=h)
+ return wrapper
+
+ if callable(realm):
+ return decorator(realm)
+ return decorator
+
+
+def auth_token_required(fn):
+ """Decorator that protects endpoints using token authentication. The token
+ should be added to the request by the client by using a query string
+ variable with a name equal to the configuration value of
+ `SECURITY_TOKEN_AUTHENTICATION_KEY` or in a request header named that of
+ the configuration value of `SECURITY_TOKEN_AUTHENTICATION_HEADER`
+ """
+
+ @wraps(fn)
+ def decorated(*args, **kwargs):
+ if _check_token():
+ return fn(*args, **kwargs)
+ return _get_unauthorized_response()
+ return decorated
+
+
+def auth_required(*auth_methods):
+ """
+ Decorator that protects enpoints through multiple mechanisms
+ Example::
+
+ @app.route('/dashboard')
+ @auth_required('token', 'session')
+ def dashboard():
+ return 'Dashboard'
+
+ :param auth_methods: Specified mechanisms.
+ """
+ login_mechanisms = {
+ 'token': lambda: _check_token(),
+ 'basic': lambda: _check_http_auth(),
+ 'session': lambda: current_user.is_authenticated()
+ }
+
+ def wrapper(fn):
+ @wraps(fn)
+ def decorated_view(*args, **kwargs):
+ mechanisms = [login_mechanisms.get(method) for method in auth_methods]
+ for mechanism in mechanisms:
+ if mechanism and mechanism():
+ return fn(*args, **kwargs)
+ return _get_unauthorized_response()
+ return decorated_view
+ return wrapper
+
+
+def roles_required(*roles):
+ """Decorator which specifies that a user must have all the specified roles.
+ Example::
+
+ @app.route('/dashboard')
+ @roles_required('admin', 'editor')
+ def dashboard():
+ return 'Dashboard'
+
+ The current user must have both the `admin` role and `editor` role in order
+ to view the page.
+
+ :param args: The required roles.
+ """
+ def wrapper(fn):
+ @wraps(fn)
+ def decorated_view(*args, **kwargs):
+ perms = [Permission(RoleNeed(role)) for role in roles]
+ for perm in perms:
+ if not perm.can():
+ return _get_unauthorized_view()
+ return fn(*args, **kwargs)
+ return decorated_view
+ return wrapper
+
+
+def roles_accepted(*roles):
+ """Decorator which specifies that a user must have at least one of the
+ specified roles. Example::
+
+ @app.route('/create_post')
+ @roles_accepted('editor', 'author')
+ def create_post():
+ return 'Create Post'
+
+ The current user must have either the `editor` role or `author` role in
+ order to view the page.
+
+ :param args: The possible roles.
+ """
+ def wrapper(fn):
+ @wraps(fn)
+ def decorated_view(*args, **kwargs):
+ perm = Permission(*[RoleNeed(role) for role in roles])
+ if perm.can():
+ return fn(*args, **kwargs)
+ return _get_unauthorized_view()
+ return decorated_view
+ return wrapper
+
+
+def anonymous_user_required(f):
+ @wraps(f)
+ def wrapper(*args, **kwargs):
+ if current_user.is_authenticated():
+ return redirect(utils.get_url(_security.post_login_view))
+ return f(*args, **kwargs)
+ return wrapper
diff --git a/wqflask/flask_security/forms.py b/wqflask/flask_security/forms.py
new file mode 100644
index 00000000..e64e1502
--- /dev/null
+++ b/wqflask/flask_security/forms.py
@@ -0,0 +1,277 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.forms
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security forms module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+import inspect
+import urlparse
+
+import flask_wtf as wtf
+
+from flask import request, current_app
+from flask_wtf import Form as BaseForm, TextField, PasswordField, \
+ SubmitField, HiddenField, BooleanField, ValidationError, Field
+from flask_login import current_user
+from werkzeug.local import LocalProxy
+
+from .confirmable import requires_confirmation
+from .utils import verify_and_update_password, get_message
+
+# Convenient reference
+_datastore = LocalProxy(lambda: current_app.extensions['security'].datastore)
+
+_default_field_labels = {
+ 'email': 'Email Address',
+ 'password': 'Password',
+ 'remember_me': 'Remember Me',
+ 'login': 'Login',
+ 'retype_password': 'Retype Password',
+ 'register': 'Register',
+ 'send_confirmation': 'Resend Confirmation Instructions',
+ 'recover_password': 'Recover Password',
+ 'reset_password': 'Reset Password',
+ 'retype_password': 'Retype Password',
+ 'new_password': 'New Password',
+ 'change_password': 'Change Password',
+ 'send_login_link': 'Send Login Link'
+}
+
+
+class ValidatorMixin(object):
+ def __call__(self, form, field):
+ if self.message and self.message.isupper():
+ self.message = get_message(self.message)[0]
+ return super(ValidatorMixin, self).__call__(form, field)
+
+
+class EqualTo(ValidatorMixin, wtf.EqualTo):
+ pass
+
+
+class Required(ValidatorMixin, wtf.Required):
+ pass
+
+
+class Email(ValidatorMixin, wtf.Email):
+ pass
+
+
+class Length(ValidatorMixin, wtf.Length):
+ pass
+
+
+email_required = Required(message='EMAIL_NOT_PROVIDED')
+email_validator = Email(message='INVALID_EMAIL_ADDRESS')
+password_required = Required(message='PASSWORD_NOT_PROVIDED')
+
+
+def get_form_field_label(key):
+ return _default_field_labels.get(key, '')
+
+
+def unique_user_email(form, field):
+ if _datastore.find_user(email=field.data) is not None:
+ msg = get_message('EMAIL_ALREADY_ASSOCIATED', email=field.data)[0]
+ raise ValidationError(msg)
+
+
+def valid_user_email(form, field):
+ form.user = _datastore.find_user(email=field.data)
+ if form.user is None:
+ raise ValidationError(get_message('USER_DOES_NOT_EXIST')[0])
+
+
+class Form(BaseForm):
+ def __init__(self, *args, **kwargs):
+ if current_app.testing:
+ self.TIME_LIMIT = None
+ super(Form, self).__init__(*args, **kwargs)
+
+
+class EmailFormMixin():
+ email = TextField(get_form_field_label('email'),
+ validators=[email_required,
+ email_validator])
+
+
+class UserEmailFormMixin():
+ user = None
+ email = TextField(get_form_field_label('email'),
+ validators=[email_required,
+ email_validator,
+ valid_user_email])
+
+
+class UniqueEmailFormMixin():
+ email = TextField(get_form_field_label('email'),
+ validators=[email_required,
+ email_validator,
+ unique_user_email])
+
+
+class PasswordFormMixin():
+ password = PasswordField(get_form_field_label('password'),
+ validators=[password_required])
+
+
+class NewPasswordFormMixin():
+ password = PasswordField(get_form_field_label('password'),
+ validators=[password_required,
+ Length(min=6, max=128)])
+
+
+class PasswordConfirmFormMixin():
+ password_confirm = PasswordField(
+ get_form_field_label('retype_password'),
+ validators=[EqualTo('password', message='RETYPE_PASSWORD_MISMATCH')])
+
+
+class NextFormMixin():
+ next = HiddenField()
+
+ def validate_next(self, field):
+ url_next = urlparse.urlsplit(field.data)
+ url_base = urlparse.urlsplit(request.host_url)
+ if url_next.netloc and url_next.netloc != url_base.netloc:
+ field.data = ''
+ raise ValidationError(get_message('INVALID_REDIRECT')[0])
+
+
+class RegisterFormMixin():
+ submit = SubmitField(get_form_field_label('register'))
+
+ def to_dict(form):
+ def is_field_and_user_attr(member):
+ return isinstance(member, Field) and \
+ hasattr(_datastore.user_model, member.name)
+
+ fields = inspect.getmembers(form, is_field_and_user_attr)
+ return dict((key, value.data) for key, value in fields)
+
+
+class SendConfirmationForm(Form, UserEmailFormMixin):
+ """The default forgot password form"""
+
+ submit = SubmitField(get_form_field_label('send_confirmation'))
+
+ def __init__(self, *args, **kwargs):
+ super(SendConfirmationForm, self).__init__(*args, **kwargs)
+ if request.method == 'GET':
+ self.email.data = request.args.get('email', None)
+
+ def validate(self):
+ if not super(SendConfirmationForm, self).validate():
+ return False
+ if self.user.confirmed_at is not None:
+ self.email.errors.append(get_message('ALREADY_CONFIRMED')[0])
+ return False
+ return True
+
+
+class ForgotPasswordForm(Form, UserEmailFormMixin):
+ """The default forgot password form"""
+
+ submit = SubmitField(get_form_field_label('recover_password'))
+
+
+class PasswordlessLoginForm(Form, UserEmailFormMixin):
+ """The passwordless login form"""
+
+ submit = SubmitField(get_form_field_label('send_login_link'))
+
+ def __init__(self, *args, **kwargs):
+ super(PasswordlessLoginForm, self).__init__(*args, **kwargs)
+
+ def validate(self):
+ if not super(PasswordlessLoginForm, self).validate():
+ return False
+ if not self.user.is_active():
+ self.email.errors.append(get_message('DISABLED_ACCOUNT')[0])
+ return False
+ return True
+
+
+class LoginForm(Form, NextFormMixin):
+ """The default login form"""
+
+ email = TextField(get_form_field_label('email'))
+ password = PasswordField(get_form_field_label('password'))
+ remember = BooleanField(get_form_field_label('remember_me'))
+ submit = SubmitField(get_form_field_label('login'))
+
+ def __init__(self, *args, **kwargs):
+ super(LoginForm, self).__init__(*args, **kwargs)
+
+ def validate(self):
+ if not super(LoginForm, self).validate():
+ return False
+
+ if self.email.data.strip() == '':
+ self.email.errors.append(get_message('EMAIL_NOT_PROVIDED')[0])
+ return False
+
+ if self.password.data.strip() == '':
+ self.password.errors.append(get_message('PASSWORD_NOT_PROVIDED')[0])
+ return False
+
+ self.user = _datastore.find_user(email=self.email.data)
+
+ if self.user is None:
+ self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0])
+ return False
+ if not verify_and_update_password(self.password.data, self.user):
+ self.password.errors.append(get_message('INVALID_PASSWORD')[0])
+ return False
+ if requires_confirmation(self.user):
+ self.email.errors.append(get_message('CONFIRMATION_REQUIRED')[0])
+ return False
+ if not self.user.is_active():
+ self.email.errors.append(get_message('DISABLED_ACCOUNT')[0])
+ return False
+ return True
+
+
+class ConfirmRegisterForm(Form, RegisterFormMixin,
+ UniqueEmailFormMixin, NewPasswordFormMixin):
+ pass
+
+
+class RegisterForm(ConfirmRegisterForm, PasswordConfirmFormMixin):
+ pass
+
+
+class ResetPasswordForm(Form, NewPasswordFormMixin, PasswordConfirmFormMixin):
+ """The default reset password form"""
+
+ submit = SubmitField(get_form_field_label('reset_password'))
+
+
+class ChangePasswordForm(Form, PasswordFormMixin):
+ """The default change password form"""
+
+ new_password = PasswordField(get_form_field_label('new_password'),
+ validators=[password_required,
+ Length(min=6, max=128)])
+
+ new_password_confirm = PasswordField(get_form_field_label('retype_password'),
+ validators=[EqualTo('new_password', message='RETYPE_PASSWORD_MISMATCH')])
+
+ submit = SubmitField(get_form_field_label('change_password'))
+
+ def validate(self):
+ if not super(ChangePasswordForm, self).validate():
+ return False
+
+ if self.password.data.strip() == '':
+ self.password.errors.append(get_message('PASSWORD_NOT_PROVIDED')[0])
+ return False
+ if not verify_and_update_password(self.password.data, current_user):
+ self.password.errors.append(get_message('INVALID_PASSWORD')[0])
+ return False
+ return True
diff --git a/wqflask/flask_security/passwordless.py b/wqflask/flask_security/passwordless.py
new file mode 100644
index 00000000..b0accb2c
--- /dev/null
+++ b/wqflask/flask_security/passwordless.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.passwordless
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security passwordless module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+from flask import request, current_app as app
+from werkzeug.local import LocalProxy
+
+from .signals import login_instructions_sent
+from .utils import send_mail, url_for_security, get_token_status, \
+ config_value
+
+
+# Convenient references
+_security = LocalProxy(lambda: app.extensions['security'])
+
+_datastore = LocalProxy(lambda: _security.datastore)
+
+
+def send_login_instructions(user):
+ """Sends the login instructions email for the specified user.
+
+ :param user: The user to send the instructions to
+ :param token: The login token
+ """
+ token = generate_login_token(user)
+ url = url_for_security('token_login', token=token)
+ login_link = request.url_root[:-1] + url
+
+ send_mail(config_value('EMAIL_SUBJECT_PASSWORDLESS'), user.email,
+ 'login_instructions', user=user, login_link=login_link)
+
+ login_instructions_sent.send(dict(user=user, login_token=token),
+ app=app._get_current_object())
+
+
+def generate_login_token(user):
+ """Generates a unique login token for the specified user.
+
+ :param user: The user the token belongs to
+ """
+ return _security.login_serializer.dumps([str(user.id)])
+
+
+def login_token_status(token):
+ """Returns the expired status, invalid status, and user of a login token.
+ For example::
+
+ expired, invalid, user = login_token_status('...')
+
+ :param token: The login token
+ """
+ return get_token_status(token, 'login', 'LOGIN')
diff --git a/wqflask/flask_security/recoverable.py b/wqflask/flask_security/recoverable.py
new file mode 100644
index 00000000..6aafc111
--- /dev/null
+++ b/wqflask/flask_security/recoverable.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.recoverable
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security recoverable module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+from flask import current_app as app, request
+from werkzeug.local import LocalProxy
+
+from .signals import password_reset, reset_password_instructions_sent
+from .utils import send_mail, md5, encrypt_password, url_for_security, \
+ get_token_status, config_value
+
+
+# Convenient references
+_security = LocalProxy(lambda: app.extensions['security'])
+
+_datastore = LocalProxy(lambda: _security.datastore)
+
+
+def send_reset_password_instructions(user):
+ """Sends the reset password instructions email for the specified user.
+
+ :param user: The user to send the instructions to
+ """
+ token = generate_reset_password_token(user)
+ url = url_for_security('reset_password', token=token)
+ reset_link = request.url_root[:-1] + url
+
+ send_mail(config_value('EMAIL_SUBJECT_PASSWORD_RESET'), user.email,
+ 'reset_instructions',
+ user=user, reset_link=reset_link)
+
+ reset_password_instructions_sent.send(dict(user=user, token=token),
+ app=app._get_current_object())
+
+
+def send_password_reset_notice(user):
+ """Sends the password reset notice email for the specified user.
+
+ :param user: The user to send the notice to
+ """
+ send_mail(config_value('EMAIL_SUBJECT_PASSWORD_NOTICE'), user.email,
+ 'reset_notice', user=user)
+
+
+def generate_reset_password_token(user):
+ """Generates a unique reset password token for the specified user.
+
+ :param user: The user to work with
+ """
+ data = [str(user.id), md5(user.password)]
+ return _security.reset_serializer.dumps(data)
+
+
+def reset_password_token_status(token):
+ """Returns the expired status, invalid status, and user of a password reset
+ token. For example::
+
+ expired, invalid, user = reset_password_token_status('...')
+
+ :param token: The password reset token
+ """
+ return get_token_status(token, 'reset', 'RESET_PASSWORD')
+
+def update_password(user, password):
+ """Update the specified user's password
+
+ :param user: The user to update_password
+ :param password: The unencrypted new password
+ """
+ user.password = encrypt_password(password)
+ _datastore.put(user)
+ send_password_reset_notice(user)
+ password_reset.send(user, app=app._get_current_object())
diff --git a/wqflask/flask_security/registerable.py b/wqflask/flask_security/registerable.py
new file mode 100644
index 00000000..4e9f357d
--- /dev/null
+++ b/wqflask/flask_security/registerable.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.registerable
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security registerable module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+from flask import current_app as app
+from werkzeug.local import LocalProxy
+
+from .confirmable import generate_confirmation_link
+from .signals import user_registered
+from .utils import do_flash, get_message, send_mail, encrypt_password, \
+ config_value
+
+# Convenient references
+_security = LocalProxy(lambda: app.extensions['security'])
+
+_datastore = LocalProxy(lambda: _security.datastore)
+
+
+def register_user(**kwargs):
+ confirmation_link, token = None, None
+ kwargs['password'] = encrypt_password(kwargs['password'])
+ user = _datastore.create_user(**kwargs)
+ _datastore.commit()
+
+ if _security.confirmable:
+ confirmation_link, token = generate_confirmation_link(user)
+ do_flash(*get_message('CONFIRM_REGISTRATION', email=user.email))
+
+ user_registered.send(dict(user=user, confirm_token=token),
+ app=app._get_current_object())
+
+ if config_value('SEND_REGISTER_EMAIL'):
+ send_mail(config_value('EMAIL_SUBJECT_REGISTER'), user.email, 'welcome',
+ user=user, confirmation_link=confirmation_link)
+
+ return user
diff --git a/wqflask/flask_security/script.py b/wqflask/flask_security/script.py
new file mode 100644
index 00000000..9c9a2469
--- /dev/null
+++ b/wqflask/flask_security/script.py
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.script
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security script module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+try:
+ import simplejson as json
+except ImportError:
+ import json
+
+import re
+
+from flask import current_app
+from flask.ext.script import Command, Option
+from werkzeug.local import LocalProxy
+
+from .utils import encrypt_password
+
+
+_datastore = LocalProxy(lambda: current_app.extensions['security'].datastore)
+
+
+def pprint(obj):
+ print json.dumps(obj, sort_keys=True, indent=4)
+
+
+def commit(fn):
+ def wrapper(*args, **kwargs):
+ fn(*args, **kwargs)
+ _datastore.commit()
+ return wrapper
+
+
+class CreateUserCommand(Command):
+ """Create a user"""
+
+ option_list = (
+ Option('-e', '--email', dest='email', default=None),
+ Option('-p', '--password', dest='password', default=None),
+ Option('-a', '--active', dest='active', default=''),
+ )
+
+ @commit
+ def run(self, **kwargs):
+ # sanitize active input
+ ai = re.sub(r'\s', '', str(kwargs['active']))
+ kwargs['active'] = ai.lower() in ['', 'y', 'yes', '1', 'active']
+
+ from flask_security.forms import ConfirmRegisterForm
+ from werkzeug.datastructures import MultiDict
+
+ form = ConfirmRegisterForm(MultiDict(kwargs), csrf_enabled=False)
+
+ if form.validate():
+ kwargs['password'] = encrypt_password(kwargs['password'])
+ _datastore.create_user(**kwargs)
+ print 'User created successfully.'
+ kwargs['password'] = '****'
+ pprint(kwargs)
+ else:
+ print 'Error creating user'
+ pprint(form.errors)
+
+
+class CreateRoleCommand(Command):
+ """Create a role"""
+
+ option_list = (
+ Option('-n', '--name', dest='name', default=None),
+ Option('-d', '--desc', dest='description', default=None),
+ )
+
+ @commit
+ def run(self, **kwargs):
+ _datastore.create_role(**kwargs)
+ print 'Role "%(name)s" created successfully.' % kwargs
+
+
+class _RoleCommand(Command):
+ option_list = (
+ Option('-u', '--user', dest='user_identifier'),
+ Option('-r', '--role', dest='role_name'),
+ )
+
+
+class AddRoleCommand(_RoleCommand):
+ """Add a role to a user"""
+
+ @commit
+ def run(self, user_identifier, role_name):
+ _datastore.add_role_to_user(user_identifier, role_name)
+ print "Role '%s' added to user '%s' successfully" % (role_name, user_identifier)
+
+
+class RemoveRoleCommand(_RoleCommand):
+ """Add a role to a user"""
+
+ @commit
+ def run(self, user_identifier, role_name):
+ _datastore.remove_role_from_user(user_identifier, role_name)
+ print "Role '%s' removed from user '%s' successfully" % (role_name, user_identifier)
+
+
+class _ToggleActiveCommand(Command):
+ option_list = (
+ Option('-u', '--user', dest='user_identifier'),
+ )
+
+
+class DeactivateUserCommand(_ToggleActiveCommand):
+ """Deactive a user"""
+
+ @commit
+ def run(self, user_identifier):
+ _datastore.deactivate_user(user_identifier)
+ print "User '%s' has been deactivated" % user_identifier
+
+
+class ActivateUserCommand(_ToggleActiveCommand):
+ """Deactive a user"""
+
+ @commit
+ def run(self, user_identifier):
+ _datastore.activate_user(user_identifier)
+ print "User '%s' has been activated" % user_identifier
diff --git a/wqflask/flask_security/signals.py b/wqflask/flask_security/signals.py
new file mode 100644
index 00000000..e1c29548
--- /dev/null
+++ b/wqflask/flask_security/signals.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.signals
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security signals module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+import blinker
+
+
+signals = blinker.Namespace()
+
+user_registered = signals.signal("user-registered")
+
+user_confirmed = signals.signal("user-confirmed")
+
+confirm_instructions_sent = signals.signal("confirm-instructions-sent")
+
+login_instructions_sent = signals.signal("login-instructions-sent")
+
+password_reset = signals.signal("password-reset")
+
+password_changed = signals.signal("password-changed")
+
+reset_password_instructions_sent = signals.signal("password-reset-instructions-sent")
diff --git a/wqflask/flask_security/templates/.DS_Store b/wqflask/flask_security/templates/.DS_Store
new file mode 100644
index 00000000..b72f1d98
Binary files /dev/null and b/wqflask/flask_security/templates/.DS_Store differ
diff --git a/wqflask/flask_security/templates/security/.DS_Store b/wqflask/flask_security/templates/security/.DS_Store
new file mode 100644
index 00000000..5008ddfc
Binary files /dev/null and b/wqflask/flask_security/templates/security/.DS_Store differ
diff --git a/wqflask/flask_security/templates/security/_macros.html b/wqflask/flask_security/templates/security/_macros.html
new file mode 100644
index 00000000..8575f3db
--- /dev/null
+++ b/wqflask/flask_security/templates/security/_macros.html
@@ -0,0 +1,16 @@
+{% macro render_field_with_errors(field) %}
+
+ {{ field.label }} {{ field(**kwargs)|safe }}
+ {% if field.errors %}
+
+ {% for error in field.errors %}
+ {{ error }}
+ {% endfor %}
+
+ {% endif %}
+
+{% endmacro %}
+
+{% macro render_field(field) %}
+
{{ field(**kwargs)|safe }}
+{% endmacro %}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/_menu.html b/wqflask/flask_security/templates/security/_menu.html
new file mode 100644
index 00000000..5291f809
--- /dev/null
+++ b/wqflask/flask_security/templates/security/_menu.html
@@ -0,0 +1,15 @@
+{% if security.registerable or security.recoverable or security.confirmabled %}
+
Menu
+
+{% endif %}
diff --git a/wqflask/flask_security/templates/security/_messages.html b/wqflask/flask_security/templates/security/_messages.html
new file mode 100644
index 00000000..179d0636
--- /dev/null
+++ b/wqflask/flask_security/templates/security/_messages.html
@@ -0,0 +1,9 @@
+{%- with messages = get_flashed_messages(with_categories=true) -%}
+ {% if messages %}
+
+ {% for category, message in messages %}
+ {{ message }}
+ {% endfor %}
+
+ {% endif %}
+{%- endwith %}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/change_password.html b/wqflask/flask_security/templates/security/change_password.html
new file mode 100644
index 00000000..8ee3eb73
--- /dev/null
+++ b/wqflask/flask_security/templates/security/change_password.html
@@ -0,0 +1,11 @@
+{% from "security/_macros.html" import render_field_with_errors, render_field %}
+{% include "security/_messages.html" %}
+
Change password
+
+
diff --git a/wqflask/flask_security/templates/security/email/change_notice.html b/wqflask/flask_security/templates/security/email/change_notice.html
new file mode 100644
index 00000000..d1224cf5
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/change_notice.html
@@ -0,0 +1,4 @@
+
Your password has been changed.
+{% if security.recoverable %}
+
If you did not change your password, click here to reset it .
+{% endif %}
diff --git a/wqflask/flask_security/templates/security/email/change_notice.txt b/wqflask/flask_security/templates/security/email/change_notice.txt
new file mode 100644
index 00000000..e74bd80d
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/change_notice.txt
@@ -0,0 +1,5 @@
+Your password has been changed
+{% if security.recoverable %}
+If you did not change your password, click the link below to reset it.
+{{ url_for_security('forgot_password', _external=True) }}
+{% endif %}
diff --git a/wqflask/flask_security/templates/security/email/confirmation_instructions.html b/wqflask/flask_security/templates/security/email/confirmation_instructions.html
new file mode 100644
index 00000000..5082a9a8
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/confirmation_instructions.html
@@ -0,0 +1,3 @@
+
Please confirm your email through the link below:
+
+
Confirm my account
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/confirmation_instructions.txt b/wqflask/flask_security/templates/security/email/confirmation_instructions.txt
new file mode 100644
index 00000000..fb435b55
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/confirmation_instructions.txt
@@ -0,0 +1,3 @@
+Please confirm your email through the link below:
+
+{{ confirmation_link }}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/login_instructions.html b/wqflask/flask_security/templates/security/email/login_instructions.html
new file mode 100644
index 00000000..45a7cb57
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/login_instructions.html
@@ -0,0 +1,5 @@
+
Welcome {{ user.email }}!
+
+
You can log into your through the link below:
+
+
Login now
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/login_instructions.txt b/wqflask/flask_security/templates/security/email/login_instructions.txt
new file mode 100644
index 00000000..1364ed65
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/login_instructions.txt
@@ -0,0 +1,5 @@
+Welcome {{ user.email }}!
+
+You can log into your through the link below:
+
+{{ login_link }}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/reset_instructions.html b/wqflask/flask_security/templates/security/email/reset_instructions.html
new file mode 100644
index 00000000..fd0b48d8
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/reset_instructions.html
@@ -0,0 +1 @@
+
Click here to reset your password
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/reset_instructions.txt b/wqflask/flask_security/templates/security/email/reset_instructions.txt
new file mode 100644
index 00000000..91ac288e
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/reset_instructions.txt
@@ -0,0 +1,3 @@
+Click the link below to reset your password:
+
+{{ reset_link }}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/reset_notice.html b/wqflask/flask_security/templates/security/email/reset_notice.html
new file mode 100644
index 00000000..536e2961
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/reset_notice.html
@@ -0,0 +1 @@
+
Your password has been reset
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/reset_notice.txt b/wqflask/flask_security/templates/security/email/reset_notice.txt
new file mode 100644
index 00000000..a3fa0b4b
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/reset_notice.txt
@@ -0,0 +1 @@
+Your password has been reset
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/welcome.html b/wqflask/flask_security/templates/security/email/welcome.html
new file mode 100644
index 00000000..55eaed61
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/welcome.html
@@ -0,0 +1,7 @@
+
Welcome {{ user.email }}!
+
+{% if security.confirmable %}
+
You can confirm your email through the link below:
+
+
Confirm my account
+{% endif %}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/email/welcome.txt b/wqflask/flask_security/templates/security/email/welcome.txt
new file mode 100644
index 00000000..fb6ee5b5
--- /dev/null
+++ b/wqflask/flask_security/templates/security/email/welcome.txt
@@ -0,0 +1,7 @@
+Welcome {{ user.email }}!
+
+{% if security.confirmable %}
+You can confirm your email through the link below:
+
+{{ confirmation_link }}
+{% endif %}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/forgot_password.html b/wqflask/flask_security/templates/security/forgot_password.html
new file mode 100644
index 00000000..90fcaf66
--- /dev/null
+++ b/wqflask/flask_security/templates/security/forgot_password.html
@@ -0,0 +1,9 @@
+{% from "security/_macros.html" import render_field_with_errors, render_field %}
+{% include "security/_messages.html" %}
+
Send password reset instructions
+
+{% include "security/_menu.html" %}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/login_user.html b/wqflask/flask_security/templates/security/login_user.html
new file mode 100644
index 00000000..d781ce08
--- /dev/null
+++ b/wqflask/flask_security/templates/security/login_user.html
@@ -0,0 +1,12 @@
+{% from "security/_macros.html" import render_field_with_errors, render_field %}
+{% include "security/_messages.html" %}
+
Login
+
+{% include "security/_menu.html" %}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/register_user.html b/wqflask/flask_security/templates/security/register_user.html
new file mode 100644
index 00000000..87cf9b1d
--- /dev/null
+++ b/wqflask/flask_security/templates/security/register_user.html
@@ -0,0 +1,13 @@
+{% from "security/_macros.html" import render_field_with_errors, render_field %}
+{% include "security/_messages.html" %}
+
Register
+
+{% include "security/_menu.html" %}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/reset_password.html b/wqflask/flask_security/templates/security/reset_password.html
new file mode 100644
index 00000000..e6fc3f58
--- /dev/null
+++ b/wqflask/flask_security/templates/security/reset_password.html
@@ -0,0 +1,10 @@
+{% from "security/_macros.html" import render_field_with_errors, render_field %}
+{% include "security/_messages.html" %}
+
Reset password
+
+{% include "security/_menu.html" %}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/send_confirmation.html b/wqflask/flask_security/templates/security/send_confirmation.html
new file mode 100644
index 00000000..3e828407
--- /dev/null
+++ b/wqflask/flask_security/templates/security/send_confirmation.html
@@ -0,0 +1,9 @@
+{% from "security/_macros.html" import render_field_with_errors, render_field %}
+{% include "security/_messages.html" %}
+
Resend confirmation instructions
+
+{% include "security/_menu.html" %}
\ No newline at end of file
diff --git a/wqflask/flask_security/templates/security/send_login.html b/wqflask/flask_security/templates/security/send_login.html
new file mode 100644
index 00000000..15611c57
--- /dev/null
+++ b/wqflask/flask_security/templates/security/send_login.html
@@ -0,0 +1,9 @@
+{% from "security/_macros.html" import render_field_with_errors, render_field %}
+{% include "security/_messages.html" %}
+
Login
+
+{% include "security/_menu.html" %}
\ No newline at end of file
diff --git a/wqflask/flask_security/utils.py b/wqflask/flask_security/utils.py
new file mode 100644
index 00000000..7397ab4f
--- /dev/null
+++ b/wqflask/flask_security/utils.py
@@ -0,0 +1,379 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.utils
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security utils module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+import base64
+import blinker
+import functools
+import hashlib
+import hmac
+from contextlib import contextmanager
+from datetime import datetime, timedelta
+
+from flask import url_for, flash, current_app, request, session, render_template
+from flask.ext.login import login_user as _login_user, \
+ logout_user as _logout_user
+from flask.ext.mail import Message
+from flask.ext.principal import Identity, AnonymousIdentity, identity_changed
+from itsdangerous import BadSignature, SignatureExpired
+from werkzeug.local import LocalProxy
+
+from .signals import user_registered, user_confirmed, \
+ confirm_instructions_sent, login_instructions_sent, \
+ password_reset, password_changed, reset_password_instructions_sent
+
+# Convenient references
+_security = LocalProxy(lambda: current_app.extensions['security'])
+
+_datastore = LocalProxy(lambda: _security.datastore)
+
+_pwd_context = LocalProxy(lambda: _security.pwd_context)
+
+
+def login_user(user, remember=True):
+ """Performs the login and sends the appropriate signal."""
+
+ if not _login_user(user, remember):
+ return False
+
+ if _security.trackable:
+ old_current_login, new_current_login = user.current_login_at, datetime.utcnow()
+ remote_addr = request.remote_addr or 'untrackable'
+ old_current_ip, new_current_ip = user.current_login_ip, remote_addr
+
+ user.last_login_at = old_current_login or new_current_login
+ user.current_login_at = new_current_login
+ user.last_login_ip = old_current_ip or new_current_ip
+ user.current_login_ip = new_current_ip
+ user.login_count = user.login_count + 1 if user.login_count else 1
+
+ _datastore.put(user)
+
+ identity_changed.send(current_app._get_current_object(),
+ identity=Identity(user.id))
+ return True
+
+
+def logout_user():
+ for key in ('identity.name', 'identity.auth_type'):
+ session.pop(key, None)
+ identity_changed.send(current_app._get_current_object(),
+ identity=AnonymousIdentity())
+ _logout_user()
+
+
+def get_hmac(password):
+ if _security.password_hash == 'plaintext':
+ return password
+
+ if _security.password_salt is None:
+ raise RuntimeError('The configuration value `SECURITY_PASSWORD_SALT` '
+ 'must not be None when the value of `SECURITY_PASSWORD_HASH` is '
+ 'set to "%s"' % _security.password_hash)
+
+ h = hmac.new(_security.password_salt, password.encode('utf-8'), hashlib.sha512)
+ return base64.b64encode(h.digest())
+
+
+def verify_password(password, password_hash):
+ return _pwd_context.verify(get_hmac(password), password_hash)
+
+
+def verify_and_update_password(password, user):
+ verified, new_password = _pwd_context.verify_and_update(get_hmac(password), user.password)
+ if verified and new_password:
+ user.password = new_password
+ _datastore.put(user)
+ return verified
+
+
+def encrypt_password(password):
+ return _pwd_context.encrypt(get_hmac(password))
+
+
+def md5(data):
+ return hashlib.md5(data).hexdigest()
+
+
+def do_flash(message, category=None):
+ """Flash a message depending on if the `FLASH_MESSAGES` configuration
+ value is set.
+
+ :param message: The flash message
+ :param category: The flash message category
+ """
+ if config_value('FLASH_MESSAGES'):
+ flash(message, category)
+
+
+def get_url(endpoint_or_url):
+ """Returns a URL if a valid endpoint is found. Otherwise, returns the
+ provided value.
+
+ :param endpoint_or_url: The endpoint name or URL to default to
+ """
+ try:
+ return url_for(endpoint_or_url)
+ except:
+ return endpoint_or_url
+
+
+def get_security_endpoint_name(endpoint):
+ return '%s.%s' % (_security.blueprint_name, endpoint)
+
+
+def url_for_security(endpoint, **values):
+ """Return a URL for the security blueprint
+
+ :param endpoint: the endpoint of the URL (name of the function)
+ :param values: the variable arguments of the URL rule
+ :param _external: if set to `True`, an absolute URL is generated. Server
+ address can be changed via `SERVER_NAME` configuration variable which
+ defaults to `localhost`.
+ :param _anchor: if provided this is added as anchor to the URL.
+ :param _method: if provided this explicitly specifies an HTTP method.
+ """
+ endpoint = get_security_endpoint_name(endpoint)
+ return url_for(endpoint, **values)
+
+
+def get_post_login_redirect():
+ """Returns the URL to redirect to after a user logs in successfully."""
+ return (get_url(request.args.get('next')) or
+ get_url(request.form.get('next')) or
+ find_redirect('SECURITY_POST_LOGIN_VIEW'))
+
+
+def find_redirect(key):
+ """Returns the URL to redirect to after a user logs in successfully.
+
+ :param key: The session or application configuration key to search for
+ """
+ rv = (get_url(session.pop(key.lower(), None)) or
+ get_url(current_app.config[key.upper()] or None) or '/')
+ return rv
+
+
+def get_config(app):
+ """Conveniently get the security configuration for the specified
+ application without the annoying 'SECURITY_' prefix.
+
+ :param app: The application to inspect
+ """
+ items = app.config.items()
+ prefix = 'SECURITY_'
+
+ def strip_prefix(tup):
+ return (tup[0].replace('SECURITY_', ''), tup[1])
+
+ return dict([strip_prefix(i) for i in items if i[0].startswith(prefix)])
+
+
+def get_message(key, **kwargs):
+ rv = config_value('MSG_' + key)
+ return rv[0] % kwargs, rv[1]
+
+
+def config_value(key, app=None, default=None):
+ """Get a Flask-Security configuration value.
+
+ :param key: The configuration key without the prefix `SECURITY_`
+ :param app: An optional specific application to inspect. Defaults to Flask's
+ `current_app`
+ :param default: An optional default value if the value is not set
+ """
+ app = app or current_app
+ return get_config(app).get(key.upper(), default)
+
+
+def get_max_age(key, app=None):
+ now = datetime.utcnow()
+ expires = now + get_within_delta(key + '_WITHIN', app)
+ td = (expires - now)
+ return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 1e6) / 1e6
+
+
+def get_within_delta(key, app=None):
+ """Get a timedelta object from the application configuration following
+ the internal convention of::
+
+
+
+ Examples of valid config values::
+
+ 5 days
+ 10 minutes
+
+ :param key: The config value key without the 'SECURITY_' prefix
+ :param app: Optional application to inspect. Defaults to Flask's
+ `current_app`
+ """
+ txt = config_value(key, app=app)
+ values = txt.split()
+ return timedelta(**{values[1]: int(values[0])})
+
+
+def send_mail(subject, recipient, template, **context):
+ """Send an email via the Flask-Mail extension.
+
+ :param subject: Email subject
+ :param recipient: Email recipient
+ :param template: The name of the email template
+ :param context: The context to render the template with
+ """
+
+ context.setdefault('security', _security)
+ context.update(_security._run_ctx_processor('mail'))
+
+ msg = Message(subject,
+ sender=_security.email_sender,
+ recipients=[recipient])
+
+ ctx = ('security/email', template)
+ msg.body = render_template('%s/%s.txt' % ctx, **context)
+ msg.html = render_template('%s/%s.html' % ctx, **context)
+
+ if _security._send_mail_task:
+ _security._send_mail_task(msg)
+ return
+
+ mail = current_app.extensions.get('mail')
+ mail.send(msg)
+
+
+def get_token_status(token, serializer, max_age=None):
+ serializer = getattr(_security, serializer + '_serializer')
+ max_age = get_max_age(max_age)
+ user, data = None, None
+ expired, invalid = False, False
+
+ try:
+ data = serializer.loads(token, max_age=max_age)
+ except SignatureExpired:
+ d, data = serializer.loads_unsafe(token)
+ expired = True
+ except BadSignature:
+ invalid = True
+
+ if data:
+ user = _datastore.find_user(id=data[0])
+
+ expired = expired and (user is not None)
+ return expired, invalid, user
+
+
+@contextmanager
+def capture_passwordless_login_requests():
+ login_requests = []
+
+ def _on(data, app):
+ login_requests.append(data)
+
+ login_instructions_sent.connect(_on)
+
+ try:
+ yield login_requests
+ finally:
+ login_instructions_sent.disconnect(_on)
+
+
+@contextmanager
+def capture_registrations():
+ """Testing utility for capturing registrations.
+
+ :param confirmation_sent_at: An optional datetime object to set the
+ user's `confirmation_sent_at` to
+ """
+ registrations = []
+
+ def _on(data, app):
+ registrations.append(data)
+
+ user_registered.connect(_on)
+
+ try:
+ yield registrations
+ finally:
+ user_registered.disconnect(_on)
+
+
+@contextmanager
+def capture_reset_password_requests(reset_password_sent_at=None):
+ """Testing utility for capturing password reset requests.
+
+ :param reset_password_sent_at: An optional datetime object to set the
+ user's `reset_password_sent_at` to
+ """
+ reset_requests = []
+
+ def _on(request, app):
+ reset_requests.append(request)
+
+ reset_password_instructions_sent.connect(_on)
+
+ try:
+ yield reset_requests
+ finally:
+ reset_password_instructions_sent.disconnect(_on)
+
+
+class CaptureSignals(object):
+ """Testing utility for capturing blinker signals.
+
+ Context manager which mocks out selected signals and registers which are `sent` on and what
+ arguments were sent. Instantiate with a list of blinker `NamedSignals` to patch. Each signal
+ has it's `send` mocked out.
+ """
+ def __init__(self, signals):
+ """Patch all given signals and make them available as attributes.
+
+ :param signals: list of signals
+ """
+ self._records = {}
+ self._receivers = {}
+ for signal in signals:
+ self._records[signal] = []
+ self._receivers[signal] = functools.partial(self._record, signal)
+
+ def __getitem__(self, signal):
+ """All captured signals are available via `ctxt[signal]`.
+ """
+ if isinstance(signal, blinker.base.NamedSignal):
+ return self._records[signal]
+ else:
+ super(CaptureSignals, self).__setitem__(signal)
+
+ def _record(self, signal, *args, **kwargs):
+ self._records[signal].append((args, kwargs))
+
+ def __enter__(self):
+ for signal, receiver in self._receivers.iteritems():
+ signal.connect(receiver)
+ return self
+
+ def __exit__(self, type, value, traceback):
+ for signal, receiver in self._receivers.iteritems():
+ signal.disconnect(receiver)
+
+ def signals_sent(self):
+ """Return a set of the signals sent.
+ :rtype: list of blinker `NamedSignals`.
+ """
+ return set([signal for signal, _ in self._records.iteritems() if self._records[signal]])
+
+
+def capture_signals():
+ """Factory method that creates a `CaptureSignals` with all the flask_security signals."""
+ return CaptureSignals([user_registered, user_confirmed,
+ confirm_instructions_sent, login_instructions_sent,
+ password_reset, password_changed,
+ reset_password_instructions_sent])
+
+
diff --git a/wqflask/flask_security/views.py b/wqflask/flask_security/views.py
new file mode 100644
index 00000000..1b8488d8
--- /dev/null
+++ b/wqflask/flask_security/views.py
@@ -0,0 +1,359 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.ext.security.views
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Flask-Security views module
+
+ :copyright: (c) 2012 by Matt Wright.
+ :license: MIT, see LICENSE for more details.
+"""
+
+from flask import current_app, redirect, request, render_template, jsonify, \
+ after_this_request, Blueprint
+from flask_login import current_user
+from werkzeug.datastructures import MultiDict
+from werkzeug.local import LocalProxy
+
+from .confirmable import send_confirmation_instructions, \
+ confirm_user, confirm_email_token_status
+from .decorators import login_required, anonymous_user_required
+from .passwordless import send_login_instructions, \
+ login_token_status
+from .recoverable import reset_password_token_status, \
+ send_reset_password_instructions, update_password
+from .changeable import change_user_password
+from .registerable import register_user
+from .utils import get_url, get_post_login_redirect, do_flash, \
+ get_message, login_user, logout_user, url_for_security as url_for, \
+ config_value
+
+
+# Convenient references
+_security = LocalProxy(lambda: current_app.extensions['security'])
+
+_datastore = LocalProxy(lambda: _security.datastore)
+
+
+def _render_json(form, include_auth_token=False):
+ has_errors = len(form.errors) > 0
+
+ if has_errors:
+ code = 400
+ response = dict(errors=form.errors)
+ else:
+ code = 200
+ response = dict(user=dict(id=str(form.user.id)))
+ if include_auth_token:
+ token = form.user.get_auth_token()
+ response['user']['authentication_token'] = token
+
+ return jsonify(dict(meta=dict(code=code), response=response))
+
+
+def _commit(response=None):
+ _datastore.commit()
+ return response
+
+
+def _ctx(endpoint):
+ return _security._run_ctx_processor(endpoint)
+
+
+@anonymous_user_required
+def login():
+ """View function for login view"""
+
+ form_class = _security.login_form
+
+ if request.json:
+ form = form_class(MultiDict(request.json))
+ else:
+ form = form_class()
+
+ if form.validate_on_submit():
+ login_user(form.user, remember=form.remember.data)
+ after_this_request(_commit)
+
+ if not request.json:
+ return redirect(get_post_login_redirect())
+
+ form.next.data = get_url(request.args.get('next')) \
+ or get_url(request.form.get('next')) or ''
+
+ if request.json:
+ return _render_json(form, True)
+
+ return render_template(config_value('LOGIN_USER_TEMPLATE'),
+ login_user_form=form,
+ **_ctx('login'))
+
+
+@login_required
+def logout():
+ """View function which handles a logout request."""
+
+ logout_user()
+
+ return redirect(request.args.get('next', None) or
+ get_url(_security.post_logout_view))
+
+
+def register():
+ """View function which handles a registration request."""
+
+ if _security.confirmable or request.json:
+ form_class = _security.confirm_register_form
+ else:
+ form_class = _security.register_form
+
+ if request.json:
+ form_data = MultiDict(request.json)
+ else:
+ form_data = request.form
+
+ form = form_class(form_data)
+
+ if form.validate_on_submit():
+ user = register_user(**form.to_dict())
+ form.user = user
+
+ if not _security.confirmable or _security.login_without_confirmation:
+ after_this_request(_commit)
+ login_user(user)
+
+ if not request.json:
+ post_register_url = get_url(_security.post_register_view)
+ post_login_url = get_url(_security.post_login_view)
+ return redirect(post_register_url or post_login_url)
+
+ if request.json:
+ return _render_json(form)
+
+ return render_template(config_value('REGISTER_USER_TEMPLATE'),
+ register_user_form=form,
+ **_ctx('register'))
+
+
+def send_login():
+ """View function that sends login instructions for passwordless login"""
+
+ form_class = _security.passwordless_login_form
+
+ if request.json:
+ form = form_class(MultiDict(request.json))
+ else:
+ form = form_class()
+
+ if form.validate_on_submit():
+ send_login_instructions(form.user)
+ if request.json is None:
+ do_flash(*get_message('LOGIN_EMAIL_SENT', email=form.user.email))
+
+ if request.json:
+ return _render_json(form)
+
+ return render_template(config_value('SEND_LOGIN_TEMPLATE'),
+ send_login_form=form,
+ **_ctx('send_login'))
+
+
+@anonymous_user_required
+def token_login(token):
+ """View function that handles passwordless login via a token"""
+
+ expired, invalid, user = login_token_status(token)
+
+ if invalid:
+ do_flash(*get_message('INVALID_LOGIN_TOKEN'))
+ if expired:
+ send_login_instructions(user)
+ do_flash(*get_message('LOGIN_EXPIRED', email=user.email,
+ within=_security.login_within))
+ if invalid or expired:
+ return redirect(url_for('login'))
+
+ login_user(user, True)
+ after_this_request(_commit)
+ do_flash(*get_message('PASSWORDLESS_LOGIN_SUCCESSFUL'))
+
+ return redirect(get_post_login_redirect())
+
+
+def send_confirmation():
+ """View function which sends confirmation instructions."""
+
+ form_class = _security.send_confirmation_form
+
+ if request.json:
+ form = form_class(MultiDict(request.json))
+ else:
+ form = form_class()
+
+ if form.validate_on_submit():
+ send_confirmation_instructions(form.user)
+ if request.json is None:
+ do_flash(*get_message('CONFIRMATION_REQUEST', email=form.user.email))
+
+ if request.json:
+ return _render_json(form)
+
+ return render_template(config_value('SEND_CONFIRMATION_TEMPLATE'),
+ send_confirmation_form=form,
+ **_ctx('send_confirmation'))
+
+
+@anonymous_user_required
+def confirm_email(token):
+ """View function which handles a email confirmation request."""
+
+ expired, invalid, user = confirm_email_token_status(token)
+
+ if not user or invalid:
+ invalid = True
+ do_flash(*get_message('INVALID_CONFIRMATION_TOKEN'))
+ if expired:
+ send_confirmation_instructions(user)
+ do_flash(*get_message('CONFIRMATION_EXPIRED', email=user.email,
+ within=_security.confirm_email_within))
+ if invalid or expired:
+ return redirect(get_url(_security.confirm_error_view) or
+ url_for('send_confirmation'))
+
+ confirm_user(user)
+ login_user(user, True)
+ after_this_request(_commit)
+ do_flash(*get_message('EMAIL_CONFIRMED'))
+
+ return redirect(get_url(_security.post_confirm_view) or
+ get_url(_security.post_login_view))
+
+
+def forgot_password():
+ """View function that handles a forgotten password request."""
+
+ form_class = _security.forgot_password_form
+
+ if request.json:
+ form = form_class(MultiDict(request.json))
+ else:
+ form = form_class()
+
+ if form.validate_on_submit():
+ send_reset_password_instructions(form.user)
+ if request.json is None:
+ do_flash(*get_message('PASSWORD_RESET_REQUEST', email=form.user.email))
+
+ if request.json:
+ return _render_json(form)
+
+ return render_template(config_value('FORGOT_PASSWORD_TEMPLATE'),
+ forgot_password_form=form,
+ **_ctx('forgot_password'))
+
+
+@anonymous_user_required
+def reset_password(token):
+ """View function that handles a reset password request."""
+
+ expired, invalid, user = reset_password_token_status(token)
+
+ if invalid:
+ do_flash(*get_message('INVALID_RESET_PASSWORD_TOKEN'))
+ if expired:
+ do_flash(*get_message('PASSWORD_RESET_EXPIRED', email=user.email,
+ within=_security.reset_password_within))
+ if invalid or expired:
+ return redirect(url_for('forgot_password'))
+
+ form = _security.reset_password_form()
+
+ if form.validate_on_submit():
+ after_this_request(_commit)
+ update_password(user, form.password.data)
+ do_flash(*get_message('PASSWORD_RESET'))
+ login_user(user, True)
+ return redirect(get_url(_security.post_reset_view) or
+ get_url(_security.post_login_view))
+
+ return render_template(config_value('RESET_PASSWORD_TEMPLATE'),
+ reset_password_form=form,
+ reset_password_token=token,
+ **_ctx('reset_password'))
+
+
+@login_required
+def change_password():
+ """View function which handles a change password request."""
+
+ form_class = _security.change_password_form
+
+ if request.json:
+ form = form_class(MultiDict(request.json))
+ else:
+ form = form_class()
+
+ if form.validate_on_submit():
+ after_this_request(_commit)
+ change_user_password(current_user, form.new_password.data)
+ if request.json is None:
+ do_flash(*get_message('PASSWORD_CHANGE'))
+ return redirect(get_url(_security.post_change_view) or
+ get_url(_security.post_login_view))
+
+ if request.json:
+ return _render_json(form)
+
+ return render_template('security/change_password.html',
+ change_password_form=form,
+ **_ctx('change_password'))
+
+
+def create_blueprint(state, import_name):
+ """Creates the security extension blueprint"""
+
+ bp = Blueprint(state.blueprint_name, import_name,
+ url_prefix=state.url_prefix,
+ subdomain=state.subdomain,
+ template_folder='templates')
+
+ bp.route(state.logout_url, endpoint='logout')(logout)
+
+ if state.passwordless:
+ bp.route(state.login_url,
+ methods=['GET', 'POST'],
+ endpoint='login')(send_login)
+ bp.route(state.login_url + '/',
+ endpoint='token_login')(token_login)
+ else:
+ bp.route(state.login_url,
+ methods=['GET', 'POST'],
+ endpoint='login')(login)
+
+ if state.registerable:
+ bp.route(state.register_url,
+ methods=['GET', 'POST'],
+ endpoint='register')(register)
+
+ if state.recoverable:
+ bp.route(state.reset_url,
+ methods=['GET', 'POST'],
+ endpoint='forgot_password')(forgot_password)
+ bp.route(state.reset_url + '/',
+ methods=['GET', 'POST'],
+ endpoint='reset_password')(reset_password)
+
+ if state.changeable:
+ bp.route(state.change_url,
+ methods=['GET', 'POST'],
+ endpoint='change_password')(change_password)
+
+ if state.confirmable:
+ bp.route(state.confirm_url,
+ methods=['GET', 'POST'],
+ endpoint='send_confirmation')(send_confirmation)
+ bp.route(state.confirm_url + '/',
+ methods=['GET', 'POST'],
+ endpoint='confirm_email')(confirm_email)
+
+ return bp
diff --git a/wqflask/wqflask/templates/security/_macros.html b/wqflask/wqflask/templates/security/_macros.html
index 83f12bf7..bd6f9786 100644
--- a/wqflask/wqflask/templates/security/_macros.html
+++ b/wqflask/wqflask/templates/security/_macros.html
@@ -1,29 +1,39 @@
{% macro render_field_with_errors(field) %}
-
- {{ field.label }} {{ field(**kwargs)|safe }}
- {% if field.errors %}
-
- {% for error in field.errors %}
- {{ error }}
- {% endfor %}
-
- {% endif %}
-
+
+ {{ field.label }} {{ field(**kwargs)|safe }}
+ {% if field.errors %}
+
+ {% for error in field.errors %}
+ {{ error }}
+ {% endfor %}
+
+ {% endif %}
+
{% endmacro %}
{% macro render_only_errors(field) %}
-
+
{% if field.errors %}
-
- {% for error in field.errors %}
- {{ error }}
- {% endfor %}
-
- {% endif %}
-
+
+ {% for error in field.errors %}
+ {% if error=="Email requires confirmation." %}
+
+
You must confirm your email address before signing in.
+
Check your email for confirmation instructions.
+
Can't find the email? Check your spam folder.
+
Still can't find it?
+ Click here to resend.
+
+ {% else %}
+
{{ error }}
+ {% endif %}
+ {% endfor %}
+
+ {% endif %}
+
{% endmacro %}
{% macro render_field(field) %}
- {{ field(**kwargs)|safe }}
+ {{ field(**kwargs)|safe }}
{% endmacro %}
diff --git a/wqflask/wqflask/templates/security/login_user.html b/wqflask/wqflask/templates/security/login_user.html
index d6f6fb63..f982dc08 100644
--- a/wqflask/wqflask/templates/security/login_user.html
+++ b/wqflask/wqflask/templates/security/login_user.html
@@ -2,6 +2,8 @@
{% include "security/_messages.html" %}
+ {{ g.identity}}
+
Don't have an account?
@@ -21,19 +23,20 @@
+ {{ render_only_errors(login_user_form.email) }}
Email Address
- {{ render_only_errors(login_user_form.email) }}
+ {{ render_only_errors(login_user_form.password) }}
Password
+
- {{ render_only_errors(login_user_form.password) }}
{% if security.recoverable %}
Forgot your password?
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index dadce4d5..63781c73 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -1,5 +1,8 @@
from __future__ import absolute_import, division, print_function
+import sys
+print("sys.path is:", sys.path)
+
import csv
import StringIO # Todo: Use cStringIO?
--
cgit 1.4.1
From f259acbe4792e8a10a5fea40262c644108f58eba Mon Sep 17 00:00:00 2001
From: Sam
Date: Fri, 17 May 2013 22:21:37 +0000
Subject: Modal windows now working better
Going to simplify the code next
---
wqflask/flask_security/__init__.py | 2 ++
wqflask/wqflask/static/new/javascript/login.coffee | 21 ++++++++++---
wqflask/wqflask/static/new/javascript/login.js | 15 ++++++---
wqflask/wqflask/templates/security/_macros.html | 2 +-
wqflask/wqflask/templates/security/login_user.html | 2 +-
.../wqflask/templates/security/register_user.html | 2 +-
.../templates/security/send_confirmation.html | 36 +++++++++++++++++-----
7 files changed, 59 insertions(+), 21 deletions(-)
(limited to 'wqflask')
diff --git a/wqflask/flask_security/__init__.py b/wqflask/flask_security/__init__.py
index 68267cff..297033c9 100644
--- a/wqflask/flask_security/__init__.py
+++ b/wqflask/flask_security/__init__.py
@@ -12,6 +12,8 @@
__version__ = '1.6.0'
+print "using internal flask security"
+
from .core import Security, RoleMixin, UserMixin, AnonymousUser, current_user
from .datastore import SQLAlchemyUserDatastore, MongoEngineUserDatastore, PeeweeUserDatastore
from .decorators import auth_token_required, http_auth_required, \
diff --git a/wqflask/wqflask/static/new/javascript/login.coffee b/wqflask/wqflask/static/new/javascript/login.coffee
index 4f38a299..658fd48d 100644
--- a/wqflask/wqflask/static/new/javascript/login.coffee
+++ b/wqflask/wqflask/static/new/javascript/login.coffee
@@ -1,8 +1,19 @@
$ ->
- $(".modalize").colorbox(
- onComplete: ->
- $(".focused").focus()
- )
+ #$(".modalize").colorbox(
+ # onComplete: ->
+ # $(".focused").focus()
+ # )
+
+ $(".modalize").on("click", (event) ->
+ console.log("modalizing!!!")
+ event.preventDefault()
+ $.colorbox(
+ href: $(this).attr("href")
+ onComplete: ->
+ $(".focused").focus()
+ )
+
+ )
modal_replace = (event) ->
event.preventDefault()
@@ -17,7 +28,7 @@ $ ->
- $(".modal_replace").on("click", modal_replace)
+ $(document).on("click", ".modal_replace", modal_replace)
form_success = (data) ->
$.colorbox(
diff --git a/wqflask/wqflask/static/new/javascript/login.js b/wqflask/wqflask/static/new/javascript/login.js
index e537ac1e..d7a89f01 100644
--- a/wqflask/wqflask/static/new/javascript/login.js
+++ b/wqflask/wqflask/static/new/javascript/login.js
@@ -3,10 +3,15 @@
$(function() {
var form_success, modal_replace, submit_form;
- $(".modalize").colorbox({
- onComplete: function() {
- return $(".focused").focus();
- }
+ $(".modalize").on("click", function(event) {
+ console.log("modalizing!!!");
+ event.preventDefault();
+ return $.colorbox({
+ href: $(this).attr("href"),
+ onComplete: function() {
+ return $(".focused").focus();
+ }
+ });
});
modal_replace = function(event) {
event.preventDefault();
@@ -20,7 +25,7 @@
});
return false;
};
- $(".modal_replace").on("click", modal_replace);
+ $(document).on("click", ".modal_replace", modal_replace);
form_success = function(data) {
return $.colorbox({
open: true,
diff --git a/wqflask/wqflask/templates/security/_macros.html b/wqflask/wqflask/templates/security/_macros.html
index bd6f9786..c2d8ad71 100644
--- a/wqflask/wqflask/templates/security/_macros.html
+++ b/wqflask/wqflask/templates/security/_macros.html
@@ -22,7 +22,7 @@
You must confirm your email address before signing in.
Check your email for confirmation instructions.
Can't find the email? Check your spam folder.
-
Still can't find it?
+ Still can't find it?
Click here to resend.
{% else %}
diff --git a/wqflask/wqflask/templates/security/login_user.html b/wqflask/wqflask/templates/security/login_user.html
index f982dc08..e1f5970b 100644
--- a/wqflask/wqflask/templates/security/login_user.html
+++ b/wqflask/wqflask/templates/security/login_user.html
@@ -1,7 +1,7 @@
{% from "security/_macros.html" import render_only_errors %}
{% include "security/_messages.html" %}
-
+
{{ g.identity}}
Don't have an account?
diff --git a/wqflask/wqflask/templates/security/register_user.html b/wqflask/wqflask/templates/security/register_user.html
index 0f068914..9bbcd29f 100644
--- a/wqflask/wqflask/templates/security/register_user.html
+++ b/wqflask/wqflask/templates/security/register_user.html
@@ -1,7 +1,7 @@
{% from "security/_macros.html" import render_only_errors %}
{% include "security/_messages.html" %}
-
+
Already have an account?
diff --git a/wqflask/wqflask/templates/security/send_confirmation.html b/wqflask/wqflask/templates/security/send_confirmation.html
index 3e828407..29a11257 100644
--- a/wqflask/wqflask/templates/security/send_confirmation.html
+++ b/wqflask/wqflask/templates/security/send_confirmation.html
@@ -1,9 +1,29 @@
-{% from "security/_macros.html" import render_field_with_errors, render_field %}
+{% from "security/_macros.html" import render_only_errors %}
{% include "security/_messages.html" %}
-Resend confirmation instructions
-
-{% include "security/_menu.html" %}
\ No newline at end of file
+
+
+
Resend confirmation instructions
+
+
+
--
cgit 1.4.1
From 66e8d76ea34b6784a451abe3223eb13107d4307f Mon Sep 17 00:00:00 2001
From: Sam
Date: Fri, 17 May 2013 22:30:11 +0000
Subject: Simplification of modal code
Created css file to hold modal padding
---
wqflask/wqflask/static/new/css/main.css | 4 ++++
wqflask/wqflask/static/new/javascript/login.coffee | 20 +++-----------------
wqflask/wqflask/static/new/javascript/login.js | 19 ++++---------------
wqflask/wqflask/templates/base.html | 2 ++
wqflask/wqflask/templates/security/_macros.html | 2 +-
wqflask/wqflask/templates/security/login_user.html | 3 +--
.../wqflask/templates/security/register_user.html | 2 +-
7 files changed, 16 insertions(+), 36 deletions(-)
create mode 100644 wqflask/wqflask/static/new/css/main.css
(limited to 'wqflask')
diff --git a/wqflask/wqflask/static/new/css/main.css b/wqflask/wqflask/static/new/css/main.css
new file mode 100644
index 00000000..017bbdb8
--- /dev/null
+++ b/wqflask/wqflask/static/new/css/main.css
@@ -0,0 +1,4 @@
+.security_box {
+ padding-left: 30px;
+ padding-right: 30px;
+}
diff --git a/wqflask/wqflask/static/new/javascript/login.coffee b/wqflask/wqflask/static/new/javascript/login.coffee
index 658fd48d..c49353d5 100644
--- a/wqflask/wqflask/static/new/javascript/login.coffee
+++ b/wqflask/wqflask/static/new/javascript/login.coffee
@@ -1,21 +1,7 @@
$ ->
- #$(".modalize").colorbox(
- # onComplete: ->
- # $(".focused").focus()
- # )
- $(".modalize").on("click", (event) ->
- console.log("modalizing!!!")
- event.preventDefault()
- $.colorbox(
- href: $(this).attr("href")
- onComplete: ->
- $(".focused").focus()
- )
-
- )
- modal_replace = (event) ->
+ modalize = (event) ->
event.preventDefault()
console.log("in modal_replace:", $(this).attr("href"))
$.colorbox(
@@ -24,11 +10,11 @@ $ ->
onComplete: ->
$(".focused").focus()
)
- return false
- $(document).on("click", ".modal_replace", modal_replace)
+
+ $(document).on("click", ".modalize", modalize)
form_success = (data) ->
$.colorbox(
diff --git a/wqflask/wqflask/static/new/javascript/login.js b/wqflask/wqflask/static/new/javascript/login.js
index d7a89f01..6c6120ec 100644
--- a/wqflask/wqflask/static/new/javascript/login.js
+++ b/wqflask/wqflask/static/new/javascript/login.js
@@ -2,30 +2,19 @@
(function() {
$(function() {
- var form_success, modal_replace, submit_form;
- $(".modalize").on("click", function(event) {
- console.log("modalizing!!!");
- event.preventDefault();
- return $.colorbox({
- href: $(this).attr("href"),
- onComplete: function() {
- return $(".focused").focus();
- }
- });
- });
- modal_replace = function(event) {
+ var form_success, modalize, submit_form;
+ modalize = function(event) {
event.preventDefault();
console.log("in modal_replace:", $(this).attr("href"));
- $.colorbox({
+ return $.colorbox({
open: true,
href: this.href,
onComplete: function() {
return $(".focused").focus();
}
});
- return false;
};
- $(document).on("click", ".modal_replace", modal_replace);
+ $(document).on("click", ".modalize", modalize);
form_success = function(data) {
return $.colorbox({
open: true,
diff --git a/wqflask/wqflask/templates/base.html b/wqflask/wqflask/templates/base.html
index 2fdfbd11..bdb1c362 100644
--- a/wqflask/wqflask/templates/base.html
+++ b/wqflask/wqflask/templates/base.html
@@ -18,6 +18,8 @@
+
+
{% block css %}
{% endblock %}
diff --git a/wqflask/wqflask/templates/security/_macros.html b/wqflask/wqflask/templates/security/_macros.html
index c2d8ad71..ee662ae6 100644
--- a/wqflask/wqflask/templates/security/_macros.html
+++ b/wqflask/wqflask/templates/security/_macros.html
@@ -22,7 +22,7 @@
You must confirm your email address before signing in.
Check your email for confirmation instructions.
Can't find the email? Check your spam folder.
- Still can't find it?
+ Still can't find it?
Click here to resend.
{% else %}
diff --git a/wqflask/wqflask/templates/security/login_user.html b/wqflask/wqflask/templates/security/login_user.html
index e1f5970b..bee4e824 100644
--- a/wqflask/wqflask/templates/security/login_user.html
+++ b/wqflask/wqflask/templates/security/login_user.html
@@ -2,12 +2,11 @@
{% include "security/_messages.html" %}
- {{ g.identity}}
Don't have an account?
- Create a new account
+ Create a new account
diff --git a/wqflask/wqflask/templates/security/register_user.html b/wqflask/wqflask/templates/security/register_user.html
index 9bbcd29f..3cd021b0 100644
--- a/wqflask/wqflask/templates/security/register_user.html
+++ b/wqflask/wqflask/templates/security/register_user.html
@@ -6,7 +6,7 @@
Sign in using existing account
+ class="btn btn-info modalize">Sign in using existing account
--
cgit 1.4.1
From 668d6be6286c646cb1ce8cc4d415aa65640bc84c Mon Sep 17 00:00:00 2001
From: Zachary Sloan
Date: Fri, 17 May 2013 23:05:36 +0000
Subject: Did a little work with quick search page
---
wqflask/wqflask/search_results.py | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
(limited to 'wqflask')
diff --git a/wqflask/wqflask/search_results.py b/wqflask/wqflask/search_results.py
index 9b2751e0..ad74f6cc 100644
--- a/wqflask/wqflask/search_results.py
+++ b/wqflask/wqflask/search_results.py
@@ -42,7 +42,7 @@ from utility import formatting
#def __init__(self, key, result_fields):
# self.key = key
# self.result_fields = result_fields
-
+
class SearchResultPage(object):
#maxReturn = 3000
@@ -91,7 +91,7 @@ class SearchResultPage(object):
"""
self.trait_list = []
-
+
species = webqtlDatabaseFunction.retrieve_species(self.dataset.group.name)
# result_set represents the results for each search term; a search of
@@ -100,7 +100,7 @@ class SearchResultPage(object):
for result in self.results:
if not result:
continue
-
+
#### Excel file needs to be generated ####
print("foo locals are:", locals())
@@ -128,13 +128,13 @@ class SearchResultPage(object):
with Bench("Doing QuickSearch Query: "):
dbresults = g.db.execute(query, no_parameters=True).fetchall()
#print("results: ", pf(results))
-
+
self.results = collections.defaultdict(list)
-
+
type_dict = {'PublishXRef': 'phenotype',
'ProbeSetXRef': 'mrna_assay',
'GenoXRef': 'genotype'}
-
+
self.species_groups = {}
for dbresult in dbresults:
this_result = {}
@@ -156,9 +156,9 @@ class SearchResultPage(object):
#if this_group not in self.species_groups[type_dict[dbresult.table_name]][this_species]:
# self.species_groups[type_dict[dbresult.table_name]][this_species].append(this_group)
self.results[type_dict[dbresult.table_name]].append(this_result)
-
+
#print("results: ", pf(self.results['phenotype']))
-
+
#def get_group_species_tree(self):
# self.species_groups = collections.default_dict(list)
# for key in self.results:
--
cgit 1.4.1
From aeb0e9b723c296709381807af136ccc33b84365e Mon Sep 17 00:00:00 2001
From: Zachary Sloan
Date: Tue, 21 May 2013 22:22:00 +0000
Subject: Added caching to the search page (for both regular and quick
searckes)
---
wqflask/wqflask/do_search.py | 8 ++++----
wqflask/wqflask/templates/index_page.html | 3 ---
wqflask/wqflask/views.py | 34 +++++++++++++++++++++----------
3 files changed, 27 insertions(+), 18 deletions(-)
(limited to 'wqflask')
diff --git a/wqflask/wqflask/do_search.py b/wqflask/wqflask/do_search.py
index 1b1b56fb..7b3e0869 100644
--- a/wqflask/wqflask/do_search.py
+++ b/wqflask/wqflask/do_search.py
@@ -36,7 +36,7 @@ class DoSearch(object):
def execute(self, query):
"""Executes query and returns results"""
query = self.normalize_spaces(query)
- print("in do_search query is:", pf(query))
+ #print("in do_search query is:", pf(query))
results = g.db.execute(query, no_parameters=True).fetchall()
#results = self.cursor.fetchall()
return results
@@ -90,7 +90,7 @@ class QuickMrnaAssaySearch(DoSearch):
AGAINST ('%s' IN BOOLEAN MODE))
""" % (escape(self.search_term[0]))
- print("final query is:", pf(query))
+ #print("final query is:", pf(query))
return self.execute(query)
@@ -134,7 +134,7 @@ class MrnaAssaySearch(DoSearch):
where_clause,
escape(self.dataset.id)))
- print("query is:", pf(query))
+ #print("query is:", pf(query))
return query
@@ -155,7 +155,7 @@ class MrnaAssaySearch(DoSearch):
""" % (escape(self.search_term[0]),
escape(str(self.dataset.id)))
- print("final query is:", pf(query))
+ #print("final query is:", pf(query))
return self.execute(query)
diff --git a/wqflask/wqflask/templates/index_page.html b/wqflask/wqflask/templates/index_page.html
index 0cc1c353..b4376ce3 100644
--- a/wqflask/wqflask/templates/index_page.html
+++ b/wqflask/wqflask/templates/index_page.html
@@ -9,7 +9,6 @@
GeneNetwork
Open source bioinformatics for systems genetics
-
- Lei Yan
@@ -43,11 +42,9 @@
class="btn btn-primary" value="Search">
-
-
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 8531561a..1af324b2 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -76,17 +76,28 @@ def search_page():
else:
return render_template("data_sharing.html", **template_vars.__dict__)
else:
- print("calling search_results.SearchResultPage")
- the_search = search_results.SearchResultPage(request.args)
- print("template_vars is:", pf(the_search.__dict__))
- #print("trait_list is:", pf(the_search.__dict__['trait_list'][0].__dict__))
- #for trait in the_search.trait_list:
- # print(" -", trait.description_display)
-
- if the_search.quick:
- return render_template("quick_search.html", **the_search.__dict__)
+ key = "search_results:v2:" + json.dumps(request.args, sort_keys=True)
+ print("key is:", pf(key))
+ with Bench("Loading cache"):
+ result = Redis.get(key)
+
+ if result:
+ print("Cache hit!!!")
+ with Bench("Loading results"):
+ result = pickle.loads(result)
else:
- return render_template("search_result_page.html", **the_search.__dict__)
+ print("calling search_results.SearchResultPage")
+ the_search = search_results.SearchResultPage(request.args)
+ result = the_search.__dict__
+
+ print("result: ", pf(result))
+ Redis.set(key, pickle.dumps(result))
+ Redis.expire(key, 60*60)
+
+ if result['quick']:
+ return render_template("quick_search.html", **result)
+ else:
+ return render_template("search_result_page.html", **result)
@app.route("/whats_new")
@@ -171,9 +182,10 @@ def marker_regression_page():
for key, value in initial_start_vars.iteritems():
if key in wanted or key.startswith(('value:')):
start_vars[key] = value
-
+
version = "v14"
key = "marker_regression:{}:".format(version) + json.dumps(start_vars, sort_keys=True)
+ print("key is:", pf(key))
with Bench("Loading cache"):
result = Redis.get(key)
--
cgit 1.4.1
From 7eb9f5d12389df0ef7440a82df0be9bd1119847e Mon Sep 17 00:00:00 2001
From: Sam
Date: Thu, 23 May 2013 00:22:54 +0000
Subject: Lots of changes around users
---
wqflask/cfg/default_settings.py | 4 +++-
wqflask/utility/formatting.py | 13 ++++++++++
wqflask/wqflask/model.py | 28 +++++++++++++++++++++-
wqflask/wqflask/templates/admin/user_manager.html | 6 ++++-
.../security/email/confirmation_instructions.html | 4 +++-
.../security/email/confirmation_instructions.txt | 4 +++-
.../wqflask/templates/security/email/welcome.html | 4 +++-
.../wqflask/templates/security/email/welcome.txt | 4 +++-
wqflask/wqflask/user_manager.py | 14 ++++++++++-
wqflask/wqflask/views.py | 9 +++++--
10 files changed, 80 insertions(+), 10 deletions(-)
(limited to 'wqflask')
diff --git a/wqflask/cfg/default_settings.py b/wqflask/cfg/default_settings.py
index d0713e4d..96f7f1a5 100644
--- a/wqflask/cfg/default_settings.py
+++ b/wqflask/cfg/default_settings.py
@@ -3,7 +3,7 @@ LOGFILE = """/tmp/flask_gn_log"""
SERVER_PORT = 5000
#This is needed because Flask turns key errors into a
-#400 bad request response with no exception/log
+#400 bad request response with no exception/log
TRAP_BAD_REQUEST_ERRORS = True
# http://pythonhosted.org/Flask-Security/configuration.html
@@ -11,3 +11,5 @@ SECURITY_CONFIRMABLE = True
SECURITY_TRACKABLE = True
SECURITY_REGISTERABLE = True
SECURITY_RECOVERABLE = True
+
+SECURITY_EMAIL_SENDER = "no-reply@genenetwork.org"
diff --git a/wqflask/utility/formatting.py b/wqflask/utility/formatting.py
index 52173417..e53dda22 100644
--- a/wqflask/utility/formatting.py
+++ b/wqflask/utility/formatting.py
@@ -10,6 +10,14 @@ def numify(number, singular=None, plural=None):
>>> numify(9, 'book', 'books')
'nine books'
+ You can add capitalize to change the capitalization
+ >>> numify(9, 'book', 'books').capitalize()
+ 'Nine books'
+
+ Or capitalize every word using title
+ >>> numify(9, 'book', 'books').title()
+ 'Nine Books'
+
>>> numify(15)
'15'
@@ -107,3 +115,8 @@ def commify(n):
if cents:
out += '.' + cents
return out
+
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()
diff --git a/wqflask/wqflask/model.py b/wqflask/wqflask/model.py
index 9f9267d9..296f1f0d 100644
--- a/wqflask/wqflask/model.py
+++ b/wqflask/wqflask/model.py
@@ -8,6 +8,30 @@ from wqflask import app
# Create database connection object
db = SQLAlchemy(app)
+# Is this right? -Sam
+#from sqlalchemy.ext.declarative import declarative_base
+#Base = declarative_base()
+
+#@classmethod
+#def get(cls, key):
+# """Convenience get method using the primary key
+#
+# If record doesn't exist, returns None
+#
+# Allows the following: User.get('121')
+#
+# """
+# print("in get cls is:", cls)
+# print(" key is {} : {}".format(type(key), key))
+# query = db.Model.query(cls)
+# print("query is: ", query)
+# record = query.get(key)
+# return record
+#
+#
+#print("db.Model is:", vars(db.Model))
+#db.Model.get = get
+
# Define models
roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
@@ -38,5 +62,7 @@ class User(db.Model, UserMixin):
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
-
db.metadata.create_all(db.engine)
+
+
+
diff --git a/wqflask/wqflask/templates/admin/user_manager.html b/wqflask/wqflask/templates/admin/user_manager.html
index c49f0d94..14cd12e0 100644
--- a/wqflask/wqflask/templates/admin/user_manager.html
+++ b/wqflask/wqflask/templates/admin/user_manager.html
@@ -16,6 +16,7 @@
+ ID
Email
Confirmed at
Active
@@ -23,7 +24,10 @@
{% for user in users %}
- {{ user.email }}
+
+ {{ user.id }}
+
+ {{ user.email }}
{{ user.confirmed_at }}
{{ user.active }}
diff --git a/wqflask/wqflask/templates/security/email/confirmation_instructions.html b/wqflask/wqflask/templates/security/email/confirmation_instructions.html
index 5082a9a8..239f670f 100644
--- a/wqflask/wqflask/templates/security/email/confirmation_instructions.html
+++ b/wqflask/wqflask/templates/security/email/confirmation_instructions.html
@@ -1,3 +1,5 @@
+Welcome to GeneNetwork!
+
Please confirm your email through the link below:
-Confirm my account
\ No newline at end of file
+Confirm my account
diff --git a/wqflask/wqflask/templates/security/email/confirmation_instructions.txt b/wqflask/wqflask/templates/security/email/confirmation_instructions.txt
index fb435b55..babedd8b 100644
--- a/wqflask/wqflask/templates/security/email/confirmation_instructions.txt
+++ b/wqflask/wqflask/templates/security/email/confirmation_instructions.txt
@@ -1,3 +1,5 @@
+Welcome to GeneNetwork!
+
Please confirm your email through the link below:
-{{ confirmation_link }}
\ No newline at end of file
+{{ confirmation_link }}
diff --git a/wqflask/wqflask/templates/security/email/welcome.html b/wqflask/wqflask/templates/security/email/welcome.html
index 55eaed61..3cb01ce0 100644
--- a/wqflask/wqflask/templates/security/email/welcome.html
+++ b/wqflask/wqflask/templates/security/email/welcome.html
@@ -1,7 +1,9 @@
Welcome {{ user.email }}!
+We hope you find GeneNetwork an amazing resource!
+
{% if security.confirmable %}
You can confirm your email through the link below:
Confirm my account
-{% endif %}
\ No newline at end of file
+{% endif %}
diff --git a/wqflask/wqflask/templates/security/email/welcome.txt b/wqflask/wqflask/templates/security/email/welcome.txt
index fb6ee5b5..9a400686 100644
--- a/wqflask/wqflask/templates/security/email/welcome.txt
+++ b/wqflask/wqflask/templates/security/email/welcome.txt
@@ -1,7 +1,9 @@
Welcome {{ user.email }}!
+We hope you find GeneNetwork an amazing resource!
+
{% if security.confirmable %}
You can confirm your email through the link below:
{{ confirmation_link }}
-{% endif %}
\ No newline at end of file
+{% endif %}
diff --git a/wqflask/wqflask/user_manager.py b/wqflask/wqflask/user_manager.py
index 4d608dc7..97ba18a3 100644
--- a/wqflask/wqflask/user_manager.py
+++ b/wqflask/wqflask/user_manager.py
@@ -11,12 +11,24 @@ from wqflask import model
from flask import Flask, g
+from pprint import pformat as pf
+
#from app import db
print("globals are:", globals())
-class UserManager(object):
+class UsersManager(object):
def __init__(self):
self.users = model.User.query.all()
print("Users are:", self.users)
+
+
+class UserManager(object):
+ def __init__(self, kw):
+ self.user_id = int(kw['user_id'])
+ print("In UserManager locals are:", pf(locals()))
+ #self.user = model.User.get(user_id)
+ #print("user is:", user)
+ self.user = model.User.query.get(self.user_id)
+ print("user is:", self.user)
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index 63781c73..b59c3b34 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -239,11 +239,16 @@ def get_temp_data():
temp_uuid = request.args['key']
return flask.jsonify(temp_data.TempData(temp_uuid).get_all())
-@app.route("/users")
+@app.route("/manage/users")
def manage_users():
- template_vars = user_manager.UserManager()
+ template_vars = user_manager.UsersManager()
return render_template("admin/user_manager.html", **template_vars.__dict__)
+@app.route("/manage/user")
+def manage_user():
+ template_vars = user_manager.UserManager(request.args)
+ return render_template("admin/ind_user_manager.html", **template_vars.__dict__)
+
def json_default_handler(obj):
'''Based on http://stackoverflow.com/a/2680060/1175849'''
--
cgit 1.4.1
From 0352c52231ca677385ba833a8f6d542cbd3378ba Mon Sep 17 00:00:00 2001
From: Sam
Date: Thu, 23 May 2013 00:23:13 +0000
Subject: Added a template
---
.../wqflask/templates/admin/ind_user_manager.html | 62 ++++++++++++++++++++++
1 file changed, 62 insertions(+)
create mode 100644 wqflask/wqflask/templates/admin/ind_user_manager.html
(limited to 'wqflask')
diff --git a/wqflask/wqflask/templates/admin/ind_user_manager.html b/wqflask/wqflask/templates/admin/ind_user_manager.html
new file mode 100644
index 00000000..9776af0b
--- /dev/null
+++ b/wqflask/wqflask/templates/admin/ind_user_manager.html
@@ -0,0 +1,62 @@
+{% extends "base.html" %}
+{% block title %}User Manager{% endblock %}
+{% block content %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Confirmed
+ {{ user.confirmed_at }}
+
+
+
+ Current login
+ {{ user.current_login_at }} from {{ user.current_login_ip }}
+
+
+
+ Last login
+ {{ user.last_login_at }} from {{ user.last_login_ip }}
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
--
cgit 1.4.1
From e31d163325d0d417bf266d1c3d9e52b6ff00f83b Mon Sep 17 00:00:00 2001
From: Lei Yan
Date: Thu, 23 May 2013 20:53:11 +0000
Subject: Now calculates correlation values for traits, but not yet in template
---
wqflask/base/data_set.py | 46 +++++++++++++-------
wqflask/wqflask/correlation/show_corr_results.py | 55 ++++++++++++++++--------
2 files changed, 67 insertions(+), 34 deletions(-)
(limited to 'wqflask')
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index 1520b180..89bbf03d 100755
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -46,7 +46,7 @@ from pprint import pformat as pf
DS_NAME_MAP = {}
def create_dataset(dataset_name):
- print("dataset_name:", dataset_name)
+ #print("dataset_name:", dataset_name)
query = """
SELECT DBType.Name
@@ -71,7 +71,7 @@ def create_dataset(dataset_name):
def mescape(*items):
"""Multiple escape"""
escaped = [escape(item) for item in items]
- print("escaped is:", escaped)
+ #print("escaped is:", escaped)
return escaped
@@ -235,6 +235,7 @@ class DataSet(object):
self.retrieve_other_names()
self.group = DatasetGroup(self) # sets self.group and self.group_id and gets genotype
+ self.group.read_genotype_file()
self.species = species.TheSpecies(self)
@@ -624,17 +625,34 @@ class MrnaAssayDataSet(DataSet):
return trait_data
def get_trait_data(self):
+ import pdb
+ pdb.set_trace()
+ #samplelist = []
+ #samplelist += self.group.samplelist
+ #samplelist += self.group.parlist
+ #samplelist += self.group.f1list
+ #self.samplelist = samplelist
+
+ self.samplelist = self.group.samplelist + self.group.parlist + self.group.f1list
+
sample_ids = []
- for sample in self.group.samplelist:
- query = """
- SELECT Strain.Id FROM Strain, Species
- WHERE Strain.Name = '{}'
- and Strain.SpeciesId=Species.Id
- and Species.name = '{}'
- """.format(*mescape(sample, self.group.species))
- this_id = g.db.execute(query).fetchone()[0]
- sample_ids.append('%d' % this_id)
- print("sample_ids size: ", len(sample_ids))
+
+ where_clause = ""
+ for sample in self.samplelist:
+ if len(where_clause):
+ where_clause += " or "
+ where_clause += """'{}'""".format(*mescape(sample))
+
+ query = """
+ SELECT Strain.Id, Strain.Name FROM Strain, Species
+ WHERE Strain.Name = '{}'
+ and Strain.SpeciesId=Species.Id
+ and Species.name = '{}'
+ """.format(*mescape(where_clause, self.group.species))
+ result = g.db.execute(query).fetchall()
+
+ print("[blueberry] result is:", pf(result))
+ #sample_ids.append('%d' % this_id)
# MySQL limits the number of tables that can be used in a join to 61,
# so we break the sample ids into smaller chunks
@@ -642,7 +660,6 @@ class MrnaAssayDataSet(DataSet):
n = len(sample_ids) / chunk_count
if len(sample_ids) % chunk_count:
n += 1
- print("n: ", n)
#XZ, 09/24/2008: build one temporary table that only contains the records associated with the input GeneId
#tempTable = None
#if GeneId and db.type == "ProbeSet":
@@ -681,10 +698,9 @@ class MrnaAssayDataSet(DataSet):
order by {}.Id
""".format(*mescape(self.type, self.type, self.type, self.type,
self.name, self.type, self.type, self.type, self.type))
- print("query: ", query)
results = g.db.execute(query).fetchall()
trait_sample_data.append(results)
-
+
trait_count = len(trait_sample_data[0])
self.trait_data = collections.defaultdict(list)
# put all of the separate data together into a dictionary where the keys are
diff --git a/wqflask/wqflask/correlation/show_corr_results.py b/wqflask/wqflask/correlation/show_corr_results.py
index 1d0368cc..ee732050 100644
--- a/wqflask/wqflask/correlation/show_corr_results.py
+++ b/wqflask/wqflask/correlation/show_corr_results.py
@@ -37,6 +37,7 @@ import time
#import pyXLWriter as xl
import pp
import math
+import collections
from pprint import pformat as pf
@@ -285,16 +286,15 @@ class CorrelationResults(object):
# name=start_vars['trait_id'],
# cellid=None)
- print("start_vars: ", pf(start_vars))
+ #print("start_vars: ", pf(start_vars))
helper_functions.get_species_dataset_trait(self, start_vars)
self.dataset.group.read_genotype_file()
-
- self.samples = [] # Want only ones with values
- self.vals = []
corr_samples_group = start_vars['corr_samples_group']
+ self.sample_data = {}
+
#The two if statements below append samples to the sample list based upon whether the user
#selected Primary Samples Only, Other Samples Only, or All Samples
@@ -310,16 +310,24 @@ class CorrelationResults(object):
self.dataset.group.f1list +
self.dataset.group.samplelist)
self.process_samples(start_vars, self.this_trait.data.keys(), primary_samples)
-
- #for i, sample in enumerate(self.samples):
- # print("{} : {}".format(sample, self.vals[i]))
-
self.target_dataset = data_set.create_dataset(start_vars['corr_dataset'])
self.target_dataset.get_trait_data()
- print("trait_list: {}".format(pf(self.target_dataset.trait_data)))
# Lei Yan todo
+ import pdb
+ pdb.set_trace()
+ correlation_data = collections.defaultdict(list)
for trait, values in self.target_dataset.trait_data.iteritems():
- correlation = calCorrelation(values, )
+ values_1 = []
+ values_2 = []
+ for index,sample in enumerate(self.target_dataset.samplelist):
+ target_value = values[index]
+ if sample in self.sample_data.keys():
+ this_value = self.sample_data[sample]
+ values_1.append(this_value)
+ values_2.append(target_value)
+ correlation = calCorrelation(values_1, values_2)
+ correlation_data[trait] = correlation
+ print ('%s %s' % (trait, correlation))
#XZ, 09/18/2008: get all information about the user selected database.
#target_db_name = fd.corr_dataset
@@ -779,19 +787,28 @@ makeWebGestaltTree(thisForm, '%s', %d, 'edag_only.php');
"""
+ #def process_samples(self, start_vars, sample_names, excluded_samples):
+ # for sample in sample_names:
+ # if sample not in excluded_samples:
+ # value = start_vars['value:' + sample]
+ # variance = start_vars['variance:' + sample]
+ # if variance.strip().lower() == 'x':
+ # variance = 0
+ # else:
+ # variance = float(variance)
+ # if value.strip().lower() != 'x':
+ # self.samples.append(str(sample))
+ # self.vals.append(float(value))
+ # #self.variances.append(variance)
+
def process_samples(self, start_vars, sample_names, excluded_samples):
for sample in sample_names:
if sample not in excluded_samples:
value = start_vars['value:' + sample]
- variance = start_vars['variance:' + sample]
- if variance.strip().lower() == 'x':
- variance = 0
+ if value.strip().lower() == 'x':
+ self.sample_data[str(sample)] = None
else:
- variance = float(variance)
- if value.strip().lower() != 'x':
- self.samples.append(str(sample))
- self.vals.append(float(value))
- #self.variances.append(variance)
+ self.sample_data[str(sample)] = float(value)
def getSortByValue(self, calculationMethod):
@@ -2134,7 +2151,7 @@ Resorting this table
def calCorrelation(values_1, values_2):
- N = Math.min(len(values_1), len(values_2))
+ N = min(len(values_1), len(values_2))
X = []
Y = []
for i in range(N):
--
cgit 1.4.1
From 953b41486b035fbe786c7d2675f7b6cf898c12da Mon Sep 17 00:00:00 2001
From: Lei Yan
Date: Thu, 23 May 2013 21:19:00 +0000
Subject: Changed the way the query that gets sample ids is generated
---
wqflask/base/data_set.py | 25 ++++++++-----------------
1 file changed, 8 insertions(+), 17 deletions(-)
(limited to 'wqflask')
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index 89bbf03d..b2836480 100755
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -625,33 +625,24 @@ class MrnaAssayDataSet(DataSet):
return trait_data
def get_trait_data(self):
- import pdb
- pdb.set_trace()
- #samplelist = []
- #samplelist += self.group.samplelist
- #samplelist += self.group.parlist
- #samplelist += self.group.f1list
- #self.samplelist = samplelist
-
self.samplelist = self.group.samplelist + self.group.parlist + self.group.f1list
-
sample_ids = []
-
where_clause = ""
- for sample in self.samplelist:
- if len(where_clause):
- where_clause += " or "
- where_clause += """'{}'""".format(*mescape(sample))
+ #for sample in self.samplelist:
+ # if len(where_clause):
+ # where_clause += " or "
+ # where_clause += "Strain.Name = '{}'".format(*mescape(sample))
query = """
SELECT Strain.Id, Strain.Name FROM Strain, Species
- WHERE Strain.Name = '{}'
+ WHERE ({})
and Strain.SpeciesId=Species.Id
and Species.name = '{}'
- """.format(*mescape(where_clause, self.group.species))
+ """.format(where_clause, *mescape(self.group.species))
+ print("raspberry query: ", query)
result = g.db.execute(query).fetchall()
- print("[blueberry] result is:", pf(result))
+ print("[blackberry] result is:", pf(result))
#sample_ids.append('%d' % this_id)
# MySQL limits the number of tables that can be used in a join to 61,
--
cgit 1.4.1
From 8d0c6166a297d2cc89394649b8f56d8c6bf5d0f7 Mon Sep 17 00:00:00 2001
From: Lei Yan
Date: Thu, 23 May 2013 23:01:54 +0000
Subject: Worked on rewriting the function in data_set.py that gets the sample
values for each trait
---
wqflask/base/data_set.py | 72 ++++++++++++++++--------
wqflask/wqflask/correlation/show_corr_results.py | 5 +-
2 files changed, 49 insertions(+), 28 deletions(-)
(limited to 'wqflask')
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index b2836480..edee6685 100755
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -38,6 +38,7 @@ from base import species
from dbFunction import webqtlDatabaseFunction
from utility import webqtlUtil
from utility.benchmark import Bench
+from wqflask.my_pylmm.pyLMM import chunks
from MySQLdb import escape_string as escape
from pprint import pformat as pf
@@ -68,6 +69,13 @@ def create_dataset(dataset_name):
dataset_class = globals()[dataset_ob]
return dataset_class(dataset_name)
+def create_in_clause(items):
+ """Create an in clause for mysql"""
+ in_clause = ', '.join("'{}'".format(x) for x in mescape(*items))
+ in_clause = '( {} )'.format(in_clause)
+ return in_clause
+
+
def mescape(*items):
"""Multiple escape"""
escaped = [escape(item) for item in items]
@@ -626,31 +634,45 @@ class MrnaAssayDataSet(DataSet):
def get_trait_data(self):
self.samplelist = self.group.samplelist + self.group.parlist + self.group.f1list
- sample_ids = []
- where_clause = ""
- #for sample in self.samplelist:
- # if len(where_clause):
- # where_clause += " or "
- # where_clause += "Strain.Name = '{}'".format(*mescape(sample))
-
+ #query_samplelist = ', '.join("'{}'".format(x) for x in mescape(*samplelist))
+ #query_samplelist = '( ' + query_samplelist + ' )'
+ #query_samplelist = create_in(samplelist)
+
+ print("self.samplelist is:", self.samplelist)
+
query = """
- SELECT Strain.Id, Strain.Name FROM Strain, Species
- WHERE ({})
+ SELECT Strain.Name, Strain.Id FROM Strain, Species
+ WHERE Strain.Name IN {}
and Strain.SpeciesId=Species.Id
and Species.name = '{}'
- """.format(where_clause, *mescape(self.group.species))
- print("raspberry query: ", query)
- result = g.db.execute(query).fetchall()
+ """.format(create_in_clause(self.samplelist), *mescape(self.group.species))
+ results = dict(g.db.execute(query).fetchall())
+ print("results are:", results)
+ print("type results are:", type(results))
+
+ #sample_ids = []
+ #for item in self.samplelist:
+ # sample_ids.append(results[item])
+
+ sample_ids = [results[item] for item in self.samplelist]
+ print("sample_ids are:", sample_ids)
+
+ #for sample in self.samplelist:
+ # pass
- print("[blackberry] result is:", pf(result))
- #sample_ids.append('%d' % this_id)
+ #for index in range(len(results)):
+ # sample_ids.append(results[index][0])
# MySQL limits the number of tables that can be used in a join to 61,
# so we break the sample ids into smaller chunks
- chunk_count = 50
- n = len(sample_ids) / chunk_count
- if len(sample_ids) % chunk_count:
- n += 1
+ # Postgres doesn't have that limit, so we can get rid of this after we transition
+ chunk_size = 50
+
+ number_chunks = int(math.ceil(len(sample_ids) / chunk_size))
+
+ trait_sample_data = []
+ for sample_ids_step in chunks.divide_into_chunks(sample_ids, number_chunks):
+
#XZ, 09/24/2008: build one temporary table that only contains the records associated with the input GeneId
#tempTable = None
#if GeneId and db.type == "ProbeSet":
@@ -664,12 +686,14 @@ class MrnaAssayDataSet(DataSet):
# TissueProbeSetFreezeId=tissueProbeSetFreezeId,
# method=method,
# returnNumber=returnNumber)
- trait_sample_data = []
- for step in range(int(n)):
- temp = []
- sample_ids_step = sample_ids[step*chunk_count:min(len(sample_ids), (step+1)*chunk_count)]
- for item in sample_ids_step:
- temp.append('T%s.value' % item)
+
+ #for step in range(int(n)):
+ #temp = []
+ #sample_ids_step = sample_ids[step*chunk_size:min(len(sample_ids), (step+1)*chunk_size)]
+ #for item in sample_ids_step:
+ # temp.append('T%s.value' % item)
+
+ temp = ['T%s.value' % item for item in sample_ids_step]
query = "SELECT {}.Name,".format(escape(self.type))
data_start_pos = 1
query += string.join(temp, ', ')
diff --git a/wqflask/wqflask/correlation/show_corr_results.py b/wqflask/wqflask/correlation/show_corr_results.py
index ee732050..9b1843bd 100644
--- a/wqflask/wqflask/correlation/show_corr_results.py
+++ b/wqflask/wqflask/correlation/show_corr_results.py
@@ -312,9 +312,6 @@ class CorrelationResults(object):
self.process_samples(start_vars, self.this_trait.data.keys(), primary_samples)
self.target_dataset = data_set.create_dataset(start_vars['corr_dataset'])
self.target_dataset.get_trait_data()
- # Lei Yan todo
- import pdb
- pdb.set_trace()
correlation_data = collections.defaultdict(list)
for trait, values in self.target_dataset.trait_data.iteritems():
values_1 = []
@@ -327,7 +324,7 @@ class CorrelationResults(object):
values_2.append(target_value)
correlation = calCorrelation(values_1, values_2)
correlation_data[trait] = correlation
- print ('%s %s' % (trait, correlation))
+ print ('correlation result: %s %s' % (trait, correlation))
#XZ, 09/18/2008: get all information about the user selected database.
#target_db_name = fd.corr_dataset
--
cgit 1.4.1
From cb639316fe007c8bcad731976e8b095dee59115e Mon Sep 17 00:00:00 2001
From: Lei Yan
Date: Tue, 28 May 2013 23:10:22 +0000
Subject: Have correlation values appearing in a table in the template
Use scipy to calculate pearson correlation instead of old GN code
---
wqflask/base/data_set.py | 34 +-
wqflask/wqflask/correlation/show_corr_results.py | 1320 ++------------------
wqflask/wqflask/templates/correlation_page.html | 1411 +---------------------
3 files changed, 152 insertions(+), 2613 deletions(-)
(limited to 'wqflask')
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index edee6685..c2380f8c 100755
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -78,7 +78,7 @@ def create_in_clause(items):
def mescape(*items):
"""Multiple escape"""
- escaped = [escape(item) for item in items]
+ escaped = [escape(str(item)) for item in items]
#print("escaped is:", escaped)
return escaped
@@ -634,12 +634,6 @@ class MrnaAssayDataSet(DataSet):
def get_trait_data(self):
self.samplelist = self.group.samplelist + self.group.parlist + self.group.f1list
- #query_samplelist = ', '.join("'{}'".format(x) for x in mescape(*samplelist))
- #query_samplelist = '( ' + query_samplelist + ' )'
- #query_samplelist = create_in(samplelist)
-
- print("self.samplelist is:", self.samplelist)
-
query = """
SELECT Strain.Name, Strain.Id FROM Strain, Species
WHERE Strain.Name IN {}
@@ -647,29 +641,13 @@ class MrnaAssayDataSet(DataSet):
and Species.name = '{}'
""".format(create_in_clause(self.samplelist), *mescape(self.group.species))
results = dict(g.db.execute(query).fetchall())
- print("results are:", results)
- print("type results are:", type(results))
-
- #sample_ids = []
- #for item in self.samplelist:
- # sample_ids.append(results[item])
-
sample_ids = [results[item] for item in self.samplelist]
- print("sample_ids are:", sample_ids)
-
- #for sample in self.samplelist:
- # pass
-
- #for index in range(len(results)):
- # sample_ids.append(results[index][0])
# MySQL limits the number of tables that can be used in a join to 61,
# so we break the sample ids into smaller chunks
# Postgres doesn't have that limit, so we can get rid of this after we transition
chunk_size = 50
-
number_chunks = int(math.ceil(len(sample_ids) / chunk_size))
-
trait_sample_data = []
for sample_ids_step in chunks.divide_into_chunks(sample_ids, number_chunks):
@@ -687,12 +665,6 @@ class MrnaAssayDataSet(DataSet):
# method=method,
# returnNumber=returnNumber)
- #for step in range(int(n)):
- #temp = []
- #sample_ids_step = sample_ids[step*chunk_size:min(len(sample_ids), (step+1)*chunk_size)]
- #for item in sample_ids_step:
- # temp.append('T%s.value' % item)
-
temp = ['T%s.value' % item for item in sample_ids_step]
query = "SELECT {}.Name,".format(escape(self.type))
data_start_pos = 1
@@ -722,10 +694,10 @@ class MrnaAssayDataSet(DataSet):
# trait names and values are lists of sample values
for j in range(trait_count):
trait_name = trait_sample_data[0][j][0]
- for i in range(int(n)):
+ for i in range(int(number_chunks)):
self.trait_data[trait_name] += trait_sample_data[i][j][data_start_pos:]
-
+
def get_trait_info(self, trait_list=None, species=''):
# Note: setting trait_list to [] is probably not a great idea.
diff --git a/wqflask/wqflask/correlation/show_corr_results.py b/wqflask/wqflask/correlation/show_corr_results.py
index 9b1843bd..aa20eba1 100644
--- a/wqflask/wqflask/correlation/show_corr_results.py
+++ b/wqflask/wqflask/correlation/show_corr_results.py
@@ -39,6 +39,8 @@ import pp
import math
import collections
+import scipy
+
from pprint import pformat as pf
from htmlgen import HTMLgen2 as HT
@@ -54,6 +56,7 @@ from utility import webqtlUtil, helper_functions
from dbFunction import webqtlDatabaseFunction
import utility.webqtlUtil #this is for parallel computing only.
from wqflask.correlation import correlationFunction
+from utility.benchmark import Bench
from pprint import pformat as pf
@@ -69,197 +72,6 @@ TISSUE_MOUSE_DB = 1
class AuthException(Exception): pass
-
-class Trait(object):
-
-
- def __init__(self, name, raw_values = None, lit_corr = None, tissue_corr = None, p_tissue = None):
- self.name = name
- self.raw_values = raw_values
- self.lit_corr = lit_corr
- self.tissue_corr = tissue_corr
- self.p_tissue = p_tissue
- self.correlation = 0
- self.p_value = 0
-
- @staticmethod
- def from_csv(line, data_start = 1):
- name = line[0]
- numbers = line[data_start:]
- # _log.info(numbers)
- numbers = [ float(number) for number in numbers ]
-
- return Trait(name, raw_values = numbers)
-
- def calculate_correlation(self, values, method):
- """Calculate the correlation value and p value according to the method specified"""
-
- #ZS: This takes the list of values of the trait our selected trait is being correlated
- #against and removes the values of the samples our trait has no value for
- #There's probably a better way of dealing with this, but I'll have to ask Christian
- updated_raw_values = []
- updated_values = []
- for i in range(len(values)):
- if values[i] != "None":
- updated_raw_values.append(self.raw_values[i])
- updated_values.append(values[i])
-
- self.raw_values = updated_raw_values
- values = updated_values
-
- if method == METHOD_SAMPLE_PEARSON or method == METHOD_LIT or method == METHOD_TISSUE_PEARSON:
- corr,nOverlap = webqtlUtil.calCorrelation(self.raw_values, values, len(values))
- else:
- corr,nOverlap = webqtlUtil.calCorrelationRank(self.raw_values, values, len(values))
-
- self.correlation = corr
- self.overlap = nOverlap
-
- if self.overlap < 3:
- self.p_value = 1.0
- else:
- #ZS - This is probably the wrong way to deal with this. Correlation values of 1.0 definitely exist (the trait correlated against itself), so zero division needs to br prevented.
- if abs(self.correlation) >= 1.0:
- self.p_value = 0.0
- else:
- #Confirm that this division works after future import
- ZValue = 0.5*log((1.0+self.correlation)/(1.0-self.correlation))
- ZValue = ZValue*sqrt(self.overlap-3)
- self.p_value = 2.0*(1.0 - reaper.normp(abs(ZValue)))
-
-
-
-#XZ, 01/14/2009: This method is for parallel computing only.
-#XZ: It is supposed to be called when "Genetic Correlation, Pearson's r" (method 1)
-#XZ: or "Genetic Correlation, Spearman's rho" (method 2) is selected
-def compute_corr(input_nnCorr, input_trait, input_list, computing_method):
-
- allcorrelations = []
- for line in input_list:
- tokens = line.split('","')
- tokens[-1] = tokens[-1][:-2] #remove the last "
- tokens[0] = tokens[0][1:] #remove the first "
-
- traitdataName = tokens[0]
- database_trait = tokens[1:]
-
- if computing_method == "1": #XZ: Pearson's r
- corr,nOverlap = utility.webqtlUtil.calCorrelationText(input_trait, database_trait, input_nnCorr)
- else: #XZ: Spearman's rho
- corr,nOverlap = utility.webqtlUtil.calCorrelationRankText(input_trait, database_trait, input_nnCorr)
- traitinfo = [traitdataName,corr,nOverlap]
- allcorrelations.append(traitinfo)
-
- return allcorrelations
-
-def get_correlation_method_key(form_data):
- #XZ, 09/28/2008: if user select "1", then display 1, 3 and 4.
- #XZ, 09/28/2008: if user select "2", then display 2, 3 and 5.
- #XZ, 09/28/2008: if user select "3", then display 1, 3 and 4.
- #XZ, 09/28/2008: if user select "4", then display 1, 3 and 4.
- #XZ, 09/28/2008: if user select "5", then display 2, 3 and 5.
-
- method = form_data.method
- if method not in ["1", "2", "3" ,"4", "5"]:
- return "1"
-
- return method
-
-
-def get_custom_trait(form_data, cursor):
- """Pulls the custom trait, if it exists, out of the form data"""
- trait_name = form_data.fullname
-
- if trait_name:
- trait = webqtlTrait(fullname=trait_name, cursor=cursor)
- trait.retrieveInfo()
- return trait
- else:
- return None
-
-
-#XZ, 09/18/2008: get the information such as value, variance of the input strain names from the form.
-def get_sample_data(fd):
- #print("fd is:", pf(fd.__dict__))
- if fd.allstrainlist:
- mdpchoice = fd.MDPChoice
- #XZ, in HTML source code, it is "BXD Only", "BXH Only", and so on
- if mdpchoice == "1":
- strainlist = fd.f1list + fd.strainlist
- #XZ, in HTML source code, it is "Non-BXD Only", "Non-BXD Only", etc
- elif mdpchoice == "2":
- strainlist = []
- strainlist2 = fd.f1list + fd.strainlist
- for strain in fd.allstrainlist:
- if strain not in strainlist2:
- strainlist.append(strain)
- #So called MDP Panel
- if strainlist:
- strainlist = fd.f1list + fd.parlist+strainlist
- #XZ, in HTML source code, it is "All Cases"
- else:
- strainlist = fd.allstrainlist
- #XZ, 09/18/2008: put the trait data into dictionary fd.allTraitData
- fd.readData(fd.allstrainlist)
- else:
- mdpchoice = None
- strainlist = fd.strainlist
- #XZ, 09/18/2008: put the trait data into dictionary fd.allTraitData
- fd.readData()
-
- return strainlist
-
-
-
-def get_species(fd, cursor):
- #XZ, 3/16/2010: variable RISet must be pass by the form
- RISet = fd.RISet
- #XZ, 12/12/2008: get species infomation
- species = webqtlDatabaseFunction.retrieveSpecies(cursor=cursor, RISet=RISet)
- return species
-
-
-def sortTraitCorrelations(traits, method="1"):
- if method in TISSUE_METHODS:
- traits.sort(key=lambda trait: trait.tissue_corr != None and abs(trait.tissue_corr), reverse=True)
- elif method == METHOD_LIT:
- traits.sort(key=lambda trait: trait.lit_corr != None and abs(trait.lit_corr), reverse=True)
- else:
- traits.sort(key=lambda trait: trait.correlation != None and abs(trait.correlation), reverse=True)
-
- return traits
-
-
-def auth_user_for_db(db, cursor, target_db_name, privilege, username):
- """Authorize a user for access to a database if that database is
- confidential. A db (identified by a record in ProbeSetFreeze) contains a
- list of authorized users who may access it, as well as its confidentiality
- level.
-
- If the current user's privilege level is greater than 'user', ie: root or
- admin, then they are automatically authed, otherwise, check the
- AuthorizedUsers field for the presence of their name."""
-
- if db.type == 'ProbeSet':
- cursor.execute('SELECT Id, Name, FullName, confidentiality, AuthorisedUsers FROM ProbeSetFreeze WHERE Name = "%s"' % target_db_name)
- indId, indName, indFullName, confidential, AuthorisedUsers = cursor.fetchall()[0]
-
- if confidential:
- authorized = 0
-
- #for the dataset that confidentiality is 1
- #1. 'admin' and 'root' can see all of the dataset
- #2. 'user' can see the dataset that AuthorisedUsers contains his id(stored in the Id field of User table)
- if webqtlConfig.USERDICT[privilege] > webqtlConfig.USERDICT['user']:
- authorized = 1
- else:
- if username in AuthorisedUsers.split(","):
- authorized = 1
-
- if not authorized:
- raise AuthException("The %s database you selected is not open to the public at this time, please go back and select other database." % indFullName)
-
-
class CorrelationResults(object):
corr_min_informative = 4
@@ -287,48 +99,55 @@ class CorrelationResults(object):
# cellid=None)
#print("start_vars: ", pf(start_vars))
-
- helper_functions.get_species_dataset_trait(self, start_vars)
- self.dataset.group.read_genotype_file()
-
- corr_samples_group = start_vars['corr_samples_group']
-
- self.sample_data = {}
-
- #The two if statements below append samples to the sample list based upon whether the user
- #selected Primary Samples Only, Other Samples Only, or All Samples
-
- #If either BXD/whatever Only or All Samples, append all of that group's samplelist
- if corr_samples_group != 'samples_other':
- self.process_samples(start_vars, self.dataset.group.samplelist, ())
-
- #If either Non-BXD/whatever or All Samples, get all samples from this_trait.data and
- #exclude the primary samples (because they would have been added in the previous
- #if statement if the user selected All Samples)
- if corr_samples_group != 'samples_primary':
+ with Bench("Doing correlations"):
+ helper_functions.get_species_dataset_trait(self, start_vars)
+ self.dataset.group.read_genotype_file()
+
+ corr_samples_group = start_vars['corr_samples_group']
+
+ self.sample_data = {}
+
+ #The two if statements below append samples to the sample list based upon whether the user
+ #rselected Primary Samples Only, Other Samples Only, or All Samples
+
primary_samples = (self.dataset.group.parlist +
self.dataset.group.f1list +
self.dataset.group.samplelist)
- self.process_samples(start_vars, self.this_trait.data.keys(), primary_samples)
- self.target_dataset = data_set.create_dataset(start_vars['corr_dataset'])
- self.target_dataset.get_trait_data()
- correlation_data = collections.defaultdict(list)
- for trait, values in self.target_dataset.trait_data.iteritems():
- values_1 = []
- values_2 = []
- for index,sample in enumerate(self.target_dataset.samplelist):
- target_value = values[index]
- if sample in self.sample_data.keys():
- this_value = self.sample_data[sample]
- values_1.append(this_value)
- values_2.append(target_value)
- correlation = calCorrelation(values_1, values_2)
- correlation_data[trait] = correlation
- print ('correlation result: %s %s' % (trait, correlation))
+
+ #If either BXD/whatever Only or All Samples, append all of that group's samplelist
+ if corr_samples_group != 'samples_other':
+ self.process_samples(start_vars, primary_samples, ())
+
+ #If either Non-BXD/whatever or All Samples, get all samples from this_trait.data and
+ #exclude the primary samples (because they would have been added in the previous
+ #if statement if the user selected All Samples)
+ if corr_samples_group != 'samples_primary':
+ self.process_samples(start_vars, self.this_trait.data.keys(), primary_samples)
+ self.target_dataset = data_set.create_dataset(start_vars['corr_dataset'])
+ self.target_dataset.get_trait_data()
+ self.correlation_data = {}
+ for trait, values in self.target_dataset.trait_data.iteritems():
+ trait_values = []
+ target_values = []
+ for index, sample in enumerate(self.target_dataset.samplelist):
+ target_value = values[index]
+ if sample in self.sample_data.keys():
+ this_value = self.sample_data[sample]
+ trait_values.append(this_value)
+ target_values.append(target_value)
+ (trait_values, target_values) = normalize_values(trait_values, target_values)
+ correlation = scipy.stats.pearsonr(trait_values, target_values)
+ #correlation = cal_correlation(trait_values, target_values)
+ self.correlation_data[trait] = correlation[0]
+ #print ('correlation result: %s %s' % (trait, correlation))
+
+ for trait in self.correlation_data:
+ print("correlation: ", self.correlation_data[trait])
+
#XZ, 09/18/2008: get all information about the user selected database.
#target_db_name = fd.corr_dataset
- self.target_db_name = start_vars['corr_dataset']
+ #self.target_db_name = start_vars['corr_dataset']
# Zach said this is ok
# Auth if needed
@@ -360,396 +179,24 @@ class CorrelationResults(object):
# We will not get Literature Correlations if there is no GeneId because there is nothing
# to look against
- self.geneid = self.this_trait.geneid
+ #self.geneid = self.this_trait.geneid
# We will not get Tissue Correlations if there is no gene symbol because there is nothing to look against
#self.trait_symbol = myTrait.symbol
#XZ, 12/12/2008: if the species is rat or human, translate the geneid to mouse geneid
- self.input_trait_mouse_gene_id = self.translateToMouseGeneID(self.dataset.group.species, self.geneid)
+ #self.input_trait_mouse_gene_id = self.translateToMouseGeneID(self.dataset.group.species, self.geneid)
#XZ: As of Nov/13/2010, this dataset is 'UTHSC Illumina V6.2 RankInv B6 D2 average CNS GI average (May 08)'
- self.tissue_probeset_freeze_id = 1
+ #self.tissue_probeset_freeze_id = 1
- traitList = self.correlate()
+ #traitList = self.correlate()
- _log.info("Done doing correlation calculation")
+ #_log.info("Done doing correlation calculation")
############################################################################################################################################
- TD_LR = HT.TD(height=200,width="100%",bgColor='#eeeeee')
-
- mainfmName = webqtlUtil.genRandStr("fm_")
- form = HT.Form(cgi = os.path.join(webqtlConfig.CGIDIR, webqtlConfig.SCRIPTFILE),
- enctype='multipart/form-data', name= mainfmName, submit=HT.Input(type='hidden'))
- hddn = {'FormID': 'showDatabase',
- 'ProbeSetID': '_',
- 'database': self.target_db_name,
- 'databaseFull': self.db.fullname,
- 'CellID': '_',
- 'RISet': fd.RISet,
- 'identification': fd.identification}
-
- if myTrait:
- hddn['fullname'] = fd.fullname
- if mdp_choice:
- hddn['MDPChoice']= mdp_choice
-
-
- #XZ, 09/18/2008: pass the trait data to next page by hidden parameters.
- webqtlUtil.exportData(hddn, fd.allTraitData)
-
- if fd.incparentsf1:
- hddn['incparentsf1']='ON'
-
- if fd.allstrainlist:
- hddn['allstrainlist'] = string.join(fd.allstrainlist, ' ')
-
-
- for key in hddn.keys():
- form.append(HT.Input(name=key, value=hddn[key], type='hidden'))
-
- #XZ, 11/21/2008: add two parameters to form
- form.append(HT.Input(name="X_geneSymbol", value="", type='hidden'))
- form.append(HT.Input(name="Y_geneSymbol", value="", type='hidden'))
-
- #XZ, 3/11/2010: add one parameter to record if the method is rank order.
- form.append(HT.Input(name="rankOrder", value="%s" % rankOrder, type='hidden'))
-
- form.append(HT.Input(name="TissueProbeSetFreezeId", value="%s" % self.tissue_probeset_freeze_id, type='hidden'))
-
- ####################################
- # generate the info on top of page #
- ####################################
-
- info = self.getTopInfo(myTrait=myTrait, method=self.method, db=self.db, target_db_name=self.target_db_name, returnNumber=self.returnNumber, methodDict=self.CORRELATION_METHODS, totalTraits=traitList, identification=fd.identification )
-
- ##############
- # Excel file #
- ##############
- filename= webqtlUtil.genRandStr("Corr_")
- xlsUrl = HT.Input(type='button', value = 'Download Table', onClick= "location.href='/tmp/%s.xls'" % filename, Class='button')
- # Create a new Excel workbook
- workbook = xl.Writer('%s.xls' % (webqtlConfig.TMPDIR+filename))
- headingStyle = workbook.add_format(align = 'center', bold = 1, border = 1, size=13, fg_color = 0x1E, color="white")
-
- #XZ, 3/18/2010: pay attention to the line number of header in this file. As of today, there are 7 lines.
- worksheet = self.createExcelFileWithTitleAndFooter(workbook=workbook, identification=fd.identification, db=self.db, returnNumber=self.returnNumber)
-
- newrow = 7
-
-
-#####################################################################
-
-
- #Select All, Deselect All, Invert Selection, Add to Collection
- mintmap = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'showIntMap');" % mainfmName)
- mintmap_img = HT.Image("/images/multiple_interval_mapping1_final.jpg", name='mintmap', alt="Multiple Interval Mapping", title="Multiple Interval Mapping", style="border:none;")
- mintmap.append(mintmap_img)
- mcorr = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'compCorr');" % mainfmName)
- mcorr_img = HT.Image("/images/compare_correlates2_final.jpg", alt="Compare Correlates", title="Compare Correlates", style="border:none;")
- mcorr.append(mcorr_img)
- cormatrix = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'corMatrix');" % mainfmName)
- cormatrix_img = HT.Image("/images/correlation_matrix1_final.jpg", alt="Correlation Matrix and PCA", title="Correlation Matrix and PCA", style="border:none;")
- cormatrix.append(cormatrix_img)
- networkGraph = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'networkGraph');" % mainfmName)
- networkGraph_img = HT.Image("/images/network_graph1_final.jpg", name='mintmap', alt="Network Graphs", title="Network Graphs", style="border:none;")
- networkGraph.append(networkGraph_img)
- heatmap = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'heatmap');" % mainfmName)
- heatmap_img = HT.Image("/images/heatmap2_final.jpg", name='mintmap', alt="QTL Heat Map and Clustering", title="QTL Heatmap and Clustering", style="border:none;")
- heatmap.append(heatmap_img)
- partialCorr = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'partialCorrInput');" % mainfmName)
- partialCorr_img = HT.Image("/images/partial_correlation_final.jpg", name='partialCorr', alt="Partial Correlation", title="Partial Correlation", style="border:none;")
- partialCorr.append(partialCorr_img)
- addselect = HT.Href(url="#redirect", onClick="addRmvSelection('%s', document.getElementsByName('%s')[0], 'addToSelection');" % (fd.RISet, mainfmName))
- addselect_img = HT.Image("/images/add_collection1_final.jpg", name="addselect", alt="Add To Collection", title="Add To Collection", style="border:none;")
- addselect.append(addselect_img)
- selectall = HT.Href(url="#redirect", onClick="checkAll(document.getElementsByName('%s')[0]);" % mainfmName)
- selectall_img = HT.Image("/images/select_all2_final.jpg", name="selectall", alt="Select All", title="Select All", style="border:none;")
- selectall.append(selectall_img)
- selectinvert = HT.Href(url="#redirect", onClick = "checkInvert(document.getElementsByName('%s')[0]);" % mainfmName)
- selectinvert_img = HT.Image("/images/invert_selection2_final.jpg", name="selectinvert", alt="Invert Selection", title="Invert Selection", style="border:none;")
- selectinvert.append(selectinvert_img)
- reset = HT.Href(url="#redirect", onClick="checkNone(document.getElementsByName('%s')[0]); return false;" % mainfmName)
- reset_img = HT.Image("/images/select_none2_final.jpg", alt="Select None", title="Select None", style="border:none;")
- reset.append(reset_img)
- selecttraits = HT.Input(type='button' ,name='selecttraits',value='Select Traits', onClick="checkTraits(this.form);",Class="button")
- selectgt = HT.Input(type='text' ,name='selectgt',value='-1.0', size=6,maxlength=10,onChange="checkNumeric(this,1.0,'-1.0','gthan','greater than filed')")
- selectlt = HT.Input(type='text' ,name='selectlt',value='1.0', size=6,maxlength=10,onChange="checkNumeric(this,-1.0,'1.0','lthan','less than field')")
- selectandor = HT.Select(name='selectandor')
- selectandor.append(('AND','and'))
- selectandor.append(('OR','or'))
- selectandor.selected.append('AND')
-
-
- #External analysis tools
- GCATButton = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'GCAT');" % mainfmName)
- GCATButton_img = HT.Image("/images/GCAT_logo_final.jpg", name="GCAT", alt="GCAT", title="GCAT", style="border:none")
- GCATButton.append(GCATButton_img)
-
- ODE = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'ODE');" % mainfmName)
- ODE_img = HT.Image("/images/ODE_logo_final.jpg", name="ode", alt="ODE", title="ODE", style="border:none")
- ODE.append(ODE_img)
-
- '''
- #XZ, 07/07/2010: I comment out this block of code.
- WebGestaltScript = HT.Script(language="Javascript")
- WebGestaltScript.append("""
-setTimeout('openWebGestalt()', 2000);
-function openWebGestalt(){
-var thisForm = document['WebGestalt'];
-makeWebGestaltTree(thisForm, '%s', %d, 'edag_only.php');
-}
- """ % (mainfmName, len(traitList)))
- '''
-
- self.cursor.execute('SELECT GeneChip.GO_tree_value FROM GeneChip, ProbeFreeze, ProbeSetFreeze WHERE GeneChip.Id = ProbeFreeze.ChipId and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id and ProbeSetFreeze.Name = "%s"' % self.db.name)
- result = self.cursor.fetchone()
-
- if result:
- GO_tree_value = result[0]
-
- if GO_tree_value:
-
- WebGestalt = HT.Href(url="#redirect", onClick="databaseFunc(document.getElementsByName('%s')[0], 'GOTree');" % mainfmName)
- WebGestalt_img = HT.Image("/images/webgestalt_icon_final.jpg", name="webgestalt", alt="Gene Set Analysis Toolkit", title="Gene Set Analysis Toolkit", style="border:none")
- WebGestalt.append(WebGestalt_img)
-
- hddnWebGestalt = {
- 'id_list':'',
- 'correlation':'',
- 'id_value':'',
- 'llid_list':'',
- 'id_type':GO_tree_value,
- 'idtype':'',
- 'species':'',
- 'list':'',
- 'client':''}
-
- hddnWebGestalt['ref_type'] = hddnWebGestalt['id_type']
- hddnWebGestalt['cat_type'] = 'GO'
- hddnWebGestalt['significancelevel'] = 'Top10'
-
- if self.species == 'rat':
- hddnWebGestalt['org'] = 'Rattus norvegicus'
- elif self.species == 'human':
- hddnWebGestalt['org'] = 'Homo sapiens'
- elif self.species == 'mouse':
- hddnWebGestalt['org'] = 'Mus musculus'
- else:
- hddnWebGestalt['org'] = ''
-
- for key in hddnWebGestalt.keys():
- form.append(HT.Input(name=key, value=hddnWebGestalt[key], type='hidden'))
-
-
- #Create tables with options, etc
-
- pageTable = HT.TableLite(cellSpacing=0,cellPadding=0,width="100%", border=0, align="Left")
-
- containerTable = HT.TableLite(cellSpacing=0,cellPadding=0,width="90%",border=0, align="Left")
-
-
- if not GO_tree_value:
- optionsTable = HT.TableLite(cellSpacing=2, cellPadding=0,width="480", height="80", border=0, align="Left")
- optionsTable.append(HT.TR(HT.TD(selectall), HT.TD(reset), HT.TD(selectinvert), HT.TD(addselect), HT.TD(GCATButton), HT.TD(ODE), align="left"))
- optionsTable.append(HT.TR(HT.TD(" "*1,"Select"), HT.TD("Deselect"), HT.TD(" "*1,"Invert"), HT.TD(" "*3,"Add"), HT.TD("Gene Set"), HT.TD(" "*2,"GCAT")))
- else:
- optionsTable = HT.TableLite(cellSpacing=2, cellPadding=0,width="560", height="80", border=0, align="Left")
- optionsTable.append(HT.TR(HT.TD(selectall), HT.TD(reset), HT.TD(selectinvert), HT.TD(addselect), HT.TD(GCATButton), HT.TD(ODE), HT.TD(WebGestalt), align="left"))
- optionsTable.append(HT.TR(HT.TD(" "*1,"Select"), HT.TD("Deselect"), HT.TD(" "*1,"Invert"), HT.TD(" "*3,"Add"), HT.TD("Gene Set"), HT.TD(" "*2,"GCAT"), HT.TD(" "*3, "ODE")))
- containerTable.append(HT.TR(HT.TD(optionsTable)))
-
- functionTable = HT.TableLite(cellSpacing=2,cellPadding=0,width="480",height="80", border=0, align="Left")
- functionRow = HT.TR(HT.TD(networkGraph, width="16.7%"), HT.TD(cormatrix, width="16.7%"), HT.TD(partialCorr, width="16.7%"), HT.TD(mcorr, width="16.7%"), HT.TD(mintmap, width="16.7%"), HT.TD(heatmap), align="left")
- labelRow = HT.TR(HT.TD(" "*1,HT.Text("Graph")), HT.TD(" "*1,HT.Text("Matrix")), HT.TD(" "*1,HT.Text("Partial")), HT.TD(HT.Text("Compare")), HT.TD(HT.Text("QTL Map")), HT.TD(HT.Text(text="Heat Map")))
- functionTable.append(functionRow, labelRow)
- containerTable.append(HT.TR(HT.TD(functionTable), HT.BR()))
-
- #more_options = HT.Image("/images/more_options1_final.jpg", name='more_options', alt="Expand Options", title="Expand Options", style="border:none;", Class="toggleShowHide")
-
- #containerTable.append(HT.TR(HT.TD(more_options, HT.BR(), HT.BR())))
-
- moreOptions = HT.Input(type='button',name='options',value='More Options', onClick="",Class="toggle")
- fewerOptions = HT.Input(type='button',name='options',value='Fewer Options', onClick="",Class="toggle")
-
- """
- if (fd.formdata.getvalue('showHideOptions') == 'less'):
- containerTable.append(HT.TR(HT.TD(" "), height="10"), HT.TR(HT.TD(HT.Div(fewerOptions, Class="toggleShowHide"))))
- containerTable.append(HT.TR(HT.TD(" ")))
- else:
- containerTable.append(HT.TR(HT.TD(" "), height="10"), HT.TR(HT.TD(HT.Div(moreOptions, Class="toggleShowHide"))))
- containerTable.append(HT.TR(HT.TD(" ")))
- """
-
- containerTable.append(HT.TR(HT.TD(HT.Span(selecttraits,' with r > ',selectgt, ' ',selectandor, ' r < ',selectlt,Class="bd1 cbddf fs11")), style="display:none;", Class="extra_options"))
-
- chrMenu = HT.Input(type='hidden',name='chromosomes',value='all')
-
- corrHeading = HT.Paragraph('Correlation Table', Class="title")
-
-
- tblobj = {}
-
- if self.db.type=="Geno":
- containerTable.append(HT.TR(HT.TD(xlsUrl, height=60)))
-
- pageTable.append(HT.TR(HT.TD(containerTable)))
-
- tblobj['header'], worksheet = self.getTableHeaderForGeno( method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
- newrow += 1
-
- sortby = self.getSortByValue( calculationMethod = self.method )
-
- corrScript = HT.Script(language="Javascript")
- corrScript.append("var corrArray = new Array();")
-
- tblobj['body'], worksheet, corrScript = self.getTableBodyForGeno(traitList=traitList, formName=mainfmName, worksheet=worksheet, newrow=newrow, corrScript=corrScript)
-
- workbook.close()
- objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
- cPickle.dump(tblobj, objfile)
- objfile.close()
-
- div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), corrScript, Id="sortable")
-
- pageTable.append(HT.TR(HT.TD(div)))
-
- form.append(HT.Input(name='ShowStrains',type='hidden', value =1),
- HT.Input(name='ShowLine',type='hidden', value =1),
- HT.P(), HT.P(), pageTable)
- TD_LR.append(corrHeading, info, form, HT.P())
-
- self.dict['body'] = str(TD_LR)
- self.dict['js1'] = ''
- self.dict['title'] = 'Correlation'
-
- elif self.db.type=="Publish":
-
- containerTable.append(HT.TR(HT.TD(xlsUrl, height=40)))
-
- pageTable.append(HT.TR(HT.TD(containerTable)))
-
- tblobj['header'], worksheet = self.getTableHeaderForPublish(method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
- newrow += 1
-
- sortby = self.getSortByValue( calculationMethod = self.method )
-
- corrScript = HT.Script(language="Javascript")
- corrScript.append("var corrArray = new Array();")
-
- tblobj['body'], worksheet, corrScript = self.getTableBodyForPublish(traitList=traitList, formName=mainfmName, worksheet=worksheet, newrow=newrow, corrScript=corrScript, species=self.species)
-
- workbook.close()
-
- objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
- cPickle.dump(tblobj, objfile)
- objfile.close()
- # NL, 07/27/2010. genTableObj function has been moved from templatePage.py to webqtlUtil.py;
- div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1"), corrScript, Id="sortable")
-
- pageTable.append(HT.TR(HT.TD(div)))
-
- form.append(
- HT.Input(name='ShowStrains',type='hidden', value =1),
- HT.Input(name='ShowLine',type='hidden', value =1),
- HT.P(), pageTable)
- TD_LR.append(corrHeading, info, form, HT.P())
-
- self.dict['body'] = str(TD_LR)
- self.dict['js1'] = ''
- self.dict['title'] = 'Correlation'
-
-
- elif self.db.type=="ProbeSet":
- tblobj['header'], worksheet = self.getTableHeaderForProbeSet(method=self.method, worksheet=worksheet, newrow=newrow, headingStyle=headingStyle)
- newrow += 1
-
- sortby = self.getSortByValue( calculationMethod = self.method )
-
- corrScript = HT.Script(language="Javascript")
- corrScript.append("var corrArray = new Array();")
-
- tblobj['body'], worksheet, corrScript = self.getTableBodyForProbeSet(traitList=traitList, primaryTrait=myTrait, formName=mainfmName, worksheet=worksheet, newrow=newrow, corrScript=corrScript, species=self.species)
-
- workbook.close()
- objfile = open('%s.obj' % (webqtlConfig.TMPDIR+filename), 'wb')
- cPickle.dump(tblobj, objfile)
- objfile.close()
-
- #XZ: here is the table of traits
- div = HT.Div(webqtlUtil.genTableObj(tblobj=tblobj, file=filename, sortby=sortby, tableID = "sortable", addIndex = "1", hiddenColumns=["Gene ID","Homologene ID"]), corrScript, Id="sortable")
-
-
- #XZ, 01/12/2009: create database menu for 'Add Correlation'
- self.cursor.execute("""
- select
- ProbeSetFreeze.FullName, ProbeSetFreeze.Id, Tissue.name
- from
- ProbeSetFreeze, ProbeFreeze, ProbeSetFreeze as ps2, ProbeFreeze as p2, Tissue
- where
- ps2.Id = %d
- and ps2.ProbeFreezeId = p2.Id
- and ProbeSetFreeze.ProbeFreezeId = ProbeFreeze.Id
- and (ProbeFreeze.InbredSetId = p2.InbredSetId or (ProbeFreeze.InbredSetId in (1, 3) and p2.InbredSetId in (1, 3)))
- and p2.ChipId = ProbeFreeze.ChipId
- and ps2.Id != ProbeSetFreeze.Id
- and ProbeFreeze.TissueId = Tissue.Id
- and ProbeSetFreeze.public > %d
- order by
- ProbeFreeze.TissueId, ProbeSetFreeze.CreateTime desc
- """ % (self.db.id, webqtlConfig.PUBLICTHRESH))
-
- results = self.cursor.fetchall()
- dbCustomizer = HT.Select(results, name = "customizer")
- databaseMenuSub = preTissue = ""
- for item in results:
- TName, TId, TTissue = item
- if TTissue != preTissue:
- if databaseMenuSub:
- dbCustomizer.append(databaseMenuSub)
- databaseMenuSub = HT.Optgroup(label = '%s mRNA ------' % TTissue)
- preTissue = TTissue
-
- databaseMenuSub.append(item[:2])
- if databaseMenuSub:
- dbCustomizer.append(databaseMenuSub)
-
- #updated by NL. Delete function generateJavaScript, move js files to dhtml.js, webqtl.js and jqueryFunction.js
- #variables: filename, strainIds and vals are required by getquerystring function
- strainIds=self.getStrainIds(species=self.species, strains=self.sample_names)
- var1 = HT.Input(name="filename", value=filename, type='hidden')
- var2 = HT.Input(name="strainIds", value=strainIds, type='hidden')
- var3 = HT.Input(name="vals", value=vals, type='hidden')
- customizerButton = HT.Input(type="button", Class="button", value="Add Correlation", onClick = "xmlhttpPost('%smain.py?FormID=AJAX_table', 'sortable', (getquerystring(this.form)))" % webqtlConfig.CGIDIR)
-
- containerTable.append(HT.TR(HT.TD(HT.Span(var1,var2,var3,customizerButton, "with", dbCustomizer, Class="bd1 cbddf fs11"), HT.BR(), HT.BR()), style="display:none;", Class="extra_options"))
-
- containerTable.append(HT.TR(HT.TD(xlsUrl, HT.BR(), HT.BR())))
-
- pageTable.append(HT.TR(HT.TD(containerTable)))
-
- pageTable.append(HT.TR(HT.TD(div)))
-
- if self.species == 'human':
- heatmap = ""
-
- form.append(HT.Input(name='ShowStrains',type='hidden', value =1),
- HT.Input(name='ShowLine',type='hidden', value =1),
- info, HT.BR(), pageTable, HT.BR())
-
- TD_LR.append(corrHeading, form, HT.P())
-
-
- self.dict['body'] = str(TD_LR)
- self.dict['title'] = 'Correlation'
- # updated by NL. Delete function generateJavaScript, move js files to dhtml.js, webqtl.js and jqueryFunction.js
- self.dict['js1'] = ''
- self.dict['js2'] = 'onLoad="pageOffset()"'
- self.dict['layer'] = self.generateWarningLayer()
- else:
- self.dict['body'] = ""
def get_all_dataset_data(self):
@@ -783,21 +230,6 @@ makeWebGestaltTree(thisForm, '%s', %d, 'edag_only.php');
ProbeSet.Id = ProbeSetXRef.ProbeSetId order by ProbeSet.Id
"""
-
- #def process_samples(self, start_vars, sample_names, excluded_samples):
- # for sample in sample_names:
- # if sample not in excluded_samples:
- # value = start_vars['value:' + sample]
- # variance = start_vars['variance:' + sample]
- # if variance.strip().lower() == 'x':
- # variance = 0
- # else:
- # variance = float(variance)
- # if value.strip().lower() != 'x':
- # self.samples.append(str(sample))
- # self.vals.append(float(value))
- # #self.variances.append(variance)
-
def process_samples(self, start_vars, sample_names, excluded_samples):
for sample in sample_names:
if sample not in excluded_samples:
@@ -807,87 +239,6 @@ makeWebGestaltTree(thisForm, '%s', %d, 'edag_only.php');
else:
self.sample_data[str(sample)] = float(value)
- def getSortByValue(self, calculationMethod):
-
- if calculationMethod == "1":
- sortby = ("Sample p(r)", "up")
- elif calculationMethod == "2":
- sortby = ("Sample p(rho)", "up")
- elif calculationMethod == "3": #XZ: literature correlation
- sortby = ("Lit Corr","down")
- elif calculationMethod == "4": #XZ: tissue correlation
- sortby = ("Tissue r", "down")
- elif calculationMethod == "5":
- sortby = ("Tissue rho", "down")
-
- return sortby
-
-
-
- def generateWarningLayer(self):
-
- layerString = """
-
-
-
-
-
-
-
-
- Sort Table
-
-
-
-
-
-Resorting this table
-
-
-
-
-
-
-
-
-
-
- """
-
- return layerString
-
-
- #XZ, 01/07/2009: In HTML code, the variable 'database' corresponds to the column 'Name' in database table.
- def getFileName(self, target_db_name): ### dcrowell August 2008
- """Returns the name of the reference database file with which correlations are calculated.
- Takes argument cursor which is a cursor object of any instance of a subclass of templatePage
- Used by correlationPage"""
-
- trait_id, full_name = g.db.execute("""SELECT Id, FullName
- FROM ProbeSetFreeze
- WHERE Name = '%s'""" % target_db_name).fetchone()
- for char in [' ', '/']:
- full_name = full_name.replace(char, '_')
-
- file_name = 'ProbeSetFreezeId_' + str(trait_id) + '_FullName_' + full_name + '.txt'
-
- return file_name
-
-
-
- #XZ, 01/29/2009: I modified this function.
- #XZ: Note that the type of StrainIds must be number, not string.
- def getStrainIds(self, species=None, strains=[]):
- StrainIds = []
- for item in strains:
- self.cursor.execute('''SELECT Strain.Id FROM Strain, Species WHERE
- Strain.Name="%s" and Strain.SpeciesId=Species.Id and Species.name = "%s" ''' % (item, species))
- Id = self.cursor.fetchone()[0]
- StrainIds.append(Id)
-
- return StrainIds
-
#XZ, 12/12/2008: if the species is rat or human, translate the geneid to mouse geneid
#XZ, 12/12/2008: if the input geneid is 'None', return 0
@@ -921,26 +272,26 @@ Resorting this table
return mouse_geneid
- #XZ, 12/16/2008: the input geneid is of mouse type
- def checkForLitInfo(self,geneId):
- q = 'SELECT 1 FROM LCorrRamin3 WHERE GeneId1=%s LIMIT 1' % geneId
- self.cursor.execute(q)
- try:
- x = self.cursor.fetchone()
- if x: return True
- else: raise
- except: return False
+ ##XZ, 12/16/2008: the input geneid is of mouse type
+ #def checkForLitInfo(self,geneId):
+ # q = 'SELECT 1 FROM LCorrRamin3 WHERE GeneId1=%s LIMIT 1' % geneId
+ # self.cursor.execute(q)
+ # try:
+ # x = self.cursor.fetchone()
+ # if x: return True
+ # else: raise
+ # except: return False
- #XZ, 12/16/2008: the input geneid is of mouse type
- def checkSymbolForTissueCorr(self, tissueProbeSetFreezeId=0, symbol=""):
- q = "SELECT 1 FROM TissueProbeSetXRef WHERE TissueProbeSetFreezeId=%s and Symbol='%s' LIMIT 1" % (tissueProbeSetFreezeId,symbol)
- self.cursor.execute(q)
- try:
- x = self.cursor.fetchone()
- if x: return True
- else: raise
- except: return False
+ ##XZ, 12/16/2008: the input geneid is of mouse type
+ #def checkSymbolForTissueCorr(self, tissueProbeSetFreezeId=0, symbol=""):
+ # q = "SELECT 1 FROM TissueProbeSetXRef WHERE TissueProbeSetFreezeId=%s and Symbol='%s' LIMIT 1" % (tissueProbeSetFreezeId,symbol)
+ # self.cursor.execute(q)
+ # try:
+ # x = self.cursor.fetchone()
+ # if x: return True
+ # else: raise
+ # except: return False
def fetchAllDatabaseData(self, species, GeneId, GeneSymbol, strains, db, method, returnNumber, tissueProbeSetFreezeId):
@@ -1247,7 +598,6 @@ Resorting this table
#Todo: Redo cached stuff using memcached
if False:
- _log.info("Using the fast method because the file exists")
lit_corrs = {}
tissue_corrs = {}
use_lit = False
@@ -1366,10 +716,24 @@ Resorting this table
datasetFile.close()
totalTraits = len(allcorrelations)
_log.info("Done correlating using the fast method")
-
+
def correlate(self):
+ self.correlation_data = collections.defaultdict(list)
+ for trait, values in self.target_dataset.trait_data.iteritems():
+ values_1 = []
+ values_2 = []
+ for index,sample in enumerate(self.target_dataset.samplelist):
+ target_value = values[index]
+ if sample in self.sample_data.keys():
+ this_value = self.sample_data[sample]
+ values_1.append(this_value)
+ values_2.append(target_value)
+ correlation = calCorrelation(values_1, values_2)
+ self.correlation_data[trait] = correlation
+ print ('correlation result: %s %s' % (trait, correlation))
+ """
correlations = []
#XZ: Use the fast method only for probeset dataset, and this dataset must have been created.
@@ -1466,6 +830,7 @@ Resorting this table
method=self.method)
return trait_list
+ """
def calculateCorrOfAllTissueTrait(self, primaryTraitSymbol=None, TissueProbeSetFreezeId=None, method=None):
@@ -1523,55 +888,6 @@ Resorting this table
return traitList
- def getTopInfo(self, myTrait=None, method=None, db=None, target_db_name=None, returnNumber=None, methodDict=None, totalTraits=None, identification=None ):
-
- if myTrait:
- if method in ["1","2"]: #genetic correlation
- info = HT.Paragraph("Values of Record %s in the " % myTrait.getGivenName(), HT.Href(text=myTrait.db.fullname,url=webqtlConfig.INFOPAGEHREF % myTrait.db.name,target="_blank", Class="fwn"),
- " database were compared to all %d records in the " % self.record_count, HT.Href(text=db.fullname,url=webqtlConfig.INFOPAGEHREF % target_db_name,target="_blank", Class="fwn"),
- ' database. The top %d correlations ranked by the %s are displayed.' % (returnNumber,methodDict[method]),
- ' You can resort this list using the small arrowheads in the top row.')
- else:
- #myTrait.retrieveInfo()#need to know geneid and symbol
- if method == "3":#literature correlation
- searchDBName = "Literature Correlation"
- searchDBLink = "/correlationAnnotation.html#literatureCorr"
- else: #tissue correlation
- searchDBName = "Tissue Correlation"
- searchDBLink = "/correlationAnnotation.html#tissueCorr"
- info = HT.Paragraph("Your input record %s in the " % myTrait.getGivenName(), HT.Href(text=myTrait.db.fullname,url=webqtlConfig.INFOPAGEHREF % myTrait.db.name,target="_blank", Class="fwn"),
- " database corresponds to ",
- HT.Href(text='gene Id %s, and gene symbol %s' % (myTrait.geneid, myTrait.symbol), target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % myTrait.geneid, Class="fs12 fwn"),
- '. GN ranked all genes in the ', HT.Href(text=searchDBName,url=searchDBLink,target="_blank", Class="fwn"),' database by the %s.' % methodDict[method],
- ' The top %d probes or probesets in the ' % returnNumber, HT.Href(text=db.fullname,url=webqtlConfig.INFOPAGEHREF % target_db_name,target="_blank", Class="fwn"),
- ' database corresponding to the top genes ranked by the %s are displayed.' %( methodDict[method]),
- ' You can resort this list using the small arrowheads in the top row.' )
-
- elif identification:
- info = HT.Paragraph('Values of %s were compared to all %d traits in ' % (identification, self.record_count),
- HT.Href(text=db.fullname,url=webqtlConfig.INFOPAGEHREF % target_db_name,target="_blank",Class="fwn"),
- ' database. The TOP %d correlations ranked by the %s are displayed.' % (returnNumber,methodDict[method]),
- ' You can resort this list using the small arrowheads in the top row.')
-
- else:
- info = HT.Paragraph('Trait values were compared to all values in ',
- HT.Href(text=db.fullname,url=webqtlConfig.INFOPAGEHREF % target_db_name,target="_blank",Class="fwn"),
- ' database. The TOP %d correlations ranked by the %s are displayed.' % (returnNumber,methodDict[method]),
- ' You can resort this list using the small arrowheads in the top row.')
-
- if db.type=="Geno":
- info.append(HT.BR(),HT.BR(),'Clicking on the Locus will open the genotypes data for that locus. Click on the correlation to see a scatter plot of the trait data.')
- elif db.type=="Publish":
- info.append(HT.BR(),HT.BR(),'Clicking on the record ID will open the published phenotype data for that publication. Click on the correlation to see a scatter plot of the trait data. ')
- elif db.type=="ProbeSet":
- info.append(HT.BR(),'Click the correlation values to generate scatter plots. Select the Record ID to open the Trait Data and Analysis form. Select the symbol to open NCBI Entrez.')
- else:
- pass
-
-
- return info
-
-
def createExcelFileWithTitleAndFooter(self, workbook=None, identification=None, db=None, returnNumber=None):
worksheet = workbook.add_worksheet()
@@ -1691,463 +1007,19 @@ Resorting this table
return tblobj_body, worksheet, corrScript
-
- def getTableHeaderForPublish(self, method=None, worksheet=None, newrow=None, headingStyle=None):
-
- tblobj_header = []
-
- if method in ["1","3","4"]:
- tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), sort=0),
- THCell(HT.TD('Record',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Record ID", idx=1),
- THCell(HT.TD('Phenotype', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Phenotype", idx=2),
- THCell(HT.TD('Authors', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Authors", idx=3),
- THCell(HT.TD('Year', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Year", idx=4),
- THCell(HT.TD('Max',HT.BR(), 'LRS', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Max LRS", idx=5),
- THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Max LRS Location", idx=6),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Sample',HT.BR(), 'r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#genetic_r"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample r", idx=7),
- THCell(HT.TD('N',HT.BR(),'Cases',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="N Cases", idx=8),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Sample',HT.BR(), 'p(r)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#genetic_p_r"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample p(r)", idx=9)]]
-
- for ncol, item in enumerate(["Record", "Phenotype", "Authors", "Year", "Pubmed Id", "Max LRS", "Max LRS Location (Chr: Mb)", "Sample r", "N Cases", "Sample p(r)"]):
- worksheet.write([newrow, ncol], item, headingStyle)
- worksheet.set_column([ncol, ncol], 2*len(item))
- else:
- tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), sort=0),
- THCell(HT.TD('Record',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Record ID", idx=1),
- THCell(HT.TD('Phenotype', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Phenotype", idx=2),
- THCell(HT.TD('Authors', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Authors", idx=3),
- THCell(HT.TD('Year', HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Year", idx=4),
- THCell(HT.TD('Max',HT.BR(), 'LRS', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Max LRS", idx=5),
- THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap="on"), text="Max LRS Location", idx=6),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Sample',HT.BR(), 'rho', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#genetic_rho"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample rho", idx=7),
- THCell(HT.TD('N',HT.BR(),'Cases',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="N Cases", idx=8),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Sample',HT.BR(), 'p(rho)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#genetic_p_rho"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample p(rho)", idx=9)]]
-
- for ncol, item in enumerate(["Record", "Phenotype", "Authors", "Year", "Pubmed Id", "Max LRS", "Max LRS Location (Chr: Mb)", "Sample rho", "N Cases", "Sample p(rho)"]):
- worksheet.write([newrow, ncol], item, headingStyle)
- worksheet.set_column([ncol, ncol], 2*len(item))
-
-
- return tblobj_header, worksheet
-
-
- def getTableBodyForPublish(self, traitList, formName=None, worksheet=None, newrow=None, corrScript=None, species=''):
-
- tblobj_body = []
-
- for thisTrait in traitList:
- tr = []
-
- trId = str(thisTrait)
-
- corrScript.append('corrArray["%s"] = {corr:%1.4f};' % (trId, thisTrait.corr))
-
- tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class="fs12 fwn ffl b1 c222"), text=trId))
-
- tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showTrait('%s', '%s')" % (formName, thisTrait.name), Class="fs12 fwn"), nowrap="yes",align="center", Class="fs12 fwn b1 c222"),str(thisTrait.name), thisTrait.name))
-
- PhenotypeString = thisTrait.post_publication_description
- if thisTrait.confidential:
- if not webqtlUtil.hasAccessToConfidentialPhenotypeTrait(privilege=self.privilege, userName=self.userName, authorized_users=thisTrait.authorized_users):
- PhenotypeString = thisTrait.pre_publication_description
-
- tr.append(TDCell(HT.TD(PhenotypeString, Class="fs12 fwn b1 c222"), PhenotypeString, PhenotypeString.upper()))
-
- tr.append(TDCell(HT.TD(thisTrait.authors, Class="fs12 fwn b1 c222 fsI"),thisTrait.authors, thisTrait.authors.strip().upper()))
-
- try:
- PubMedLinkText = myear = repr = int(thisTrait.year)
- except:
- PubMedLinkText = repr = "--"
- myear = 0
- if thisTrait.pubmed_id:
- PubMedLink = HT.Href(text= repr,url= webqtlConfig.PUBMEDLINK_URL % thisTrait.pubmed_id,target='_blank', Class="fs12 fwn")
- else:
- PubMedLink = repr
-
- tr.append(TDCell(HT.TD(PubMedLink, Class="fs12 fwn b1 c222", align='center'), repr, myear))
-
- #LRS and its location
- LRS_score_repr = '--'
- LRS_score_value = 0
- LRS_location_repr = '--'
- LRS_location_value = 1000000
- LRS_flag = 1
-
- #Max LRS and its Locus location
- if thisTrait.lrs and thisTrait.locus:
- self.cursor.execute("""
- select Geno.Chr, Geno.Mb from Geno, Species
- where Species.Name = '%s' and
- Geno.Name = '%s' and
- Geno.SpeciesId = Species.Id
- """ % (species, thisTrait.locus))
- result = self.cursor.fetchone()
-
- if result:
- if result[0] and result[1]:
- LRS_Chr = result[0]
- LRS_Mb = result[1]
-
- #XZ: LRS_location_value is used for sorting
- try:
- LRS_location_value = int(LRS_Chr)*1000 + float(LRS_Mb)
- except:
- if LRS_Chr.upper() == 'X':
- LRS_location_value = 20*1000 + float(LRS_Mb)
- else:
- LRS_location_value = ord(str(LRS_chr).upper()[0])*1000 + float(LRS_Mb)
-
-
- LRS_score_repr = '%3.1f' % thisTrait.lrs
- LRS_score_value = thisTrait.lrs
- LRS_location_repr = 'Chr%s: %.6f' % (LRS_Chr, float(LRS_Mb) )
- LRS_flag = 0
-
- #tr.append(TDCell(HT.TD(HT.Href(text=LRS_score_repr,url="javascript:showIntervalMapping('%s', '%s : %s')" % (formName, thisTrait.db.shortname, thisTrait.name), Class="fs12 fwn"), Class="fs12 fwn ffl b1 c222", align='right', nowrap="on"),LRS_score_repr, LRS_score_value))
- tr.append(TDCell(HT.TD(LRS_score_repr, Class="fs12 fwn b1 c222", align='right', nowrap="on"), LRS_score_repr, LRS_score_value))
- tr.append(TDCell(HT.TD(LRS_location_repr, Class="fs12 fwn b1 c222"), LRS_location_repr, LRS_location_value))
-
- if LRS_flag:
- tr.append(TDCell(HT.TD(LRS_score_repr, Class="fs12 fwn b1 c222"), LRS_score_repr, LRS_score_value))
- tr.append(TDCell(HT.TD(LRS_location_repr, Class="fs12 fwn b1 c222"), LRS_location_repr, LRS_location_value))
-
- repr = '%3.4f' % thisTrait.corr
- tr.append(TDCell(HT.TD(HT.Href(text=repr,url="javascript:showCorrPlot('%s', '%s')" % (formName,thisTrait.name), Class="fs12 fwn"), Class="fs12 fwn b1 c222", align='right',nowrap="on"), repr, abs(thisTrait.corr)))
-
- repr = '%d' % thisTrait.nOverlap
- tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.nOverlap))
-
- repr = webqtlUtil.SciFloat(thisTrait.corrPValue)
- tr.append(TDCell(HT.TD(repr,nowrap='ON', Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.corrPValue))
-
- tblobj_body.append(tr)
-
- for ncol, item in enumerate([thisTrait.name, PhenotypeString, thisTrait.authors, thisTrait.year, thisTrait.pubmed_id, LRS_score_repr, LRS_location_repr, thisTrait.corr, thisTrait.nOverlap, thisTrait.corrPValue]):
- worksheet.write([newrow, ncol], item)
- newrow += 1
-
- return tblobj_body, worksheet, corrScript
-
-
- def getTableHeaderForProbeSet(self, method=None, worksheet=None, newrow=None, headingStyle=None):
-
- tblobj_header = []
-
- if method in ["1","3","4"]:
- tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), sort=0),
- THCell(HT.TD('Record',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Record ID", idx=1),
- THCell(HT.TD('Gene',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Gene ID", idx=2),
- THCell(HT.TD('Homologene',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Homologene ID", idx=3),
- THCell(HT.TD('Symbol',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Symbol", idx=4),
- THCell(HT.TD('Description',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Description", idx=5),
- THCell(HT.TD('Location',HT.BR(), 'Chr and Mb', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Location (Chr: Mb)", idx=6),
- THCell(HT.TD('Mean',HT.BR(),'Expr',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Mean Expr", idx=7),
- THCell(HT.TD('Max',HT.BR(),'LRS',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Max LRS", idx=8),
- THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Max LRS Location (Chr: Mb)", idx=9),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Sample',HT.BR(), 'r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#genetic_r"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample r", idx=10),
- THCell(HT.TD('N',HT.BR(),'Cases',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="N Cases", idx=11),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Sample',HT.BR(), 'p(r)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#genetic_p_r"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample p(r)", idx=12),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Lit',HT.BR(), 'Corr', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#literatureCorr"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Lit Corr", idx=13),
- #XZ, 09/22/2008: tissue correlation
- THCell(HT.TD(HT.Href(
- text = HT.Span('Tissue',HT.BR(), 'r', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#tissue_r"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Tissue r", idx=14),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Tissue',HT.BR(), 'p(r)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#tissue_p_r"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Tissue p(r)", idx=15)]]
-
- for ncol, item in enumerate(['Record', 'Gene ID', 'Homologene ID', 'Symbol', 'Description', 'Location (Chr: Mb)', 'Mean Expr', 'Max LRS', 'Max LRS Location (Chr: Mb)', 'Sample r', 'N Cases', 'Sample p(r)', 'Lit Corr', 'Tissue r', 'Tissue p(r)']):
- worksheet.write([newrow, ncol], item, headingStyle)
- worksheet.set_column([ncol, ncol], 2*len(item))
- else:
- tblobj_header = [[THCell(HT.TD(' ', Class="fs13 fwb ffl b1 cw cbrb",nowrap='ON'), sort=0),
- THCell(HT.TD('Record',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Record ID", idx=1),
- THCell(HT.TD('Gene',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Gene ID", idx=2),
- THCell(HT.TD('Homologene',HT.BR(), 'ID',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Homologene ID", idx=3),
- THCell(HT.TD('Symbol',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Symbol", idx=4),
- THCell(HT.TD('Description',HT.BR(),HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Description", idx=5),
- THCell(HT.TD('Location',HT.BR(), 'Chr and Mb', HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Location (Chr: Mb)", idx=6),
- THCell(HT.TD('Mean',HT.BR(),'Expr',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="Mean Expr", idx=7),
- THCell(HT.TD('Max',HT.BR(),'LRS',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Max LRS", idx=8),
- THCell(HT.TD('Max LRS Location',HT.BR(),'Chr and Mb',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Max LRS Location (Chr: Mb)", idx=9),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Sample',HT.BR(), 'rho', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#genetic_rho"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample rho", idx=10),
- THCell(HT.TD('N',HT.BR(),'Cases',HT.BR(), Class="fs13 fwb ffl b1 cw cbrb"), text="N Cases", idx=11),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Sample',HT.BR(), 'p(rho)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#genetic_p_rho"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Sample p(rho)", idx=12),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Lit',HT.BR(), 'Corr', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#literatureCorr"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Lit Corr", idx=13),
- #XZ, 09/22/2008: tissue correlation
- THCell(HT.TD(HT.Href(
- text = HT.Span('Tissue',HT.BR(), 'rho', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#tissue_r"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Tissue rho", idx=14),
- THCell(HT.TD(HT.Href(
- text = HT.Span('Tissue',HT.BR(), 'p(rho)', HT.Sup(' ?', style="color:#f00"),HT.BR(), Class="fs13 fwb ffl cw"),
- target = '_blank',
- url = "/correlationAnnotation.html#tissue_p_r"),
- Class="fs13 fwb ffl b1 cw cbrb", nowrap='ON'), text="Tissue p(rho)", idx=15)]]
-
- for ncol, item in enumerate(['Record ID', 'Gene ID', 'Homologene ID', 'Symbol', 'Description', 'Location (Chr: Mb)', 'Mean Expr', 'Max LRS', 'Max LRS Location (Chr: Mb)', 'Sample rho', 'N Cases', 'Sample p(rho)', 'Lit Corr', 'Tissue rho', 'Tissue p(rho)']):
- worksheet.write([newrow, ncol], item, headingStyle)
- worksheet.set_column([ncol, ncol], 2*len(item))
-
- return tblobj_header, worksheet
-
-
- def getTableBodyForProbeSet(self, traitList=[], primaryTrait=None, formName=None, worksheet=None, newrow=None, corrScript=None, species=''):
-
- tblobj_body = []
-
- for thisTrait in traitList:
-
- if thisTrait.symbol:
- pass
- else:
- thisTrait.symbol = "--"
-
- if thisTrait.geneid:
- symbolurl = HT.Href(text=thisTrait.symbol,target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s" % thisTrait.geneid, Class="fs12 fwn")
- else:
- symbolurl = HT.Href(text=thisTrait.symbol,target='_blank',url="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?CMD=search&DB=gene&term=%s" % thisTrait.symbol, Class="fs12 fwn")
-
- tr = []
-
- trId = str(thisTrait)
-
- corrScript.append('corrArray["%s"] = {corr:%1.4f};' % (trId, thisTrait.corr))
-
- #XZ, 12/08/2008: checkbox
- tr.append(TDCell(HT.TD(HT.Input(type="checkbox", Class="checkbox", name="searchResult",value=trId, onClick="highlight(this)"), nowrap="on", Class="fs12 fwn ffl b1 c222"), text=trId))
-
- #XZ, 12/08/2008: probeset name
- tr.append(TDCell(HT.TD(HT.Href(text=thisTrait.name,url="javascript:showTrait('%s', '%s')" % (formName,thisTrait.name), Class="fs12 fwn"), Class="fs12 fwn b1 c222"), thisTrait.name, thisTrait.name.upper()))
-
- #XZ, 12/08/2008: gene id
- if thisTrait.geneid:
- tr.append(TDCell(None, thisTrait.geneid, val=999))
- else:
- tr.append(TDCell(None, thisTrait.geneid, val=999))
-
- #XZ, 12/08/2008: homologene id
- if thisTrait.homologeneid:
- tr.append(TDCell("", thisTrait.homologeneid, val=999))
- else:
- tr.append(TDCell("", thisTrait.homologeneid, val=999))
-
- #XZ, 12/08/2008: gene symbol
- tr.append(TDCell(HT.TD(symbolurl, Class="fs12 fwn b1 c222 fsI"),thisTrait.symbol, thisTrait.symbol.upper()))
-
- #XZ, 12/08/2008: description
- #XZ, 06/05/2009: Rob asked to add probe target description
- description_string = str(thisTrait.description).strip()
- target_string = str(thisTrait.probe_target_description).strip()
-
- description_display = ''
-
- if len(description_string) > 1 and description_string != 'None':
- description_display = description_string
- else:
- description_display = thisTrait.symbol
-
- if len(description_display) > 1 and description_display != 'N/A' and len(target_string) > 1 and target_string != 'None':
- description_display = description_display + '; ' + target_string.strip()
-
- tr.append(TDCell(HT.TD(description_display, Class="fs12 fwn b1 c222"), description_display, description_display))
-
- #XZ: trait_location_value is used for sorting
- trait_location_repr = '--'
- trait_location_value = 1000000
-
- if thisTrait.chr and thisTrait.mb:
- try:
- trait_location_value = int(thisTrait.chr)*1000 + thisTrait.mb
- except:
- if thisTrait.chr.upper() == 'X':
- trait_location_value = 20*1000 + thisTrait.mb
- else:
- trait_location_value = ord(str(thisTrait.chr).upper()[0])*1000 + thisTrait.mb
-
- trait_location_repr = 'Chr%s: %.6f' % (thisTrait.chr, float(thisTrait.mb) )
-
- tr.append(TDCell(HT.TD(trait_location_repr, Class="fs12 fwn b1 c222", nowrap="on"), trait_location_repr, trait_location_value))
-
- """
- #XZ, 12/08/2008: chromosome number
- #XZ, 12/10/2008: use Mbvalue to sort chromosome
- tr.append(TDCell( HT.TD(thisTrait.chr, Class="fs12 fwn b1 c222", align='right'), thisTrait.chr, Mbvalue) )
-
- #XZ, 12/08/2008: Rob wants 6 digit precision, and we have to deal with that the mb could be None
- if not thisTrait.mb:
- tr.append(TDCell(HT.TD(thisTrait.mb, Class="fs12 fwn b1 c222",align='right'), thisTrait.mb, Mbvalue))
- else:
- tr.append(TDCell(HT.TD('%.6f' % thisTrait.mb, Class="fs12 fwn b1 c222", align='right'), thisTrait.mb, Mbvalue))
- """
-
-
-
- #XZ, 01/12/08: This SQL query is much faster.
- self.cursor.execute("""
- select ProbeSetXRef.mean from ProbeSetXRef, ProbeSet
- where ProbeSetXRef.ProbeSetFreezeId = %d and
- ProbeSet.Id = ProbeSetXRef.ProbeSetId and
- ProbeSet.Name = '%s'
- """ % (thisTrait.db.id, thisTrait.name))
- result = self.cursor.fetchone()
- if result:
- if result[0]:
- mean = result[0]
- else:
- mean=0
- else:
- mean = 0
-
- #XZ, 06/05/2009: It is neccessary to turn on nowrap
- repr = "%2.3f" % mean
- tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right', nowrap='ON'),repr, mean))
-
- #LRS and its location
- LRS_score_repr = '--'
- LRS_score_value = 0
- LRS_location_repr = '--'
- LRS_location_value = 1000000
- LRS_flag = 1
-
- #Max LRS and its Locus location
- if thisTrait.lrs and thisTrait.locus:
- self.cursor.execute("""
- select Geno.Chr, Geno.Mb from Geno, Species
- where Species.Name = '%s' and
- Geno.Name = '%s' and
- Geno.SpeciesId = Species.Id
- """ % (species, thisTrait.locus))
- result = self.cursor.fetchone()
-
- if result:
- if result[0] and result[1]:
- LRS_Chr = result[0]
- LRS_Mb = result[1]
-
- #XZ: LRS_location_value is used for sorting
- try:
- LRS_location_value = int(LRS_Chr)*1000 + float(LRS_Mb)
- except:
- if LRS_Chr.upper() == 'X':
- LRS_location_value = 20*1000 + float(LRS_Mb)
- else:
- LRS_location_value = ord(str(LRS_chr).upper()[0])*1000 + float(LRS_Mb)
-
-
- LRS_score_repr = '%3.1f' % thisTrait.lrs
- LRS_score_value = thisTrait.lrs
- LRS_location_repr = 'Chr%s: %.6f' % (LRS_Chr, float(LRS_Mb) )
- LRS_flag = 0
-
- #tr.append(TDCell(HT.TD(HT.Href(text=LRS_score_repr,url="javascript:showIntervalMapping('%s', '%s : %s')" % (formName, thisTrait.db.shortname, thisTrait.name), Class="fs12 fwn"), Class="fs12 fwn ffl b1 c222", align='right', nowrap="on"),LRS_score_repr, LRS_score_value))
- tr.append(TDCell(HT.TD(LRS_score_repr, Class="fs12 fwn b1 c222", align='right', nowrap="on"), LRS_score_repr, LRS_score_value))
- tr.append(TDCell(HT.TD(LRS_location_repr, Class="fs12 fwn b1 c222", nowrap="on"), LRS_location_repr, LRS_location_value))
-
- if LRS_flag:
- tr.append(TDCell(HT.TD(LRS_score_repr, Class="fs12 fwn b1 c222"), LRS_score_repr, LRS_score_value))
- tr.append(TDCell(HT.TD(LRS_location_repr, Class="fs12 fwn b1 c222"), LRS_location_repr, LRS_location_value))
-
-
- #XZ, 12/08/2008: generic correlation
- repr='%3.3f' % thisTrait.corr
- tr.append(TDCell(HT.TD(HT.Href(text=repr, url="javascript:showCorrPlot('%s', '%s')" % (formName, thisTrait.name), Class="fs12 fwn ffl"), Class="fs12 fwn ffl b1 c222", align='right'),repr,abs(thisTrait.corr)))
-
- #XZ, 12/08/2008: number of overlaped cases
- repr = '%d' % thisTrait.nOverlap
- tr.append(TDCell(HT.TD(repr, Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.nOverlap))
-
- #XZ, 12/08/2008: p value of genetic correlation
- repr = webqtlUtil.SciFloat(thisTrait.corrPValue)
- tr.append(TDCell(HT.TD(repr,nowrap='ON', Class="fs12 fwn ffl b1 c222", align='right'),repr,thisTrait.corrPValue))
-
- #XZ, 12/08/2008: literature correlation
- LCorr = 0.0
- LCorrStr = "--"
- if hasattr(thisTrait, 'LCorr') and thisTrait.LCorr:
- LCorr = thisTrait.LCorr
- LCorrStr = "%2.3f" % thisTrait.LCorr
- tr.append(TDCell(HT.TD(LCorrStr, Class="fs12 fwn b1 c222", align='right'), LCorrStr, abs(LCorr)))
-
- #XZ, 09/22/2008: tissue correlation.
- TCorr = 0.0
- TCorrStr = "--"
- #XZ, 11/20/2008: need to pass two geneids: input_trait_mouse_geneid and thisTrait.mouse_geneid
- if hasattr(thisTrait, 'tissueCorr') and thisTrait.tissueCorr:
- TCorr = thisTrait.tissueCorr
- TCorrStr = "%2.3f" % thisTrait.tissueCorr
- # NL, 07/19/2010: add a new parameter rankOrder for js function 'showTissueCorrPlot'
- rankOrder = self.RANK_ORDERS[self.method]
- TCorrPlotURL = "javascript:showTissueCorrPlot('%s','%s','%s',%d)" %(formName, primaryTrait.symbol, thisTrait.symbol,rankOrder)
- tr.append(TDCell(HT.TD(HT.Href(text=TCorrStr, url=TCorrPlotURL, Class="fs12 fwn ff1"), Class="fs12 fwn ff1 b1 c222", align='right'), TCorrStr, abs(TCorr)))
- else:
- tr.append(TDCell(HT.TD(TCorrStr, Class="fs12 fwn b1 c222", align='right'), TCorrStr, abs(TCorr)))
-
- #XZ, 12/08/2008: p value of tissue correlation
- TPValue = 1.0
- TPValueStr = "--"
- if hasattr(thisTrait, 'tissueCorr') and thisTrait.tissuePValue: #XZ, 09/22/2008: thisTrait.tissuePValue can't be used here because it could be 0
- TPValue = thisTrait.tissuePValue
- TPValueStr = "%2.3f" % thisTrait.tissuePValue
- tr.append(TDCell(HT.TD(TPValueStr, Class="fs12 fwn b1 c222", align='right'), TPValueStr, TPValue))
-
- tblobj_body.append(tr)
-
- for ncol, item in enumerate([thisTrait.name, thisTrait.geneid, thisTrait.homologeneid, thisTrait.symbol, thisTrait.description, trait_location_repr, mean, LRS_score_repr, LRS_location_repr, thisTrait.corr, thisTrait.nOverlap, thisTrait.corrPValue, LCorr, TCorr, TPValue]):
- worksheet.write([newrow, ncol], item)
-
- newrow += 1
-
- return tblobj_body, worksheet, corrScript
+def normalize_values(values_1, values_2):
+ N = min(len(values_1), len(values_2))
+ X = []
+ Y = []
+ for i in range(N):
+ if values_1[i]!= None and values_2[i]!= None:
+ X.append(values_1[i])
+ Y.append(values_2[i])
+
+ return (X, Y)
-def calCorrelation(values_1, values_2):
+def cal_correlation(values_1, values_2):
N = min(len(values_1), len(values_2))
X = []
Y = []
diff --git a/wqflask/wqflask/templates/correlation_page.html b/wqflask/wqflask/templates/correlation_page.html
index 40c14aaa..be750a0c 100644
--- a/wqflask/wqflask/templates/correlation_page.html
+++ b/wqflask/wqflask/templates/correlation_page.html
@@ -1,1358 +1,53 @@
- {% extends "base.html" %}
- {% block title %}Correlation{% endblock %}
- {% block content %}
-
-
-
-
-
-
- Correlation Table
-
-
-
-
-
-
-
-
-
-
- {% endblock %}
\ No newline at end of file
+{% extends "base.html" %}
+{% block content %}
+
+
+
+ Correlation
+
+
+
+ {% for trait in correlation_data %}
+
+ {{ correlation_data[trait] }}
+
+ {% endfor %}
+
+
+{% endblock %}
+
+
+{% block js %}
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
--
cgit 1.4.1
From 466be48f92d4943995c7a3e7bcb9fd1efd775bf6 Mon Sep 17 00:00:00 2001
From: Lei Yan
Date: Thu, 30 May 2013 23:14:50 +0000
Subject: Rewrote some code in get_trait_info in dataset.py
Added spearman correlation to show_corr_results and template
---
wqflask/base/data_set.py | 123 +++++++++++++----------
wqflask/base/trait.py | 4 +-
wqflask/wqflask/correlation/show_corr_results.py | 36 ++++---
wqflask/wqflask/templates/correlation_page.html | 52 +++++++---
4 files changed, 126 insertions(+), 89 deletions(-)
(limited to 'wqflask')
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index c2380f8c..4c5c46a5 100755
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -672,12 +672,13 @@ class MrnaAssayDataSet(DataSet):
query += ' FROM ({}, {}XRef, {}Freeze) '.format(*mescape(self.type,
self.type,
self.type))
- #XZ, 03/04/2009: Xiaodong changed Data to %sData and changed parameters from %(item,item, db.type,item,item) to %(db.type, item,item, db.type,item,item)
+
for item in sample_ids_step:
query += """
left join {}Data as T{} on T{}.Id = {}XRef.DataId
and T{}.StrainId={}\n
""".format(*mescape(self.type, item, item, self.type, item, item))
+
query += """
WHERE {}XRef.{}FreezeId = {}Freeze.Id
and {}Freeze.Name = '{}'
@@ -690,17 +691,19 @@ class MrnaAssayDataSet(DataSet):
trait_count = len(trait_sample_data[0])
self.trait_data = collections.defaultdict(list)
+
# put all of the separate data together into a dictionary where the keys are
# trait names and values are lists of sample values
- for j in range(trait_count):
- trait_name = trait_sample_data[0][j][0]
- for i in range(int(number_chunks)):
- self.trait_data[trait_name] += trait_sample_data[i][j][data_start_pos:]
-
+ for trait_counter in range(trait_count):
+ trait_name = trait_sample_data[0][trait_counter][0]
+ for chunk_counter in range(int(number_chunks)):
+ self.trait_data[trait_name] += (
+ trait_sample_data[chunk_counter][trait_counter][data_start_pos:])
+
def get_trait_info(self, trait_list=None, species=''):
- # Note: setting trait_list to [] is probably not a great idea.
+ # Note: setting trait_list to [] is probably not a great idea.
if not trait_list:
trait_list = []
@@ -709,9 +712,7 @@ class MrnaAssayDataSet(DataSet):
if not this_trait.haveinfo:
this_trait.retrieveInfo(QTL=1)
- if this_trait.symbol:
- pass
- else:
+ if not this_trait.symbol:
this_trait.symbol = "N/A"
#XZ, 12/08/2008: description
@@ -719,60 +720,56 @@ class MrnaAssayDataSet(DataSet):
description_string = str(this_trait.description).strip()
target_string = str(this_trait.probe_target_description).strip()
- description_display = ''
-
if len(description_string) > 1 and description_string != 'None':
description_display = description_string
else:
description_display = this_trait.symbol
- if len(description_display) > 1 and description_display != 'N/A' and len(target_string) > 1 and target_string != 'None':
+ if (len(description_display) > 1 and description_display != 'N/A' and
+ len(target_string) > 1 and target_string != 'None'):
description_display = description_display + '; ' + target_string.strip()
# Save it for the jinja2 template
this_trait.description_display = description_display
- #print(" xxxxdd [%s]: %s" % (type(this_trait.description_display), description_display))
#XZ: trait_location_value is used for sorting
trait_location_repr = 'N/A'
trait_location_value = 1000000
if this_trait.chr and this_trait.mb:
- try:
- trait_location_value = int(this_trait.chr)*1000 + this_trait.mb
- except:
- if this_trait.chr.upper() == 'X':
- trait_location_value = 20*1000 + this_trait.mb
- else:
- trait_location_value = ord(str(this_trait.chr).upper()[0])*1000 + this_trait.mb
-
- this_trait.location_repr = 'Chr %s: %.4f Mb' % (this_trait.chr, float(this_trait.mb) )
+ #Checks if the chromosome number can be cast to an int (i.e. isn't "X" or "Y")
+ #This is so we can convert the location to a number used for sorting
+ trait_location_value = self.convert_location_to_value(this_trait.chr, this_trait.mb)
+ #try:
+ # trait_location_value = int(this_trait.chr)*1000 + this_trait.mb
+ #except ValueError:
+ # if this_trait.chr.upper() == 'X':
+ # trait_location_value = 20*1000 + this_trait.mb
+ # else:
+ # trait_location_value = (ord(str(this_trait.chr).upper()[0])*1000 +
+ # this_trait.mb)
+
+ #ZS: Put this in function currently called "convert_location_to_value"
+ this_trait.location_repr = 'Chr %s: %.4f Mb' % (this_trait.chr,
+ float(this_trait.mb))
this_trait.location_value = trait_location_value
- #this_trait.trait_location_value = trait_location_value
- #XZ, 01/12/08: This SQL query is much faster.
+ #Get mean expression value
query = (
-"""select ProbeSetXRef.mean from ProbeSetXRef, ProbeSet
- where ProbeSetXRef.ProbeSetFreezeId = %s and
- ProbeSet.Id = ProbeSetXRef.ProbeSetId and
- ProbeSet.Name = '%s'
+ """select ProbeSetXRef.mean from ProbeSetXRef, ProbeSet
+ where ProbeSetXRef.ProbeSetFreezeId = %s and
+ ProbeSet.Id = ProbeSetXRef.ProbeSetId and
+ ProbeSet.Name = '%s'
""" % (escape(str(this_trait.dataset.id)),
escape(this_trait.name)))
print("query is:", pf(query))
result = g.db.execute(query).fetchone()
+
+ mean = result[0] if result else 0
- if result:
- if result[0]:
- mean = result[0]
- else:
- mean=0
- else:
- mean = 0
-
- #XZ, 06/05/2009: It is neccessary to turn on nowrap
- this_trait.mean = repr = "%2.3f" % mean
+ this_trait.mean = "%2.3f" % mean
#LRS and its location
this_trait.LRS_score_repr = 'N/A'
@@ -791,23 +788,39 @@ class MrnaAssayDataSet(DataSet):
result = self.cursor.fetchone()
if result:
- if result[0] and result[1]:
- LRS_Chr = result[0]
- LRS_Mb = result[1]
-
- #XZ: LRS_location_value is used for sorting
- try:
- LRS_location_value = int(LRS_Chr)*1000 + float(LRS_Mb)
- except:
- if LRS_Chr.upper() == 'X':
- LRS_location_value = 20*1000 + float(LRS_Mb)
- else:
- LRS_location_value = ord(str(LRS_chr).upper()[0])*1000 + float(LRS_Mb)
+ #if result[0] and result[1]:
+ # lrs_chr = result[0]
+ # lrs_mb = result[1]
+ lrs_chr, lrs_mb = result
+ #XZ: LRS_location_value is used for sorting
+ lrs_location_value = self.convert_location_to_value(lrs_chr, lrs_mb)
+
+ #try:
+ # lrs_location_value = int(lrs_chr)*1000 + float(lrs_mb)
+ #except:
+ # if lrs_chr.upper() == 'X':
+ # lrs_location_value = 20*1000 + float(lrs_mb)
+ # else:
+ # lrs_location_value = (ord(str(LRS_chr).upper()[0])*1000 +
+ # float(lrs_mb))
+
+ this_trait.LRS_score_repr = '%3.1f' % this_trait.lrs
+ this_trait.LRS_score_value = this_trait.lrs
+ this_trait.LRS_location_repr = 'Chr %s: %.4f Mb' % (lrs_chr, float(lrs_mb))
+
+
+ def convert_location_to_value(chromosome, mb):
+ try:
+ location_value = int(chromosome)*1000 + float(mb)
+ except ValueError:
+ if chromosome.upper() == 'X':
+ location_value = 20*1000 + float(mb)
+ else:
+ location_value = (ord(str(chromosome).upper()[0])*1000 +
+ float(mb))
+
+ return location_value
- this_trait.LRS_score_repr = LRS_score_repr = '%3.1f' % this_trait.lrs
- this_trait.LRS_score_value = LRS_score_value = this_trait.lrs
- this_trait.LRS_location_repr = LRS_location_repr = 'Chr %s: %.4f Mb' % (LRS_Chr, float(LRS_Mb) )
-
def get_sequence(self):
query = """
SELECT
diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py
index 7c1c035c..5fde114f 100755
--- a/wqflask/base/trait.py
+++ b/wqflask/base/trait.py
@@ -15,7 +15,7 @@ from pprint import pformat as pf
from flask import Flask, g
-class GeneralTrait:
+class GeneralTrait(object):
"""
Trait class defines a trait in webqtl, can be either Microarray,
Published phenotype, genotype, or user input trait
@@ -78,7 +78,7 @@ class GeneralTrait:
#desc = self.handle_pca(desc)
stringy = desc
return stringy
-
+
def display_name(self):
diff --git a/wqflask/wqflask/correlation/show_corr_results.py b/wqflask/wqflask/correlation/show_corr_results.py
index aa20eba1..5d40c835 100644
--- a/wqflask/wqflask/correlation/show_corr_results.py
+++ b/wqflask/wqflask/correlation/show_corr_results.py
@@ -30,7 +30,6 @@
from __future__ import absolute_import, print_function, division
import string
-from math import *
import cPickle
import os
import time
@@ -106,6 +105,7 @@ class CorrelationResults(object):
corr_samples_group = start_vars['corr_samples_group']
self.sample_data = {}
+ self.corr_method = start_vars['corr_sample_method']
#The two if statements below append samples to the sample list based upon whether the user
#rselected Primary Samples Only, Other Samples Only, or All Samples
@@ -123,27 +123,31 @@ class CorrelationResults(object):
#if statement if the user selected All Samples)
if corr_samples_group != 'samples_primary':
self.process_samples(start_vars, self.this_trait.data.keys(), primary_samples)
+
self.target_dataset = data_set.create_dataset(start_vars['corr_dataset'])
self.target_dataset.get_trait_data()
+
self.correlation_data = {}
for trait, values in self.target_dataset.trait_data.iteritems():
- trait_values = []
+ this_trait_values = []
target_values = []
for index, sample in enumerate(self.target_dataset.samplelist):
- target_value = values[index]
- if sample in self.sample_data.keys():
- this_value = self.sample_data[sample]
- trait_values.append(this_value)
- target_values.append(target_value)
- (trait_values, target_values) = normalize_values(trait_values, target_values)
- correlation = scipy.stats.pearsonr(trait_values, target_values)
- #correlation = cal_correlation(trait_values, target_values)
- self.correlation_data[trait] = correlation[0]
- #print ('correlation result: %s %s' % (trait, correlation))
-
- for trait in self.correlation_data:
- print("correlation: ", self.correlation_data[trait])
-
+ if sample in self.sample_data:
+ sample_value = self.sample_data[sample]
+ target_sample_value = values[index]
+ this_trait_values.append(sample_value)
+ target_values.append(target_sample_value)
+
+ this_trait_values, target_values = normalize_values(this_trait_values, target_values)
+ if self.corr_method == 'pearson':
+ sample_r, sample_p = scipy.stats.pearsonr(this_trait_values, target_values)
+ else:
+ sample_r, sample_p = scipy.stats.spearmanr(this_trait_values, target_values)
+ self.correlation_data[trait] = [sample_r, sample_p]
+ self.correlation_data = collections.OrderedDict(
+ sorted(self.correlation_data.items(),
+ key=lambda t: -abs(t[1][0])))
+
#XZ, 09/18/2008: get all information about the user selected database.
#target_db_name = fd.corr_dataset
diff --git a/wqflask/wqflask/templates/correlation_page.html b/wqflask/wqflask/templates/correlation_page.html
index be750a0c..68fe81ed 100644
--- a/wqflask/wqflask/templates/correlation_page.html
+++ b/wqflask/wqflask/templates/correlation_page.html
@@ -1,21 +1,42 @@
{% extends "base.html" %}
-{% block content %}
-
-
-
- Correlation
-
-
-
- {% for trait in correlation_data %}
-
- {{ correlation_data[trait] }}
-
- {% endfor %}
-
-
+{% block css %}
+
+
+
+
{% endblock %}
+{% block content %}
+
+
+
+
+
+ Trait
+ {% if corr_method == 'pearson' %}
+ Sample r
+ Sample p(r)
+ {% else %}
+ Sample rho
+ Sample p(rho)
+ {% endif %}
+
+
+
+ {% for trait in correlation_data %}
+
+ {{ trait }}
+ {{ correlation_data[trait][0] }}
+ {{ correlation_data[trait][1] }}
+
+ {% endfor %}
+
+
+{% endblock %}
{% block js %}
@@ -23,7 +44,6 @@
-
@@ -274,9 +175,14 @@
-
@@ -175,16 +275,9 @@
+
{% endblock %}
+
diff --git a/wqflask/wqflask/templates/show_trait_details.html b/wqflask/wqflask/templates/show_trait_details.html
index c3abfc9f..b57c3c21 100644
--- a/wqflask/wqflask/templates/show_trait_details.html
+++ b/wqflask/wqflask/templates/show_trait_details.html
@@ -19,11 +19,11 @@
BLAT Specifity
- {{ "%.1f" % (this_trait.probe_set_specificity) }}
+ {{ "%s" % (this_trait.probe_set_specificity) }}
{% endif %}
{% if this_trait.probe_set_blat_score %}
BLAT Score
- {{ "%i" % (this_trait.probe_set_blat_score) }}
+ {{ "%s" % (this_trait.probe_set_blat_score) }}
{% endif %}
--
cgit 1.4.1
From 0e633460f37cb9b7c23805c4c31b1044e0704d1b Mon Sep 17 00:00:00 2001
From: Sam
Date: Thu, 13 Jun 2013 20:13:22 +0000
Subject: Small changes
---
wqflask/wqflask/model.py | 3 +--
wqflask/wqflask/user_manager.py | 6 ++++++
wqflask/wqflask/views.py | 2 +-
3 files changed, 8 insertions(+), 3 deletions(-)
(limited to 'wqflask')
diff --git a/wqflask/wqflask/model.py b/wqflask/wqflask/model.py
index 296f1f0d..5beba9ff 100644
--- a/wqflask/wqflask/model.py
+++ b/wqflask/wqflask/model.py
@@ -64,5 +64,4 @@ security = Security(app, user_datastore)
db.metadata.create_all(db.engine)
-
-
+user_datastore.create_role(name="Genentech", description="Genentech Beta Project(testing)")
diff --git a/wqflask/wqflask/user_manager.py b/wqflask/wqflask/user_manager.py
index 97ba18a3..b8ebc71f 100644
--- a/wqflask/wqflask/user_manager.py
+++ b/wqflask/wqflask/user_manager.py
@@ -32,3 +32,9 @@ class UserManager(object):
#print("user is:", user)
self.user = model.User.query.get(self.user_id)
print("user is:", self.user)
+
+
+class RolesManager(object):
+ def __init__(self):
+ self.roles = model.Role.query.all()
+ print("Roles are:", self.roles)
diff --git a/wqflask/wqflask/views.py b/wqflask/wqflask/views.py
index b59c3b34..f92042bd 100644
--- a/wqflask/wqflask/views.py
+++ b/wqflask/wqflask/views.py
@@ -69,7 +69,7 @@ def data_sharing_page():
htmlfilelist=htmlfilelist)
-@app.route("/search")
+@app.route("/search", methods=('POST',))
def search_page():
print("in search_page")
if 'info_database' in request.args:
--
cgit 1.4.1
From aac1dd2f9c5b216b24c6e35676ba5d50f9d5d3c2 Mon Sep 17 00:00:00 2001
From: Zachary Sloan
Date: Thu, 13 Jun 2013 20:15:30 +0000
Subject: Put the template html for the quick search page when all trait types
are displayed in a separate file that is included in quick_search.html
---
wqflask/wqflask/templates/all_results.html | 134 +++++++++++++++++++++++++++++
1 file changed, 134 insertions(+)
create mode 100644 wqflask/wqflask/templates/all_results.html
(limited to 'wqflask')
diff --git a/wqflask/wqflask/templates/all_results.html b/wqflask/wqflask/templates/all_results.html
new file mode 100644
index 00000000..a42e42d8
--- /dev/null
+++ b/wqflask/wqflask/templates/all_results.html
@@ -0,0 +1,134 @@
+
+ {% for species in species_groups %}
+ {{ species }}
+ {% endfor %}
+
+
+ {% for species in species_groups %}
+
+
+
+ {% if species_groups[species]['phenotype'] %}
+ Phenotype
+ {% endif %}
+ {% if species_groups[species]['mrna_assay'] %}
+ mRNA Assay
+ {% endif %}
+ {% if species_groups[species]['genotype'] %}
+ Genotype
+ {% endif %}
+
+
+ {% if species_groups[species]['phenotype'] %}
+
+
+
+
+ Id
+ Species
+ Group
+ Description
+ LRS
+ Year
+ Authors
+
+
+
+ {% for result in results.phenotype %}
+ {% if result.result_fields['species'] == species %}
+
+ {{ result.result_fields['phenotype_id'] }}
+ {{ result.result_fields['species'] }}
+ {{ result.result_fields['group_name'] }}
+ {{ result.result_fields['description'] }}
+ {{ result.result_fields['lrs'] }}
+
+
+ {{ result.result_fields['year'] }}
+
+
+ {{ result.result_fields['authors'] }}
+
+ {% endif %}
+ {% endfor %}
+
+
+
+ {% endif %}
+ {% if species_groups[species]['mrna_assay'] %}
+
+
+
+
+ Record ID
+ Species
+ Group
+ Data Set
+ Symbol
+ Description
+ Location
+ Mean Expr
+ Max LRS
+
+
+
+ {% for result in results.mrna_assay %}
+ {% if result.result_fields['species'] == species %}
+
+
+
+
+ {{ result.result_fields['species'] }}
+ {{ result.result_fields['group_name'] }}
+ {{ result.result_fields['dataset_name'] }}
+ {{ result.result_fields['symbol'] }}
+ {{ result.result_fields['description'] }}
+ {{ result.result_fields['chr'] }} : {{ result['mb'] }}
+ {{ result.result_fields['mean'] }}
+ {{ result.result_fields['lrs'] }}
+
+ {% endif %}
+ {% endfor %}
+
+
+
+ {% endif %}
+ {% if species_groups[species]['genotype'] %}
+
+
+
+
+ Marker
+ Species
+ Group
+ Data Set
+ Location
+
+
+
+ {% for result in results.genotype %}
+ {% if result.result_fields['species'] == species %}
+
+
+
+ {{ result.result_fields['marker_name'] }}
+
+
+ {{ result.result_fields['species'] }}
+ {{ result.result_fields['group_name'] }}
+ {{ result.result_fields['dataset_name'] }}
+ {{ result.result_fields['chr'] }} : {{ result.result_fields['mb'] }}
+
+ {% endif %}
+ {% endfor %}
+
+
+
+ {% endif %}
+
+
+
+ {% endfor %}
+
\ No newline at end of file
--
cgit 1.4.1
From 25bd2fa7ac229eb7862fe778fe03eb75ff34368c Mon Sep 17 00:00:00 2001
From: Lei Yan
Date: Thu, 13 Jun 2013 21:13:51 +0000
Subject: Fixed issue where too much memory was used as a result of creating a
dataset object for each trait in the correlation results
Added new fields/columns for each trait in the correlation result table
(max LRS, max LRS location, mean expression)
Fixed error if trait doesn't have these fields
---
wqflask/base/data_set.py | 30 +++----
wqflask/base/trait.py | 27 +++++--
wqflask/utility/helper_functions.py | 2 +-
wqflask/wqflask/correlation/show_corr_results.py | 99 +++++++++++-------------
wqflask/wqflask/search_results.py | 2 +-
5 files changed, 83 insertions(+), 77 deletions(-)
(limited to 'wqflask')
diff --git a/wqflask/base/data_set.py b/wqflask/base/data_set.py
index 0c7676c4..0903bf16 100755
--- a/wqflask/base/data_set.py
+++ b/wqflask/base/data_set.py
@@ -90,8 +90,8 @@ class Markers(object):
self.markers = json.load(json_data_fh)
def add_pvalues(self, p_values):
- print("length of self.markers:", len(self.markers))
- print("length of p_values:", len(p_values))
+ #print("length of self.markers:", len(self.markers))
+ #print("length of p_values:", len(p_values))
# THIS IS only needed for the case when we are limiting the number of p-values calculated
if len(self.markers) < len(p_values):
@@ -161,7 +161,7 @@ class DatasetGroup(object):
self.f1list = None
self.parlist = None
self.get_f1_parent_strains()
- print("parents/f1s: {}:{}".format(self.parlist, self.f1list))
+ #print("parents/f1s: {}:{}".format(self.parlist, self.f1list))
self.species = webqtlDatabaseFunction.retrieve_species(self.name)
@@ -170,7 +170,7 @@ class DatasetGroup(object):
def get_markers(self):
- print("self.species is:", self.species)
+ #print("self.species is:", self.species)
if self.species == "human":
marker_class = HumanMarkers
else:
@@ -293,14 +293,14 @@ class DataSet(object):
self.name,
self.name,
self.name))
- print("query_args are:", query_args)
+ #print("query_args are:", query_args)
- print("""
- SELECT Id, Name, FullName, ShortName
- FROM %s
- WHERE public > %s AND
- (Name = '%s' OR FullName = '%s' OR ShortName = '%s')
- """ % (query_args))
+ #print("""
+ # SELECT Id, Name, FullName, ShortName
+ # FROM %s
+ # WHERE public > %s AND
+ # (Name = '%s' OR FullName = '%s' OR ShortName = '%s')
+ # """ % (query_args))
self.id, self.name, self.fullname, self.shortname = g.db.execute("""
SELECT Id, Name, FullName, ShortName
@@ -624,12 +624,12 @@ class MrnaAssayDataSet(DataSet):
and ProbeSetFreezeId = {}
""".format(escape(str(self.id)))
results = g.db.execute(query).fetchall()
- print("After get_trait_list query")
+ #print("After get_trait_list query")
trait_data = {}
for trait in results:
print("Retrieving sample_data for ", trait[0])
trait_data[trait[0]] = self.retrieve_sample_data(trait[0])
- print("After retrieve_sample_data")
+ #print("After retrieve_sample_data")
return trait_data
def get_trait_data(self):
@@ -763,7 +763,7 @@ class MrnaAssayDataSet(DataSet):
""" % (escape(str(this_trait.dataset.id)),
escape(this_trait.name)))
- print("query is:", pf(query))
+ #print("query is:", pf(query))
result = g.db.execute(query).fetchone()
@@ -926,7 +926,7 @@ class TempDataSet(DataSet):
def geno_mrna_confidentiality(ob):
dataset_table = ob.type + "Freeze"
- print("dataset_table [%s]: %s" % (type(dataset_table), dataset_table))
+ #print("dataset_table [%s]: %s" % (type(dataset_table), dataset_table))
query = '''SELECT Id, Name, FullName, confidentiality,
AuthorisedUsers FROM %s WHERE Name = %%s''' % (dataset_table)
diff --git a/wqflask/base/trait.py b/wqflask/base/trait.py
index 53f41779..f333d5a7 100755
--- a/wqflask/base/trait.py
+++ b/wqflask/base/trait.py
@@ -1,6 +1,8 @@
from __future__ import absolute_import, division, print_function
import string
+import resource
+
from htmlgen import HTMLgen2 as HT
@@ -15,6 +17,10 @@ from pprint import pformat as pf
from flask import Flask, g
+def print_mem(stage=""):
+ mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
+ print("{}: {}".format(stage, mem/1024))
+
class GeneralTrait(object):
"""
Trait class defines a trait in webqtl, can be either Microarray,
@@ -23,8 +29,12 @@ class GeneralTrait(object):
"""
def __init__(self, **kw):
- #print("in GeneralTrait")
- self.dataset = kw.get('dataset') # database name
+ # xor assertion
+ assert bool(kw.get('dataset')) != bool(kw.get('dataset_name')), "Needs dataset ob. xor name";
+ if kw.get('dataset_name'):
+ self.dataset = create_dataset(kw.get('dataset_name'))
+ else:
+ self.dataset = kw.get('dataset')
self.name = kw.get('name') # Trait ID, ProbeSet ID, Published ID, etc.
self.cellid = kw.get('cellid')
self.identification = kw.get('identification', 'un-named trait')
@@ -39,8 +49,6 @@ class GeneralTrait(object):
# self.cellid is set to None above
elif len(name2) == 3:
self.dataset, self.name, self.cellid = name2
-
- self.dataset = create_dataset(self.dataset)
# Todo: These two lines are necessary most of the time, but perhaps not all of the time
# So we could add a simple if statement to short-circuit this if necessary
@@ -355,8 +363,17 @@ class GeneralTrait(object):
#traitQTL = self.cursor.fetchone()
if traitQTL:
self.locus, self.lrs, self.pvalue, self.mean = traitQTL
+ if self.locus:
+ result = g.db.execute("""
+ select Geno.Chr, Geno.Mb from Geno, Species
+ where Species.Name = '%s' and
+ Geno.Name = '%s' and
+ Geno.SpeciesId = Species.Id
+ """, (species, self.locus)).fetchone()
+ self.locus_chr = result[0]
+ self.locus_mb = result[1]
else:
- self.locus = self.lrs = self.pvalue = self.mean = ""
+ self.locus = self.locus_chr = self.locus_mb = self.lrs = self.pvalue = self.mean = ""
if self.dataset.type == 'Publish':
traitQTL = g.db.execute("""
SELECT
diff --git a/wqflask/utility/helper_functions.py b/wqflask/utility/helper_functions.py
index 28242c27..d76a32ce 100644
--- a/wqflask/utility/helper_functions.py
+++ b/wqflask/utility/helper_functions.py
@@ -9,7 +9,7 @@ def get_species_dataset_trait(self, start_vars):
#assert type(read_genotype) == type(bool()), "Expecting boolean value for read_genotype"
self.dataset = data_set.create_dataset(start_vars['dataset'])
self.species = TheSpecies(dataset=self.dataset)
- self.this_trait = GeneralTrait(dataset=self.dataset.name,
+ self.this_trait = GeneralTrait(dataset=self.dataset,
name=start_vars['trait_id'],
cellid=None)
diff --git a/wqflask/wqflask/correlation/show_corr_results.py b/wqflask/wqflask/correlation/show_corr_results.py
index 96c0155b..3b8b7ba2 100644
--- a/wqflask/wqflask/correlation/show_corr_results.py
+++ b/wqflask/wqflask/correlation/show_corr_results.py
@@ -92,11 +92,6 @@ class CorrelationResults(object):
#
#RANK_ORDERS = {"1": 0, "2": 1, "3": 0, "4": 0, "5": 1}
-
- #def error(self, message, *args, **kw):
- # heading = heading or self.PAGE_HEADING
- # return templatePage.error(heading = heading, detail = [message], error=error)
-
def __init__(self, start_vars):
# get trait list from db (database name)
# calculate correlation with Base vector and targets
@@ -104,10 +99,8 @@ class CorrelationResults(object):
#self.this_trait = GeneralTrait(dataset=self.dataset.name,
# name=start_vars['trait_id'],
# cellid=None)
-
#print("start_vars: ", pf(start_vars))
with Bench("Doing correlations"):
- print_mem("At beginning")
helper_functions.get_species_dataset_trait(self, start_vars)
self.dataset.group.read_genotype_file()
@@ -138,7 +131,6 @@ class CorrelationResults(object):
self.correlation_data = {}
- print_mem("Before calculating correlations")
for trait, values in self.target_dataset.trait_data.iteritems():
this_trait_values = []
target_values = []
@@ -150,63 +142,60 @@ class CorrelationResults(object):
target_values.append(target_sample_value)
this_trait_values, target_values = normalize_values(this_trait_values, target_values)
-
+
if self.corr_method == 'pearson':
sample_r, sample_p = scipy.stats.pearsonr(this_trait_values, target_values)
else:
sample_r, sample_p = scipy.stats.spearmanr(this_trait_values, target_values)
-
+
self.correlation_data[trait] = [sample_r, sample_p]
-
- print_mem("After calculating correlations")
-
+
self.correlation_data = collections.OrderedDict(sorted(self.correlation_data.items(),
key=lambda t: -abs(t[1][0])))
-
+
self.correlation_data_slice = collections.OrderedDict()
-
- old_memory_usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
-
+
for trait_counter, trait in enumerate(self.correlation_data.keys()[:300]):
- print_mem("In trait info loop")
- print("\nTrait #:", trait_counter)
- print_mem("Before trait_object")
- trait_object = GeneralTrait(dataset=self.dataset.name, name=trait)
- print_mem("After trait object")
- trait_info = dict(
- correlation = float(self.correlation_data[trait][0]),
- p_value = float(self.correlation_data[trait][1]),
- symbol = trait_object.symbol,
- alias = trait_object.alias,
- description = trait_object.description,
- chromosome = trait_object.chr,
- mb = trait_object.mb
- )
- print_mem("Before deleting trait object")
- del trait_object
- print_mem("After deleting trait object")
- gc.collect()
- print_mem("After colleting garabage")
- print("** trait_info:", pf(trait_info))
- print("\n** Start trait_info")
- counter = 1
- for key, value in trait_info.iteritems():
- print(" <{}> [{}] {}: [{}] {}\n".format(
- counter, type(key), key, type(value), value))
- counter += 1
- print("** Done trait_info")
+ trait_object = GeneralTrait(dataset=self.dataset, name=trait)
+ if self.dataset.type == 'ProbeSet':
+ trait_info = collections.OrderedDict(
+ correlation = float(self.correlation_data[trait][0]),
+ p_value = float(self.correlation_data[trait][1]),
+ symbol = trait_object.symbol,
+ alias = trait_object.alias,
+ description = trait_object.description,
+ chromosome = trait_object.chr,
+ mb = trait_object.mb
+ )
+ if hasattr(trait_object, 'mean'):
+ trait_info[mean] = trait_object.mean
+ if hasattr(trait_object, 'lrs'):
+ trait_info[lrs] = trait_object.lrs
+ if hasattr(trait_object, 'locus_chr'):
+ trait_info[locus_chr] = trait_object.locus_chr
+ if hasattr(trait_object, 'locus_mb'):
+ trait_info[locus_mb] = trait_object.locus_mb
+ elif self.dataset.type == 'Geno':
+ trait_info = collections.OrderedDict(
+ correlation = float(self.correlation_data[trait][0]),
+ p_value = float(self.correlation_data[trait][1]),
+ symbol = trait_object.symbol,
+ alias = trait_object.alias,
+ description = trait_object.description,
+ chromosome = trait_object.chr,
+ mb = trait_object.mb
+ )
+ else: # 'Publish'
+ trait_info = collections.OrderedDict(
+ correlation = float(self.correlation_data[trait][0]),
+ p_value = float(self.correlation_data[trait][1]),
+ symbol = trait_object.symbol,
+ alias = trait_object.alias,
+ description = trait_object.description,
+ chromosome = trait_object.chr,
+ mb = trait_object.mb
+ )
self.correlation_data_slice[trait] = trait_info
- #self.correlation_data_slice[trait].append(trait_object)
-
- new_memory_usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
- print("Memory difference:", new_memory_usage-old_memory_usage)
- old_memory_usage = new_memory_usage
- print_mem("End of purple loop")
- print("*************************** End purple ******** ")
-
- print_mem("After getting trait info")
- print("Garbage colleting...")
- gc.collect()
#XZ, 09/18/2008: get all information about the user selected database.
#target_db_name = fd.corr_dataset
diff --git a/wqflask/wqflask/search_results.py b/wqflask/wqflask/search_results.py
index dc872a8b..e171f1ab 100644
--- a/wqflask/wqflask/search_results.py
+++ b/wqflask/wqflask/search_results.py
@@ -106,7 +106,7 @@ class SearchResultPage(object):
print("foo locals are:", locals())
trait_id = result[0]
- this_trait = GeneralTrait(dataset=self.dataset.name, name=trait_id)
+ this_trait = GeneralTrait(dataset=self.dataset, name=trait_id)
this_trait.retrieve_info(QTL=True)
self.trait_list.append(this_trait)
--
cgit 1.4.1
From 392272095baf02496405031d488e32ef68b0f85f Mon Sep 17 00:00:00 2001
From: Zachary Sloan
Date: Thu, 13 Jun 2013 23:04:38 +0000
Subject: Made a few changes while trying to figure out why the search isn't
working post-merging with Sam's code
---
wqflask/wqflask/search_results.py | 1 +
wqflask/wqflask/templates/index_page.html | 1 +
wqflask/wqflask/views.py | 1 +
3 files changed, 3 insertions(+)
(limited to 'wqflask')
diff --git a/wqflask/wqflask/search_results.py b/wqflask/wqflask/search_results.py
index 63aa481e..d6432c86 100644
--- a/wqflask/wqflask/search_results.py
+++ b/wqflask/wqflask/search_results.py
@@ -77,6 +77,7 @@ class SearchResultPage(object):
self.quick_search()
else:
self.results = []
+ print("kw is:", kw)
#self.quick_search = False
self.search_terms = kw['search_terms']
self.dataset = create_dataset(kw['dataset'])
diff --git a/wqflask/wqflask/templates/index_page.html b/wqflask/wqflask/templates/index_page.html
index 2b298eeb..f9c5188f 100644
--- a/wqflask/wqflask/templates/index_page.html
+++ b/wqflask/wqflask/templates/index_page.html
@@ -30,6 +30,7 @@
+