<commit_before>import logging
import os
import shutil
import pwd
import grp
import base64
from bson import objectid

import _judger

import yamajudge
from yamajudge import db
from yamajudge import request
from yamajudge import error
from yamajudge import workspace
from yamajudge import judge
from yamajudge.constant import record
from yamajudge.constant import language

_logger = logging.getLogger(__name__)

class JudgeTask(object):
    def __init__(self, rid: objectid.ObjectId):
        self.rid = rid
        _logger.info('Judge request incoming: {0}'.format(rid))
        try:
            rdoc, pdoc, ddoc = self.fetch_data()
        except error.Error as e:
            _logger.error('Fetch record information failed: {0}'.format(repr(e)))
            raise e

        _logger.info('Record data fetched.')
        self.code = rdoc['code']
        self.lang = rdoc['lang']
        self.time_ms = pdoc['time_ms']
        self.memory_kb = pdoc['memory_kb']
        self.data = ddoc['data']
        self.judge_mode = pdoc.get('judge_mode', record.MODE_COMPARE_IGNORE_SPACE)
        self.config = language.lang_config[rdoc['lang']]
        if self.judge_mode == record.MODE_SPECIAL_JUDGE:
            try:
                self.judger_bin = pdoc['judger_bin']
            except KeyError as e:
                _logger.error('This problem is Special Judge but it haven\'t judger.')
                raise e

    def fetch_data(self):
        record_coll = db.Collection('record')
        problem_coll = db.Collection('problem')
        data_coll = db.Collection('testdata')

        # Get record doc.
        rdoc = record_coll.find_one({'_id': self.rid})
        if not rdoc:
            raise error.RecordNotFoundError(self.rid)
        # Get problem doc.
        pdoc = problem_coll.find_one({'_id': rdoc['pid']})
        if not pdoc:
            raise error.ProblemNotFoundError(rdoc['pid'])
        if rdoc['data_id']:
            data_id = rdoc['data_id']
        else:
            data_id = pdoc['data']
        # Get data.
        ddoc = data_coll.find_one({'_id': data_id})
        if not ddoc:
            raise error.TestDataNotFoundError(data_id)
        return rdoc, pdoc, ddoc

    def prepare_file(self, work_dir):
        with open(work_dir.join(self.config['src_name']), 'w') as file:
            file.write(self.code)
        if self.judge_mode == record.MODE_SPECIAL_JUDGE:
            with open(work_dir.join('judger'), 'wb') as file:
                file.write(base64.b64decode(self.judger_bin))
            os.chmod(work_dir.join('judger'), 0o755)
        shutil.copy(os.path.join(os.path.dirname(os.path.dirname(yamajudge.__file__)),
                                 'java_policy'), str(work_dir))

    def compile(self, work_dir):
        _logger.info('Compiling...')
        command = self.config['compile_command'].split(' ')
        compile_out = work_dir.join('compile.out')
        result = _judger.run(max_cpu_time=10000,
                             max_real_time=10000,
                             max_memory=_judger.UNLIMITED,
                             max_output_size=16 * 1024 * 1024,   # 16 MiB
                             max_process_number=_judger.UNLIMITED,
                             exe_path=command[0],
                             input_path=work_dir.join(self.config['src_name']),
                             output_path=compile_out,
                             error_path=compile_out,
                             args=command[1:],
                             env=['PATH=' + os.getenv('PATH')],
                             log_path=work_dir.join('compile.log'),
                             seccomp_rule_name=None,
                             uid=pwd.getpwnam('judger').pw_uid,
                             gid=grp.getgrnam('judger').gr_gid)

        compiler_text = ''
        if os.path.exists(compile_out):
            with open(compile_out) as file:
                compiler_text = file.read(2 * 1024).strip()  # 2 KiB
        return result['result'], compiler_text

    def execute(self, work_dir, input_str):
        in_file = work_dir.join('in_file')
        out_file = work_dir.join('out_file')
        err_file = work_dir.join('err_file')
        log_file = work_dir.join('runner.out')
        command = self.config['run_command'].format(memory_kb=self.memory_kb).split(' ')
        with open(in_file, 'w') as file:
            file.write(input_str)
        result = _judger.run(max_cpu_time=int(self.time_ms * self.config['time_rate']),
                             max_real_time=int(self.time_ms * 5 * self.config['time_rate']),
                             max_memory=self.memory_kb * 1024 if self.lang != 'java' else _judger.UNLIMITED,
                             max_output_size=1024 * 1024,   # 1 MiB
                             max_process_number=_judger.UNLIMITED,
                             exe_path=command[0],
                             input_path=in_file,
                             output_path=out_file,
                             error_path=err_file,
                             args=command[1:],
                             env=['PATH=' + os.getenv('PATH')],
                             log_path=log_file,
                             seccomp_rule_name=self.config['seccomp_rule'],
                             uid=pwd.getpwnam('nobody').pw_uid,
                             gid=grp.getgrnam('nogroup').gr_gid)

        out_ans = ''
        if result['result'] == _judger.RESULT_SUCCESS:
            try:
                with open(out_file) as file:
                    out_ans = file.read()
            except ValueError:
                out_ans = ''

        # check memory out in stderr
        if result['result'] == record.STATUS_RUNTIME_ERROR:
            with open(err_file) as file:
                err_out = file.read()
            if 'java.lang.OutOfMemoryError' in err_out:
                result['result'] = record.STATUS_MEMORY_LIMIT_EXCEEDED
                result['memory'] = self.memory_kb * 1024

        result['memory'] //= 1024
        return result, out_ans

    def judge(self, work_dir, user_out, correct_out):
        # TODO: add special judge.
        if self.judge_mode == record.MODE_COMPARE_IGNORE_SPACE:
            return judge.judge(user_out, correct_out, ignore_space=True)
        elif self.judge_mode == record.MODE_COMPARE:
            return judge.judge(user_out, correct_out, ignore_space=False)
        elif self.judge_mode == record.MODE_SPECIAL_JUDGE:
            return self.special_judge(work_dir, user_out, correct_out)

    def special_judge(self, work_dir, user_out, correct_out):
        in_file = work_dir.join('in_file')
        user_file = work_dir.join('out_file')
        out_file = work_dir.join('correct_file')
        judger_err_file = work_dir.join('judger_err_file')
        with open(work_dir.join('correct_file'), 'w') as file:
            file.write(correct_out)
        log_file = work_dir.join('judger.out')
        result = _judger.run(max_cpu_time=int(self.time_ms * self.config['time_rate']),
                             max_real_time=int(self.time_ms * 5 * self.config['time_rate']),
                             max_memory=self.memory_kb * 1024 if self.lang != 'java' else _judger.UNLIMITED,
                             max_output_size=1024 * 1024,   # 1 MiB
                             max_process_number=_judger.UNLIMITED,
                             exe_path=work_dir.join('judger'),
                             input_path='/dev/null',
                             output_path=log_file,
                             error_path=judger_err_file,
                             args=[in_file, out_file, user_file],
                             env=['PATH=' + os.getenv('PATH')],
                             log_path='/dev/null',
                             seccomp_rule_name=None,
                             uid=pwd.getpwnam('judger').pw_uid,
                             gid=grp.getgrnam('judger').gr_gid)
        with open(log_file) as file:
            judger_out = file.read()
        judge_res = record.STATUS_ACCEPTED if result['exit_code'] == 0 else record.STATUS_WRONG_ANSWER
        return judge_res, 'Judger Output: {0}'.format(judger_out)

    def next_judge(self, **kwargs):
        request.next_judge(self.rid, **kwargs)

    def end_judge(self, status: int, time_ms: int=0, memory_kb: int=0):
        request.end_judge(self.rid, status, time_ms, memory_kb)

    def run(self):
        with workspace.WorkSpace(self.rid) as work_dir:
            try:
                _logger.info('Judge workspace created.')
                # Prepare some files
                os.chdir(str(work_dir))
                self.prepare_file(work_dir)
                self.next_judge(status=record.STATUS_COMPILING)
                # Compile your program
                compile_result, compiler_text = self.compile(work_dir)
                self.next_judge(compiler_text=compiler_text)
                if compile_result != _judger.RESULT_SUCCESS:  # Compile Error
                    _logger.info('Compile Error.')
                    self.end_judge(record.STATUS_COMPILE_ERROR)
                    return
                # Execute your program
                total_time_ms = 0
                max_memory = 0
                final_result = record.STATUS_ACCEPTED
                self.next_judge(status=record.STATUS_JUDGING, progress=0.0)

                for index, case in enumerate(self.data, start=1):
                    _logger.info('Running case {0}/{1}...'.format(index, len(self.data)))
                    result, user_out = self.execute(work_dir, case[0])
                    judge_text = ''
                    if result['result'] == _judger.RESULT_SUCCESS:
                        # Have to judge
                        result['result'], judge_text = self.judge(work_dir, user_out, case[1])
                    if result['cpu_time'] < 10:
                        result['cpu_time'] = 0

                    # Update record information
                    total_time_ms += result['cpu_time']
                    max_memory = max(max_memory, result['memory'])
                    final_result = max(final_result, result['result'])

                    self.next_judge(progress=index / len(self.data),
                                    case=True,
                                    case_status=result['result'],
                                    case_time_ms=result['cpu_time'],
                                    case_memory_kb=result['memory'],
                                    case_judge_text=judge_text)
                    if result['result'] == record.STATUS_SYSTEM_ERROR or \
                            result['result'] == record.STATUS_TIME_LIMIT_EXCEEDED:
                        # TLE or SE will stop judge immediately
                        self.end_judge(status=result['result'],
                                       time_ms=total_time_ms,
                                       memory_kb=max_memory)
                        return

                _logger.info('Judge ended.')
                self.end_judge(status=final_result, time_ms=total_time_ms, memory_kb=max_memory)
            except Exception as e:
                _logger.error('An error occurred: {0}'.format(repr(e)))
                work_dir.dump()
                raise e
