text:
package com.reimaginebanking.api.nessieandroidsdk.requestclients;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import com.reimaginebanking.api.nessieandroidsdk.requestservices.AccountService;
import com.reimaginebanking.api.nessieandroidsdk.requestservices.AtmService;
import com.reimaginebanking.api.nessieandroidsdk.requestservices.BillService;
import com.reimaginebanking.api.nessieandroidsdk.requestservices.BranchService;
import com.reimaginebanking.api.nessieandroidsdk.requestservices.CustomerService;
import com.reimaginebanking.api.nessieandroidsdk.requestservices.DepositService;
import com.reimaginebanking.api.nessieandroidsdk.requestservices.EnterpriseService;
import com.reimaginebanking.api.nessieandroidsdk.requestservices.MerchantService;
import com.reimaginebanking.api.nessieandroidsdk.requestservices.PurchaseService;
import com.reimaginebanking.api.nessieandroidsdk.requestservices.TransferService;
import com.reimaginebanking.api.nessieandroidsdk.requestservices.WithdrawalService;

import retrofit.RestAdapter;
import retrofit.converter.GsonConverter;

/**
 * A parent class for all of the Nessie Clients that holds shared logic
 */
public class NessieClient {

    private String key;

    /* SERVICES */

    private AccountService accountService;

    private AtmService atmService;

    private BillService billService;

    private BranchService branchService;

    private CustomerService customerService;

    private DepositService depositService;

    private EnterpriseService enterpriseService;

    private MerchantService merchantService;

    private PurchaseService purchaseService;

    private TransferService transferService;

    private WithdrawalService withdrawalService;

    /* CLIENTS */

    private static NessieClient INSTANCE;

    public final AccountClient ACCOUNT;

    public final AtmClient ATM;

    public final BillClient BILL;

    public final BranchClient BRANCH;

    public final CustomerClient CUSTOMER;

    public final DepositClient DEPOSIT;

    public final EnterpriseClient ENTERPRISE;

    public final MerchantClient MERCHANT;

    public final PurchaseClient PURCHASE;

    public final TransferClient TRANSFER;

    public final WithdrawalClient WITHDRAWAL;

    private NessieClient(String key, RestAdapter ra) {
        this.key = key;

        Gson gson = new GsonBuilder()
            .create();

        RestAdapter restAdapter;

        if (ra == null) {
            restAdapter = new RestAdapter.Builder()
                .setEndpoint("http://api.reimaginebanking.com")
                .setConverter(new GsonConverter(gson))
                .build();
        } else {
            restAdapter = ra;
        }

        // Instantiate services
        accountService = restAdapter.create(AccountService.class);
        atmService = restAdapter.create(AtmService.class);
        billService = restAdapter.create(BillService.class);
        branchService = restAdapter.create(BranchService.class);
        customerService = restAdapter.create(CustomerService.class);
        depositService = restAdapter.create(DepositService.class);
        enterpriseService = restAdapter.create(EnterpriseService.class);
        merchantService = restAdapter.create(MerchantService.class);
        purchaseService = restAdapter.create(PurchaseService.class);
        transferService = restAdapter.create(TransferService.class);
        withdrawalService = restAdapter.create(WithdrawalService.class);

        // Instantiate other clients for access through NessieClient
        ACCOUNT = AccountClient.getInstance(this.key, accountService);
        ATM = AtmClient.getInstance(this.key, atmService);
        BILL = BillClient.getInstance(this.key, billService);
        BRANCH = BranchClient.getInstance(this.key, branchService);
        CUSTOMER = CustomerClient.getInstance(this.key, customerService);
        DEPOSIT = DepositClient.getInstance(this.key, depositService);
        ENTERPRISE = EnterpriseClient.getInstance(this.key, enterpriseService);
        MERCHANT = MerchantClient.getInstance(this.key, merchantService);
        PURCHASE = PurchaseClient.getInstance(this.key, purchaseService);
        TRANSFER = TransferClient.getInstance(this.key, transferService);
        WITHDRAWAL = WithdrawalClient.getInstance(this.key, withdrawalService);
    }

    public static NessieClient getInstance(String key){
        if (INSTANCE == null) {
            INSTANCE = new NessieClient(key, null);
        }

        return INSTANCE;
    }

    public static NessieClient getInstance(String key, RestAdapter ra) {
        if (INSTANCE == null) {
            INSTANCE = new NessieClient(key, ra);
        }

        return INSTANCE;
    }
}


text:
<?php
/**
 * Model for the SEO Meta table.
 *
 * @package Yoast\YoastSEO\Models
 */

namespace Yoast\WP\Free\Models;

use Yoast\WP\Free\Yoast_Model;

/**
 * Table definition for the SEO Meta table.
 *
 * @property int $object_id
 * @property int $internal_link_count
 * @property int $incoming_link_count
 */
class SEO_Meta extends Yoast_Model {

	/**
	 * Overwrites the default ID column name.
	 *
	 * @var string
	 */
	public static $id_column = 'object_id';

	/**
	 * Finds the SEO meta for given post.
	 *
	 * @param int $post_id The post ID.
	 *
	 * @return SEO_Meta The SEO meta.
	 */
	public static function find_by_post_id( $post_id ) {
		return Yoast_Model::of_type( 'SEO_Meta' )
			->where( 'object_id', $post_id )
			->find_one();
	}
}

redpajama_set_name: RedPajamaGithub


text:
#include "callchain.h"
#include "debug.h"
#include "event.h"
#include "evsel.h"
#include "hist.h"
#include "machine.h"
#include "map.h"
#include "sort.h"
#include "strlist.h"
#include "thread.h"
#include <stdbool.h>
#include <symbol/kallsyms.h>
#include "unwind.h"

int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
{
	map_groups__init(&machine->kmaps);
	RB_CLEAR_NODE(&machine->rb_node);
	INIT_LIST_HEAD(&machine->user_dsos);
	INIT_LIST_HEAD(&machine->kernel_dsos);

	machine->threads = RB_ROOT;
	INIT_LIST_HEAD(&machine->dead_threads);
	machine->last_match = NULL;

	machine->kmaps.machine = machine;
	machine->pid = pid;

	machine->symbol_filter = NULL;
	machine->id_hdr_size = 0;

	machine->root_dir = strdup(root_dir);
	if (machine->root_dir == NULL)
		return -ENOMEM;

	if (pid != HOST_KERNEL_ID) {
		struct thread *thread = machine__findnew_thread(machine, 0,
								pid);
		char comm[64];

		if (thread == NULL)
			return -ENOMEM;

		snprintf(comm, sizeof(comm), "[guest/%d]", pid);
		thread__set_comm(thread, comm, 0);
	}

	return 0;
}

struct machine *machine__new_host(void)
{
	struct machine *machine = malloc(sizeof(*machine));

	if (machine != NULL) {
		machine__init(machine, "", HOST_KERNEL_ID);

		if (machine__create_kernel_maps(machine) < 0)
			goto out_delete;
	}

	return machine;
out_delete:
	free(machine);
	return NULL;
}

static void dsos__delete(struct list_head *dsos)
{
	struct dso *pos, *n;

	list_for_each_entry_safe(pos, n, dsos, node) {
		list_del(&pos->node);
		dso__delete(pos);
	}
}

void machine__delete_dead_threads(struct machine *machine)
{
	struct thread *n, *t;

	list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
		list_del(&t->node);
		thread__delete(t);
	}
}

void machine__delete_threads(struct machine *machine)
{
	struct rb_node *nd = rb_first(&machine->threads);

	while (nd) {
		struct thread *t = rb_entry(nd, struct thread, rb_node);

		rb_erase(&t->rb_node, &machine->threads);
		nd = rb_next(nd);
		thread__delete(t);
	}
}

void machine__exit(struct machine *machine)
{
	map_groups__exit(&machine->kmaps);
	dsos__delete(&machine->user_dsos);
	dsos__delete(&machine->kernel_dsos);
	zfree(&machine->root_dir);
}

void machine__delete(struct machine *machine)
{
	machine__exit(machine);
	free(machine);
}

void machines__init(struct machines *machines)
{
	machine__init(&machines->host, "", HOST_KERNEL_ID);
	machines->guests = RB_ROOT;
	machines->symbol_filter = NULL;
}

void machines__exit(struct machines *machines)
{
	machine__exit(&machines->host);
	/* XXX exit guest */
}

struct machine *machines__add(struct machines *machines, pid_t pid,
			      const char *root_dir)
{
	struct rb_node **p = &machines->guests.rb_node;
	struct rb_node *parent = NULL;
	struct machine *pos, *machine = malloc(sizeof(*machine));

	if (machine == NULL)
		return NULL;

	if (machine__init(machine, root_dir, pid) != 0) {
		free(machine);
		return NULL;
	}

	machine->symbol_filter = machines->symbol_filter;

	while (*p != NULL) {
		parent = *p;
		pos = rb_entry(parent, struct machine, rb_node);
		if (pid < pos->pid)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

	rb_link_node(&machine->rb_node, parent, p);
	rb_insert_color(&machine->rb_node, &machines->guests);

	return machine;
}

void machines__set_symbol_filter(struct machines *machines,
				 symbol_filter_t symbol_filter)
{
	struct rb_node *nd;

	machines->symbol_filter = symbol_filter;
	machines->host.symbol_filter = symbol_filter;

	for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
		struct machine *machine = rb_entry(nd, struct machine, rb_node);

		machine->symbol_filter = symbol_filter;
	}
}

struct machine *machines__find(struct machines *machines, pid_t pid)
{
	struct rb_node **p = &machines->guests.rb_node;
	struct rb_node *parent = NULL;
	struct machine *machine;
	struct machine *default_machine = NULL;

	if (pid == HOST_KERNEL_ID)
		return &machines->host;

	while (*p != NULL) {
		parent = *p;
		machine = rb_entry(parent, struct machine, rb_node);
		if (pid < machine->pid)
			p = &(*p)->rb_left;
		else if (pid > machine->pid)
			p = &(*p)->rb_right;
		else
			return machine;
		if (!machine->pid)
			default_machine = machine;
	}

	return default_machine;
}

struct machine *machines__findnew(struct machines *machines, pid_t pid)
{
	char path[PATH_MAX];
	const char *root_dir = "";
	struct machine *machine = machines__find(machines, pid);

	if (machine && (machine->pid == pid))
		goto out;

	if ((pid != HOST_KERNEL_ID) &&
	    (pid != DEFAULT_GUEST_KERNEL_ID) &&
	    (symbol_conf.guestmount)) {
		sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
		if (access(path, R_OK)) {
			static struct strlist *seen;

			if (!seen)
				seen = strlist__new(true, NULL);

			if (!strlist__has_entry(seen, path)) {
				pr_err("Can't access file %s\n", path);
				strlist__add(seen, path);
			}
			machine = NULL;
			goto out;
		}
		root_dir = path;
	}

	machine = machines__add(machines, pid, root_dir);
out:
	return machine;
}

void machines__process_guests(struct machines *machines,
			      machine__process_t process, void *data)
{
	struct rb_node *nd;

	for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
		struct machine *pos = rb_entry(nd, struct machine, rb_node);
		process(pos, data);
	}
}

char *machine__mmap_name(struct machine *machine, char *bf, size_t size)
{
	if (machine__is_host(machine))
		snprintf(bf, size, "[%s]", "kernel.kallsyms");
	else if (machine__is_default_guest(machine))
		snprintf(bf, size, "[%s]", "guest.kernel.kallsyms");
	else {
		snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms",
			 machine->pid);
	}

	return bf;
}

