Exemple #1
0
def stop_experiment(project, experiment_id):
    """
    Get an experiment.

    :param project: The project
    :param experiment_id: The id of the experiment
    :return: (start, end_date)
    """
    service = _get_service(project)
    #get current state, change name to current name appended with end date
    current = get_experiment(project, experiment_id)
    if current['status'] != 'ENDED':
        #get start time from name
        start = datetime.strptime(current['name'], 'IGA - %Y-%m-%d %H:%M:%S')
        end_str = datetime.now(project_setting(
            project, 'time_zone')).strftime('%Y-%m-%d %H:%M:%S')
        # remove timezone and nanoseconds as we also did in the start
        end = datetime.strptime(end_str, '%Y-%m-%d %H:%M:%S')
        current['name'] = current['name'] + " - " + end_str
        current['status'] = 'ENDED'

        s = service.management().experiments().update(
            accountId=project_setting(project, 'ga_account'),
            webPropertyId=project_setting(project, 'ga_property'),
            profileId=project_setting(project, 'ga_profile'),
            experimentId=experiment_id,
            body=current).execute()
    else:
        dates = current['name'].split(" - ")
        start = datetime.strptime(dates[1], '%Y-%m-%d %H:%M:%S')
        end = datetime.strptime(dates[2], '%Y-%m-%d %H:%M:%S')
    vars = [c['name'] for c in current['variations']]
    return vars, start, end
Exemple #2
0
 def __init__(self, project):
     self.project = project
     self.db = MySQLdb.connect(
         host=project_setting(self.project, 'db_host'),
         user=project_setting(self.project, 'db_user'),
         passwd=project_setting(self.project, 'db_password'),
         db=project_setting(self.project, 'db_db')
     )
Exemple #3
0
def list_experiments(project):
    """
    List the experiments.

    :param project: Project to list the experiments for.
    :return: A list consisting of all the experiments.
    """
    service = _get_service(project)
    s = service.management().experiments().list(
        accountId=project_setting(project, 'ga_account'),
        webPropertyId=project_setting(project, 'ga_property'),
        profileId=project_setting(project, 'ga_profile')).execute()

    return s.get('items')
Exemple #4
0
    def _make_initial_population(self):
        pop_size = project_setting(self.project, 'population_size')
        start_code = project_setting(self.project, 'start_code')
        vars = search_space(self.project)

        # start code is always in population
        pop = [start_code]

        # rest are randomly generated samples
        for i in xrange(0, pop_size):
            ind = []
            for v in vars:
                ind.append(str(np.random.choice(vars[v], 1)[0]))
            pop.append("-".join(ind))
        self._new_population(pop)
Exemple #5
0
def experiment(project):
    f = get_fitness(project)
    e = f.get_current_experiment()

    prefix = project_setting(project, 'prefix')
    body = 'function getQueryVariable(variable){var query = window.location.search.substring(1);var vars = query.split("&");for (var i=0;i<vars.length;i++) {var pair = vars[i].split("=");if(pair[0] == variable){return pair[1];}}return(false);}' \
           'var code = getQueryVariable(\'iga-code\');console.log(code);' \
           'if (code === false) {'
    if e is None:
        body += 'console.log("[iga] Currently no active experiments");'
    else:
        vars = json.dumps(e['variations']).replace('"', '\\"')
        body += 'document.write("<sc"+"ript src=\'http" + (document.location.protocol == \'https:\' ? \'s://ssl\' : \'://www\') + ".google-analytics.com/cx/api.js?experiment=' + \
                e['experiment_id'] + '\'><\\/script>");' \
                                     'document.write("<script>var chosenVariation = cxApi.chooseVariation(); var variations =' + vars + '; var code = variations[chosenVariation]; ' \
                                                                                                                                        'document.write(\\"<sc\\"+\\"ript src=\'' + prefix + 'code-\\"+code+\\".js\'></scri\\"+\\"pt>\\");</scri"+"pt>");'

    body += '} else {' \
            'document.write("<sc"+"ript src=\'' + prefix + 'code-"+code+".js\'></scri"+"pt>");}'
    return Response(body,
                    status=200,
                    mimetype="application/javascript",
                    headers={
                        'Access-Control-Allow-Origin': '*',
                        'Cache-Control': 'max-age=3600'
                    })
Exemple #6
0
def get_experiment(project, experiment_id):
    """
    Get an experiment.

    :param project: The project
    :param experiment_id: The id of the experiment
    :return: Experiment object
    """
    service = _get_service(project)
    s = service.management().experiments().get(
        accountId=project_setting(project, 'ga_account'),
        webPropertyId=project_setting(project, 'ga_property'),
        profileId=project_setting(project, 'ga_profile'),
        experimentId=experiment_id).execute()

    return s
Exemple #7
0
def remove_experiment(project, experiment_id):
    """
    Remove an experiment.

    :param project: The project
    :param experiment_id: The id of the experiment
    :return: Resource object
    """
    service = _get_service(project)
    s = service.management().experiments().delete(
        accountId=project_setting(project, 'ga_account'),
        webPropertyId=project_setting(project, 'ga_property'),
        profileId=project_setting(project, 'ga_profile'),
        experimentId=experiment_id).execute()

    return s
Exemple #8
0
def run(project):
    sa = project_setting(project, 'search_algorithm')
    if sa == 'IGA':
        iga = get_IGA(project)
        iga.run()
    elif sa == 'BF':
        bf = get_bf(project)
        bf.run()
    else:
        raise Exception("No valid search algorithm found %s" % sa)