<commit_msg>Update task.py<commit_after>import logging
import os
import shutil
import pwd
import grp
import base64
from bson import objectid

import _judger

import yamajudge
from yamajudge import db
from yamajudge import request
from yamajudge import error
from yamajudge import workspace
from yamajudge import judge
from yamajudge.constant import record
from yamajudge.constant import language

_logger = logging.getLogger(__name__)

class JudgeTask(object):
    def __init__(self, rid: objectid.ObjectId):
        self.rid = rid
        _logger.info('Judge request incoming: {0}'.format(rid))
        try:
            rdoc, pdoc, ddoc = self.fetch_data()
        except error.Error as e:
            _logger.error('Fetch record information failed: {0}'.format(repr(e)))
            raise e

        _logger.info('Record data fetched.')
        self.code = rdoc['code']
        self.lang = rdoc['lang']
        self.time_ms = pdoc['time_ms']
        self.memory_kb = pdoc['memory_kb']
        self.data = ddoc['data']
        self.judge_mode = pdoc.get('judge_mode', record.MODE_COMPARE_IGNORE_SPACE)
        self.config = language.lang_config[rdoc['lang']]
        if self.judge_mode == record.MODE_SPECIAL_JUDGE:
            try:
                self.judger_bin = pdoc['judger_bin']
            except KeyError as e:
                _logger.error('This problem is Special Judge but it haven\'t judger.')
                raise e

    def fetch_data(self):
        record_coll = db.Collection('record')
        problem_coll = db.Collection('problem')
        data_coll = db.Collection('testdata')

        # Get record doc.
        rdoc = record_coll.find_one({'_id': self.rid})
        if not rdoc:
            raise error.RecordNotFoundError(self.rid)
        # Get problem doc.
        pdoc = problem_coll.find_one({'_id': rdoc['pid']})
        if not pdoc:
            raise error.ProblemNotFoundError(rdoc['pid'])
        if rdoc['data_id']:
            data_id = rdoc['data_id']
        else:
            data_id = pdoc['data']
        # Get data.
        ddoc = data_coll.find_one({'_id': data_id})
        if not ddoc:
            raise error.TestDataNotFoundError(data_id)
        return rdoc, pdoc, ddoc

    def prepare_file(self, work_dir):
        with open(work_dir.join(self.config['src_name']), 'w') as file:
            file.write(self.code.encode('utf8'))
        if self.judge_mode == record.MODE_SPECIAL_JUDGE:
            with open(work_dir.join('judger'), 'wb') as file:
                file.write(base64.b64decode(self.judger_bin))
            os.chmod(work_dir.join('judger'), 0o755)
        shutil.copy(os.path.join(os.path.dirname(os.path.dirname(yamajudge.__file__)),
                                 'java_policy'), str(work_dir))

    def compile(self, work_dir):
        _logger.info('Compiling...')
        command = self.config['compile_command'].split(' ')
        compile_out = work_dir.join('compile.out')
        result = _judger.run(max_cpu_time=10000,
                             max_real_time=10000,
                             max_memory=_judger.UNLIMITED,
                             max_output_size=16 * 1024 * 1024,   # 16 MiB
                             max_process_number=_judger.UNLIMITED,
                             exe_path=command[0],
                             input_path=work_dir.join(self.config['src_name']),
                             output_path=compile_out,
                             error_path=compile_out,
                             args=command[1:],
                             env=['PATH=' + os.getenv('PATH')],
                             log_path=work_dir.join('compile.log'),
                             seccomp_rule_name=None,
                             uid=pwd.getpwnam('judger').pw_uid,
                             gid=grp.getgrnam('judger').gr_gid)

        compiler_text = ''
        if os.path.exists(compile_out):
            with open(compile_out) as file:
                compiler_text = file.read(2 * 1024).strip()  # 2 KiB
        return result['result'], compiler_text

    def execute(self, work_dir, input_str):
        in_file = work_dir.join('in_file')
        out_file = work_dir.join('out_file')
        err_file = work_dir.join('err_file')
        log_file = work_dir.join('runner.out')
        command = self.config['run_command'].format(memory_kb=self.memory_kb).split(' ')
        with open(in_file, 'w') as file:
            file.write(input_str)
        result = _judger.run(max_cpu_time=int(self.time_ms * self.config['time_rate']),
                             max_real_time=int(self.time_ms * 5 * self.config['time_rate']),
                             max_memory=self.memory_kb * 1024 if self.lang != 'java' else _judger.UNLIMITED,
                             max_output_size=1024 * 1024,   # 1 MiB
                             max_process_number=_judger.UNLIMITED,
                             exe_path=command[0],
                             input_path=in_file,
                             output_path=out_file,
                             error_path=err_file,
                             args=command[1:],
                             env=['PATH=' + os.getenv('PATH')],
                             log_path=log_file,
                             seccomp_rule_name=self.config['seccomp_rule'],
                             uid=pwd.getpwnam('nobody').pw_uid,
                             gid=grp.getgrnam('nogroup').gr_gid)

        out_ans = ''
        if result['result'] == _judger.RESULT_SUCCESS:
            try:
                with open(out_file) as file:
                    out_ans = file.read()
            except ValueError:
                out_ans = ''

        # check memory out in stderr
        if result['result'] == record.STATUS_RUNTIME_ERROR:
            with open(err_file) as file:
                err_out = file.read()
            if 'java.lang.OutOfMemoryError' in err_out:
                result['result'] = record.STATUS_MEMORY_LIMIT_EXCEEDED
                result['memory'] = self.memory_kb * 1024

        result['memory'] //= 1024
        return result, out_ans

    def judge(self, work_dir, user_out, correct_out):
        # TODO: add special judge.
        if self.judge_mode == record.MODE_COMPARE_IGNORE_SPACE:
            return judge.judge(user_out, correct_out, ignore_space=True)
        elif self.judge_mode == record.MODE_COMPARE:
            return judge.judge(user_out, correct_out, ignore_space=False)
        elif self.judge_mode == record.MODE_SPECIAL_JUDGE:
            return self.special_judge(work_dir, user_out, correct_out)

    def special_judge(self, work_dir, user_out, correct_out):
        in_file = work_dir.join('in_file')
        user_file = work_dir.join('out_file')
        out_file = work_dir.join('correct_file')
        judger_err_file = work_dir.join('judger_err_file')
        with open(work_dir.join('correct_file'), 'w') as file:
            file.write(correct_out)
        log_file = work_dir.join('judger.out')
        result = _judger.run(max_cpu_time=int(self.time_ms * self.config['time_rate']),
                             max_real_time=int(self.time_ms * 5 * self.config['time_rate']),
                             max_memory=self.memory_kb * 1024 if self.lang != 'java' else _judger.UNLIMITED,
                             max_output_size=1024 * 1024,   # 1 MiB
                             max_process_number=_judger.UNLIMITED,
                             exe_path=work_dir.join('judger'),
                             input_path='/dev/null',
                             output_path=log_file,
                             error_path=judger_err_file,
                             args=[in_file, out_file, user_file],
                             env=['PATH=' + os.getenv('PATH')],
                             log_path='/dev/null',
                             seccomp_rule_name=None,
                             uid=pwd.getpwnam('judger').pw_uid,
                             gid=grp.getgrnam('judger').gr_gid)
        with open(log_file) as file:
            judger_out = file.read()
        judge_res = record.STATUS_ACCEPTED if result['exit_code'] == 0 else record.STATUS_WRONG_ANSWER
        return judge_res, 'Judger Output: {0}'.format(judger_out)

    def next_judge(self, **kwargs):
        request.next_judge(self.rid, **kwargs)

    def end_judge(self, status: int, time_ms: int=0, memory_kb: int=0):
        request.end_judge(self.rid, status, time_ms, memory_kb)

    def run(self):
        with workspace.WorkSpace(self.rid) as work_dir:
            try:
                _logger.info('Judge workspace created.')
                # Prepare some files
                os.chdir(str(work_dir))
                self.prepare_file(work_dir)
                self.next_judge(status=record.STATUS_COMPILING)
                # Compile your program
                compile_result, compiler_text = self.compile(work_dir)
                self.next_judge(compiler_text=compiler_text)
                if compile_result != _judger.RESULT_SUCCESS:  # Compile Error
                    _logger.info('Compile Error.')
                    self.end_judge(record.STATUS_COMPILE_ERROR)
                    return
                # Execute your program
                total_time_ms = 0
                max_memory = 0
                final_result = record.STATUS_ACCEPTED
                self.next_judge(status=record.STATUS_JUDGING, progress=0.0)

                for index, case in enumerate(self.data, start=1):
                    _logger.info('Running case {0}/{1}...'.format(index, len(self.data)))
                    result, user_out = self.execute(work_dir, case[0])
                    judge_text = ''
                    if result['result'] == _judger.RESULT_SUCCESS:
                        # Have to judge
                        result['result'], judge_text = self.judge(work_dir, user_out, case[1])
                    if result['cpu_time'] < 10:
                        result['cpu_time'] = 0

                    # Update record information
                    total_time_ms += result['cpu_time']
                    max_memory = max(max_memory, result['memory'])
                    final_result = max(final_result, result['result'])

                    self.next_judge(progress=index / len(self.data),
                                    case=True,
                                    case_status=result['result'],
                                    case_time_ms=result['cpu_time'],
                                    case_memory_kb=result['memory'],
                                    case_judge_text=judge_text)
                    if result['result'] == record.STATUS_SYSTEM_ERROR or \
                            result['result'] == record.STATUS_TIME_LIMIT_EXCEEDED:
                        # TLE or SE will stop judge immediately
                        self.end_judge(status=result['result'],
                                       time_ms=total_time_ms,
                                       memory_kb=max_memory)
                        return

                _logger.info('Judge ended.')
                self.end_judge(status=final_result, time_ms=total_time_ms, memory_kb=max_memory)
            except Exception as e:
                _logger.error('An error occurred: {0}'.format(repr(e)))
                work_dir.dump()
                raise e