void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size)
{
	struct rb_node *node;
	struct machine *machine;

	machines->host.id_hdr_size = id_hdr_size;

	for (node = rb_first(&machines->guests); node; node = rb_next(node)) {
		machine = rb_entry(node, struct machine, rb_node);
		machine->id_hdr_size = id_hdr_size;
	}

	return;
}

static struct thread *__machine__findnew_thread(struct machine *machine,
						pid_t pid, pid_t tid,
						bool create)
{
	struct rb_node **p = &machine->threads.rb_node;
	struct rb_node *parent = NULL;
	struct thread *th;

	/*
	 * Front-end cache - TID lookups come in blocks,
	 * so most of the time we dont have to look up
	 * the full rbtree:
	 */
	if (machine->last_match && machine->last_match->tid == tid) {
		if (pid && pid != machine->last_match->pid_)
			machine->last_match->pid_ = pid;
		return machine->last_match;
	}

	while (*p != NULL) {
		parent = *p;
		th = rb_entry(parent, struct thread, rb_node);

		if (th->tid == tid) {
			machine->last_match = th;
			if (pid && pid != th->pid_)
				th->pid_ = pid;
			return th;
		}

		if (tid < th->tid)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

	if (!create)
		return NULL;

	th = thread__new(pid, tid);
	if (th != NULL) {
		rb_link_node(&th->rb_node, parent, p);
		rb_insert_color(&th->rb_node, &machine->threads);
		machine->last_match = th;
	}

	return th;
}

struct thread *machine__findnew_thread(struct machine *machine, pid_t pid,
				       pid_t tid)
{
	return __machine__findnew_thread(machine, pid, tid, true);
}

struct thread *machine__find_thread(struct machine *machine, pid_t tid)
{
	return __machine__findnew_thread(machine, 0, tid, false);
}

int machine__process_comm_event(struct machine *machine, union perf_event *event,
				struct perf_sample *sample)
{
	struct thread *thread = machine__findnew_thread(machine,
							event->comm.pid,
							event->comm.tid);

	if (dump_trace)
		perf_event__fprintf_comm(event, stdout);

	if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) {
		dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
		return -1;
	}

	return 0;
}

int machine__process_lost_event(struct machine *machine __maybe_unused,
				union perf_event *event, struct perf_sample *sample __maybe_unused)
{
	dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
		    event->lost.id, event->lost.lost);
	return 0;
}

struct map *machine__new_module(struct machine *machine, u64 start,
				const char *filename)
{
	struct map *map;
	struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);

	if (dso == NULL)
		return NULL;

	map = map__new2(start, dso, MAP__FUNCTION);
	if (map == NULL)
		return NULL;

	if (machine__is_host(machine))
		dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
	else
		dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
	map_groups__insert(&machine->kmaps, map);
	return map;
}

size_t machines__fprintf_dsos(struct machines *machines, FILE *fp)
{
	struct rb_node *nd;
	size_t ret = __dsos__fprintf(&machines->host.kernel_dsos, fp) +
		     __dsos__fprintf(&machines->host.user_dsos, fp);

	for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
		struct machine *pos = rb_entry(nd, struct machine, rb_node);
		ret += __dsos__fprintf(&pos->kernel_dsos, fp);
		ret += __dsos__fprintf(&pos->user_dsos, fp);
	}

	return ret;
}

size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
				     bool (skip)(struct dso *dso, int parm), int parm)
{
	return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) +
	       __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm);
}

size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
				     bool (skip)(struct dso *dso, int parm), int parm)
{
	struct rb_node *nd;
	size_t ret = machine__fprintf_dsos_buildid(&machines->host, fp, skip, parm);

	for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
		struct machine *pos = rb_entry(nd, struct machine, rb_node);
		ret += machine__fprintf_dsos_buildid(pos, fp, skip, parm);
	}
	return ret;
}

size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
{
	int i;
	size_t printed = 0;
	struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso;

	if (kdso->has_build_id) {
		char filename[PATH_MAX];
		if (dso__build_id_filename(kdso, filename, sizeof(filename)))
			printed += fprintf(fp, "[0] %s\n", filename);
	}

	for (i = 0; i < vmlinux_path__nr_entries; ++i)
		printed += fprintf(fp, "[%d] %s\n",
				   i + kdso->has_build_id, vmlinux_path[i]);

	return printed;
}

size_t machine__fprintf(struct machine *machine, FILE *fp)
{
	size_t ret = 0;
	struct rb_node *nd;

	for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
		struct thread *pos = rb_entry(nd, struct thread, rb_node);

		ret += thread__fprintf(pos, fp);
	}

	return ret;
}

static struct dso *machine__get_kernel(struct machine *machine)
{
	const char *vmlinux_name = NULL;
	struct dso *kernel;

	if (machine__is_host(machine)) {
		vmlinux_name = symbol_conf.vmlinux_name;
		if (!vmlinux_name)
			vmlinux_name = "[kernel.kallsyms]";

		kernel = dso__kernel_findnew(machine, vmlinux_name,
					     "[kernel]",
					     DSO_TYPE_KERNEL);
	} else {
		char bf[PATH_MAX];

		if (machine__is_default_guest(machine))
			vmlinux_name = symbol_conf.default_guest_vmlinux_name;
		if (!vmlinux_name)
			vmlinux_name = machine__mmap_name(machine, bf,
							  sizeof(bf));

		kernel = dso__kernel_findnew(machine, vmlinux_name,
					     "[guest.kernel]",
					     DSO_TYPE_GUEST_KERNEL);
	}

	if (kernel != NULL && (!kernel->has_build_id))
		dso__read_running_kernel_build_id(kernel, machine);

	return kernel;
}

struct process_args {
	u64 start;
};

static int symbol__in_kernel(void *arg, const char *name,
			     char type __maybe_unused, u64 start)
{
	struct process_args *args = arg;

	if (strchr(name, '['))
		return 0;

	args->start = start;
	return 1;
}

static void machine__get_kallsyms_filename(struct machine *machine, char *buf,
					   size_t bufsz)
{
	if (machine__is_default_guest(machine))
		scnprintf(buf, bufsz, "%s", symbol_conf.default_guest_kallsyms);
	else
		scnprintf(buf, bufsz, "%s/proc/kallsyms", machine->root_dir);
}

/* Figure out the start address of kernel map from /proc/kallsyms */
static u64 machine__get_kernel_start_addr(struct machine *machine)
{
	char filename[PATH_MAX];
	struct process_args args;

	machine__get_kallsyms_filename(machine, filename, PATH_MAX);

	if (symbol__restricted_filename(filename, "/proc/kallsyms"))
		return 0;

	if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
		return 0;

	return args.start;
}

int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
{
	enum map_type type;
	u64 start = machine__get_kernel_start_addr(machine);

	for (type = 0; type < MAP__NR_TYPES; ++type) {
		struct kmap *kmap;

		machine->vmlinux_maps[type] = map__new2(start, kernel, type);
		if (machine->vmlinux_maps[type] == NULL)
			return -1;

		machine->vmlinux_maps[type]->map_ip =
			machine->vmlinux_maps[type]->unmap_ip =
				identity__map_ip;
		kmap = map__kmap(machine->vmlinux_maps[type]);
		kmap->kmaps = &machine->kmaps;
		map_groups__insert(&machine->kmaps,
				   machine->vmlinux_maps[type]);
	}

	return 0;
}

void machine__destroy_kernel_maps(struct machine *machine)
{
	enum map_type type;

	for (type = 0; type < MAP__NR_TYPES; ++type) {
		struct kmap *kmap;

		if (machine->vmlinux_maps[type] == NULL)
			continue;

		kmap = map__kmap(machine->vmlinux_maps[type]);
		map_groups__remove(&machine->kmaps,
				   machine->vmlinux_maps[type]);
		if (kmap->ref_reloc_sym) {
			/*
			 * ref_reloc_sym is shared among all maps, so free just
			 * on one of them.
			 */
			if (type == MAP__FUNCTION) {
				zfree((char **)&kmap->ref_reloc_sym->name);
				zfree(&kmap->ref_reloc_sym);
			} else
				kmap->ref_reloc_sym = NULL;
		}

		map__delete(machine->vmlinux_maps[type]);
		machine->vmlinux_maps[type] = NULL;
	}
}

int machines__create_guest_kernel_maps(struct machines *machines)
{
	int ret = 0;
	struct dirent **namelist = NULL;
	int i, items = 0;
	char path[PATH_MAX];
	pid_t pid;
	char *endp;

	if (symbol_conf.default_guest_vmlinux_name ||
	    symbol_conf.default_guest_modules ||
	    symbol_conf.default_guest_kallsyms) {
		machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID);
	}

	if (symbol_conf.guestmount) {
		items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL);
		if (items <= 0)
			return -ENOENT;
		for (i = 0; i < items; i++) {
			if (!isdigit(namelist[i]->d_name[0])) {
				/* Filter out . and .. */
				continue;
			}
			pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10);
			if ((*endp != '\0') ||
			    (endp == namelist[i]->d_name) ||
			    (errno == ERANGE)) {
				pr_debug("invalid directory (%s). Skipping.\n",
					 namelist[i]->d_name);
				continue;
			}
			sprintf(path, "%s/%s/proc/kallsyms",
				symbol_conf.guestmount,
				namelist[i]->d_name);
			ret = access(path, R_OK);
			if (ret) {
				pr_debug("Can't access file %s\n", path);
				goto failure;
			}
			machines__create_kernel_maps(machines, pid);
		}
failure:
		free(namelist);
	}

	return ret;
}

void machines__destroy_kernel_maps(struct machines *machines)
{
	struct rb_node *next = rb_first(&machines->guests);

	machine__destroy_kernel_maps(&machines->host);

	while (next) {
		struct machine *pos = rb_entry(next, struct machine, rb_node);

		next = rb_next(&pos->rb_node);
		rb_erase(&pos->rb_node, &machines->guests);
		machine__delete(pos);
	}
}

int machines__create_kernel_maps(struct machines *machines, pid_t pid)
{
	struct machine *machine = machines__findnew(machines, pid);

	if (machine == NULL)
		return -1;

	return machine__create_kernel_maps(machine);
}

int machine__load_kallsyms(struct machine *machine, const char *filename,
			   enum map_type type, symbol_filter_t filter)
{
	struct map *map = machine->vmlinux_maps[type];
	int ret = dso__load_kallsyms(map->dso, filename, map, filter);

	if (ret > 0) {
		dso__set_loaded(map->dso, type);
		/*
		 * Since /proc/kallsyms will have multiple sessions for the
		 * kernel, with modules between them, fixup the end of all
		 * sections.
		 */
		__map_groups__fixup_end(&machine->kmaps, type);
	}

	return ret;
}

int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
			       symbol_filter_t filter)
{
	struct map *map = machine->vmlinux_maps[type];
	int ret = dso__load_vmlinux_path(map->dso, map, filter);

	if (ret > 0)
		dso__set_loaded(map->dso, type);

	return ret;
}

static void map_groups__fixup_end(struct map_groups *mg)
{
	int i;
	for (i = 0; i < MAP__NR_TYPES; ++i)
		__map_groups__fixup_end(mg, i);
}

static char *get_kernel_version(const char *root_dir)
{
	char version[PATH_MAX];
	FILE *file;
	char *name, *tmp;
	const char *prefix = "Linux version ";

	sprintf(version, "%s/proc/version", root_dir);
	file = fopen(version, "r");
	if (!file)
		return NULL;

	version[0] = '\0';
	tmp = fgets(version, sizeof(version), file);
	fclose(file);

	name = strstr(version, prefix);
	if (!name)
		return NULL;
	name += strlen(prefix);
	tmp = strchr(name, ' ');
	if (tmp)
		*tmp = '\0';

	return strdup(name);
}