Exemple #9
0
def start_experiments(project, variations):
    """
    Start experiments.

    :param project:     The project for which the experiments should start.
    :param variations:  The variations of the experiments (list of variation names).
    :return: Experiment Id.
    """
    service = _get_service(project)
    start_code = project_setting(project, 'start_code')
    base_url = project_setting(project, 'example_url')
    body = {
        'name':
        'IGA - ' + datetime.now(project_setting(
            project, 'time_zone')).strftime('%Y-%m-%d %H:%M:%S'),
        'variations': [{
            'name':
            v,
            'url': (base_url if start_code == v else '?iga-code=' + v)
        } for v in variations],
        'servingFramework':
        'API',
        'objectiveMetric':
        'ga:pageviews',
        'equalWeighting':
        True,
        'status':
        'RUNNING'
    }

    return service.management().experiments().insert(
        accountId=project_setting(project, 'ga_account'),
        webPropertyId=project_setting(project, 'ga_property'),
        profileId=project_setting(project, 'ga_profile'),
        body=body).execute()['id']
Exemple #10
0
    def _new_experiment(self, variations=[]):
        # everything is cached, we don't want to send something to analytics now..
        if variations is []:
            pass
        else:
            # default variation is always present and the first
            default_population = project_setting(self.project, 'start_code')

            if default_population in variations:
                variations.remove(default_population)
            variations.insert(0, default_population)

            # start experiment in GA
            ex_id = start_experiments(self.project, variations)
            self._save_current_experiment({"experiment_id":ex_id, "variations":variations})
Exemple #11
0
    def get_fitness(self, population=[]):
        """
        Call this function when you want to retrieve the results of a population
        :param population:
        :return:
        """
        if False:
            raise Exception("Fatal get_fitness called while population not valid")
        else:
            default_population = project_setting(self.project, 'start_code')
            hits = self.db.try_to_find_fitness_for(population)
            # Calculate part of population that is not yet cached and should therefore come from ga
            variations = [p for p in population if p not in hits.keys()]

            # when we need data from google analytics
            if len(variations) > 0:
                log = {}
                ex = self.get_current_experiment()

                # retrieve fitness we need from analytics
                score = get_experiment_score(self.project, ex['experiment_id'])
                experiment_vars = ex['variations']
                if score.shape[1] < 1:
                    self.db.delay_exp(ex['id'], 3600)
                else:
                    base = 0.0
                    for i in range(score.shape[1]):
                        if experiment_vars[i] == default_population:
                            base = score[1,i]
                    for i in range(score.shape[1]):
                        v = experiment_vars[i]
                        if v in variations:
                            variations.remove(v)

                            hits[v] = self._calc_fitness(score[1,i], base)
                            log[v] = (hits[v], score[1,i], int(score[0,i]))

                    # log all results
                    self.save_ga(ex['id'], log, base)

                    # make sure to return in correct order
                    return [hits[p] for p in population]
            else:
                return [hits[p] for p in population]
        return False
Exemple #12
0
 def _save_current_experiment(self, ex):
     pop = ex['variations']
     time_per = project_setting(self.project, 'evaluation_time_per_individual')
     id = self.db.save_ga_experiment(ex['experiment_id'],86300)
     self.db.save_ga_population(id, pop)
Exemple #13
0
def _s3_connect(project):
    return boto3.resource('s3').Bucket(project_setting(project, 's3_bucket'))
Exemple #14
0
def _list_s3(project):
    return boto3.client('s3').list_objects(
        Bucket=project_setting(project, 's3_bucket'))
Exemple #15
0
def _get_experiment_data(project,
                         experiment_id,
                         metrics='ga:pageviews, ga:exitRate',
                         start_date='30daysAgo',
                         end_date='today'):
    """
    Get data for an experiment.

    :param project:         The project to get the data for.
    :param experiment_id:   The ID of the experiment.
    :param metrics:         The metrics which should be retrieved.
    :param start_date:      The start date for which to include data for.
    :param end_date:        The end date for which to include data for.
    :return:
    """
    ids = 'ga:%s' % project_setting(project, 'ga_profile')
    filters = 'ga:experimentId==%s' % experiment_id

    service = _get_service(project)
    s = service.data().ga().get(ids=ids,
                                start_date=start_date,
                                end_date=end_date,
                                metrics=metrics,
                                dimensions='ga:experimentVariant',
                                filters=filters).execute()

    # Modify the rows such that it is possible to do computations on the numbers
    data = {}
    column_names = ['index'
                    ] + [metric.strip() for metric in metrics.split(',')]
    for column in column_names:
        data[column] = []
    if 'rows' in s:
        for row in s['rows']:
            for index in range(len(row)):
                value = row[index]
                value = int(value) if index == 0 else float(value)
                column = column_names[index]
                data[column].append(value)
    s['data'] = data
    # Ugly: bounceRate is percentage (not ratio), so convert it to ratios
    if 'ga:bounceRate' in s['data']:
        s['data']['ga:bounceRate'] = [
            item / 100. for item in s['data']['ga:bounceRate']
        ]

    # Make sessions ints
    if 'ga:sessions' in s['data']:
        s['data']['ga:sessions'] = [
            int(item) for item in s['data']['ga:sessions']
        ]

    # Ugly: exitRate is percentage (not ratio), so convert it to ratios
    if 'ga:exitRate' in s['data']:
        s['data']['ga:exitRate'] = [
            item / 100. for item in s['data']['ga:exitRate']
        ]

    # Make sessions ints
    if 'ga:pageviews' in s['data']:
        s['data']['ga:pageviews'] = [
            int(item) for item in s['data']['ga:pageviews']
        ]

    # stop & log
    vars, start, stop = stop_experiment(project, experiment_id)
    totals = s['totalsForAllResults']
    #_log_experiment_results(project, experiment_id, start.isoformat(), stop.isoformat(), totals['ga:pageviews'], totals['ga:exitRate'], vars, s['data'])
    return s