<|endoftext|>


<commit_before>import csv
# The django-request analytics package, NOT the python URL library requests!
from request.models import Request
import logging

from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import resolve
from django.contrib import messages
from django.db.models import Avg, Count
from django.http import HttpResponse
from django.views.generic import TemplateView, View
from django.utils.translation import ugettext as _

from TWLight.applications.models import Application
from TWLight.resources.models import Partner
from TWLight.users.models import Editor

from .helpers import (get_application_status_data,
                      get_data_count_by_month,
                      get_users_by_partner_by_month,
                      get_js_timestamp,
                      get_wiki_distribution_pie_data,
                      get_wiki_distribution_bar_data,
                      get_time_open_histogram,
                      get_median_decision_time,
                      PYTHON)

logger = logging.getLogger(__name__)

class DashboardView(TemplateView):
    """
    Let people see metrics about the application process.
    """
    template_name = 'dashboard.html'

    def _get_partner_from_path(self, path):
        if not path.startswith('/'):
            path = '/' + path
        if not path.endswith('/'):
            path = path + '/'

        try:
            pk = resolve(path).kwargs['pk']
        except KeyError:
            return None

        try:
            return Partner.even_not_available.get(pk=pk)
        except Partner.DoesNotExist:
            return None

    def get_context_data(self, **kwargs):
        context = super(DashboardView, self).get_context_data(**kwargs)

        # Pageview data
        # ----------------------------------------------------------------------
        top_pages = Request.objects.exclude(path='/favicon.ico'
                    ).values('path'
                    ).annotate(the_count=Count('path')
                    ).order_by('-the_count')[:10]
        context['top_pages'] = top_pages

        # filter by response code to prevent the report itself from hosing.
        # 2xx reposnse codes are all valid, so this was a quick and dirty way
        # to fix the issue.  This view probably needs to be rethought.
        partner_pages = Request.objects.filter(response__startswith='2'
                    ).filter(path__startswith='/partners/'
                    ).values('path'
                    ).annotate(the_count=Count('path')
                    ).order_by('-the_count')

        partner_pages = [dict(
                            {'partner': self._get_partner_from_path(x['path'])},
                            **x
                         ) for x in partner_pages]

        context['partner_pages'] = partner_pages

        # Overall application-related data
        # ----------------------------------------------------------------------

        context['total_apps'] = Application.objects.count()
        context['total_editors'] = Editor.objects.count()
        context['total_partners'] = Partner.objects.count()

        # Partnership data
        # ----------------------------------------------------------------------

        context['partner_time_data'] = get_data_count_by_month(
                Partner.objects.all()
            )

        # Editor data
        # ----------------------------------------------------------------------

        # Although normally we'd want JSON for graphs, the pie chart can consume
        # a normal dict, and the for loop to create the table requires a dict,
        # not JSON.
        context['home_wiki_pie_data'] = get_wiki_distribution_pie_data(
            data_format=PYTHON)

        context['home_wiki_bar_data'] = get_wiki_distribution_bar_data()

        # Application data
        # ----------------------------------------------------------------------

        # The application that has been waiting the longest for a final status
        # determination. -------------------------------------------------------
        try:
            app = Application.objects.filter(
                status__in=[Application.PENDING, Application.QUESTION]
            ).earliest('date_created')
        except Application.DoesNotExist:
            app = None

        context['longest_open'] = app

        # Average number of days until a final decision gets made on an
        # application. ---------------------------------------------------------

        closed_apps = Application.objects.filter(
                status__in=[Application.APPROVED, Application.NOT_APPROVED]
            )

        average_duration = closed_apps.aggregate(
                Avg('days_open')
            )['days_open__avg']

        if average_duration:
            avg_days_open = float(average_duration)
        else:
            avg_days_open = None

        context['avg_days_open'] = avg_days_open

        # Histogram of time open -----------------------------------------------

        context['app_time_histogram_data'] = get_time_open_histogram(closed_apps)

        # Median decision time per month ---------------------------------------
        # Exlude imported applications
        context['app_medians_data'] = get_median_decision_time(
                Application.objects.exclude(imported=True)
            )

        # Application status pie chart -----------------------------------------

        context['app_distribution_data'] = get_application_status_data(
                Application.objects.all()
            )

        return context

# CSV-generating views ---------------------------------------------------------

# These views power "download as CSV" buttons. They provide the same data sets
# that are reflected in the DashboardView, but as HttpResponses with csv data.

class _CSVDownloadView(View):
    """
    Base view powering CSV downloads. Not intended to be used directly.
    URLs should point at subclasses of this view. Subclasses should implement a
    _write_data() method.
    """
    def get(self, request, *args, **kwargs):
        # Create the HttpResponse object with the appropriate CSV header.
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="data.csv"'

        self._write_data(response)

        return response

    def _write_data(self, response):
        raise NotImplementedError

class CSVNumPartners(_CSVDownloadView):
    def _write_data(self, response):
        if 'pk' in self.kwargs:
            pk = self.kwargs['pk']

            try:
                queryset = Partner.objects.get(pk=pk)
            except Partner.DoesNotExist:
                logger.exception('Tried to access data for partner #{pk}, who '
                                 'does not exist'.format(pk=pk))
                raise

        else:
            queryset =Partner.objects.all()

        data = get_data_count_by_month(queryset, data_format=PYTHON)
        writer = csv.writer(response)
        # Translators: This is the heading of a data file, for a column containing date data.
        writer.writerow([_('Date'),
                         # Translators: This is the heading of a data file. 'Number of partners' refers to the total number of publishers/databases open to applications on the website.
                         _('Number of partners')])

        for row in data:
            writer.writerow(row)