static int map_groups__set_modules_path_dir(struct map_groups *mg,
				const char *dir_name)
{
	struct dirent *dent;
	DIR *dir = opendir(dir_name);
	int ret = 0;

	if (!dir) {
		pr_debug("%s: cannot open %s dir\n", __func__, dir_name);
		return -1;
	}

	while ((dent = readdir(dir)) != NULL) {
		char path[PATH_MAX];
		struct stat st;

		/*sshfs might return bad dent->d_type, so we have to stat*/
		snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
		if (stat(path, &st))
			continue;

		if (S_ISDIR(st.st_mode)) {
			if (!strcmp(dent->d_name, ".") ||
			    !strcmp(dent->d_name, ".."))
				continue;

			ret = map_groups__set_modules_path_dir(mg, path);
			if (ret < 0)
				goto out;
		} else {
			char *dot = strrchr(dent->d_name, '.'),
			     dso_name[PATH_MAX];
			struct map *map;
			char *long_name;

			if (dot == NULL || strcmp(dot, ".ko"))
				continue;
			snprintf(dso_name, sizeof(dso_name), "[%.*s]",
				 (int)(dot - dent->d_name), dent->d_name);

			strxfrchar(dso_name, '-', '_');
			map = map_groups__find_by_name(mg, MAP__FUNCTION,
						       dso_name);
			if (map == NULL)
				continue;

			long_name = strdup(path);
			if (long_name == NULL) {
				ret = -1;
				goto out;
			}
			dso__set_long_name(map->dso, long_name, true);
			dso__kernel_module_get_build_id(map->dso, "");
		}
	}

out:
	closedir(dir);
	return ret;
}

static int machine__set_modules_path(struct machine *machine)
{
	char *version;
	char modules_path[PATH_MAX];

	version = get_kernel_version(machine->root_dir);
	if (!version)
		return -1;

	snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
		 machine->root_dir, version);
	free(version);

	return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
}

static int machine__create_module(void *arg, const char *name, u64 start)
{
	struct machine *machine = arg;
	struct map *map;

	map = machine__new_module(machine, start, name);
	if (map == NULL)
		return -1;

	dso__kernel_module_get_build_id(map->dso, machine->root_dir);

	return 0;
}

static int machine__create_modules(struct machine *machine)
{
	const char *modules;
	char path[PATH_MAX];

	if (machine__is_default_guest(machine)) {
		modules = symbol_conf.default_guest_modules;
	} else {
		snprintf(path, PATH_MAX, "%s/proc/modules", machine->root_dir);
		modules = path;
	}

	if (symbol__restricted_filename(modules, "/proc/modules"))
		return -1;

	if (modules__parse(modules, machine, machine__create_module))
		return -1;

	if (!machine__set_modules_path(machine))
		return 0;

	pr_debug("Problems setting modules path maps, continuing anyway...\n");

	return 0;
}

const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};

int machine__create_kernel_maps(struct machine *machine)
{
	struct dso *kernel = machine__get_kernel(machine);
	char filename[PATH_MAX];
	const char *name;
	u64 addr = 0;
	int i;

	machine__get_kallsyms_filename(machine, filename, PATH_MAX);

	for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
		addr = kallsyms__get_function_start(filename, name);
		if (addr)
			break;
	}
	if (!addr)
		return -1;

	if (kernel == NULL ||
	    __machine__create_kernel_maps(machine, kernel) < 0)
		return -1;

	if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
		if (machine__is_host(machine))
			pr_debug("Problems creating module maps, "
				 "continuing anyway...\n");
		else
			pr_debug("Problems creating module maps for guest %d, "
				 "continuing anyway...\n", machine->pid);
	}

	/*
	 * Now that we have all the maps created, just set the ->end of them:
	 */
	map_groups__fixup_end(&machine->kmaps);

	if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name,
					     addr)) {
		machine__destroy_kernel_maps(machine);
		return -1;
	}

	return 0;
}

static void machine__set_kernel_mmap_len(struct machine *machine,
					 union perf_event *event)
{
	int i;

	for (i = 0; i < MAP__NR_TYPES; i++) {
		machine->vmlinux_maps[i]->start = event->mmap.start;
		machine->vmlinux_maps[i]->end   = (event->mmap.start +
						   event->mmap.len);
		/*
		 * Be a bit paranoid here, some perf.data file came with
		 * a zero sized synthesized MMAP event for the kernel.
		 */
		if (machine->vmlinux_maps[i]->end == 0)
			machine->vmlinux_maps[i]->end = ~0ULL;
	}
}

static bool machine__uses_kcore(struct machine *machine)
{
	struct dso *dso;

	list_for_each_entry(dso, &machine->kernel_dsos, node) {
		if (dso__is_kcore(dso))
			return true;
	}

	return false;
}

static int machine__process_kernel_mmap_event(struct machine *machine,
					      union perf_event *event)
{
	struct map *map;
	char kmmap_prefix[PATH_MAX];
	enum dso_kernel_type kernel_type;
	bool is_kernel_mmap;

	/* If we have maps from kcore then we do not need or want any others */
	if (machine__uses_kcore(machine))
		return 0;

	machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
	if (machine__is_host(machine))
		kernel_type = DSO_TYPE_KERNEL;
	else
		kernel_type = DSO_TYPE_GUEST_KERNEL;

	is_kernel_mmap = memcmp(event->mmap.filename,
				kmmap_prefix,
				strlen(kmmap_prefix) - 1) == 0;
	if (event->mmap.filename[0] == '/' ||
	    (!is_kernel_mmap && event->mmap.filename[0] == '[')) {

		char short_module_name[1024];
		char *name, *dot;

		if (event->mmap.filename[0] == '/') {
			name = strrchr(event->mmap.filename, '/');
			if (name == NULL)
				goto out_problem;

			++name; /* skip / */
			dot = strrchr(name, '.');
			if (dot == NULL)
				goto out_problem;
			snprintf(short_module_name, sizeof(short_module_name),
					"[%.*s]", (int)(dot - name), name);
			strxfrchar(short_module_name, '-', '_');
		} else
			strcpy(short_module_name, event->mmap.filename);

		map = machine__new_module(machine, event->mmap.start,
					  event->mmap.filename);
		if (map == NULL)
			goto out_problem;

		name = strdup(short_module_name);
		if (name == NULL)
			goto out_problem;

		dso__set_short_name(map->dso, name, true);
		map->end = map->start + event->mmap.len;
	} else if (is_kernel_mmap) {
		const char *symbol_name = (event->mmap.filename +
				strlen(kmmap_prefix));
		/*
		 * Should be there already, from the build-id table in
		 * the header.
		 */
		struct dso *kernel = __dsos__findnew(&machine->kernel_dsos,
						     kmmap_prefix);
		if (kernel == NULL)
			goto out_problem;

		kernel->kernel = kernel_type;
		if (__machine__create_kernel_maps(machine, kernel) < 0)
			goto out_problem;

		machine__set_kernel_mmap_len(machine, event);

		/*
		 * Avoid using a zero address (kptr_restrict) for the ref reloc
		 * symbol. Effectively having zero here means that at record
		 * time /proc/sys/kernel/kptr_restrict was non zero.
		 */
		if (event->mmap.pgoff != 0) {
			maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
							 symbol_name,
							 event->mmap.pgoff);
		}

		if (machine__is_default_guest(machine)) {
			/*
			 * preload dso of guest kernel and modules
			 */
			dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION],
				  NULL);
		}
	}
	return 0;
out_problem:
	return -1;
}

int machine__process_mmap2_event(struct machine *machine,
				 union perf_event *event,
				 struct perf_sample *sample __maybe_unused)
{
	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
	struct thread *thread;
	struct map *map;
	enum map_type type;
	int ret = 0;

	if (dump_trace)
		perf_event__fprintf_mmap2(event, stdout);

	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
	    cpumode == PERF_RECORD_MISC_KERNEL) {
		ret = machine__process_kernel_mmap_event(machine, event);
		if (ret < 0)
			goto out_problem;
		return 0;
	}

	thread = machine__findnew_thread(machine, event->mmap2.pid,
					event->mmap2.pid);
	if (thread == NULL)
		goto out_problem;

	if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA)
		type = MAP__VARIABLE;
	else
		type = MAP__FUNCTION;

	map = map__new(&machine->user_dsos, event->mmap2.start,
			event->mmap2.len, event->mmap2.pgoff,
			event->mmap2.pid, event->mmap2.maj,
			event->mmap2.min, event->mmap2.ino,
			event->mmap2.ino_generation,
			event->mmap2.filename, type);

	if (map == NULL)
		goto out_problem;

	thread__insert_map(thread, map);
	return 0;

out_problem:
	dump_printf("problem processing PERF_RECORD_MMAP2, skipping event.\n");
	return 0;
}

int machine__process_mmap_event(struct machine *machine, union perf_event *event,
				struct perf_sample *sample __maybe_unused)
{
	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
	struct thread *thread;
	struct map *map;
	enum map_type type;
	int ret = 0;

	if (dump_trace)
		perf_event__fprintf_mmap(event, stdout);

	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
	    cpumode == PERF_RECORD_MISC_KERNEL) {
		ret = machine__process_kernel_mmap_event(machine, event);
		if (ret < 0)
			goto out_problem;
		return 0;
	}

	thread = machine__findnew_thread(machine, event->mmap.pid,
					 event->mmap.pid);
	if (thread == NULL)
		goto out_problem;

	if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA)
		type = MAP__VARIABLE;
	else
		type = MAP__FUNCTION;

	map = map__new(&machine->user_dsos, event->mmap.start,
			event->mmap.len, event->mmap.pgoff,
			event->mmap.pid, 0, 0, 0, 0,
			event->mmap.filename,
			type);

	if (map == NULL)
		goto out_problem;

	thread__insert_map(thread, map);
	return 0;

out_problem:
	dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
	return 0;
}

static void machine__remove_thread(struct machine *machine, struct thread *th)
{
	machine->last_match = NULL;
	rb_erase(&th->rb_node, &machine->threads);
	/*
	 * We may have references to this thread, for instance in some hist_entry
	 * instances, so just move them to a separate list.
	 */
	list_add_tail(&th->node, &machine->dead_threads);
}

int machine__process_fork_event(struct machine *machine, union perf_event *event,
				struct perf_sample *sample)
{
	struct thread *thread = machine__find_thread(machine, event->fork.tid);
	struct thread *parent = machine__findnew_thread(machine,
							event->fork.ppid,
							event->fork.ptid);

	/* if a thread currently exists for the thread id remove it */
	if (thread != NULL)
		machine__remove_thread(machine, thread);

	thread = machine__findnew_thread(machine, event->fork.pid,
					 event->fork.tid);
	if (dump_trace)
		perf_event__fprintf_task(event, stdout);

	if (thread == NULL || parent == NULL ||
	    thread__fork(thread, parent, sample->time) < 0) {
		dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
		return -1;
	}

	return 0;
}

int machine__process_exit_event(struct machine *machine, union perf_event *event,
				struct perf_sample *sample __maybe_unused)
{
	struct thread *thread = machine__find_thread(machine, event->fork.tid);

	if (dump_trace)
		perf_event__fprintf_task(event, stdout);

	if (thread != NULL)
		thread__exited(thread);

	return 0;
}

int machine__process_event(struct machine *machine, union perf_event *event,
			   struct perf_sample *sample)
{
	int ret;

	switch (event->header.type) {
	case PERF_RECORD_COMM:
		ret = machine__process_comm_event(machine, event, sample); break;
	case PERF_RECORD_MMAP:
		ret = machine__process_mmap_event(machine, event, sample); break;
	case PERF_RECORD_MMAP2:
		ret = machine__process_mmap2_event(machine, event, sample); break;
	case PERF_RECORD_FORK:
		ret = machine__process_fork_event(machine, event, sample); break;
	case PERF_RECORD_EXIT:
		ret = machine__process_exit_event(machine, event, sample); break;
	case PERF_RECORD_LOST:
		ret = machine__process_lost_event(machine, event, sample); break;
	default:
		ret = -1;
		break;
	}

	return ret;
}

static bool symbol__match_regex(struct symbol *sym, regex_t *regex)
{
	if (sym->name && !regexec(regex, sym->name, 0, NULL, 0))
		return 1;
	return 0;
}

static const u8 cpumodes[] = {
	PERF_RECORD_MISC_USER,
	PERF_RECORD_MISC_KERNEL,
	PERF_RECORD_MISC_GUEST_USER,
	PERF_RECORD_MISC_GUEST_KERNEL
};
#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))

static void ip__resolve_ams(struct machine *machine, struct thread *thread,
			    struct addr_map_symbol *ams,
			    u64 ip)
{
	struct addr_location al;
	size_t i;
	u8 m;

	memset(&al, 0, sizeof(al));

	for (i = 0; i < NCPUMODES; i++) {
		m = cpumodes[i];
		/*
		 * We cannot use the header.misc hint to determine whether a
		 * branch stack address is user, kernel, guest, hypervisor.
		 * Branches may straddle the kernel/user/hypervisor boundaries.
		 * Thus, we have to try consecutively until we find a match
		 * or else, the symbol is unknown
		 */
		thread__find_addr_location(thread, machine, m, MAP__FUNCTION,
				ip, &al);
		if (al.map)
			goto found;
	}
found:
	ams->addr = ip;
	ams->al_addr = al.addr;
	ams->sym = al.sym;
	ams->map = al.map;
}

static void ip__resolve_data(struct machine *machine, struct thread *thread,
			     u8 m, struct addr_map_symbol *ams, u64 addr)
{
	struct addr_location al;

	memset(&al, 0, sizeof(al));

	thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr,
				   &al);
	ams->addr = addr;
	ams->al_addr = al.addr;
	ams->sym = al.sym;
	ams->map = al.map;
}

struct mem_info *machine__resolve_mem(struct machine *machine,
				      struct thread *thr,
				      struct perf_sample *sample,
				      u8 cpumode)
{
	struct mem_info *mi = zalloc(sizeof(*mi));

	if (!mi)
		return NULL;

	ip__resolve_ams(machine, thr, &mi->iaddr, sample->ip);
	ip__resolve_data(machine, thr, cpumode, &mi->daddr, sample->addr);
	mi->data_src.val = sample->data_src;

	return mi;
}

struct branch_info *machine__resolve_bstack(struct machine *machine,
					    struct thread *thr,
					    struct branch_stack *bs)
{
	struct branch_info *bi;
	unsigned int i;

	bi = calloc(bs->nr, sizeof(struct branch_info));
	if (!bi)
		return NULL;

	for (i = 0; i < bs->nr; i++) {
		ip__resolve_ams(machine, thr, &bi[i].to, bs->entries[i].to);
		ip__resolve_ams(machine, thr, &bi[i].from, bs->entries[i].from);
		bi[i].flags = bs->entries[i].flags;
	}
	return bi;
}

static int machine__resolve_callchain_sample(struct machine *machine,
					     struct thread *thread,
					     struct ip_callchain *chain,
					     struct symbol **parent,
					     struct addr_location *root_al,
					     int max_stack)
{
	u8 cpumode = PERF_RECORD_MISC_USER;
	int chain_nr = min(max_stack, (int)chain->nr);
	int i;
	int err;

	callchain_cursor_reset(&callchain_cursor);

	if (chain->nr > PERF_MAX_STACK_DEPTH) {
		pr_warning("corrupted callchain. skipping...\n");
		return 0;
	}

	for (i = 0; i < chain_nr; i++) {
		u64 ip;
		struct addr_location al;

		if (callchain_param.order == ORDER_CALLEE)
			ip = chain->ips[i];
		else
			ip = chain->ips[chain->nr - i - 1];

		if (ip >= PERF_CONTEXT_MAX) {
			switch (ip) {
			case PERF_CONTEXT_HV:
				cpumode = PERF_RECORD_MISC_HYPERVISOR;
				break;
			case PERF_CONTEXT_KERNEL:
				cpumode = PERF_RECORD_MISC_KERNEL;
				break;
			case PERF_CONTEXT_USER:
				cpumode = PERF_RECORD_MISC_USER;
				break;
			default:
				pr_debug("invalid callchain context: "
					 "%"PRId64"\n", (s64) ip);
				/*
				 * It seems the callchain is corrupted.
				 * Discard all.
				 */
				callchain_cursor_reset(&callchain_cursor);
				return 0;
			}
			continue;
		}

		al.filtered = false;
		thread__find_addr_location(thread, machine, cpumode,
					   MAP__FUNCTION, ip, &al);
		if (al.sym != NULL) {
			if (sort__has_parent && !*parent &&
			    symbol__match_regex(al.sym, &parent_regex))
				*parent = al.sym;
			else if (have_ignore_callees && root_al &&
			  symbol__match_regex(al.sym, &ignore_callees_regex)) {
				/* Treat this symbol as the root,
				   forgetting its callees. */
				*root_al = al;
				callchain_cursor_reset(&callchain_cursor);
			}
		}

		err = callchain_cursor_append(&callchain_cursor,
					      ip, al.map, al.sym);
		if (err)
			return err;
	}

	return 0;
}

static int unwind_entry(struct unwind_entry *entry, void *arg)
{
	struct callchain_cursor *cursor = arg;
	return callchain_cursor_append(cursor, entry->ip,
				       entry->map, entry->sym);
}

int machine__resolve_callchain(struct machine *machine,
			       struct perf_evsel *evsel,
			       struct thread *thread,
			       struct perf_sample *sample,
			       struct symbol **parent,
			       struct addr_location *root_al,
			       int max_stack)
{
	int ret;

	ret = machine__resolve_callchain_sample(machine, thread,
						sample->callchain, parent,
						root_al, max_stack);
	if (ret)
		return ret;

	/* Can we do dwarf post unwind? */
	if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
	      (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
		return 0;

	/* Bail out if nothing was captured. */
	if ((!sample->user_regs.regs) ||
	    (!sample->user_stack.size))
		return 0;

	return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
				   thread, evsel->attr.sample_regs_user,
				   sample, max_stack);

}

int machine__for_each_thread(struct machine *machine,
			     int (*fn)(struct thread *thread, void *p),
			     void *priv)
{
	struct rb_node *nd;
	struct thread *thread;
	int rc = 0;

	for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
		thread = rb_entry(nd, struct thread, rb_node);
		rc = fn(thread, priv);
		if (rc != 0)
			return rc;
	}

	list_for_each_entry(thread, &machine->dead_threads, node) {
		rc = fn(thread, priv);
		if (rc != 0)
			return rc;
	}
	return rc;
}

int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
				  struct target *target, struct thread_map *threads,
				  perf_event__handler_t process, bool data_mmap)
{
	if (target__has_task(target))
		return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap);
	else if (target__has_cpu(target))
		return perf_event__synthesize_threads(tool, process, machine, data_mmap);
	/* command specified */
	return 0;
}


text:
'use strict'