class CSVHomeWikiPie(_CSVDownloadView):
    def _write_data(self, response):
        data = get_wiki_distribution_pie_data(data_format=PYTHON)

        writer = csv.DictWriter(response, fieldnames=['label', 'data'])
        # Translators: This is the heading of a data file. Home Wiki refers to the Wikimedia site that a user is most active on.
        writer.writerow({'label': _('Home wiki'),
                         'data': _('Number of users')})

        for row in data:
            writer.writerow(row)

class CSVHomeWikiOverTime(_CSVDownloadView):
    def _write_data(self, response):
        data = get_wiki_distribution_bar_data(data_format=PYTHON)

        writer = csv.writer(response)

        writer.writerow(
            # Translators: This is the heading of a data file. 'Wiki' refers to the Wikimedia site that a user is most active on.
            [_('Wiki'),
             _('Date'),
             # Translators: This is the heading of a data file. This labels the number of users who registered from a particular Wikimedia site.
             _('Number of users')])

        for elem in data:
            for point in elem['data']:
                writer.writerow([elem['label'], point[0], point[1]])

class CSVAppTimeHistogram(_CSVDownloadView):
    def _write_data(self, response):
        closed_apps = Application.objects.filter(
            status__in=[Application.APPROVED, Application.NOT_APPROVED]
        )

        data = get_time_open_histogram(closed_apps, data_format=PYTHON)

        writer = csv.writer(response)

        writer.writerow(
            # Translators: This is the heading of a data file which lists the number of days it took to decide on applications that have already been accepted/rejected.
            [_('Days until decision'),
             # Translators: This is the heading of a data file which lists the number of days it took to decide on applications that have already been accepted/rejected. This heading denotes the number of applicants for a particular number of days.
             _('Number of applications')])

        for row in data:
            writer.writerow(row)

class CSVAppMedians(_CSVDownloadView):
    def _write_data(self, response):
        # Exlude imported applications
        data = get_median_decision_time(
            Application.objects.exclude(imported=True),
            data_format=PYTHON
        )

        writer = csv.writer(response)

        writer.writerow(
            # Translators: This is the heading of a data file, denoting the column which contains the dates (months) corresponding to data collection
            [_('Month'),
             # Translators: This is the heading of a data file which lists the median (not mean) number of days until a decision (approve or reject) was made on applications.
             _('Median days until decision')])

        for row in data:
            writer.writerow(row)

class CSVAppDistribution(_CSVDownloadView):
    def _write_data(self, response):
        data = get_application_status_data(
            Application.objects.all(),
            data_format=PYTHON
        )

        writer = csv.DictWriter(response, fieldnames=['label', 'data'])

        writer.writerow({'label': _('Status'),
                         'data': _('Number of applications')})

        for row in data:
            writer.writerow(row)

class CSVAppCountByPartner(_CSVDownloadView):
    def _write_data(self, response):
        pk = self.kwargs['pk']
        try:
            partner = Partner.objects.get(pk=pk)
        except Partner.DoesNotExist:
            logger.exception('Tried to access data for partner #{pk}, who '
                             'does not exist'.format(pk=pk))
            raise

        queryset = Application.objects.filter(partner=partner)

        if 'approved_or_sent' in self.kwargs:
            queryset = queryset.filter(status__in=(Application.APPROVED, Application.SENT))

        data = get_data_count_by_month(queryset, data_format=PYTHON)

        writer = csv.writer(response)

        writer.writerow([_('Date'),
            # Translators: This is the heading of a data file which lists the number of applications to a partner. Don't translate {partner}.
            _('Number of applications to {partner}').format(partner=partner)])

        for row in data:
            writer.writerow(row)

class CSVUserCountByPartner(_CSVDownloadView):
    def _write_data(self, response):
        pk = self.kwargs['pk']

        try:
            partner = Partner.objects.get(pk=pk)
        except Partner.DoesNotExist:
            logger.exception('Tried to access data for partner #{pk}, who '
                             'does not exist'.format(pk=pk))
            raise

        data = get_users_by_partner_by_month(partner, data_format=PYTHON)

        writer = csv.writer(response)

        writer.writerow([_('Date'),
            # Translators: This is the heading of a data file which lists the number of unique (not counting repeat applications) users who have applied to a partner. Don't translate {partner}.
            _('Number of unique users who have applied to {partner}').format(partner=partner)])

        for row in data:
            writer.writerow(row)

class CSVPageViews(_CSVDownloadView):

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_staff:
            return super(CSVPageViews, self).dispatch(request, *args, **kwargs)
        else:
            messages.add_message (request, messages.WARNING,
                # Translators: This is a warning which is shown when a user who is not a staff member attempts to download the pageview data file.
                _('You must be staff to do that.'))
            raise PermissionDenied

    def _write_data(self, response):
        path_list = Request.objects.values('path').annotate(
            the_count=Count('path')).order_by()

        writer = csv.writer(response)
        # Translators: This is the heading for a downloadable data file showing the number of visitors to each page on the website. Page URL is the column which lists the URL of each page
        writer.writerow([_('Page URL'),
            _('Number of (non-unique) visitors')])

        for elem in path_list:
            writer.writerow([elem['path'], elem['the_count']])

class CSVPageViewsByPath(_CSVDownloadView):

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_staff:
            return super(CSVPageViewsByPath, self).dispatch(
                request, *args, **kwargs)
        else:
            messages.add_message (request, messages.WARNING,
                _('You must be staff to do that.'))
            raise PermissionDenied

    def _write_data(self, response):
        path = self.kwargs['path']

        # The captured pattern likely won't start or end with /, but the
        # database stores paths starting and ending with /.
        if not path.startswith('/'):
            path = '/' + path
        if not path.endswith('/'):
            path = path + '/'

        path_count = Request.objects.filter(path=path).count()
        writer = csv.writer(response)

        writer.writerow([_('Page URL'),
            # Translators: This is the heading for a downloadable data file showing the number of visitors to each page on the website.
            _('Number of (non-unique) visitors')])

        writer.writerow([path, path_count])
<commit_msg>Fixed download as csv not being partner specific on partner pages (T158428)<commit_after>import csv
# The django-request analytics package, NOT the python URL library requests!
from request.models import Request
import logging

from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import resolve
from django.contrib import messages
from django.db.models import Avg, Count
from django.http import HttpResponse
from django.views.generic import TemplateView, View
from django.utils.translation import ugettext as _

from TWLight.applications.models import Application
from TWLight.resources.models import Partner
from TWLight.users.models import Editor

from .helpers import (get_application_status_data,
                      get_data_count_by_month,
                      get_users_by_partner_by_month,
                      get_js_timestamp,
                      get_wiki_distribution_pie_data,
                      get_wiki_distribution_bar_data,
                      get_time_open_histogram,
                      get_median_decision_time,
                      PYTHON)

logger = logging.getLogger(__name__)