describe('Plugin interface', function() {
  const PORT = 6242
  const authUrl = 'nats://localhost:' + PORT
  let server

  before(function(done) {
    server = HemeraTestsuite.start_server(PORT, done)
  })

  after(function() {
    server.kill()
  })

  it('Should be able to use a plugin', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    // Plugin
    let myPlugin = Hp(
      function(hemera, options, done) {
        hemera.add(
          {
            topic: 'math',
            cmd: 'add'
          },
          (resp, cb) => {
            cb(null, {
              result: resp.a + resp.b
            })
          }
        )

        done()
      },
      {
        name: 'myPlugin',
        options: { a: 1 }
      }
    )

    hemera.use(myPlugin)

    hemera.ready(() => {
      hemera.act(
        {
          topic: 'math',
          cmd: 'add',
          a: 1,
          b: 2
        },
        (err, resp) => {
          expect(err).to.be.not.exists()
          expect(resp).not.to.be.equals(3)
          hemera.close(done)
        }
      )
    })
  })

  it('Should pass plugin options', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    // Plugin
    let myPlugin = Hp(
      function(hemera, options, done) {
        expect(options).to.be.equals({ a: 1 })

        hemera.add(
          {
            topic: 'math',
            cmd: 'add'
          },
          (resp, cb) => {
            cb(null, {
              result: resp.a + resp.b
            })
          }
        )

        done()
      },
      {
        name: 'myPlugin',
        options: { a: 1 }
      }
    )

    hemera.use(myPlugin)

    hemera.ready(() => {
      hemera.act(
        {
          topic: 'math',
          cmd: 'add',
          a: 1,
          b: 2
        },
        (err, resp) => {
          expect(err).to.be.not.exists()
          expect(resp).not.to.be.equals(3)
          hemera.close(done)
        }
      )
    })
  })

  it('Should merge plugin options and respect reference values', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)
    let ref = { b: 2 }

    // Plugin
    let myPlugin = Hp(
      function(hemera, options, done) {
        expect(options).to.be.equals({ a: 1, ref })
        expect(ref).to.be.shallow.equals(ref)

        hemera.add(
          {
            topic: 'math',
            cmd: 'add'
          },
          (resp, cb) => {
            cb(null, {
              result: resp.a + resp.b
            })
          }
        )

        done()
      },
      {
        name: 'myPlugin',
        options: { a: 1, ref }
      }
    )

    hemera.use(myPlugin)

    hemera.ready(() => {
      hemera.act(
        {
          topic: 'math',
          cmd: 'add',
          a: 1,
          b: 2
        },
        (err, resp) => {
          expect(err).to.be.not.exists()
          expect(resp).not.to.be.equals(3)
          hemera.close(done)
        }
      )
    })
  })

  it('Should merge default plugin options / 2', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    // Plugin
    let myPlugin = Hp(
      function(hemera, options, done) {
        expect(options).to.be.equals({
          port: 3000,
          host: '127.0.0.1',
          errors: {
            propBlacklist: []
          },
          pattern: {}
        })

        hemera.add(
          {
            topic: 'math',
            cmd: 'add'
          },
          (resp, cb) => {
            cb(null, {
              result: resp.a + resp.b
            })
          }
        )

        done()
      },
      {
        name: 'myPlugin',
        options: {
          port: 3000,
          host: '127.0.0.1',
          errors: {
            propBlacklist: ['stack']
          },
          pattern: {}
        }
      }
    )

    hemera.use(myPlugin, {
      errors: {
        propBlacklist: []
      }
    })

    hemera.ready(() => {
      hemera.act(
        {
          topic: 'math',
          cmd: 'add',
          a: 1,
          b: 2
        },
        (err, resp) => {
          expect(err).to.be.not.exists()
          expect(resp).not.to.be.equals(3)
          hemera.close(done)
        }
      )
    })
  })

  it('Should load plugins only on ready', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)
    const pluginCb = Sinon.spy()

    // Plugin
    let myPlugin = Hp(function(hemera, options, done) {
      pluginCb()
      done()
    })

    hemera.use(myPlugin)

    setTimeout(() => {
      expect(pluginCb.called).to.be.equals(false)
      hemera.ready(() => {
        expect(pluginCb.calledOnce).to.be.equals(true)
        hemera.close(done)
      })
    }, 100)
  })

  it('Should be able to register extensions globally inside plugin when scoped is skipped', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)
    let ext1 = Sinon.spy()
    let ext2 = Sinon.spy()

    let myPlugin = Hp(
      function(hemera, options, done) {
        hemera.ext('preHandler', function(ctx, req, res, next) {
          ext1()
          next()
        })
        hemera.add(
          {
            topic: 'math',
            cmd: 'add'
          },
          (resp, cb) => {
            cb(null, {
              result: resp.a + resp.b
            })
          }
        )

        done()
      },
      {
        scoped: false
      }
    )

    hemera.use(myPlugin)

    let myPlugin2 = Hp(
      function(hemera, options, done) {
        hemera.ext('preHandler', function(ctx, req, res, next) {
          ext2()
          next()
        })

        done()
      },
      {
        scoped: false
      }
    )
    hemera.use(myPlugin2)

    hemera.ready(() => {
      hemera.act(
        {
          topic: 'math',
          cmd: 'add',
          a: 1,
          b: 2
        },
        (err, resp) => {
          expect(err).to.be.not.exists()
          expect(resp).not.to.be.equals(3)
          expect(ext1.calledOnce).to.be.equals(true)
          expect(ext2.calledOnce).to.be.equals(true)
          hemera.close(done)
        }
      )
    })
  })

  it('Should not be able to add extensions for parent scope inside plugins', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)
    let ext1 = Sinon.spy()
    let ext2 = Sinon.spy()

    hemera.add(
      {
        topic: 'math',
        cmd: 'add'
      },
      (resp, cb) => {
        cb(null, {
          result: resp.a + resp.b
        })
      }
    )

    let myPlugin = Hp(function(hemera, options, done) {
      hemera.ext('preHandler', function(ctx, req, res, next) {
        ext1()
        next()
      })
      done()
    })
    hemera.use(myPlugin)

    let myPlugin2 = Hp(function(hemera, options, done) {
      hemera.ext('preHandler', function(ctx, req, res, next) {
        ext2()
        next()
      })

      done()
    })
    hemera.use(myPlugin2)

    hemera.ready(() => {
      hemera.act(
        {
          topic: 'math',
          cmd: 'add',
          a: 1,
          b: 2
        },
        (err, resp) => {
          expect(err).to.be.not.exists()
          expect(resp).not.to.be.equals(3)
          expect(ext1.calledOnce).to.be.equals(false)
          expect(ext2.calledOnce).to.be.equals(false)
          hemera.close(done)
        }
      )
    })
  })

  it('Should not be able to add extensions and influence other independent scopes', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)
    let ext1 = Sinon.spy()
    let ext2 = Sinon.spy()
    let ext3 = Sinon.spy()

    let myPlugin = Hp(function(hemera, options, done) {
      hemera.ext('preHandler', function(ctx, req, res, next) {
        ext1()
        next()
      })
      hemera.add(
        {
          topic: 'math',
          cmd: 'add'
        },
        (resp, cb) => {
          cb(null, {
            result: resp.a + resp.b
          })
        }
      )
      hemera.ext('preHandler', function(ctx, req, res, next) {
        ext2()
        next()
      })

      done()
    })
    hemera.use(myPlugin)

    let myPlugin2 = Hp(function(hemera, options, done) {
      hemera.ext('preHandler', function(ctx, req, res, next) {
        ext3()
        next()
      })

      done()
    })
    hemera.use(myPlugin2)

    hemera.ready(() => {
      hemera.act(
        {
          topic: 'math',
          cmd: 'add',
          a: 1,
          b: 2
        },
        (err, resp) => {
          expect(err).to.be.not.exists()
          expect(resp).not.to.be.equals(3)
          expect(ext1.calledOnce).to.be.equals(true)
          expect(ext2.calledOnce).to.be.equals(true)
          expect(ext3.calledOnce).to.be.equals(false)
          hemera.close(done)
        }
      )
    })
  })

  it('Should be able to pass extensions from upper scope to lower scope', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)
    let ext1 = Sinon.spy()
    let ext2 = Sinon.spy()
    let ext3 = Sinon.spy()
    let ext4 = Sinon.spy()

    hemera.ext('preHandler', function(ctx, req, res, next) {
      ext1()
      next()
    })

    let myPlugin = Hp(function(hemera, options, done) {
      hemera.ext('preHandler', function(ctx, req, res, next) {
        ext2()
        next()
      })

      hemera.add(
        {
          topic: 'math',
          cmd: 'add'
        },
        (resp, cb) => {
          cb(null, {
            result: resp.a + resp.b
          })
        }
      )

      let myPlugin2 = Hp(function(hemera, options, done) {
        hemera.ext('preHandler', function(ctx, req, res, next) {
          ext3()
          next()
        })

        done()
      })

      hemera.use(myPlugin2)

      done()
    })
    hemera.use(myPlugin)

    function plugin3(hemera, options, done) {
      hemera.ext('preHandler', function(ctx, req, res, next) {
        ext4()
        next()
      })

      done()
    }
    hemera.use(plugin3)

    hemera.ready(() => {
      hemera.act(
        {
          topic: 'math',
          cmd: 'add',
          a: 1,
          b: 2
        },
        (err, resp) => {
          expect(err).to.be.not.exists()
          expect(resp).not.to.be.equals(3)
          expect(ext1.calledOnce).to.be.equals(true)
          expect(ext2.calledOnce).to.be.equals(true)
          expect(ext3.calledOnce).to.be.equals(false)
          expect(ext4.calledOnce).to.be.equals(false)
          hemera.close(done)
        }
      )
    })
  })

  it('Should be able to use after', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(function(hemera, options, done) {
      done()
    })

    hemera.use(plugin).after(err => {
      expect(err).to.be.not.exists()
      hemera.close(done)
    })

    hemera.ready(err => {
      expect(err).to.be.not.exists()
    })
  })

  it('Should be able to use after on root', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(function(hemera, options, done) {
      done()
    })

    hemera.use(plugin)

    hemera.after(err => {
      expect(err).to.be.not.exists()
      hemera.close(done)
    })

    hemera.ready(err => {
      expect(err).to.be.not.exists()
    })
  })

  it('Should be able to register a plugin in a plugin', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    // Plugin
    let plugin = Hp(
      function(hemera, options, done) {
        let plugin2 = Hp(
          function(hemera, options, done) {
            expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals(['myPlugin', 'myPlugin2'])
            done()
          },
          {
            name: 'myPlugin2',
            options: { a: 2 }
          }
        )

        expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals(['myPlugin'])

        hemera.use(plugin2)

        done()
      },
      {
        name: 'myPlugin',
        options: { a: 1 }
      }
    )

    hemera.use(plugin)

    hemera.ready(err => {
      expect(err).to.be.not.exists()
      expect(hemera[HemeraSymbols.sRegisteredPlugins]).to.be.equals(['myPlugin'])
      hemera.close(done)
    })
  })

  it('Plugin is encapsulated', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let parent = Hp(
      function(hemera, options, done) {
        let plugin = Hp(
          function(hemera, options, done) {
            hemera.decorate('test', true)
            expect(hemera.test).to.be.exists()
            expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals(['parent', 'myPlugin'])
            done()
          },
          {
            name: 'myPlugin'
          }
        )

        let plugin2 = Hp(
          function(hemera, options, done) {
            expect(hemera.test).to.be.exists()
            expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals([
              'parent',
              'myPlugin',
              'myPlugin2'
            ])
            done()
          },
          {
            name: 'myPlugin2'
          }
        )

        hemera.use(plugin)
        hemera.use(plugin2)

        done()
      },
      {
        name: 'parent'
      }
    )

    hemera.use(parent)

    hemera.use(
      Hp(function(hemera, options, done) {
        expect(hemera.test).to.be.exists()
        expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals(['parent', 'plugin.spec'])
        done()
      })
    )

    hemera.ready(err => {
      expect(err).to.be.not.exists()
      expect(hemera.test).to.be.exists()

      expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals(['parent', 'plugin.spec'])
      hemera.close(done)
    })
  })

  it('Plugin which is not encapsulated should be registered with name as well', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let parent = Hp(
      function(hemera, options, done) {
        done()
      },
      {
        scoped: false,
        name: 'parent'
      }
    )

    hemera.use(parent)

    hemera.ready(err => {
      expect(err).to.be.not.exists()
      expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals(['parent'])
      hemera.close(done)
    })
  })

  it('Plugin is not encapsulated when use skip-override', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let parent = Hp(
      function(hemera, options, done) {
        expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals(['parent'])
        done()
      },
      {
        scoped: false,
        name: 'parent'
      }
    )

    hemera.use(parent)

    hemera.use(
      Hp(function(hemera, options, done) {
        expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals(['parent', 'plugin.spec'])
        hemera.use(
          Hp(function(hemera, options, done) {
            expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals([
              'parent',
              'plugin.spec',
              'plugin.spec'
            ])
            done()
          })
        )
        done()
      })
    )

    hemera.ready(err => {
      expect(err).to.be.not.exists()
      expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals(['parent', 'plugin.spec'])
      hemera.close(done)
    })
  })

  it('Should be able to pass a callback after plugins was initialized', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(
      function(hemera, options, done) {
        done()
      },
      {
        name: 'myPlugin'
      }
    )

    hemera.use(plugin).after(err => {
      expect(err).to.be.not.exists()
      hemera.close(done)
    })

    hemera.ready(err => {
      expect(err).to.be.not.exists()
    })
  })

  it('Should be able to list all plugins', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(
      function(hemera, options, done) {
        done()
      },
      {
        name: 'myPlugin'
      }
    )

    hemera.use(plugin)

    hemera.ready(() => {
      expect(hemera[HemeraSymbols.sRegisteredPlugins].slice()).to.be.equals(['myPlugin'])
      hemera.close(done)
    })
  })

  it('Should throw when plugin dependency could not be found', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(
      function(hemera, options, next) {
        next()
      },
      {
        dependencies: ['hemera-joi']
      }
    )

    hemera.use(plugin)

    hemera.ready(err => {
      expect(err.message).to.be.equals(`The dependency 'hemera-joi' is not registered`)
      hemera.close(done)
    })
  })

  it('Should reject when plugin dependency could not be found', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(
      function(hemera, options, next) {
        next()
      },
      {
        dependencies: ['hemera-joi']
      }
    )

    hemera.use(plugin)

    hemera.ready().catch(err => {
      expect(err.message).to.be.equals(`The dependency 'hemera-joi' is not registered`)
      hemera.close(done)
    })
  })

  it('Should throw error because could not resolve all decorator deps', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(function(hemera, options, next) {
      try {
        hemera.decorate('b', 1, ['a'])
      } catch (err) {
        expect(err.message).to.equals(`Missing member dependency 'a'`)
        hemera.close(done)
      }
      next()
    })

    hemera.use(plugin)

    hemera.ready()
  })

  it('Should throw error when plugin decorators was not registered before', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(
      function(hemera, options, next) {
        next()
      },
      {
        decorators: ['test']
      }
    )

    hemera.use(plugin)
    hemera.ready(err => {
      expect(err).to.be.exists()
      expect(err.message).to.equals(`The decorator dependency 'test' is not registered`)
      done()
    })
  })

  it('Should reject error when plugin decorators was not registered before', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(
      function(hemera, options, next) {
        next()
      },
      {
        decorators: ['test']
      }
    )

    hemera.use(plugin)
    hemera.ready().catch(err => {
      expect(err).to.be.exists()
      expect(err.message).to.equals(`The decorator dependency 'test' is not registered`)
      done()
    })
  })

  it('Should satisfy all decorate deps', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(function(hemera, options, next) {
      hemera.decorate('a', 2)
      hemera.decorate('b', 1, ['a'])
      next()
    })

    hemera.use(plugin)

    hemera.ready(() => {
      hemera.close(done)
    })
  })

  it('Should be able to compare plugin hemera errors with instanceof', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(
      function(hemera, options, done) {
        const FooBarError = hemera.createError('FooBarError')

        hemera.decorate('pluginErrors', {
          FooBarError
        })

        hemera.add(
          {
            topic: 'math',
            cmd: 'add'
          },
          (resp, cb) => {
            cb(new FooBarError('test'))
          }
        )

        done()
      },
      {
        name: 'myPlugin'
      }
    )

    hemera.use(plugin)

    hemera.ready(() => {
      hemera.act(
        {
          topic: 'math',
          cmd: 'add'
        },
        (err, resp) => {
          expect(err).to.be.exists()
          expect(err.name).to.be.equals('FooBarError')
          expect(err.message).to.be.equals('test')
          expect(err instanceof hemera.pluginErrors.FooBarError).to.be.equals(true)
          hemera.close(done)
        }
      )
    })
  })

  it('Should throw an error when we trying to overwrite an existing prototype property', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(
      function(hemera, options, next) {
        hemera.decorate('test', 1)
        try {
          hemera.decorate('test', 1)
        } catch (err) {
          expect(err).to.exists()
          hemera.close(done)
        }
        next()
      },
      {
        name: 'myPlugin'
      }
    )

    hemera.use(plugin)

    hemera.ready()
  })

  it('Should throw an error when we trying to overwrite an existing prototype property / 2', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(function(hemera, options, next) {
      hemera.decorate('test', 1)

      let plugin2 = Hp(function(hemera, options, next) {
        try {
          hemera.decorate('test', 1)
        } catch (err) {
          expect(err).to.exists()
          hemera.close(done)
        }
        next()
      })

      hemera.use(plugin2)
      next()
    })

    hemera.use(plugin)

    hemera.ready()
  })

  it('Should be able to decorate the root instance', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(function(hemera, options, next) {
      hemera.decorate('test', 1)
      next()
    })

    hemera.use(plugin)

    hemera.ready(err => {
      expect(err).to.not.exists()
      expect(hemera.test).to.be.equals(1)
      hemera.close(done)
    })
  })

  it('Should be able to decorate root instance / 2', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(function(hemera, options, next) {
      let plugin2 = Hp(function(hemera, options, next) {
        hemera.decorate('test', 1)
        next()
      })
      hemera.use(plugin2)
      next()
    })

    hemera.use(plugin)

    hemera.ready(err => {
      expect(err).to.not.exists()
      expect(hemera.test).to.be.exists()
      hemera.close(done)
    })
  })

  it('Should be able to access the decorated prototype propertys inside nested plugins', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(function(hemera, options, next) {
      hemera.decorate('test', 1)

      expect(hemera.test).to.be.equals(1)

      let plugin2 = Hp(function(hemera, options, next) {
        expect(hemera.test).to.be.equals(1)
        next()
      })

      hemera.use(plugin2)

      next()
    })

    hemera.use(plugin)

    hemera.ready(err => {
      expect(err).to.not.exists()
      expect(hemera.test).to.be.equals(1)
      hemera.close(done)
    })
  })

  it('Should thrown plugin error during initialization', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(function(hemera, options, next) {
      next(new Error('test'))
    })

    hemera.use(plugin)

    hemera.ready(err => {
      expect(err).to.exists()
      expect(err.name).to.be.equals('Error')
      expect(err.message).to.be.equals('test')
      hemera.close(done)
    })
  })

  it('Should thrown super plugin error during initialization', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(function(hemera, options, done) {
      done(new UnauthorizedError('test'))
    })

    hemera.use(plugin)

    hemera.ready(err => {
      expect(err).to.exists()
      expect(err.name).to.be.equals('Unauthorized')
      expect(err.message).to.be.equals('test')
      hemera.close(done)
    })
  })

  it('Should not decorate the root prototype chain', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats)

    let plugin = Hp(function(hemera, options, next) {
      hemera.decorate('test', 1)
      next()
    })

    hemera.use(plugin)

    hemera.ready(err => {
      expect(err).to.not.exists()
      expect(hemera.test).to.be.equals(1)

      let hemera2 = new Hemera(nats)
      expect(hemera2.test).to.not.exists()
      hemera.close(() => {
        hemera2.close(done)
      })
    })
  })

  it('Should be able to use child logger', function(done) {
    const nats = require('nats').connect(authUrl)

    const hemera = new Hemera(nats, {
      childLogger: true
    })

    let plugin = Hp(function(hemera, options, done) {
      hemera.log.info('test')
      done()
    })

    hemera.use(plugin)

    hemera.ready(err => {
      expect(err).to.not.exists()
      hemera.close(done)
    })
  })
})


text:
import collections
import datetime
import random
import re
import StringIO
import sys

import bio
import features
import vcf

DELETE_BASE = '-'

class ProbabilisticFasta(object):
  '''
    generate fasta with probabilities attached from mapped fragments
  '''

  def __init__( self, log=None ):
    self.genome = {} # counts over position { 'A': [ 1, 0, 2, ... ], 'G': [ 2, 2, 0, ... ] } roughly means [AGG][GG][AA]...
    self.insertions = {} # { 0: { 'AAA': 1, 'BB': 2 } } means at position 0, insertion of AAA with 1 confidence; BB with 2 confidence
    self.inserted = {}
    self.deleted = set()
    self.prior = {} # overall counts
    self.total = 0 # total # of nucleotides
    self.length = 0 # length of genome
    self.log = log

  def add( self, fragment, start, confidence=1.0, debug=None ):
    '''
      process a directly mapped fragment of dna
      @fragment: the piece of dna
      @start: where in the reference genome it starts
      @confidence: how confident in this mapping
    '''
    for i in xrange(0, len(fragment) ):
      value = fragment[i]
      position = start + i
      if value not in self.genome:
        self.genome[value] = []
        self.prior[value] = 0
      if len(self.genome[value]) < position + 1:
        self.genome[value].extend( [0] * ( position - len(self.genome[value]) + 1 ) )
        if len(self.genome[value]) > self.length:
          self.length = len(self.genome[value])
      #self.log( "adding confidence %f to %s at %i; start %i" % ( confidence, value, position, start ) )
      #self.log( "capacity %i" % ( len(self.genome[value] ) ) )
      if position >= 0: # mappers can clip off the end
        self.genome[value][position] += confidence
        self.prior[value] += 1
        self.total += 1
        #if position == 39415: # debugging
        #  self.log( 'start %i: added %f to %s, total %f, line %s' % ( start, confidence, value, self.genome[value][position], debug ) )

  def insert( self, fragment, start, confidence=1.0 ):
    '''
      @fragment: the piece of dna to insert
      @start: where the insertion starts on the reference
      @confidence: how confident in this insertion
    '''
    if start not in self.insertions:
      self.insertions[start] = {}
    if fragment not in self.insertions[start]:
      self.insertions[start] = { fragment: 0 }
    self.insertions[start][fragment] += confidence

  def delete( self, start, count, confidence=1.0 ):
    fragment = DELETE_BASE * count
    self.add( fragment, start, confidence )

  def count( self, position ):
    '''
      counts of nucleotides seen at a position
      e.g. { 'A': 10, 'G': 4 }
    '''
    result = collections.defaultdict(int)
    for value in self.genome:
      if len(self.genome[value]) > position:
        result[value] = self.genome[value][position]
    return result

  def confidence( self, position ):
    '''
      returns probabilities of nucleotides
      TODO priors
    '''
    counts = self.count( position ) # e.g. { 'A': 4, 'C': 1 }
    denominator = sum( counts[k] for k in counts ) + len(self.prior) # laplacian smoothing
    probabilities = {}
    for count in counts:
      probabilities[count] = ( counts[count] + 1.0 ) / denominator
    return probabilities

  def consensus_at( self, i=0, call_strategy='consensus' ):
    '''
      returns the majority base at given position i, or N if no coverage (move, best, confidence, coverage)
      @return move, result, best, coverage
       - move: how many bases to move candidate (1 is normal)
       - result: best variation
       - best: confidence of this variation
       - coverage: total # reads covering this base
    '''
    best = 'N' # default if no coverage
    best_value = 0
    coverage = 0
    result = ''
    move = 0
    # consensus at this base
    for value in self.genome: # i.e. A, C, G, T
      if i < len(self.genome[value]): # check in range
        coverage += self.genome[value][i]
        if self.genome[value][i] > best_value:
          best_value = self.genome[value][i] # best count
          best = value # best base
    #self.log( 'consensus at %i: best %s: %i of %i' % ( i, best, best_value, coverage ) )
    # find consensus insertion
    if i in self.insertions:
      # pick highest
      best_insertion = None
      best_insertion_value = 0
      insertion_coverage = 0
      for insertion in self.insertions[i]:
        insertion_coverage += self.insertions[i][insertion]
        if best_insertion is None or self.insertions[i][insertion] > best_insertion_value:
          best_insertion = insertion
          best_insertion_value = self.insertions[i][insertion]
      if best_insertion is not None and ( call_strategy == 'aggressive' or best_insertion_value > ( coverage - insertion_coverage ) ):
        result = best_insertion
        self.inserted[i] = best_insertion
        #if self.log:
        #  self.log( 'included insertion %s at ref %i' % (best_insertion, i) )
        move = len(best_insertion)
      else:
        pass
        if self.log:
          pass #self.log( 'skipped insertion at %i with val %f with noinsert %f' % ( i, best_insertion_value, coverage - insertion_coverage ) )
    # was the consensus to delete?
    if best == DELETE_BASE:
      self.deleted.add(i)
      #if self.log:
      #  self.log( 'deletion at %i' % (i) )
    else:
      result += best
      move += 1

    return (move, result, best_value, coverage) # TODO only returning confidence for variation, not indel

  def consensus_count( self, start=0, count=1 ):
    '''
      get the next count characters from start
      can return more than count if insertions at the end of the segment
      can return less than count if at end of string
    '''
    result = ''
    total_move = 0
    reference_move = 0
    while len(result) <= count and start + reference_move < self.length:
      move, s, confidence, coverage = self.consensus_at( start + reference_move )
      result += s
      reference_move += 1
    #self.log( 'consensus for %i count %i is %s (%i)' % (start, count, result, len(result)) )
    return (reference_move, result)

  def consensus( self, start=0, end=-1 ):
    '''
      return the corresponding string for the segment specified.
      returned segment can be longer or shorter than end-start - segment applies to the reference.
      inclusive of start, exclusive of end

    '''
    if end == -1 or end > self.length:
      end = self.length
    result = ''
    self.insertion_count = 0
    for i in xrange(start, end):
      move, add, confidence, coverage = self.consensus_at( i )
      result += add
    #self.log( 'consensus for %i to %i is %s (%i)' % (start, end, result, len(result)) )
    return result

class MultiFastaMutate(object):
  def __init__( self, multi_reader, log=bio.log_stderr, vcf_file=None, snp_prob=0.01, insert_prob=0.01, delete_prob=0.01, min_insert_len=1, max_insert_len=1, min_delete_len=1, max_delete_len=1, min_variation_dist=0, min_variation_start=0, probabilistic=True, insert_source='random', allow_end_mutate=False, tandem_count=1 ):
    for reader in multi_reader.items():
      FastaMutate( reader, log, vcf_file, snp_prob, insert_prob, delete_prob, min_insert_len, max_insert_len, min_delete_len, max_delete_len, min_variation_dist, min_variation_start, probabilistic, insert_source, allow_end_mutate, tandem_count=1 )