class DashboardView(TemplateView):
    """
    Let people see metrics about the application process.
    """
    template_name = 'dashboard.html'

    def _get_partner_from_path(self, path):
        if not path.startswith('/'):
            path = '/' + path
        if not path.endswith('/'):
            path = path + '/'

        try:
            pk = resolve(path).kwargs['pk']
        except KeyError:
            return None

        try:
            return Partner.even_not_available.get(pk=pk)
        except Partner.DoesNotExist:
            return None

    def get_context_data(self, **kwargs):
        context = super(DashboardView, self).get_context_data(**kwargs)

        # Pageview data
        # ----------------------------------------------------------------------
        top_pages = Request.objects.exclude(path='/favicon.ico'
                    ).values('path'
                    ).annotate(the_count=Count('path')
                    ).order_by('-the_count')[:10]
        context['top_pages'] = top_pages

        # filter by response code to prevent the report itself from hosing.
        # 2xx reposnse codes are all valid, so this was a quick and dirty way
        # to fix the issue.  This view probably needs to be rethought.
        partner_pages = Request.objects.filter(response__startswith='2'
                    ).filter(path__startswith='/partners/'
                    ).values('path'
                    ).annotate(the_count=Count('path')
                    ).order_by('-the_count')

        partner_pages = [dict(
                            {'partner': self._get_partner_from_path(x['path'])},
                            **x
                         ) for x in partner_pages]

        context['partner_pages'] = partner_pages

        # Overall application-related data
        # ----------------------------------------------------------------------

        context['total_apps'] = Application.objects.count()
        context['total_editors'] = Editor.objects.count()
        context['total_partners'] = Partner.objects.count()

        # Partnership data
        # ----------------------------------------------------------------------

        context['partner_time_data'] = get_data_count_by_month(
                Partner.objects.all()
            )

        # Editor data
        # ----------------------------------------------------------------------

        # Although normally we'd want JSON for graphs, the pie chart can consume
        # a normal dict, and the for loop to create the table requires a dict,
        # not JSON.
        context['home_wiki_pie_data'] = get_wiki_distribution_pie_data(
            data_format=PYTHON)

        context['home_wiki_bar_data'] = get_wiki_distribution_bar_data()

        # Application data
        # ----------------------------------------------------------------------

        # The application that has been waiting the longest for a final status
        # determination. -------------------------------------------------------
        try:
            app = Application.objects.filter(
                status__in=[Application.PENDING, Application.QUESTION]
            ).earliest('date_created')
        except Application.DoesNotExist:
            app = None

        context['longest_open'] = app

        # Average number of days until a final decision gets made on an
        # application. ---------------------------------------------------------

        closed_apps = Application.objects.filter(
                status__in=[Application.APPROVED, Application.NOT_APPROVED]
            )

        average_duration = closed_apps.aggregate(
                Avg('days_open')
            )['days_open__avg']

        if average_duration:
            avg_days_open = float(average_duration)
        else:
            avg_days_open = None

        context['avg_days_open'] = avg_days_open

        # Histogram of time open -----------------------------------------------

        context['app_time_histogram_data'] = get_time_open_histogram(closed_apps)

        # Median decision time per month ---------------------------------------
        # Exlude imported applications
        context['app_medians_data'] = get_median_decision_time(
                Application.objects.exclude(imported=True)
            )

        # Application status pie chart -----------------------------------------

        context['app_distribution_data'] = get_application_status_data(
                Application.objects.all()
            )

        return context

# CSV-generating views ---------------------------------------------------------

# These views power "download as CSV" buttons. They provide the same data sets
# that are reflected in the DashboardView, but as HttpResponses with csv data.

class _CSVDownloadView(View):
    """
    Base view powering CSV downloads. Not intended to be used directly.
    URLs should point at subclasses of this view. Subclasses should implement a
    _write_data() method.
    """
    def get(self, request, *args, **kwargs):
        # Create the HttpResponse object with the appropriate CSV header.
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="data.csv"'

        self._write_data(response)

        return response

    def _write_data(self, response):
        raise NotImplementedError

class CSVNumPartners(_CSVDownloadView):
    def _write_data(self, response):
        if 'pk' in self.kwargs:
            pk = self.kwargs['pk']

            try:
                queryset = Partner.objects.get(pk=pk)
            except Partner.DoesNotExist:
                logger.exception('Tried to access data for partner #{pk}, who '
                                 'does not exist'.format(pk=pk))
                raise

        else:
            queryset =Partner.objects.all()

        data = get_data_count_by_month(queryset, data_format=PYTHON)
        writer = csv.writer(response)
        # Translators: This is the heading of a data file, for a column containing date data.
        writer.writerow([_('Date'),
                         # Translators: This is the heading of a data file. 'Number of partners' refers to the total number of publishers/databases open to applications on the website.
                         _('Number of partners')])

        for row in data:
            writer.writerow(row)

class CSVHomeWikiPie(_CSVDownloadView):
    def _write_data(self, response):
        data = get_wiki_distribution_pie_data(data_format=PYTHON)

        writer = csv.DictWriter(response, fieldnames=['label', 'data'])
        # Translators: This is the heading of a data file. Home Wiki refers to the Wikimedia site that a user is most active on.
        writer.writerow({'label': _('Home wiki'),
                         'data': _('Number of users')})

        for row in data:
            writer.writerow(row)

class CSVHomeWikiOverTime(_CSVDownloadView):
    def _write_data(self, response):
        data = get_wiki_distribution_bar_data(data_format=PYTHON)

        writer = csv.writer(response)

        writer.writerow(
            # Translators: This is the heading of a data file. 'Wiki' refers to the Wikimedia site that a user is most active on.
            [_('Wiki'),
             _('Date'),
             # Translators: This is the heading of a data file. This labels the number of users who registered from a particular Wikimedia site.
             _('Number of users')])

        for elem in data:
            for point in elem['data']:
                writer.writerow([elem['label'], point[0], point[1]])

class CSVAppTimeHistogram(_CSVDownloadView):
    def _write_data(self, response):
        closed_apps = Application.objects.filter(
            status__in=[Application.APPROVED, Application.NOT_APPROVED]
        )

        data = get_time_open_histogram(closed_apps, data_format=PYTHON)

        writer = csv.writer(response)

        writer.writerow(
            # Translators: This is the heading of a data file which lists the number of days it took to decide on applications that have already been accepted/rejected.
            [_('Days until decision'),
             # Translators: This is the heading of a data file which lists the number of days it took to decide on applications that have already been accepted/rejected. This heading denotes the number of applicants for a particular number of days.
             _('Number of applications')])

        for row in data:
            writer.writerow(row)

class CSVAppMedians(_CSVDownloadView):
    def _write_data(self, response):
        # Exlude imported applications
        data = get_median_decision_time(
            Application.objects.exclude(imported=True),
            data_format=PYTHON
        )

        writer = csv.writer(response)

        writer.writerow(
            # Translators: This is the heading of a data file, denoting the column which contains the dates (months) corresponding to data collection
            [_('Month'),
             # Translators: This is the heading of a data file which lists the median (not mean) number of days until a decision (approve or reject) was made on applications.
             _('Median days until decision')])

        for row in data:
            writer.writerow(row)

class CSVAppDistribution(_CSVDownloadView):
    def _write_data(self, response):
        if 'pk' in self.kwargs:
            pk = self.kwargs['pk']
            try:
                partner = Partner.objects.get(pk=pk)
            except Partner.DoesNotExist:
                logger.exception('Tried to access data for partner #{pk}, who '
                                 'does not exist'.format(pk=pk))
                raise

            csv_queryset = Application.objects.filter(partner=partner)

        else:
            csv_queryset = Application.objects.all()

        data = get_application_status_data(
            csv_queryset,
            data_format=PYTHON
        )

        writer = csv.DictWriter(response, fieldnames=['label', 'data'])

        writer.writerow({'label': _('Status'),
                         'data': _('Number of applications')})

        for row in data:
            writer.writerow(row)

class CSVAppCountByPartner(_CSVDownloadView):
    def _write_data(self, response):
        pk = self.kwargs['pk']
        try:
            partner = Partner.objects.get(pk=pk)
        except Partner.DoesNotExist:
            logger.exception('Tried to access data for partner #{pk}, who '
                             'does not exist'.format(pk=pk))
            raise

        queryset = Application.objects.filter(partner=partner)

        if 'approved_or_sent' in self.kwargs:
            queryset = queryset.filter(status__in=(Application.APPROVED, Application.SENT))

        data = get_data_count_by_month(queryset, data_format=PYTHON)

        writer = csv.writer(response)

        writer.writerow([_('Date'),
            # Translators: This is the heading of a data file which lists the number of applications to a partner. Don't translate {partner}.
            _('Number of applications to {partner}').format(partner=partner)])

        for row in data:
            writer.writerow(row)

class CSVUserCountByPartner(_CSVDownloadView):
    def _write_data(self, response):
        pk = self.kwargs['pk']

        try:
            partner = Partner.objects.get(pk=pk)
        except Partner.DoesNotExist:
            logger.exception('Tried to access data for partner #{pk}, who '
                             'does not exist'.format(pk=pk))
            raise

        data = get_users_by_partner_by_month(partner, data_format=PYTHON)

        writer = csv.writer(response)

        writer.writerow([_('Date'),
            # Translators: This is the heading of a data file which lists the number of unique (not counting repeat applications) users who have applied to a partner. Don't translate {partner}.
            _('Number of unique users who have applied to {partner}').format(partner=partner)])

        for row in data:
            writer.writerow(row)

class CSVPageViews(_CSVDownloadView):

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_staff:
            return super(CSVPageViews, self).dispatch(request, *args, **kwargs)
        else:
            messages.add_message (request, messages.WARNING,
                # Translators: This is a warning which is shown when a user who is not a staff member attempts to download the pageview data file.
                _('You must be staff to do that.'))
            raise PermissionDenied

    def _write_data(self, response):
        path_list = Request.objects.values('path').annotate(
            the_count=Count('path')).order_by()

        writer = csv.writer(response)
        # Translators: This is the heading for a downloadable data file showing the number of visitors to each page on the website. Page URL is the column which lists the URL of each page
        writer.writerow([_('Page URL'),
            _('Number of (non-unique) visitors')])

        for elem in path_list:
            writer.writerow([elem['path'], elem['the_count']])