class FastaMutate(object):
  '''
    change a reference fasta
  '''

  def __init__( self, reader, log=bio.log_stderr, vcf_file=None, snp_prob=0.01, insert_prob=0.01, delete_prob=0.01, min_insert_len=1, max_insert_len=1, min_delete_len=1, max_delete_len=1, min_variation_dist=0, min_variation_start=0, probabilistic=True, insert_source='random', allow_end_mutate=False, probabilities='AACCCTTGGG', tandem_count=1, max_variation_count=1e6 ):
    '''
      @reader: FastaReader
      @vcf_file: write mutations to vcf
    '''
    self.reader = reader
    self.snp_prob = snp_prob
    self.insert_prob = insert_prob
    self.delete_prob = delete_prob
    self.min_insert_len = min_insert_len
    self.max_insert_len = max_insert_len
    self.min_delete_len = min_delete_len
    self.max_delete_len = max_delete_len
    self.min_variation_dist = min_variation_dist
    self.min_variation_start = min_variation_start
    self.deletion_remain = 0
    self.mutations = 0
    self.vcf_file = vcf_file
    self.probabilistic = probabilistic
    self.probabilities = probabilities
    self.insert_source = insert_source
    self.tandem_count = tandem_count
    self.max_variation_count = max_variation_count
    self.variation_count = 0
    self.insert_source_data = ''
    if vcf_file is not None:
      self.vcf = vcf.VCF( writer=vcf.VCFWriter(vcf_file) )
    else:
      self.vcf = vcf.VCF()
    self.pos = 0
    self.last_variation_pos = None # this is the end position of the last variation
    self.allow_end_mutate = allow_end_mutate

    seed = random.randint(0, sys.maxint)
    random.seed(seed)
    if log is not None:
      log( 'seed: %i; insert_source %s' % (seed, insert_source) )
    self.log = log

  def items(self):
    while True:
      fragment = self.reader.next_item()
      if fragment is None: # no more fragments
        if self.deletion_remain > 0:
          self.end_deletion()
        break
      if self.insert_source == 'repeat':
        self.insert_source_data += str(fragment)
      elif self.insert_source == 'tandem':
        self.insert_source_data += str(fragment)
        if len(self.insert_source_data) > len(str(fragment)) + self.max_insert_len: # keep this fragment + length
          self.insert_source_data = self.insert_source_data[-len(str(fragment)) - self.max_insert_len:]
        #self.log( 'insert_source_data: %s' % self.insert_source_data )
      # apply mutations
      if self.allow_end_mutate or self.reader.has_next_item(): # don't mutate last fragment
        fragment = self.mutate( fragment )
      yield fragment

  def add_snp(self, c):
    '''
      generates a single snp, adds to vcf, returns new base
    '''
    new_c = self.probabilities[random.randint(0, len(self.probabilities)-1)]
    while new_c == c:
      new_c = self.probabilities[random.randint(0, len(self.probabilities)-1)]
    self.mutations += 1
    if self.vcf is not None:
      self.vcf.snp( self.pos, c, new_c )
    return new_c

  def add_insertion(self, c, fragment_pos, fragment_len ):
    '''
      generates a new insertion and returns it
      insertion gets placed before current base
    '''
    insert_len = random.randint(self.min_insert_len, self.max_insert_len) # decide insertion len
    # generate actual insertion
    if self.insert_source == 'repeat' and len(self.insert_source_data) >= insert_len:
      #self.log( 'choosing repeated fragment up to %i' % len(self.insert_source_data) )
      fragment_start = random.randint(0, len(self.insert_source_data) - insert_len)
      new_c = self.insert_source_data[fragment_start:fragment_start + insert_len]
      #self.log( "repeat %s from %i:%i" % ( new_c, fragment, position ) )
    elif self.insert_source == 'tandem' and len(self.insert_source_data) >= insert_len + fragment_len:
      #self.log( 'choosing tandem fragment up to %i from %s' % ( len(self.insert_source_data), self.insert_source_data ) )
      # want the insert_len chars directly before fragment_pos, where data is len fragment_len + insert_len
      dist_from_end = fragment_len - fragment_pos
      new_c = self.insert_source_data[ -insert_len -dist_from_end: -dist_from_end ]
    elif self.insert_source == 'random':
      new_c = ''
      while insert_len > 0:
        insert_len -= 1
        new_c += self.probabilities[random.randint(0, len(self.probabilities)-1)]
      #self.log( "random %s" % ( new_c ) )
    else: #if self.insert_source == 'simple':
      possibles = 'ACGT'
      new_c = possibles[random.randint(0, len(possibles)-1)] * insert_len
    #elif self.insert_source == 'novel':
    #  pass
    self.mutations += 1
    # add to vcf
    if self.vcf is not None:
      self.vcf.indel( self.pos, self.previous + c, self.previous + new_c + c )
    return new_c

  def add_deletion(self, c):
    self.mutations += 1
    self.deletion_remain = random.randint(self.min_delete_len, self.max_delete_len)
    self.deleted = ''
    self.deletion_start = self.pos
    self.deletion_previous = self.previous
    self.continue_deletion( c )

  def continue_deletion(self, c):
    self.deletion_remain -= 1
    self.deleted += c
    if self.deletion_remain == 0:
      self.end_deletion()

  def end_deletion(self):
      if self.vcf is not None:
        self.vcf.indel( self.deletion_start - 1, self.deletion_previous + self.deleted, self.deletion_previous )

  def mutate(self, fragment):
    result = ''
    for fragment_pos, c in enumerate(fragment): # iterate over each base in fragment
      #self.log( 'evaluating %s' % c )
      if self.deletion_remain > 0:
        self.continue_deletion( c )
      elif self.probabilistic:
        # snp
        if self.variation_count < self.max_variation_count and random.uniform(0, 1) < self.snp_prob and self.pos >= self.min_variation_start and ( self.last_variation_pos is None or self.last_variation_pos + self.min_variation_dist <= self.pos ):
          new_c = self.add_snp( c )
          #self.log( 'added snp at %i' % self.pos )
          result += new_c
          self.last_variation_pos = self.pos
          self.variation_count += 1
        # insert
        elif self.variation_count < self.max_variation_count and random.uniform(0, 1) < self.insert_prob and self.pos >= self.min_variation_start and self.pos > self.max_insert_len and ( self.last_variation_pos is None or self.last_variation_pos + self.min_variation_dist <= self.pos ): # TODO reads can get -ve reference
          new_c = self.add_insertion( c, fragment_pos, len(fragment) )
          #self.log( 'added insertion at %i' % self.pos )
          result += new_c + c # insertion gets placed before current base
          self.last_variation_pos = self.pos - 1 # -1 because insertion is placed before current
          self.variation_count += 1
        # delete
        elif self.variation_count < self.max_variation_count and self.pos > 0 and random.uniform(0, 1) < self.delete_prob and self.pos >= self.min_variation_start and ( self.last_variation_pos is None or self.last_variation_pos + self.min_variation_dist <= self.pos ):
          self.add_deletion( c )
          #self.log( 'added deletion at %i' % self.pos )
          self.last_variation_pos = self.pos + self.deletion_remain
          self.variation_count += 1
        # no mutation
        else:
          result += c
      else: # deterministic
        pass

      self.pos += 1
      self.previous = c
    return result

class FastaDiff(object):
  '''
    compare fastas
  '''

  def __init__( self, reader, candidate, log, vcf=None ):
    '''
      @reader: FastaReader of known donor
      @candidate: ProbabilisticFasta of imputed genome
      @vcf: use to keep fastas properly aligned
    '''
    self.candidate_pos = 1
    self.last_log_pos = 0
    self.last_error_total_logged = 0
    self.errors = {}
    self.error_positions = set() # set of incorrect positions
    self.error_total = 0
    self.candidate = candidate
    self.log = log
    self.vcf = vcf
    candidate_remainder = ''
    for item in reader.items():
      # gets the corresponding segment from the candidate
      move, candidate_item = candidate.consensus_count( self.candidate_pos, len(item) )
      candidate_item = candidate_remainder + candidate_item
      candidate_remainder = candidate_item[len(item):]
      #self.log( 'truth: %s pred:  %s' % ( item, candidate_item ) ) # debug
      if candidate_item != item:
        # find differences
        self.find_differences( item, candidate_item, self.candidate_pos )
      self.candidate_pos += move #len(item)
      if self.candidate_pos < 10000 and self.candidate_pos - self.last_log_pos >= 1000 or self.candidate_pos - self.last_log_pos >= 10000:
        self.log_error()

  def log_error( self, i=0 ):
    self.log( 'processed cand %i items - %i errors' % ( self.candidate_pos + i, self.error_total ) )
    self.last_log_pos = self.candidate_pos
    self.last_error_total_logged = self.error_total

  def find_differences( self, item, candidate, start ):
    for i in xrange(0, min(len(item), len(candidate))):
      if item[i] != candidate[i]:
        self.error_total += 1
        if self.error_total < 100 and self.error_total != self.last_error_total_logged:
          self.log_error(i)
        key = '%s->%s' % ( item[i], candidate[i] )
        if self.error_total < 100 or self.error_total % 1000 == 0:
          self.log( 'error: actual->predicted %s at cand %i + %i (%i): counts %s\ntruth: %s\npred:  %s' % ( key, start, i, start + i, self.candidate.count( start + i ), item, candidate ) )
        if key not in self.errors:
          self.errors[key] = 0
        self.errors[key] += 1
        self.error_positions.add( start + i )

    if len(item) != len(candidate):
      key = 'length'
      if key not in self.errors:
        self.errors[key] = 0
      self.errors[key] += 1

class FastaLength(object):
  def __init__(self, reader):
    self.reader = reader
    self.length = 0
    for item in self.reader.items():
       self.length += len(item)

class Fasta(object):
  '''
    keeps the whole fasta in memory for random access
  '''
  def __init__(self, reader):
    '''
      @reader: FastaReader
    '''
    self.reader = reader
    self._length = None
    self.fasta = ''

  @property
  def length(self):
    if self._length is None:
      # read the whole thing
      for item in self.reader.items():
         self.fasta += item
      self._length = len(self.fasta)
    return self._length

  def base_at(self, i):
    if i >= len(self.fasta):
      for item in self.reader.items():
        self.fasta += item
        if i < len(self.fasta): # success
          break
    if i < len(self.fasta):
      return self.fasta[i]
    else:
      return None

  def fragment(self, start=0, end=-1 ):
    if end == -1:
      end = self.length
    result = ''
    for i in xrange(start, end):
      result += self.base_at(i)
    return result

  def read_to( self, pos ):
    '''
      read up to pos; return false if unable
    '''
    if pos >= len(self.fasta):
      for item in self.reader.items():
        self.fasta += item
        if pos < len(self.fasta): # success
          return True
      return False # failed
    else:
      return True

class FastaReaderFromVCF(object):
  def __init__(self, fasta, vcf):
    self.reader = fasta
    self.vcf = vcf
    self.pos = 0

  def items(self):
    while True:
      next_fragment = self.next_item()
      if next_fragment is None:
        break
      else:
        yield next_fragment

  def next_item(self):
    fragment = self.reader.next_item()
    if fragment is None:
      return None
    else:
      fragment = list(fragment)
      new_pos = self.pos + len(fragment)
      for i in xrange(self.pos, new_pos):
        if i in self.vcf.snp_map:
          fragment[i - self.pos] = self.vcf.snp_list[self.vcf.snp_map[i]]['alt']
      self.pos = new_pos
      return ''.join(fragment)