class CSVPageViewsByPath(_CSVDownloadView):

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_staff:
            return super(CSVPageViewsByPath, self).dispatch(
                request, *args, **kwargs)
        else:
            messages.add_message (request, messages.WARNING,
                _('You must be staff to do that.'))
            raise PermissionDenied

    def _write_data(self, response):
        path = self.kwargs['path']

        # The captured pattern likely won't start or end with /, but the
        # database stores paths starting and ending with /.
        if not path.startswith('/'):
            path = '/' + path
        if not path.endswith('/'):
            path = path + '/'

        path_count = Request.objects.filter(path=path).count()
        writer = csv.writer(response)

        writer.writerow([_('Page URL'),
            # Translators: This is the heading for a downloadable data file showing the number of visitors to each page on the website.
            _('Number of (non-unique) visitors')])

        writer.writerow([path, path_count])
<|endoftext|>


<commit_before>VERSION = '1.15.8'
<commit_msg>add influxuploader plugin<commit_after>VERSION = '1.15.9'
<|endoftext|>


<commit_before>#!/usr/bin/env python
#
#  viewer_low_level_util.py
#
#  Copyright (C) 2014 Diamond Light Source
#
#  Author: Luis Fuentes-Montero (Luiso)
#
#  This code is distributed under the BSD license, a copy of which is
#  included in the root directory of this package.

from dials.array_family import flex
from from_flex_to_wxbitmap import wxbitmap_convert

import wx
import numpy as np
import wx.lib.scrolledpanel as scroll_pan
import wx.grid as gridlib
import math

class flex_3d_frame(wx.Frame):
  def __init__(self, parent, title):
    super(flex_3d_frame, self).__init__(parent, title = title,
          size = wx.DefaultSize)

  def frame_ini_img(self, in_upper_panel, text_data = None):
    self.img_panel = in_upper_panel

    if( text_data != None):
      self.myGrid = text_data

    self.my_sizer = wx.BoxSizer(wx.VERTICAL)
    self.my_sizer.Add(self.img_panel, proportion = 1,
                      flag =  wx.EXPAND | wx.ALL, border = 3)

    if( text_data != None):
      self.my_sizer.Add(self.myGrid, proportion = 1,
                        flag =  wx.EXPAND | wx.ALL, border = 3)

    self.my_sizer.SetMinSize((50, 20))

    self.SetSizer(self.my_sizer)

class TupTable(gridlib.PyGridTableBase):
  def __init__(self, data, rowLabels=None, colLabels=None):
    gridlib.PyGridTableBase.__init__(self)
    self.data = data
    self.rowLabels = rowLabels
    self.colLabels = colLabels

  def GetNumberRows(self):
    return len(self.data)

  def GetNumberCols(self):
    return len(self.data[0])

  def GetColLabelValue(self, col):
    if self.colLabels:
      return self.colLabels[col]

  def GetRowLabelValue(self, row):
    if self.rowLabels:
      return self.rowLabels[row]

  def IsEmptyCell(self, row, col):
    return False

  def GetValue(self, row, col):
    return self.data[row][col]

  def SetValue(self, row, col, value):
    pass

class MyGrid(gridlib.Grid):

  def __init__(self, parent_frame):
    """Constructor"""
    super(MyGrid, self).__init__(parent_frame)

  def ini_n_intro(self, table_in):

    import time
    time1 = time.time()

    #new_code = '''
    lst_keys = []
    data = []

    for key in table_in.keys():
      if(key != "shoebox"):
        lst_keys.append(key)
        col = table_in[key]
        col_strs = map(str, col)
        data.append(col_strs)

    data = tuple(zip(*data))
    colLabels = tuple(lst_keys)
    rowLabels = tuple(range(len(data)))

    tableBase = TupTable(data, rowLabels, colLabels)
    self.SetTable(tableBase)
    #'''

    old_code = '''
    self.CreateGrid(len(table_in), len(table_in[0]))
    for col_pos, key in enumerate(table_in.keys()):
      print col_pos, key
      self.SetColLabelValue(col_pos, str(key))
    for nm, data in enumerate(table_in):
      #for col_pos, key in enumerate(table_in[nm].keys()):
      for col_pos, key in enumerate(table_in.keys()):
        self.SetCellValue(nm, col_pos, str(table_in[nm][key]))
    #'''

    self.AutoSizeColumns(True)
    self.EnableEditing(False)
    self.EnableDragGridSize(False)

    self.Bind(gridlib.EVT_GRID_CELL_LEFT_CLICK, self.OnCellLeftClick)

    time2 = time.time()
    timedif = time2 - time1
    print "timedif =", timedif

  def OnCellLeftClick(self, evt):
    print "OnCellLeftClick: (%d,%d) %s\n" % (evt.GetRow(),
                                             evt.GetCol(),
                                             evt.GetPosition())
    evt.Skip()

class flex_arr_img_panel(wx.Panel):
  def __init__(self, parent_frame):
    super(flex_arr_img_panel, self).__init__(parent_frame)
    self.show_nums = True
    self.show_mask = True

  def ini_n_intro(self, flex_arr_one, flex_arr_two = None):
    self.first_lst_in, self.segn_lst_in = flex_arr_one, flex_arr_two
    self.scale = 1.0
    self.bmp_lst = self._mi_list_of_wxbitmaps()
    self.panel_01 = buttons_panel(self)
    self.panel_02 = multi_img_scrollable(self, self.bmp_lst)
    sizer = wx.BoxSizer(wx.HORIZONTAL)
    sizer.Add(self.panel_01, 0, wx.ALIGN_CENTRE)
    sizer.Add(self.panel_02, 1, wx.EXPAND)
    self.SetSizer(sizer)
    self.Show(True)

  def _mi_list_of_wxbitmaps(self, re_scaling = False):
    if(re_scaling == False):
      if(self.show_mask == True):
        self.lst_bmp_obj = wxbitmap_convert(self.first_lst_in, self.segn_lst_in)
      else:
        self.lst_bmp_obj = wxbitmap_convert(self.first_lst_in, None)
      return self.lst_bmp_obj.get_wxbitmap_lst(show_nums = self.show_nums,
                                      scale = self.scale)

    else:
      return self.lst_bmp_obj.scaling(scale = self.scale)

  def to_hide_nums(self):
    self.show_nums = False
    self.bmp_lst = self._mi_list_of_wxbitmaps()
    self.panel_02.img_refresh(self.bmp_lst)

  def to_show_nums(self):
    self.show_nums = True
    self.bmp_lst = self._mi_list_of_wxbitmaps()
    self.panel_02.img_refresh(self.bmp_lst)

  def to_show_mask(self):
    self.show_mask = True
    self.bmp_lst = self._mi_list_of_wxbitmaps()
    self.panel_02.img_refresh(self.bmp_lst)

  def to_hide_mask(self):
    self.show_mask = False
    self.bmp_lst = self._mi_list_of_wxbitmaps()
    self.panel_02.img_refresh(self.bmp_lst)

  def to_re_zoom(self, rot_sn):
    if( rot_sn > 0 ):
      for ntimes in range(int(math.fabs(rot_sn))):
        self.scale = self.scale * 1.05
        if( self.scale > 3.0 ):
          #Maximum possible zoom reached
          self.scale = 3.0

    elif( rot_sn < 0):
      for ntimes in range(int(math.fabs(rot_sn))):
        self.scale = self.scale * 0.95
        if( self.scale < 0.2 ):
          #Minimum possible zoom reached
          self.scale = 0.2

    self.bmp_lst = self._mi_list_of_wxbitmaps(re_scaling = True)
    self.panel_02.img_refresh(self.bmp_lst)