class FastaReader(object):
  '''
    yields fragments from a fasta file object
>>> import StringIO
>>> g = StringIO.StringIO( '>\nabc\ndef' )
>>> p = bio.FastaReader( g )
>>> [ f for f in p.items() ]
['abc', 'def']
  '''
  def __init__(self, genome, include_headers=False):
    self.genome = genome
    self.name = None
    self.has_next = True
    self.include_headers = include_headers
    self.future_fragment = self._next_item()

  def items(self):
    while True:
      current_fragment = self.future_fragment
      if current_fragment is None:
        break
      self.future_fragment = self._next_item()
      self.has_next = self.future_fragment is not None
      yield current_fragment

  #def items(self):
  #  while True:
  #    current_fragment = self.next_item()
  #    if current_fragment is None:
  #      break
  #    yield current_fragment

  def next_item(self):
    current_fragment = self.future_fragment
    self.future_fragment = self._next_item()
    self.has_next = self.future_fragment is not None
    return current_fragment

  def _next_item(self):
    for line in self.genome:
      if line.startswith( '>' ):
        self.name = line[1:].strip()
      if line.startswith( '>' ) and not self.include_headers:
          pass
      else:
        return line.strip()
    return None

  def has_next_item(self):
    return self.has_next

  def __repr__(self):
    return "name: %s" % self.name

class FastaStats(object):
  '''calculate some overall stats for a fasta file'''
  def __init__( self, fasta, read_length=100, log=bio.log_stderr ):
    '''
      @fasta: file handle
    '''
    self.stats = { 'count': 0, 'gc': [], 'entropy': [] }
    self.base_counter = collections.Counter()
    current = ''
    lines = 0
    for line in fasta:
      line = line.strip()
      if not line.startswith( '>' ):
        self.stats['count'] += len(line) # total fasta length
        current += line
        self.base_counter.update(line)
        if len(current) >= read_length:
          add = len(current) - read_length
          for idx in xrange(0, add):
            feature = features.ReadFeature( current[idx:idx+read_length] )
            self.stats['gc'].append( feature.gc() )
            self.stats['entropy'].append( feature.entropy() )
          current = current[add:]
      lines += 1
      if lines % 1000 == 0:
        log( '%i lines processed' % lines )
    #log( self.stats )
    log( '%i lines processed' % lines )

class MultiFastaReaderContainer(object):
  def __init__(self, genome):
    reader = MultiFastaReader( genome )
    self.fastas = {}
    for item in reader.items():
      self.fastas[item.name] = item

  def find_chromosome( self, name ):
    if name in self.fastas:
      return self.fastas[name]
    for key in self.fastas:
      if key.split( ' ' )[0] == name:
        return self.fastas[key]
    return None

class MultiFastaReader(object):
  '''
    use items to iterate over a list of FastaReader objects
  '''
  def __init__(self, genome):
    '''
      genome is a file like object
    '''
    self.genome = genome

  def items( self ):
    '''
      iterate over fasta sequences
    '''
    current = []
    found_header = False
    for line in self.genome:
      if line.startswith( '>' ):
        if found_header:
          yield FastaReader( genome=StringIO.StringIO( ''.join(current) ) ) # TODO inefficient
          current = [ line ]
        else:
          found_header = True
          current.append( line )
      else:
        current.append( line )
    yield FastaReader( genome = StringIO.StringIO( ''.join(current) ) )

class ErrorGenerator(object):
  def __init__( self, error_profile ):
    self.error_profile = error_profile

  def apply_errors( self, dna ):
    result = []
    for x in dna:
      result.append( self.error_profile( x ) )
    return ''.join( result )

  @staticmethod
  def create_uniform_error_profile( error_prob ):
    '''snv errors with probability error_prob'''
    transitions = { 'A': 'TGC', 'T': 'GCA', 'G': 'ACT', 'C': 'AGT', 'N': 'N' }
    def uniform_error_profile( bp ):
      if random.random() < error_prob:
        return transitions[bp][random.randint(0, len(transitions[bp]) - 1)]
      else:
        return bp
    return uniform_error_profile

  @staticmethod
  def create_homopolymer_error_profile( error_prob, error_length ):
    possibles = 'ACGT'
    def homopolymer_error_profile( bp ):
      if random.random() < error_prob:
        return ''.join( ( bp, possibles[random.randint(0, len(possibles)-1)] * error_length ) )
      else:
        return bp
    return homopolymer_error_profile

class RepeatedMultiFastaGenerator( object ):
  def __init__( self, multi_reader, out_fh, multiplier, cfg ):
    for reader in multi_reader.items():
      RepeatedFastaGenerator( reader, out_fh, multiplier, cfg )

class RepeatedFastaGenerator( object ):
  def __init__( self, reader, out_fh, multiplier, cfg, log=bio.log_quiet ):
    '''
      this just makes repeats of an entire fasta with a specified snp mutation prob
      @reader: FastaReader
      @cfg: config dictionary
    '''
    # reader = bio.FastaReader( open( sys.argv[2], 'r' ) )
    out_fh.write( '>generated fasta %ix from %s\n' % ( multiplier, reader.name ) )
    sequence = StringIO.StringIO()
    for item in reader.items():
      if len(item) > 0:
        out_fh.write( '%s\n' % item ) # write unmodified
        sequence.write( '%s\n' % item ) # remember

    for i in xrange(0, multiplier - 1):
      sequence.seek(0)
      reader = FastaReader( sequence )
      mutator = FastaMutate( reader, snp_prob=float(cfg['mult_snp_prob']), insert_prob=0, delete_prob=0, log=log )
      for item in mutator.items():
        if len(item) > 0:
          out_fh.write( '%s\n' % item ) # write unmodified
       #sys.stdout.write( sequence )

BASES = 'ACGT'

class SequenceGenerator( object ):
  def __init__( self, length, probs=(0.25, 0.25, 0.25, 0.25), repeat_length=None ):
    result = []
    if repeat_length is None:
      repeat_length = length
    for _ in xrange( repeat_length ):
      x = random.random()
      for prob_idx in xrange(len(probs)):
        if x < sum(probs[:prob_idx+1]):
          result.append(BASES[prob_idx])
          break
    if length > 0 and repeat_length > 0:
      mult = length / repeat_length
      if repeat_length % length != 0:
        mult += 1
      self.sequence = ''.join(result * mult)
      self.sequence = self.sequence[:length]
    else:
      self.sequence = ''

  def mutate( self, position ):
    current_base_index = BASES.index(self.sequence[position])
    next_base_index = ( current_base_index + 1 ) % len(BASES)
    new_base = BASES[ next_base_index ]
    self.sequence = self.sequence[:position] + new_base + self.sequence[position+1:]

if __name__ == "__main__":
  pass


text:
require 'scoruby/models/random_forest/data'
require 'forwardable'

module Scoruby
  module Models
    module RandomForest
      class Model
        extend Forwardable
        def_delegators :@data, :decision_trees, :categorical_features,
                       :continuous_features, :regression?

        def initialize(xml)
          @data = Data.new(xml)
        end

        def score(features)
          decisions_count = decisions_count(features)

          if regression?
            {
              response: sum(decisions_count.map { |k, v| k.to_f * v }) / sum(decisions_count.values)
            }
          else
            decision = decisions_count.max_by { |_, v| v }
            {
              label: decision[0],
              score: decision[1] / sum(decisions_count.values).to_f
            }
          end
        end

        def decisions_count(features)
          formatted_features = Features.new(features).formatted
          decisions = traverse_trees(formatted_features)
          aggregate_decisions(decisions)
        end

        private

        def traverse_trees(formatted_features)
          decision_trees.map do |decision_tree|
            decision_tree.decide(formatted_features).score
          end
        end

        def aggregate_decisions(decisions)
          decisions.each_with_object(Hash.new(0)) do |score, counts|
            counts[score] += 1
          end
        end

        def sum(values)
          values.reduce(0, :+)
        end
      end
    end
  end
end


text:
//Size of the space occupied by the diagram
var totalWidth = 1000;
var totalHeight = 500;
//Margins for axis
var axisMargin = {top: 2, left: 30, bottom: 20, right: 0};
//Margin around the graph
var graphMargin = {top: 10, left: 10, bottom: 10, right: 40};
//Margin around bars
var barMargin = {top: 5, left: 3, bottom: 5, right: 3};
//calculate width of container
var diagramWidth = totalWidth - axisMargin.left - axisMargin.right;
//calculate height of container
var diagramHeight = totalHeight - axisMargin.top - axisMargin.bottom;
//calculate width of graph
var graphWidth = diagramWidth - graphMargin.left - graphMargin.right;
//calculate height of graph
var graphHeight = diagramHeight - graphMargin.top - graphMargin.bottom;
//select graph
var chart = d3.select(".chart")
	.attr("width", totalWidth)
	.attr("height", totalHeight)
	.attr("fill","red");
var	chartMoved=chart
	//position container
	.append("g");
	chartMoved
	.attr("transform", "translate(" + axisMargin.left + "," +  axisMargin.top + ")")
	chartMoved
	//show graph area with axis
	.append("rect")
	.attr("width", diagramWidth)
	.attr("height", diagramHeight)
	.attr("fill","darkgrey");
var graph = chartMoved
	//show graph area without axis
	.append("g")
	.attr("id","graph")
	.attr("transform", "translate(" + graphMargin.left + "," +  graphMargin.top + ")");
	graph
	.append("rect")
	.attr("width", graphWidth)
	.attr("height", graphHeight)
	.attr("fill","black");

var data;

d3.json("./DYBE_Class.json", function (data) {

	var x = d3.scale.ordinal()
		.domain(data.map(function (d) {
				return d.surname + " " + d.forename;
			}))
		.rangeRoundBands([0, graphWidth]);
	var y = d3.scale.linear()
		.domain([0, d3.max(data.map(function (d) {
					return parseFloat(d.Access);
				}))])
		.range([graphHeight - barMargin.top - barMargin.bottom,0]);
	//axis objects
	var xAxis = d3.svg.axis()
		.scale(x)
		.orient("bottom");
	var yAxis = d3.svg.axis()
		.scale(y)
		.orient("left");

	//calculate width of a single bar
	var barWidth = graphWidth / data.length;

	//calculate top coordinate of bar
	function barTop(data)
	{
		return y(data.Access)+ barMargin.top;
	}

	//calculate bottom coordinate of bar
	function barBottom(data)
	{
		return graphHeight;
	}

	//calculate position of a single bar
	function moveBar(data, index)
	{
		return "translate(" + (index * barWidth + barMargin.left) + ",0)";
	}

	//get the bars
	var bars = graph.selectAll("g")
		.data(data);
		bars=bars
		.enter().append("g");
		bars=bars
		.attr("transform", moveBar);

	chartMoved.append("g")
		.attr("class", "x axis")
		.attr("transform", "translate(" + graphMargin.left+ "," + (diagramHeight) + ")")
		.call(xAxis);

	chartMoved.append("g")
		.attr("class", "y axis")
		.attr("transform", "translate(0," + (barMargin.bottom + graphMargin.top) +")")
		.call(yAxis);

	//draw block
	bars.append("rect")
	.attr("y", graphHeight - barMargin.bottom)
	.attr("height", 0)
	.attr("width", barWidth - barMargin.left - barMargin.right)
	//determine color
	.attr("fill","steelblue")
	//set class
	.attr("class","bar");

	//draw text (Access time)
	bars.append("text")
	.attr("x", (barWidth - barMargin.left) / 2)
	.attr("y", function (d) {return barBottom(d);})
	//adjust vertical position
	.attr("dy", "-1em")
	.text(function (d) {
		return d.Access;
	})
	//animate
var animations=d3.selectAll(".bar");
	animations
	.transition()
	.duration(1500)
	.delay(function(d,index){return index*100;})
	.ease("exp-out")
	.attr("y",function (d) {return barTop(d);})
	.attr("height",function (d) {return graphHeight - barMargin.top - barMargin.bottom - y(d.Access);});
});