class multi_img_scrollable(scroll_pan.ScrolledPanel):
  def __init__(self, outer_panel, bmp_lst_in):
    super(multi_img_scrollable, self).__init__(outer_panel)
    self.parent_panel  = outer_panel
    self.lst_2d_bmp = bmp_lst_in
    self.set_scroll_content()
    self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
    self.Bind(wx.EVT_IDLE, self.OnIdle)
    self.SetupScrolling()
    self.scroll_rot = 0
    self.SetBackgroundColour(wx.Colour(200, 200, 200))
    aprox_len_pix = len(self.lst_2d_bmp) * 10
    self.SetScrollbars(1, 1, aprox_len_pix * 10, aprox_len_pix * 10)

  def set_scroll_content(self):

    img_lst_vert_sizer = wx.BoxSizer(wx.VERTICAL)

    for lst_1d in self.lst_2d_bmp:
      img_lst_hor_sizer = wx.BoxSizer(wx.HORIZONTAL)

      for i, bmp_lst in enumerate(lst_1d):
        local_bitmap = wx.StaticBitmap(self, bitmap = bmp_lst)
        slice_string = "Slice[" + str(i) + ":" + str(i + 1) + ", :, :]"
        slice_sub_info_txt = wx.StaticText(self, -1, slice_string)
        sigle_slice_sizer = wx.BoxSizer(wx.VERTICAL)
        sigle_slice_sizer.Add(local_bitmap, proportion = 0,
                              flag = wx.ALIGN_CENTRE | wx.ALL, border = 2)
        sigle_slice_sizer.Add(slice_sub_info_txt, proportion = 0,
                              flag = wx.ALIGN_CENTRE | wx.ALL, border = 2)
        img_lst_hor_sizer.Add(sigle_slice_sizer, proportion = 0,
                              flag = wx.ALIGN_CENTER | wx.ALL, border = 2)

      img_lst_vert_sizer.Add(img_lst_hor_sizer, proportion = 0,
                             flag = wx.ALIGN_CENTER | wx.TOP, border = 6)

    self.SetSizer(img_lst_vert_sizer)

  def OnMouseWheel(self, event):

    #saving amount of scroll steps to do
    sn_mov = math.copysign(1, float(event.GetWheelRotation()))
    self.scroll_rot += sn_mov

    #saving relative position of scrolling area to keep after scrolling
    v_size_x, v_size_y = self.GetVirtualSize()

    self.x_to_keep, self.y_to_keep = self.GetViewStart()
    self.x_to_keep = float(self.x_to_keep) / float(v_size_x)
    self.y_to_keep = float(self.y_to_keep) / float(v_size_y)

    debugg_screen_log = '''
    print "self.GetVirtualSize() =", self.GetVirtualSize()
    print "self.GetViewStart() =", self.GetViewStart()
    print "self.GetScrollPixelsPerUnit() =", self.GetScrollPixelsPerUnit()
    print "self.x_to_keep =", self.x_to_keep
    print "self.y_to_keep =", self.y_to_keep
    '''

  def img_refresh(self, bmp_lst_new):
    self.lst_2d_bmp = bmp_lst_new
    for child in self.GetChildren():
      child.Destroy()

    self.set_scroll_content()
    self.Layout()
    self.parent_panel.Layout()
    self.Refresh()

  def OnIdle(self, event):
    if( self.scroll_rot != 0 ):
      self.parent_panel.to_re_zoom(self.scroll_rot)
      self.scroll_rot = 0
      v_size_x, v_size_y = self.GetVirtualSize()
      self.Scroll(self.x_to_keep * v_size_x, self.y_to_keep * v_size_y)

class buttons_panel(wx.Panel):
  def __init__(self, outer_panel):
    super(buttons_panel, self).__init__(outer_panel)
    self.parent_panel  = outer_panel

    Show_Its_CheckBox = wx.CheckBox(self, -1, "Show I nums")
    Show_Its_CheckBox.SetValue(True)
    Show_Its_CheckBox.Bind(wx.EVT_CHECKBOX, self.OnItsCheckbox)

    if( self.parent_panel.segn_lst_in != None ):
      Show_Msk_CheckBox = wx.CheckBox(self, -1, "Show Mask")
      Show_Msk_CheckBox.SetValue(True)
      Show_Msk_CheckBox.Bind(wx.EVT_CHECKBOX, self.OnMskCheckbox)

    self.my_sizer = wx.BoxSizer(wx.VERTICAL)
    self.my_sizer.Add(Show_Its_CheckBox, proportion = 0,
                      flag = wx.ALIGN_TOP, border = 5)

    if( self.parent_panel.segn_lst_in != None ):
      self.my_sizer.Add(Show_Msk_CheckBox, proportion = 0,
                        flag = wx.ALIGN_TOP, border = 5)

    self.my_sizer.SetMinSize((50, 20))
    self.SetSizer(self.my_sizer)

  def OnItsCheckbox(self, event):
    debugg_screen_log = '''
    print "OnItsCheckbox"
    print "event.IsChecked() =", event.IsChecked()
    '''
    if(event.IsChecked() == True):
      self.parent_panel.to_show_nums()
    else:
      self.parent_panel.to_hide_nums()

  def OnMskCheckbox(self, event):
    debugg_screen_log = '''
    print "OnMskCheckbox"
    print "event.IsChecked() =", event.IsChecked()
    '''
    if(event.IsChecked() == True):
      self.parent_panel.to_show_mask()
    else:
      self.parent_panel.to_hide_mask()

<commit_msg>commenting debugging code<commit_after>#!/usr/bin/env python
#
#  viewer_low_level_util.py
#
#  Copyright (C) 2014 Diamond Light Source
#
#  Author: Luis Fuentes-Montero (Luiso)
#
#  This code is distributed under the BSD license, a copy of which is
#  included in the root directory of this package.

from dials.array_family import flex
from from_flex_to_wxbitmap import wxbitmap_convert

import wx
import numpy as np
import wx.lib.scrolledpanel as scroll_pan
import wx.grid as gridlib
import math

class flex_3d_frame(wx.Frame):
  def __init__(self, parent, title):
    super(flex_3d_frame, self).__init__(parent, title = title,
          size = wx.DefaultSize)

  def frame_ini_img(self, in_upper_panel, text_data = None):
    self.img_panel = in_upper_panel

    if( text_data != None):
      self.myGrid = text_data

    self.my_sizer = wx.BoxSizer(wx.VERTICAL)
    self.my_sizer.Add(self.img_panel, proportion = 1,
                      flag =  wx.EXPAND | wx.ALL, border = 3)

    if( text_data != None):
      self.my_sizer.Add(self.myGrid, proportion = 1,
                        flag =  wx.EXPAND | wx.ALL, border = 3)

    self.my_sizer.SetMinSize((50, 20))

    self.SetSizer(self.my_sizer)

class TupTable(gridlib.PyGridTableBase):
  def __init__(self, data, rowLabels=None, colLabels=None):
    gridlib.PyGridTableBase.__init__(self)
    self.data = data
    self.rowLabels = rowLabels
    self.colLabels = colLabels

  def GetNumberRows(self):
    return len(self.data)

  def GetNumberCols(self):
    return len(self.data[0])

  def GetColLabelValue(self, col):
    if self.colLabels:
      return self.colLabels[col]

  def GetRowLabelValue(self, row):
    if self.rowLabels:
      return self.rowLabels[row]

  def IsEmptyCell(self, row, col):
    return False

  def GetValue(self, row, col):
    return self.data[row][col]

  def SetValue(self, row, col, value):
    pass

class MyGrid(gridlib.Grid):

  def __init__(self, parent_frame):
    """Constructor"""
    super(MyGrid, self).__init__(parent_frame)

  def ini_n_intro(self, table_in):

    timing_for_debugging = '''
    import time
    time1 = time.time()
    '''

    #new_code = '''
    lst_keys = []
    data = []

    for key in table_in.keys():
      if(key != "shoebox"):
        lst_keys.append(key)
        col = table_in[key]
        col_strs = map(str, col)
        data.append(col_strs)

    data = tuple(zip(*data))
    colLabels = tuple(lst_keys)
    rowLabels = tuple(range(len(data)))

    tableBase = TupTable(data, rowLabels, colLabels)
    self.SetTable(tableBase)
    #'''

    old_code = '''
    self.CreateGrid(len(table_in), len(table_in[0]))
    for col_pos, key in enumerate(table_in.keys()):
      print col_pos, key
      self.SetColLabelValue(col_pos, str(key))
    for nm, data in enumerate(table_in):
      #for col_pos, key in enumerate(table_in[nm].keys()):
      for col_pos, key in enumerate(table_in.keys()):
        self.SetCellValue(nm, col_pos, str(table_in[nm][key]))
    #'''

    self.AutoSizeColumns(True)
    self.EnableEditing(False)
    self.EnableDragGridSize(False)

    self.Bind(gridlib.EVT_GRID_CELL_LEFT_CLICK, self.OnCellLeftClick)

    timing_for_debugging = '''
    time2 = time.time()
    timedif = time2 - time1
    print "timedif =", timedif
    '''

  def OnCellLeftClick(self, evt):
    print "OnCellLeftClick: (%d,%d) %s\n" % (evt.GetRow(),
                                             evt.GetCol(),
                                             evt.GetPosition())
    evt.Skip()

class flex_arr_img_panel(wx.Panel):
  def __init__(self, parent_frame):
    super(flex_arr_img_panel, self).__init__(parent_frame)
    self.show_nums = True
    self.show_mask = True

  def ini_n_intro(self, flex_arr_one, flex_arr_two = None):
    self.first_lst_in, self.segn_lst_in = flex_arr_one, flex_arr_two
    self.scale = 1.0
    self.bmp_lst = self._mi_list_of_wxbitmaps()
    self.panel_01 = buttons_panel(self)
    self.panel_02 = multi_img_scrollable(self, self.bmp_lst)
    sizer = wx.BoxSizer(wx.HORIZONTAL)
    sizer.Add(self.panel_01, 0, wx.ALIGN_CENTRE)
    sizer.Add(self.panel_02, 1, wx.EXPAND)
    self.SetSizer(sizer)
    self.Show(True)

  def _mi_list_of_wxbitmaps(self, re_scaling = False):
    if(re_scaling == False):
      if(self.show_mask == True):
        self.lst_bmp_obj = wxbitmap_convert(self.first_lst_in, self.segn_lst_in)
      else:
        self.lst_bmp_obj = wxbitmap_convert(self.first_lst_in, None)
      return self.lst_bmp_obj.get_wxbitmap_lst(show_nums = self.show_nums,
                                      scale = self.scale)

    else:
      return self.lst_bmp_obj.scaling(scale = self.scale)

  def to_hide_nums(self):
    self.show_nums = False
    self.bmp_lst = self._mi_list_of_wxbitmaps()
    self.panel_02.img_refresh(self.bmp_lst)

  def to_show_nums(self):
    self.show_nums = True
    self.bmp_lst = self._mi_list_of_wxbitmaps()
    self.panel_02.img_refresh(self.bmp_lst)

  def to_show_mask(self):
    self.show_mask = True
    self.bmp_lst = self._mi_list_of_wxbitmaps()
    self.panel_02.img_refresh(self.bmp_lst)

  def to_hide_mask(self):
    self.show_mask = False
    self.bmp_lst = self._mi_list_of_wxbitmaps()
    self.panel_02.img_refresh(self.bmp_lst)

  def to_re_zoom(self, rot_sn):
    if( rot_sn > 0 ):
      for ntimes in range(int(math.fabs(rot_sn))):
        self.scale = self.scale * 1.05
        if( self.scale > 3.0 ):
          #Maximum possible zoom reached
          self.scale = 3.0

    elif( rot_sn < 0):
      for ntimes in range(int(math.fabs(rot_sn))):
        self.scale = self.scale * 0.95
        if( self.scale < 0.2 ):
          #Minimum possible zoom reached
          self.scale = 0.2

    self.bmp_lst = self._mi_list_of_wxbitmaps(re_scaling = True)
    self.panel_02.img_refresh(self.bmp_lst)

class multi_img_scrollable(scroll_pan.ScrolledPanel):
  def __init__(self, outer_panel, bmp_lst_in):
    super(multi_img_scrollable, self).__init__(outer_panel)
    self.parent_panel  = outer_panel
    self.lst_2d_bmp = bmp_lst_in
    self.set_scroll_content()
    self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
    self.Bind(wx.EVT_IDLE, self.OnIdle)
    self.SetupScrolling()
    self.scroll_rot = 0
    self.SetBackgroundColour(wx.Colour(200, 200, 200))
    aprox_len_pix = len(self.lst_2d_bmp) * 10
    self.SetScrollbars(1, 1, aprox_len_pix * 10, aprox_len_pix * 10)

  def set_scroll_content(self):

    img_lst_vert_sizer = wx.BoxSizer(wx.VERTICAL)

    for lst_1d in self.lst_2d_bmp:
      img_lst_hor_sizer = wx.BoxSizer(wx.HORIZONTAL)

      for i, bmp_lst in enumerate(lst_1d):
        local_bitmap = wx.StaticBitmap(self, bitmap = bmp_lst)
        slice_string = "Slice[" + str(i) + ":" + str(i + 1) + ", :, :]"
        slice_sub_info_txt = wx.StaticText(self, -1, slice_string)
        sigle_slice_sizer = wx.BoxSizer(wx.VERTICAL)
        sigle_slice_sizer.Add(local_bitmap, proportion = 0,
                              flag = wx.ALIGN_CENTRE | wx.ALL, border = 2)
        sigle_slice_sizer.Add(slice_sub_info_txt, proportion = 0,
                              flag = wx.ALIGN_CENTRE | wx.ALL, border = 2)
        img_lst_hor_sizer.Add(sigle_slice_sizer, proportion = 0,
                              flag = wx.ALIGN_CENTER | wx.ALL, border = 2)

      img_lst_vert_sizer.Add(img_lst_hor_sizer, proportion = 0,
                             flag = wx.ALIGN_CENTER | wx.TOP, border = 6)

    self.SetSizer(img_lst_vert_sizer)

  def OnMouseWheel(self, event):

    #saving amount of scroll steps to do
    sn_mov = math.copysign(1, float(event.GetWheelRotation()))
    self.scroll_rot += sn_mov

    #saving relative position of scrolling area to keep after scrolling
    v_size_x, v_size_y = self.GetVirtualSize()

    self.x_to_keep, self.y_to_keep = self.GetViewStart()
    self.x_to_keep = float(self.x_to_keep) / float(v_size_x)
    self.y_to_keep = float(self.y_to_keep) / float(v_size_y)

    debugg_screen_log = '''
    print "self.GetVirtualSize() =", self.GetVirtualSize()
    print "self.GetViewStart() =", self.GetViewStart()
    print "self.GetScrollPixelsPerUnit() =", self.GetScrollPixelsPerUnit()
    print "self.x_to_keep =", self.x_to_keep
    print "self.y_to_keep =", self.y_to_keep
    '''

  def img_refresh(self, bmp_lst_new):
    self.lst_2d_bmp = bmp_lst_new
    for child in self.GetChildren():
      child.Destroy()

    self.set_scroll_content()
    self.Layout()
    self.parent_panel.Layout()
    self.Refresh()

  def OnIdle(self, event):
    if( self.scroll_rot != 0 ):
      self.parent_panel.to_re_zoom(self.scroll_rot)
      self.scroll_rot = 0
      v_size_x, v_size_y = self.GetVirtualSize()
      self.Scroll(self.x_to_keep * v_size_x, self.y_to_keep * v_size_y)

class buttons_panel(wx.Panel):
  def __init__(self, outer_panel):
    super(buttons_panel, self).__init__(outer_panel)
    self.parent_panel  = outer_panel

    Show_Its_CheckBox = wx.CheckBox(self, -1, "Show I nums")
    Show_Its_CheckBox.SetValue(True)
    Show_Its_CheckBox.Bind(wx.EVT_CHECKBOX, self.OnItsCheckbox)

    if( self.parent_panel.segn_lst_in != None ):
      Show_Msk_CheckBox = wx.CheckBox(self, -1, "Show Mask")
      Show_Msk_CheckBox.SetValue(True)
      Show_Msk_CheckBox.Bind(wx.EVT_CHECKBOX, self.OnMskCheckbox)

    self.my_sizer = wx.BoxSizer(wx.VERTICAL)
    self.my_sizer.Add(Show_Its_CheckBox, proportion = 0,
                      flag = wx.ALIGN_TOP, border = 5)

    if( self.parent_panel.segn_lst_in != None ):
      self.my_sizer.Add(Show_Msk_CheckBox, proportion = 0,
                        flag = wx.ALIGN_TOP, border = 5)

    self.my_sizer.SetMinSize((50, 20))
    self.SetSizer(self.my_sizer)

  def OnItsCheckbox(self, event):
    debugg_screen_log = '''
    print "OnItsCheckbox"
    print "event.IsChecked() =", event.IsChecked()
    '''
    if(event.IsChecked() == True):
      self.parent_panel.to_show_nums()
    else:
      self.parent_panel.to_hide_nums()

  def OnMskCheckbox(self, event):
    debugg_screen_log = '''
    print "OnMskCheckbox"
    print "event.IsChecked() =", event.IsChecked()
    '''
    if(event.IsChecked() == True):
      self.parent_panel.to_show_mask()
    else:
      self.parent_panel.to_hide_mask()

<|endoftext|>