--- /dev/null
+Improvements:
+
+* Auto restart spoolwatcher's watch
+
+ * use dbus to detect newly mounted drive (hard to do)
+ * spoolwatcher hangs out on jabber and accepts a "make new drive" command
+ (which runs a script to format/mount/watch the drive) (security hole)
+ * a script is added to jumpgate which does the drive formatting/mounting/etc
+ and then when finishes sends an xml-rpc message to spoolwatcher to
+ start watching again.
+
+* Change umask group for the rsync to be writable for multiple users
+ really really needs to be 002
+* the directory also needs to be set group id
+* need to make sure that there's a final rsync that finishes without coping any files
+* demon processes need to restart
+
+ * most likely solution, they should detect if there's a currently running
+ version and stop running. This'd allow a cron script to restart them
+
+* The machine to machine communication needs to be via xml-rpc
+
+ * Update benderjab and/or xmppy to send/receive xml-rpc messages
+
+* Add logging to everything
+
+ * high priority messages go out as jabber messages
+ * low priority go to disk
+ * some subset of recent messages should be stored in ram so they can
+ be retrieved by a user jabber status message (or a web page view)
+
+* Generate config files
+
+ * For goat (from brandon's web interface)
+ * For bed file generator
+
+* Need longish term storage to make generating bed and mapped read files
+ from multiple lanes on multiple flow cells
+
+* View current status page.
+
+ * once xml-rpc is working it should be easier to update the jumpgate
+ web page to report the current status of a run.
+
+ * sequencing
+ * waiting on copy (final rsync)
+ * running goat
+ * running pipeline
+ * ... (more processing)
--- /dev/null
+Conversion SQLs for Caltech DB (schema of 2008Aug08 @ 5:06 PM)
+______________________________________________________________
+
+
+Step by step do the following:
+
+''' Note: Instead of '?' you can put one of your machine names.
+sqlite> ALTER TABLE fctracker_flowcell ADD cluster_mac_id varchar(50) NOT NULL DEFAULT '?';
+sqlite> ALTER TABLE fctracker_flowcell ADD seq_mac_id varchar(50) NOT NULL DEFAULT '?';
+sqlite> ALTER TABLE fctracker_library RENAME TO PREV_fctracker_library;
+
+Now, do a syncdb. The output should look like this (assuming you have migrated to the new models.py):
+sh-3.2# pym syncdb
+Creating table fctracker_cellline
+Creating table fctracker_library
+Creating table fctracker_primer
+Creating table fctracker_antibody
+Creating table fctracker_condition
+Creating table exp_track_datarun
+Creating table exp_track_flowcell
+Creating table analys_track_project
+Creating table analys_track_task
+Creating table htsw_reports_progressreport
+Installing index for fctracker.Library model
+Failed to install index for fctracker.Library model: index fctracker_library_library_species_id already existsInstalling index for fctracker.Primer model
+Installing index for fctracker.Antibody model
+Installing index for exp_track.DataRun model
+Installing index for exp_track.FlowCell model
+Installing index for analys_track.Task model
+Installing index for htsw_reports.ProgressReport model
+sh-3.2#
+
+''' Copy all records from "fctracker_flowcell" to "exp_track_flowcell" table. (Why? Because, Flowcell table moves now from the "fctracker" to the "exp_track" component).
+sqlite> insert into experiments_flowcell select * from fctracker_flowcell;
+
+''' Now to fctracker_library, a bit more complex case
+
+'''Back to the sqlite prompt..
+sqlite> insert into samples_cellline (cellline_name,notes) values('Unknown','Unknown');
+sqlite> insert into samples_condition (condition_name,notes) values('Unknown','Unknown');
+''' Now we can put 1 in these fields for the Library insert.
+''' Note: avg_lib_size field is missing in Caltech DB (although it's in the models.py Trac), so I put default value 225.
+
+''' Now the actual migration to the new fctracker_library table
+''' (This version looses data, the current Nov 11, 2008 schema, has made_for as a one to many
+''' relationship to the auth_user table, instead of being a text field. Here I just assigned
+''' the made for to a (semi)-random user.
+sqlite> INSERT INTO samples_library (library_id,library_name,library_species_id,experiment_type,cell_line_id,condition_id,replicate,made_by,creation_date,made_for_id,stopping_point,amplified_from_sample_id,undiluted_concentration,ten_nM_dilution,successful_pM,avg_lib_size,notes) select library_id,library_name,library_species_id,'unknown',1,1,1,made_by,creation_date,12,stopping_point,amplified_from_sample_id,undiluted_concentration,ten_nM_dilution,successful_pM,0,notes from PREV_fctracker_library;
+
+''' Set the right values for "experiment_type"
+sqlite> update samples_library set experiment_type = "RNA-seq" where library_idin (select library_id from prev_fctracker_library where RNASeq = 1);
+''' YOU CAN ADD SIMILAR SQL CMD TO SET THE VALUE FOR "avg_lib_size" FIELD (WHICH IS NOW SET TO 0) ...
+
+----------------------------------------------------------------------------------------
+THAT SHOULD BE IT --- NOW YOUR WEB SITE SHOULD SUCESSFULY LOAD THE NEW DB WITH YOUR DATA.
+
+2009 Jan 13
+
+I had a working database and then merged in a few more changes from
+stanford. I ended up needing to do the following:
+
+alter table analysis_task add task_params varchar(200) null;
+alter table samples_cellline add nickname varchar(20) null;
+alter table samples_condition add nickname varchar(20) null;
+
+Those changes might happen automatically when reconverting from our
+original database, or they might not.
+
+CREATE TABLE "samples_library_tags" (
+ "id" integer NOT NULL PRIMARY KEY,
+ "library_id" varchar(30) NOT NULL REFERENCES "samples_library" ("library_id"),
+ "tag_id" integer NOT NULL REFERENCES "samples_tag" ("id"),
+ UNIQUE ("library_id", "tag_id")
+)
+;
+
--- /dev/null
+# mostly I just renamed tables
+#
+
+alter table analys_track_projects rename to analysis_projects;
+alter table analys_track_project rename to analysis_project;
+alter table analys_track_project_tasks rename to analysis_project_tasks;
+alter table analys_track_task rename to analysis_task;
+alter table exp_track_datarun rename to experiments_datarun;
+alter table exp_track_flowcell rename to experiments_flowcell;
+alter table fctracker_affiliation rename to samples_affiliation;
+alter table fctracker_antibody rename to samples_antibody;
+alter table fctracker_cellline rename to samples_cellline;
+alter table fctracker_condition rename to samples_condition;
+alter table fctracker_flowcell rename to samples_flowcell;
+alter table fctracker_library rename to samples_library;
+alter table fctracker_library_affiliations rename to samples_library_affiliations;
+alter table fctracker_library_tags rename to samples_library_tags;
+alter table fctracker_primary rename to samples_primer;
+alter table fctracker_species rename to samples_species;
+alter table fctracker_tag rename to samples_tag;
+alter table htsw_reports_progressreport rename to reports_progressreport;
--- /dev/null
+"""
+Read the made-for field and split them up into different affiliations
+while fixing the different spellings for some of our users
+"""
+import os
+
+script_dir = os.path.split(__file__)[0]
+settings_path = os.path.join(script_dir, 'htsworkflow','frontend')
+os.environ['DJANGO_SETTINGS_MODULE'] = 'htsworkflow.frontend.settings'
+
+from htsworkflow.frontend.samples import models as samples
+
+def main():
+ # names ( {'target name': ('current name', 'current name') )
+ names = [
+ 'Unknown',
+ 'Adam Rosenthal',
+ 'Adler Dillman',
+ 'Ali',
+ 'Ali/EHD',
+ 'Ali/PWS',
+ 'Andrew Medina-Marino',
+ 'Brian Williams',
+ 'Davidson',
+ 'Elowitz',
+ 'Erich Schwarz',
+ 'Georgi Warinov',
+ 'Gilberto Desalvo',
+ 'Gilberto Hernandez',
+ 'Gordon Kwan',
+ 'Hudson-Alpha',
+ 'James Puckett',
+ 'Jingli Zhang',
+ 'Ellen Rothenberg',
+ 'Jose Luis',
+ 'Katherine Fisher',
+ 'Meyerowitz',
+ 'Ryan',
+ 'Demo',
+ 'Angela Stathopoulos',
+ 'Steven Kuntz',
+ 'Tony',
+ 'Tristan',
+ 'Yuling Jiao',
+ u'Anil Ozdemir',
+ ]
+
+ name_map = {
+ '': ('Unknown',) ,
+ 'Adam Rosenthal': ('Adam Rosenthal',),
+ 'Adler Dillman': ('Adler Dillman',),
+ 'Ali': ('Ali',),
+ 'Ali/EHD': ('Ali/EHD',),
+ 'Ali/PWS': ('Ali/PWS',),
+ 'Andrew Medina-Marina': ('Andrew Medina-Marino',),
+ 'Andrew Medina-Marino': ('Andrew Medina-Marino',),
+ 'Brian': ('Brian Williams',),
+ 'Brian Williams': ('Brian Williams',),
+ 'Davidson': ('Davidson',),
+ 'Elowitz': ('Elowitz',),
+ 'Erich Schwarz': ('Erich Schwarz',),
+ 'Erich Schwartz': ('Erich Schwarz',),
+ 'Georgi Warinov': ('Georgi Warinov',),
+ 'Gilberto Desalvo': ('Gilberto Desalvo',),
+ 'Gilberto Hernandez': ('Gilberto Hernandez',),
+ 'Gordon Kwan': ('Gordon Kwan',),
+ 'Gordon': ('Gordon Kwan',),
+ 'Alpha-Hudson': ('Hudson-Alpha',),
+ 'Hudson-Alpha': ('Hudson-Alpha',),
+ 'James Puckett': ('James Puckett',),
+ 'Jingli Zhang, Rothenberg': ('Jingli Zhang', 'Ellen Rothenberg',),
+ 'Jingli Zhang': ('Jingli Zhang',),
+ 'Jose Luis': ('Jose Luis',),
+ 'Katherine Fisher': ('Katherine Fisher',),
+ 'Katherine, Gigio': ('Katherine Fisher', 'Gilberto Desalvo',),
+ 'Meyerowitz': ('Meyerowitz',),
+ 'Ryan, Demo': ('Ryan', 'Demo',),
+ 'Stathopoulos': ('Angela Stathopoulos',),
+ 'Steve Kuntz': ('Steven Kuntz',),
+ 'Steven Kuntz': ('Steven Kuntz',),
+ 'Tony': ('Tony',),
+ 'Tristan': ('Tristan',),
+ 'Yuling Jiao': ('Yuling Jiao',),
+ u'Anil Ozdemir': (u'Anil Ozdemir',),
+ }
+
+ affiliations = {}
+ for name in names:
+ aff = samples.Affiliation(name=name)
+ affiliations[name] = aff
+ aff.save()
+
+ for lib in samples.Library.objects.all():
+ made_list = name_map[lib.made_for]
+ assert type(made_list) == type((None,))
+ affiliation_list = []
+ for n in made_list:
+ lib.affiliations.add(affiliations[n])
+ lib.save()
+
+if __name__ == "__main__":
+ print "don't run this unless you know what its for"
+ print "it converts the caltech 'made_for' field into a set of"
+ print "affiliations."
+ print ""
+ print "The user lists are hard coded and exist mostly for my"
+ print "convienence."
+ main()
--- /dev/null
+import shutil
+import sqlite3
+import sys
+
+def main(cmdline=None):
+ if len(cmdline) == 1:
+ dest='/tmp/fctracker.db'
+ else:
+ dest = cmdline[1]
+ shutil.copy(cmdline[0], dest)
+ conn = sqlite3.connect(dest)
+ c = conn.cursor()
+ c.execute('drop table fctracker_elandresult');
+ c.execute('''CREATE TABLE "experiments_clusterstation" (
+ "id" integer NOT NULL PRIMARY KEY,
+ "name" varchar(50) NOT NULL UNIQUE);''')
+ c.execute('''INSERT INTO experiments_clusterstation (name) values ("station");''')
+ c.execute('''CREATE TABLE "experiments_sequencer" (
+ "id" integer NOT NULL PRIMARY KEY,
+ "name" varchar(50) NOT NULL UNIQUE);''')
+ c.execute('''INSERT INTO experiments_sequencer (name) values ("HWI-EAS229");''')
+
+ c.execute('''CREATE TABLE "experiments_flowcell" (
+ "id" integer NOT NULL PRIMARY KEY,
+ "flowcell_id" varchar(20) NOT NULL UNIQUE,
+ "run_date" datetime NOT NULL,
+ "advanced_run" bool NOT NULL,
+ "paired_end" bool NOT NULL,
+ "read_length" integer NOT NULL,
+ "lane_1_library_id" integer NOT NULL REFERENCES "samples_library" ("id"),
+ "lane_2_library_id" integer NOT NULL REFERENCES "samples_library" ("id"),
+ "lane_3_library_id" integer NOT NULL REFERENCES "samples_library" ("id"),
+ "lane_4_library_id" integer NOT NULL REFERENCES "samples_library" ("id"),
+ "lane_5_library_id" integer NOT NULL REFERENCES "samples_library" ("id"),
+ "lane_6_library_id" integer NOT NULL REFERENCES "samples_library" ("id"),
+ "lane_7_library_id" integer NOT NULL REFERENCES "samples_library" ("id"),
+ "lane_8_library_id" integer NOT NULL REFERENCES "samples_library" ("id"),
+ "lane_1_pM" decimal NOT NULL,
+ "lane_2_pM" decimal NOT NULL,
+ "lane_3_pM" decimal NOT NULL,
+ "lane_4_pM" decimal NOT NULL,
+ "lane_5_pM" decimal NOT NULL,
+ "lane_6_pM" decimal NOT NULL,
+ "lane_7_pM" decimal NOT NULL,
+ "lane_8_pM" decimal NOT NULL,
+ "lane_1_cluster_estimate" integer NULL,
+ "lane_2_cluster_estimate" integer NULL,
+ "lane_3_cluster_estimate" integer NULL,
+ "lane_4_cluster_estimate" integer NULL,
+ "lane_5_cluster_estimate" integer NULL,
+ "lane_6_cluster_estimate" integer NULL,
+ "lane_7_cluster_estimate" integer NULL,
+ "lane_8_cluster_estimate" integer NULL,
+ "cluster_station_id" integer NOT NULL REFERENCES "experiments_clusterstation" ("id"),
+ "sequencer_id" integer NOT NULL REFERENCES "experiments_sequencer" ("id"),
+ "notes" text NOT NULL
+);''')
+ c.execute('''insert into experiments_flowcell
+ (id, flowcell_id, run_date, advanced_run, paired_end, read_length,
+ lane_1_library_id, lane_2_library_id, lane_3_library_id,
+ lane_4_library_id, lane_5_library_id, lane_6_library_id,
+ lane_7_library_id, lane_8_library_id, lane_1_pm,
+ lane_2_pM, lane_3_pM, lane_4_pM, lane_5_pM, lane_6_pM,
+ lane_7_pM, lane_8_pM, lane_1_cluster_estimate,
+ lane_2_cluster_estimate, lane_3_cluster_estimate,
+ lane_4_cluster_estimate, lane_5_cluster_estimate,
+ lane_6_cluster_estimate, lane_7_cluster_estimate,
+ lane_8_cluster_estimate, cluster_station_id, sequencer_id,
+ notes)
+ select
+ id, flowcell_id, run_date, advanced_run, paired_end, read_length,
+ lane_1_library_id, lane_2_library_id, lane_3_library_id,
+ lane_4_library_id, lane_5_library_id, lane_6_library_id,
+ lane_7_library_id, lane_8_library_id, lane_1_pm,
+ lane_2_pM, lane_3_pM, lane_4_pM, lane_5_pM, lane_6_pM,
+ lane_7_pM, lane_8_pM, lane_1_cluster_estimate,
+ lane_2_cluster_estimate, lane_3_cluster_estimate,
+ lane_4_cluster_estimate, lane_5_cluster_estimate,
+ lane_6_cluster_estimate, lane_7_cluster_estimate,
+ lane_8_cluster_estimate, 1, 1,
+ notes from fctracker_flowcell;''')
+ c.execute('''drop table fctracker_flowcell;''')
+
+ # create samples.cellline
+ c.execute('''CREATE TABLE "samples_cellline" (
+ "id" integer NOT NULL PRIMARY KEY,
+ "cellline_name" varchar(100) NOT NULL UNIQUE,
+ "nickname" varchar(20) NULL,
+ "notes" text NOT NULL);''')
+ c.execute('''insert into samples_cellline (cellline_name,notes) values("Unknown","Unknown");''')
+
+ # Create samples.condition
+ c.execute('''CREATE TABLE "samples_condition" (
+ "id" integer NOT NULL PRIMARY KEY,
+ "condition_name" varchar(2000) NOT NULL UNIQUE,
+ "nickname" varchar(20) NULL,
+ "notes" text NOT NULL);''')
+ c.execute('''insert into samples_condition (condition_name,notes) values("Unknown","Unknown");''')
+
+ # create samples.experiment type
+ c.execute('''CREATE TABLE "samples_experimenttype" (
+ "id" integer NOT NULL PRIMARY KEY,
+ "name" varchar(50) NOT NULL UNIQUE);''')
+ for et in [ ('Unknown',),
+ ('ChIP-seq',),
+ ('Sheared',),
+ ('RNA-seq',),
+ ('Methyl-seq',),
+ ('DIP-seq',),
+ ('De Novo',)]:
+ c.execute('insert into samples_experimenttype (name) values (?)', et)
+
+ # create samples.library
+ c.execute('''CREATE TABLE "samples_library" (
+ "id" integer NOT NULL PRIMARY KEY,
+ "library_id" varchar(30) NOT NULL,
+ "library_name" varchar(100) NOT NULL UNIQUE,
+ "library_species_id" integer NOT NULL REFERENCES "samples_species" ("id"),
+ "hidden" bool NOT NULL,
+ "cell_line_id" integer NOT NULL REFERENCES "samples_cellline" ("id"),
+ "condition_id" integer NOT NULL REFERENCES "samples_condition" ("id"),
+ "antibody_id" integer NULL REFERENCES "samples_antibody" ("id"),
+ "replicate" smallint unsigned NOT NULL,
+ "experiment_type_id" NOT NULL REFERENCES "samples_experimenttype" ("id"),
+ "creation_date" date NULL,
+ "made_for" varchar(50) NOT NULL,
+ "made_by" varchar(50) NOT NULL,
+ "stopping_point" varchar(25) NOT NULL,
+ "amplified_from_sample_id" integer NULL,
+ "undiluted_concentration" decimal NULL,
+ "successful_pM" decimal NULL,
+ "ten_nM_dilution" bool NOT NULL,
+ "avg_lib_size" integer NULL,
+ "notes" text NOT NULL);''')
+ c.execute('''INSERT INTO samples_library
+ (id,library_id,library_name,library_species_id, hidden, experiment_type_id,
+ cell_line_id,condition_id,replicate,made_by,creation_date,
+ made_for,stopping_point,amplified_from_sample_id,
+ undiluted_concentration,ten_nM_dilution,successful_pM,
+ avg_lib_size,notes)
+select library_id,library_id,library_name,library_species_id, 0, 1,
+ 1, 1, 1, made_by,creation_date,
+ made_for,stopping_point,amplified_from_sample_id,
+ undiluted_concentration,ten_nM_dilution,successful_pM,
+ 225,notes from fctracker_library;''');
+
+ # mark gel isolates as "hidden"
+ c.execute('''update samples_library set hidden=1
+ where stopping_point = "1A" or stopping_point = "1Ab";''');
+
+ # get pk for RNA-seq experiment type
+ c.execute('select id from samples_experimenttype where name = "RNA-seq";')
+ rna_seq_id = list(c)[0]
+ # change everything marked as rnaseq to experiment_type rnaseq
+ c.execute('''update samples_library set experiment_type_id=? where library_id in (select library_id from fctracker_library where RNASeq = 1);''', rna_seq_id)
+ #c.execute('''drop table fctracker_library;''')
+
+ # add affiliation linking table
+ c.execute('''CREATE TABLE "samples_library_affiliations" (
+ "id" integer NOT NULL PRIMARY KEY,
+ "library_id" integer NOT NULL REFERENCES "samples_library" ("id"),
+ "affiliation_id" integer NOT NULL REFERENCES "samples_affiliation" ("id"),
+ UNIQUE ("library_id", "affiliation_id"));''')
+
+ # add library to tags linking table
+ c.execute('''CREATE TABLE "samples_library_tags" (
+ "id" integer NOT NULL PRIMARY KEY,
+ "library_id" integer NOT NULL REFERENCES "samples_library" ("id"),
+ "tag_id" integer NOT NULL REFERENCES "samples_tag" ("id"),
+ UNIQUE ("library_id", "tag_id"));''')
+
+
+
+ #
+ c.execute('''CREATE TABLE "samples_species" (
+ "id" integer NOT NULL PRIMARY KEY,
+ "scientific_name" varchar(256) NOT NULL,
+ "common_name" varchar(256) NOT NULL);''')
+ c.execute('''insert into samples_species
+ (id, scientific_name, common_name)
+ select
+ id, scientific_name, common_name
+ from fctracker_species;''')
+ c.execute('''drop table fctracker_species''')
+ conn.commit()
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<XMI xmlns:UML="http://schema.omg.org/spec/UML/1.3" verified="false" timestamp="2008-01-11T15:30:52" xmi.version="1.2" >
+ <XMI.header>
+ <XMI.documentation>
+ <XMI.exporter>umbrello uml modeller http://uml.sf.net</XMI.exporter>
+ <XMI.exporterVersion>1.5.8</XMI.exporterVersion>
+ <XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>
+ </XMI.documentation>
+ <XMI.metamodel xmi.name="UML" href="UML.xml" xmi.version="1.3" />
+ </XMI.header>
+ <XMI.content>
+ <UML:Model isSpecification="false" isLeaf="false" isRoot="false" xmi.id="m1" isAbstract="false" name="UML Model" >
+ <UML:Namespace.ownedElement>
+ <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="folder" isRoot="false" isAbstract="false" name="folder" />
+ <UML:Stereotype isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="datatype" isRoot="false" isAbstract="false" name="datatype" />
+ <UML:Model stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="Logical View" isRoot="false" isAbstract="false" name="Logical View" >
+ <UML:Namespace.ownedElement>
+ <UML:Package stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="Datatypes" isRoot="false" isAbstract="false" name="Datatypes" >
+ <UML:Namespace.ownedElement>
+ <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="zHGiO7QUZRiX" isRoot="false" isAbstract="false" name="int" />
+ <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="LzF7NnxDIQZy" isRoot="false" isAbstract="false" name="char" />
+ <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="rF1bLfYctE0z" isRoot="false" isAbstract="false" name="bool" />
+ <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="eTY593cV1paM" isRoot="false" isAbstract="false" name="float" />
+ <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="dYZty7spMrOf" isRoot="false" isAbstract="false" name="double" />
+ <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="UuHO7GNlhtpq" isRoot="false" isAbstract="false" name="short" />
+ <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="xPJyEuIpQpjO" isRoot="false" isAbstract="false" name="long" />
+ <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="wZCGOYvqRDEY" isRoot="false" isAbstract="false" name="unsigned int" />
+ <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="RZH8T4yOTGKi" isRoot="false" isAbstract="false" name="unsigned short" />
+ <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="AcXaREwMl6c9" isRoot="false" isAbstract="false" name="unsigned long" />
+ <UML:DataType stereotype="datatype" isSpecification="false" isLeaf="false" visibility="public" namespace="Datatypes" xmi.id="dYy4jCaAkpGB" isRoot="false" isAbstract="false" name="string" />
+ </UML:Namespace.ownedElement>
+ </UML:Package>
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="lZR99u8H0ec9" isRoot="false" isAbstract="false" name="SpoolWatcher" />
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="GkJy5VAr2ZyC" isRoot="false" isAbstract="false" name="Copier" >
+ <UML:Classifier.feature>
+ <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="74kpdjSI8Fmc" isRoot="false" isAbstract="false" isQuery="false" name="startCopy" />
+ <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="ZEGJnJU2LB4i" isRoot="false" isAbstract="false" isQuery="false" name="sequencingFinished" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter isSpecification="false" visibility="private" xmi.id="0F6mtJp0LYow" value="" type="dYy4jCaAkpGB" name="runDir" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ </UML:Classifier.feature>
+ </UML:Class>
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="0UoIUrhibyff" isRoot="false" isAbstract="false" name="Runner" >
+ <UML:Classifier.feature>
+ <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="t3UPqTGoZoip" isRoot="false" isAbstract="false" isQuery="false" name="sequencingFinished" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter isSpecification="false" visibility="private" xmi.id="RRzKx8Z14iIF" value="" type="dYy4jCaAkpGB" name="runDir" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="4yuLbdrUeJtU" isRoot="false" isAbstract="false" isQuery="false" name="pipelineFinished" >
+ <UML:BehavioralFeature.parameter>
+ <UML:Parameter isSpecification="false" visibility="private" xmi.id="n7GKuy9LN9fK" value="" type="dYy4jCaAkpGB" name="runDir" />
+ </UML:BehavioralFeature.parameter>
+ </UML:Operation>
+ </UML:Classifier.feature>
+ </UML:Class>
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="ZEsHfPFxkUD5" isRoot="false" isAbstract="false" name="Jumpgate" >
+ <UML:Classifier.feature>
+ <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="crYTwksc84xx" isRoot="false" isAbstract="false" isQuery="false" name="rsync" />
+ </UML:Classifier.feature>
+ </UML:Class>
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="Logical View" xmi.id="fOCNrWNOlFdQ" isRoot="false" isAbstract="false" name="Cellcenter" >
+ <UML:Classifier.feature>
+ <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="bKJKYukBj6Uz" isRoot="false" isAbstract="false" isQuery="false" name="configPipeline" />
+ <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="dtnBd3KDtsgp" isRoot="false" isAbstract="false" isQuery="false" name="runPipeline" />
+ </UML:Classifier.feature>
+ </UML:Class>
+ <UML:Association isSpecification="false" visibility="public" namespace="Logical View" xmi.id="YzXPgsx8JY4f" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="Xd2ysTXicS6i" aggregation="none" type="wDCVwIFrhMaS" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="iqOSoVoV96r4" aggregation="none" type="aary2tTYpejI" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ </UML:Namespace.ownedElement>
+ <XMI.extension xmi.extender="umbrello" >
+ <diagrams>
+ <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="100" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="908" snapy="10" showatts="1" xmi.id="qsXVOiQh2k6g" documentation="" type="1" showops="1" showpackage="0" name="class diagram" localid="" showstereotype="0" showscope="1" snapcsgrid="0" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="598" >
+ <widgets/>
+ <messages/>
+ <associations/>
+ </diagram>
+ <diagram snapgrid="1" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="100" showgrid="1" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="908" snapy="10" showatts="1" xmi.id="ngoLeq2pOCZE" documentation="" type="3" showops="1" showpackage="0" name="Automation Messages" localid="dqOLIZOnXkGB" showstereotype="0" showscope="1" snapcsgrid="0" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="598" >
+ <widgets>
+ <objectwidget usesdiagramfillcolor="0" width="112" x="150" fillcolor="#ffffc0" y="50" instancename="" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="lZR99u8H0ec9" decon="0" localid="5MaOitMlK05R" multipleinstance="0" drawasactor="0" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,1,0,0,0" linecolor="#ff0000" />
+ <objectwidget usesdiagramfillcolor="0" width="64" x="300" fillcolor="#ffffc0" y="50" instancename="" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="GkJy5VAr2ZyC" decon="0" localid="R6RQi1ZnL9A3" multipleinstance="0" drawasactor="0" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,1,0,0,0" linecolor="#ff0000" />
+ <objectwidget usesdiagramfillcolor="0" width="68" x="420" fillcolor="#ffffc0" y="50" instancename="" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="0UoIUrhibyff" decon="0" localid="RnWUKUelY3BH" multipleinstance="0" drawasactor="0" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,1,0,0,0" linecolor="#ff0000" />
+ <objectwidget usesdiagramfillcolor="0" width="84" x="40" fillcolor="#ffffc0" y="50" instancename="" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="ZEsHfPFxkUD5" decon="0" localid="X0MTdrbPt7CP" multipleinstance="0" drawasactor="0" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,1,0,0,0" linecolor="#ff0000" />
+ <objectwidget usesdiagramfillcolor="0" width="88" x="550" fillcolor="#ffffc0" y="50" instancename="" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="fOCNrWNOlFdQ" decon="0" localid="dqOLIZOnXkGB" multipleinstance="0" drawasactor="0" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,1,0,0,0" linecolor="#ff0000" />
+ <notewidget usesdiagramfillcolor="1" width="84" x="610" fillcolor="none" y="320" linewidth="none" height="50" usefillcolor="1" isinstance="0" xmi.id="yQmtlfQN4OB7" text="Other Analysis" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </widgets>
+ <messages>
+ <messagewidget usesdiagramfillcolor="1" width="124" x="207" fillcolor="none" y="122" operation="74kpdjSI8Fmc" linewidth="none" widgetbid="R6RQi1ZnL9A3" height="8" usefillcolor="1" seqnum="" textid="nCbzGolht3FI" widgetaid="5MaOitMlK05R" isinstance="0" xmi.id="74kpdjSI8Fmc" sequencemessagetype="1001" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" >
+ <floatingtext usesdiagramfillcolor="1" width="89" x="210" fillcolor="none" y="100" linewidth="none" posttext="" role="704" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="nCbzGolht3FI" text=": startCopy()" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </messagewidget>
+ <messagewidget usesdiagramfillcolor="1" width="124" x="207" fillcolor="none" y="156" operation="74kpdjSI8Fmc" linewidth="none" widgetbid="R6RQi1ZnL9A3" height="8" usefillcolor="1" seqnum="" textid="6DI3dhqqGq64" widgetaid="5MaOitMlK05R" isinstance="0" xmi.id="74kpdjSI8Fmc" sequencemessagetype="1001" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" >
+ <floatingtext usesdiagramfillcolor="1" width="89" x="210" fillcolor="none" y="130" linewidth="none" posttext="" role="704" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="6DI3dhqqGq64" text=": startCopy()" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </messagewidget>
+ <messagewidget usesdiagramfillcolor="1" width="124" x="207" fillcolor="none" y="211" operation="74kpdjSI8Fmc" linewidth="none" widgetbid="R6RQi1ZnL9A3" height="8" usefillcolor="1" seqnum="" textid="HQIrp1PvEiws" widgetaid="5MaOitMlK05R" isinstance="0" xmi.id="74kpdjSI8Fmc" sequencemessagetype="1001" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" >
+ <floatingtext usesdiagramfillcolor="1" width="89" x="230" fillcolor="none" y="190" linewidth="none" posttext="" role="704" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="HQIrp1PvEiws" text=": startCopy()" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </messagewidget>
+ <messagewidget usesdiagramfillcolor="1" width="124" x="207" fillcolor="none" y="253" operation="ZEGJnJU2LB4i" linewidth="none" widgetbid="R6RQi1ZnL9A3" height="8" usefillcolor="1" seqnum="" textid="fVIZsE2zucZA" widgetaid="5MaOitMlK05R" isinstance="0" xmi.id="ZEGJnJU2LB4i" sequencemessagetype="1001" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" >
+ <floatingtext usesdiagramfillcolor="1" width="243" x="210" fillcolor="none" y="230" linewidth="none" posttext="" role="704" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="fVIZsE2zucZA" text=": sequencingFinished(runDir : string)" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </messagewidget>
+ <messagewidget usesdiagramfillcolor="1" width="120" x="333" fillcolor="none" y="282" operation="t3UPqTGoZoip" linewidth="none" widgetbid="RnWUKUelY3BH" height="8" usefillcolor="1" seqnum="" textid="uyOuUAqAf6hV" widgetaid="R6RQi1ZnL9A3" isinstance="0" xmi.id="t3UPqTGoZoip" sequencemessagetype="1001" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" >
+ <floatingtext usesdiagramfillcolor="1" width="243" x="340" fillcolor="none" y="260" linewidth="none" posttext="" role="704" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="uyOuUAqAf6hV" text=": sequencingFinished(runDir : string)" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </messagewidget>
+ <messagewidget usesdiagramfillcolor="1" width="258" x="74" fillcolor="none" y="243" operation="crYTwksc84xx" linewidth="none" widgetbid="X0MTdrbPt7CP" height="32" usefillcolor="1" seqnum="" textid="R4DtGIV3Lxs4" widgetaid="R6RQi1ZnL9A3" isinstance="0" xmi.id="crYTwksc84xx" sequencemessagetype="1000" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" >
+ <floatingtext usesdiagramfillcolor="1" width="61" x="80" fillcolor="none" y="220" linewidth="none" posttext="" role="704" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="R4DtGIV3Lxs4" text=": rsync()" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </messagewidget>
+ <messagewidget usesdiagramfillcolor="1" width="138" x="455" fillcolor="none" y="302" operation="bKJKYukBj6Uz" linewidth="none" widgetbid="dqOLIZOnXkGB" height="8" usefillcolor="1" seqnum="" textid="jD2f9bGadRRu" widgetaid="RnWUKUelY3BH" isinstance="0" xmi.id="bKJKYukBj6Uz" sequencemessagetype="1001" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" >
+ <floatingtext usesdiagramfillcolor="1" width="118" x="460" fillcolor="none" y="280" linewidth="none" posttext="" role="704" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="jD2f9bGadRRu" text=": configPipeline()" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </messagewidget>
+ <messagewidget usesdiagramfillcolor="1" width="138" x="455" fillcolor="none" y="330" operation="dtnBd3KDtsgp" linewidth="none" widgetbid="dqOLIZOnXkGB" height="8" usefillcolor="1" seqnum="" textid="oy8nMfs4rsj0" widgetaid="RnWUKUelY3BH" isinstance="0" xmi.id="dtnBd3KDtsgp" sequencemessagetype="1001" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" >
+ <floatingtext usesdiagramfillcolor="1" width="99" x="470" fillcolor="none" y="310" linewidth="none" posttext="" role="704" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="oy8nMfs4rsj0" text=": runPipeline()" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </messagewidget>
+ <messagewidget usesdiagramfillcolor="1" width="258" x="74" fillcolor="none" y="145" operation="crYTwksc84xx" linewidth="none" widgetbid="X0MTdrbPt7CP" height="32" usefillcolor="1" seqnum="" textid="VoaFYvDhgi96" widgetaid="R6RQi1ZnL9A3" isinstance="0" xmi.id="crYTwksc84xx" sequencemessagetype="1000" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" >
+ <floatingtext usesdiagramfillcolor="1" width="61" x="80" fillcolor="none" y="120" linewidth="none" posttext="" role="704" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="VoaFYvDhgi96" text=": rsync()" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </messagewidget>
+ </messages>
+ <associations/>
+ </diagram>
+ <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="100" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="908" snapy="10" showatts="1" xmi.id="RiyrnSAT4B8Q" documentation="" type="6" showops="1" showpackage="0" name="Workflow" localid="" showstereotype="0" showscope="1" snapcsgrid="0" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="598" >
+ <widgets>
+ <activitywidget usesdiagramfillcolor="1" width="18" activityname="" x="339" fillcolor="none" y="42" linewidth="none" height="18" usefillcolor="1" isinstance="0" xmi.id="nDqhFC5OuUo0" documentation="" activitytype="2" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <activitywidget usesdiagramfillcolor="1" width="85" activityname="Sequencing" x="306" fillcolor="none" y="92" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="cmmyYRDzACpv" documentation="" activitytype="1" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <activitywidget usesdiagramfillcolor="0" width="199" activityname="Copy Files to Analysis Server" x="250" fillcolor="#ffffc0" y="215" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="cxOg8W7uhvbu" documentation="" activitytype="1" usesdiagramusefillcolor="0" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="#ff0000" />
+ <activitywidget usesdiagramfillcolor="1" width="91" activityname="Run Pipeline" x="303" fillcolor="none" y="273" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="DvKN59Gi6eMD" documentation="" activitytype="1" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <activitywidget usesdiagramfillcolor="1" width="157" activityname="Write to external drive" x="271" fillcolor="none" y="154" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="9R7qMgjRKzQT" documentation="" activitytype="1" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <activitywidget usesdiagramfillcolor="1" width="142" activityname="Move External Drive" x="501" fillcolor="none" y="154" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="BvRo4ZPN3mCG" documentation="" activitytype="1" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <activitywidget usesdiagramfillcolor="1" width="89" activityname="Install Drive" x="136" fillcolor="none" y="153" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="5eRwnFjqlrtq" documentation="" activitytype="1" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <activitywidget usesdiagramfillcolor="1" width="77" activityname="Save Data" x="523" fillcolor="none" y="264" linewidth="none" height="28" usefillcolor="1" isinstance="0" xmi.id="aBdJn5SgWGi6" documentation="" activitytype="1" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </widgets>
+ <messages/>
+ <associations>
+ <assocwidget totalcounta="2" indexa="1" visibilityB="200" totalcountb="2" indexb="1" linewidth="none" widgetbid="nDqhFC5OuUo0" widgetaid="cmmyYRDzACpv" roleBdoc="" documentation="" roleAdoc="" type="515" changeabilityA="900" changeabilityB="900" linecolor="none" visibilityA="200" >
+ <linepath>
+ <startpoint startx="348" starty="92" />
+ <endpoint endx="348" endy="60" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" visibilityB="200" totalcountb="2" indexb="1" linewidth="none" widgetbid="cmmyYRDzACpv" widgetaid="9R7qMgjRKzQT" roleBdoc="" documentation="" roleAdoc="" type="515" changeabilityA="900" changeabilityB="900" linecolor="none" visibilityA="200" >
+ <linepath>
+ <startpoint startx="349" starty="154" />
+ <endpoint endx="348" endy="120" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" visibilityB="200" totalcountb="2" indexb="1" linewidth="none" widgetbid="9R7qMgjRKzQT" widgetaid="cxOg8W7uhvbu" roleBdoc="" documentation="" roleAdoc="" type="515" changeabilityA="900" changeabilityB="900" linecolor="none" visibilityA="200" >
+ <linepath>
+ <startpoint startx="349" starty="215" />
+ <endpoint endx="349" endy="182" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" visibilityB="200" totalcountb="2" indexb="1" linewidth="none" widgetbid="cxOg8W7uhvbu" widgetaid="DvKN59Gi6eMD" roleBdoc="" documentation="" roleAdoc="" type="515" changeabilityA="900" changeabilityB="900" linecolor="none" visibilityA="200" >
+ <linepath>
+ <startpoint startx="348" starty="273" />
+ <endpoint endx="349" endy="243" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" visibilityB="200" totalcountb="2" indexb="1" linewidth="none" widgetbid="9R7qMgjRKzQT" widgetaid="BvRo4ZPN3mCG" roleBdoc="" documentation="" roleAdoc="" type="515" changeabilityA="900" changeabilityB="900" linecolor="none" visibilityA="200" >
+ <linepath>
+ <startpoint startx="501" starty="168" />
+ <endpoint endx="428" endy="168" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" visibilityB="200" totalcountb="2" indexb="1" linewidth="none" widgetbid="9R7qMgjRKzQT" widgetaid="5eRwnFjqlrtq" roleBdoc="" documentation="" roleAdoc="" type="515" changeabilityA="900" changeabilityB="900" linecolor="none" visibilityA="200" >
+ <linepath>
+ <startpoint startx="225" starty="167" />
+ <endpoint endx="271" endy="168" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" visibilityB="200" totalcountb="2" indexb="1" linewidth="none" widgetbid="DvKN59Gi6eMD" widgetaid="aBdJn5SgWGi6" roleBdoc="" documentation="" roleAdoc="" type="515" changeabilityA="900" changeabilityB="900" linecolor="none" visibilityA="200" >
+ <linepath>
+ <startpoint startx="523" starty="278" />
+ <endpoint endx="394" endy="287" />
+ </linepath>
+ </assocwidget>
+ </associations>
+ </diagram>
+ </diagrams>
+ </XMI.extension>
+ </UML:Model>
+ <UML:Model stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="Use Case View" isRoot="false" isAbstract="false" name="Use Case View" >
+ <UML:Namespace.ownedElement>
+ <UML:Actor isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="wDCVwIFrhMaS" isRoot="false" isAbstract="false" name="Operator" />
+ <UML:UseCase comment="Provide information about whats on the flow cell" isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="aary2tTYpejI" isRoot="false" isAbstract="false" name="Record Flowcell" />
+ <UML:UseCase isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="v00EW2tPUmHx" isRoot="false" isAbstract="false" name="Load Flowcell" />
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="D32Eg5GAZoTf" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="im2Ma7pqk1go" aggregation="none" type="wDCVwIFrhMaS" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="JGXPBjJbeiAi" aggregation="none" type="v00EW2tPUmHx" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:Actor isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="xXmvstAj2F1b" isRoot="false" isAbstract="false" name="Scientist" />
+ <UML:UseCase isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="6W9A6jRKMyiY" isRoot="false" isAbstract="false" name="Invent Experiment" />
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="HXNdOVEJ2yFu" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="yITcydItLy4l" aggregation="none" type="xXmvstAj2F1b" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="a9t0EMzPekMx" aggregation="none" type="6W9A6jRKMyiY" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:Actor isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="zIN0Fcs4yUuY" isRoot="false" isAbstract="false" name="Tech" />
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="6IDDq0N6EshP" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="sAgD6kygrqe4" aggregation="none" type="6W9A6jRKMyiY" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="CcTqMqnYuKTD" aggregation="none" type="zIN0Fcs4yUuY" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:UseCase isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="RAZe0E33zvnD" isRoot="false" isAbstract="false" name="Make Library/Flowcell" />
+ <UML:UseCase isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="pbO2oXRaYvK4" isRoot="false" isAbstract="false" name="Run Sequencer" />
+ <UML:UseCase isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="Fbgs2TKUbr8c" isRoot="false" isAbstract="false" name="Analyze Results" />
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="5Bd35QEuzaun" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="oOnDUNhItqyD" aggregation="none" type="zIN0Fcs4yUuY" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="agjwu5fvAtpc" aggregation="none" type="RAZe0E33zvnD" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="1pz0NtlUD78R" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="btsXOnyABmNd" aggregation="none" type="RAZe0E33zvnD" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="72tyrqBRWuOO" aggregation="none" type="pbO2oXRaYvK4" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="wf97mFWW4OYF" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="x1K7u7hTya0K" aggregation="none" type="zIN0Fcs4yUuY" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="LxUWjq7qsyoj" aggregation="none" type="pbO2oXRaYvK4" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:UseCase isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="0WdsQGkGLh4j" isRoot="false" isAbstract="false" name="Run Pipeline" />
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="emmY8xZHM4vp" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="6Zs37qLSnowW" aggregation="none" type="pbO2oXRaYvK4" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="e3KU18Co5L7u" aggregation="none" type="0WdsQGkGLh4j" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="v4mH9h65lcXr" name="pipelineFinished" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="qogMqYmu7cvE" aggregation="none" type="0WdsQGkGLh4j" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="THgG5cnhd59c" aggregation="none" type="Fbgs2TKUbr8c" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="m2hVcDMd6HZv" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="ELOHeVCUKsq8" aggregation="none" type="Fbgs2TKUbr8c" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="Ob2VDwhgBNvG" aggregation="none" type="xXmvstAj2F1b" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:Actor isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="orBOqPqaQhh9" isRoot="false" isAbstract="false" name="Unix Operator" />
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="zrptlXTBrDvp" name="sequencerFinished" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="3RTNHJVgsVB4" aggregation="none" type="pbO2oXRaYvK4" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="PtiaEdoAHji3" aggregation="none" type="orBOqPqaQhh9" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="x3IpEDeI7z8A" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="mr08PF6QeZnu" aggregation="none" type="orBOqPqaQhh9" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="rGajljlBaUln" aggregation="none" type="0WdsQGkGLh4j" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:UseCase isSpecification="false" isLeaf="false" visibility="public" namespace="Use Case View" xmi.id="fRDOlDmrPkQK" isRoot="false" isAbstract="false" name="Add experiment to FCTracker" />
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="W1lC1TWN9J6x" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="uOynvlhbBsxw" aggregation="none" type="RAZe0E33zvnD" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="4jnTTClxDUAD" aggregation="none" type="fRDOlDmrPkQK" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="xgY5yc2s10ew" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="mJVvCSrEBdhd" aggregation="none" type="fRDOlDmrPkQK" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="nQayukBpPiuN" aggregation="none" type="pbO2oXRaYvK4" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ <UML:Association isSpecification="false" visibility="public" namespace="Use Case View" xmi.id="KuDJvrGfBlaL" name="" >
+ <UML:Association.connection>
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="CPZN0EyncZmU" aggregation="none" type="pbO2oXRaYvK4" name="" />
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="HvJedC1y6DHz" aggregation="none" type="orBOqPqaQhh9" name="" />
+ </UML:Association.connection>
+ </UML:Association>
+ </UML:Namespace.ownedElement>
+ <XMI.extension xmi.extender="umbrello" >
+ <diagrams>
+ <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="100" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="908" snapy="10" showatts="1" xmi.id="chIzX4xQS4VY" documentation="" type="2" showops="1" showpackage="0" name="Basic Pipeline Use" localid="" showstereotype="0" showscope="1" snapcsgrid="0" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="598" >
+ <widgets>
+ <actorwidget usesdiagramfillcolor="1" width="66" x="114" fillcolor="none" y="41" linewidth="none" height="63" usefillcolor="1" isinstance="0" xmi.id="xXmvstAj2F1b" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <usecasewidget usesdiagramfillcolor="1" width="144" x="227" fillcolor="none" y="35" linewidth="none" height="53" usefillcolor="1" isinstance="0" xmi.id="6W9A6jRKMyiY" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <actorwidget usesdiagramfillcolor="1" width="41" x="405" fillcolor="none" y="44" linewidth="none" height="63" usefillcolor="1" isinstance="0" xmi.id="zIN0Fcs4yUuY" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <usecasewidget usesdiagramfillcolor="0" width="169" x="423" fillcolor="#ffffc0" y="117" linewidth="none" height="53" usefillcolor="1" isinstance="0" xmi.id="RAZe0E33zvnD" usesdiagramusefillcolor="0" font="Sans Serif,8,-1,5,75,0,0,0,0,0" linecolor="#ff0000" />
+ <usecasewidget usesdiagramfillcolor="1" width="120" x="435" fillcolor="none" y="326" linewidth="none" height="53" usefillcolor="1" isinstance="0" xmi.id="pbO2oXRaYvK4" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,75,0,0,0,0,0" linecolor="none" />
+ <usecasewidget usesdiagramfillcolor="1" width="126" x="68" fillcolor="none" y="142" linewidth="none" height="53" usefillcolor="1" isinstance="0" xmi.id="Fbgs2TKUbr8c" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <usecasewidget usesdiagramfillcolor="1" width="101" x="136" fillcolor="none" y="304" linewidth="none" height="53" usefillcolor="1" isinstance="0" xmi.id="0WdsQGkGLh4j" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <actorwidget usesdiagramfillcolor="1" width="101" x="309" fillcolor="none" y="325" linewidth="none" height="63" usefillcolor="1" isinstance="0" xmi.id="orBOqPqaQhh9" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <notewidget usesdiagramfillcolor="1" width="134" x="302" fillcolor="none" y="394" linewidth="none" height="79" usefillcolor="1" isinstance="0" xmi.id="FKXM4QcNkVr5" text="GAWorkflow Replaces this person" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <notewidget usesdiagramfillcolor="1" width="144" x="187" fillcolor="none" y="253" linewidth="none" height="50" usefillcolor="1" isinstance="0" xmi.id="t032iSzd0y7F" text="Solexa Pipeline" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <notewidget usesdiagramfillcolor="1" width="95" x="13" fillcolor="none" y="201" linewidth="none" height="88" usefillcolor="1" isinstance="0" xmi.id="5fYgSqBh8i2C" text="Peak Calling, MRPM, etc." usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ <usecasewidget usesdiagramfillcolor="1" width="226" x="418" fillcolor="none" y="226" linewidth="none" height="53" usefillcolor="1" isinstance="0" xmi.id="fRDOlDmrPkQK" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </widgets>
+ <messages/>
+ <associations>
+ <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="6W9A6jRKMyiY" widgetaid="xXmvstAj2F1b" xmi.id="HXNdOVEJ2yFu" type="512" linecolor="none" >
+ <linepath>
+ <startpoint startx="180" starty="72" />
+ <endpoint endx="227" endy="61" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="zIN0Fcs4yUuY" widgetaid="6W9A6jRKMyiY" xmi.id="6IDDq0N6EshP" type="512" linecolor="none" >
+ <linepath>
+ <startpoint startx="371" starty="61" />
+ <endpoint endx="405" endy="75" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="RAZe0E33zvnD" widgetaid="zIN0Fcs4yUuY" xmi.id="5Bd35QEuzaun" type="512" linecolor="none" >
+ <linepath>
+ <startpoint startx="446" starty="75" />
+ <endpoint endx="507" endy="117" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="Fbgs2TKUbr8c" widgetaid="0WdsQGkGLh4j" xmi.id="v4mH9h65lcXr" type="512" linecolor="none" >
+ <linepath>
+ <startpoint startx="186" starty="304" />
+ <endpoint endx="131" endy="195" />
+ <point x="147" y="245" />
+ </linepath>
+ <floatingtext usesdiagramfillcolor="1" width="114" x="140" fillcolor="none" y="244" linewidth="none" posttext="" role="703" height="22" usefillcolor="1" pretext="" isinstance="0" xmi.id="5YxNFdO1TO7q" text="pipelineFinished" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="none" />
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="xXmvstAj2F1b" widgetaid="Fbgs2TKUbr8c" xmi.id="m2hVcDMd6HZv" type="512" linecolor="none" >
+ <linepath>
+ <startpoint startx="131" starty="142" />
+ <endpoint endx="147" endy="104" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="0WdsQGkGLh4j" widgetaid="orBOqPqaQhh9" xmi.id="x3IpEDeI7z8A" type="512" linecolor="none" >
+ <linepath>
+ <startpoint startx="309" starty="356" />
+ <endpoint endx="237" endy="330" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="fRDOlDmrPkQK" widgetaid="RAZe0E33zvnD" xmi.id="W1lC1TWN9J6x" type="512" linecolor="none" >
+ <linepath>
+ <startpoint startx="507" starty="170" />
+ <endpoint endx="531" endy="226" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="pbO2oXRaYvK4" widgetaid="fRDOlDmrPkQK" xmi.id="xgY5yc2s10ew" type="512" linecolor="none" >
+ <linepath>
+ <startpoint startx="531" starty="279" />
+ <endpoint endx="495" endy="326" />
+ </linepath>
+ </assocwidget>
+ <assocwidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="orBOqPqaQhh9" widgetaid="pbO2oXRaYvK4" xmi.id="KuDJvrGfBlaL" type="512" linecolor="none" >
+ <linepath>
+ <startpoint startx="435" starty="352" />
+ <endpoint endx="410" endy="356" />
+ </linepath>
+ </assocwidget>
+ </associations>
+ </diagram>
+ </diagrams>
+ </XMI.extension>
+ </UML:Model>
+ <UML:Model stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="Component View" isRoot="false" isAbstract="false" name="Component View" >
+ <UML:Namespace.ownedElement/>
+ </UML:Model>
+ <UML:Model stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="Deployment View" isRoot="false" isAbstract="false" name="Deployment View" >
+ <UML:Namespace.ownedElement>
+ <UML:Node isSpecification="false" isLeaf="false" visibility="public" namespace="Deployment View" xmi.id="vP7jn92WuoSw" isRoot="false" isAbstract="false" name="Cellcenter" />
+ </UML:Namespace.ownedElement>
+ <XMI.extension xmi.extender="umbrello" >
+ <diagrams>
+ <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="100" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="908" snapy="10" showatts="1" xmi.id="tO955ukeZk7l" documentation="" type="8" showops="1" showpackage="0" name="Caltech GAWorkflow" localid="" showstereotype="0" showscope="1" snapcsgrid="0" font="Sans Serif,8,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="598" >
+ <widgets>
+ <nodewidget usesdiagramfillcolor="1" width="104" x="296" fillcolor="none" y="179" linewidth="none" height="66" usefillcolor="1" isinstance="0" xmi.id="vP7jn92WuoSw" usesdiagramusefillcolor="1" font="Sans Serif,8,-1,5,75,0,0,0,0,0" linecolor="none" />
+ </widgets>
+ <messages/>
+ <associations/>
+ </diagram>
+ </diagrams>
+ </XMI.extension>
+ </UML:Model>
+ <UML:Model stereotype="folder" isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="Entity Relationship Model" isRoot="false" isAbstract="false" name="Entity Relationship Model" >
+ <UML:Namespace.ownedElement/>
+ </UML:Model>
+ </UML:Namespace.ownedElement>
+ </UML:Model>
+ </XMI.content>
+ <XMI.extensions xmi.extender="umbrello" >
+ <docsettings viewid="chIzX4xQS4VY" documentation="" uniqueid="HvJedC1y6DHz" />
+ <listview>
+ <listitem open="1" type="800" label="Views" >
+ <listitem open="0" type="801" id="Logical View" >
+ <listitem open="0" type="807" id="qsXVOiQh2k6g" label="class diagram" />
+ <listitem open="0" type="809" id="RiyrnSAT4B8Q" label="Workflow" />
+ <listitem open="0" type="810" id="ngoLeq2pOCZE" label="Automation Messages" />
+ <listitem open="1" type="813" id="fOCNrWNOlFdQ" >
+ <listitem open="0" type="815" id="bKJKYukBj6Uz" />
+ <listitem open="0" type="815" id="dtnBd3KDtsgp" />
+ </listitem>
+ <listitem open="1" type="813" id="GkJy5VAr2ZyC" >
+ <listitem open="0" type="815" id="74kpdjSI8Fmc" />
+ <listitem open="0" type="815" id="ZEGJnJU2LB4i" />
+ </listitem>
+ <listitem open="1" type="813" id="ZEsHfPFxkUD5" >
+ <listitem open="0" type="815" id="crYTwksc84xx" />
+ </listitem>
+ <listitem open="1" type="813" id="0UoIUrhibyff" >
+ <listitem open="0" type="815" id="t3UPqTGoZoip" />
+ <listitem open="0" type="815" id="4yuLbdrUeJtU" />
+ </listitem>
+ <listitem open="1" type="813" id="lZR99u8H0ec9" />
+ <listitem open="0" type="830" id="Datatypes" >
+ <listitem open="1" type="829" id="rF1bLfYctE0z" />
+ <listitem open="1" type="829" id="LzF7NnxDIQZy" />
+ <listitem open="1" type="829" id="dYZty7spMrOf" />
+ <listitem open="1" type="829" id="eTY593cV1paM" />
+ <listitem open="1" type="829" id="zHGiO7QUZRiX" />
+ <listitem open="1" type="829" id="xPJyEuIpQpjO" />
+ <listitem open="1" type="829" id="UuHO7GNlhtpq" />
+ <listitem open="1" type="829" id="dYy4jCaAkpGB" />
+ <listitem open="1" type="829" id="wZCGOYvqRDEY" />
+ <listitem open="1" type="829" id="AcXaREwMl6c9" />
+ <listitem open="1" type="829" id="RZH8T4yOTGKi" />
+ </listitem>
+ </listitem>
+ <listitem open="1" type="802" id="Use Case View" >
+ <listitem open="0" type="805" id="chIzX4xQS4VY" label="Basic Pipeline Use" />
+ <listitem open="1" type="811" id="wDCVwIFrhMaS" />
+ <listitem open="1" type="811" id="xXmvstAj2F1b" />
+ <listitem open="1" type="811" id="zIN0Fcs4yUuY" />
+ <listitem open="1" type="811" id="orBOqPqaQhh9" />
+ <listitem open="1" type="812" id="fRDOlDmrPkQK" />
+ <listitem open="1" type="812" id="Fbgs2TKUbr8c" />
+ <listitem open="1" type="812" id="6W9A6jRKMyiY" />
+ <listitem open="1" type="812" id="v00EW2tPUmHx" />
+ <listitem open="1" type="812" id="RAZe0E33zvnD" />
+ <listitem open="1" type="812" id="aary2tTYpejI" />
+ <listitem open="1" type="812" id="0WdsQGkGLh4j" />
+ <listitem open="1" type="812" id="pbO2oXRaYvK4" />
+ </listitem>
+ <listitem open="1" type="821" id="Component View" />
+ <listitem open="1" type="827" id="Deployment View" >
+ <listitem open="0" type="825" id="tO955ukeZk7l" label="Caltech GAWorkflow" />
+ <listitem open="1" type="828" id="vP7jn92WuoSw" />
+ </listitem>
+ <listitem open="1" type="836" id="Entity Relationship Model" />
+ </listitem>
+ </listview>
+ <codegeneration>
+ <codegenerator language="C++" />
+ </codegeneration>
+ </XMI.extensions>
+</XMI>
--- /dev/null
+[frontend]
+; database engine, currently only sqlite3 will work right
+database_engine=sqlite3
+; location of the sqlite3 database
+database_name=/htsworkflow/htswfrontend/dev_tracker.db
+
+; settings for what email server to use
+email_host = localhost
+email_port = 25
+
+; default timezone for this server
+time_zone = America/Los_Angels
+
+; set the default picomolarity when creating a new flowcell
+default_pm = 5
+
+
+[allowed_hosts]
+localhost=localhost
+
+[allowed_analysis_hosts]
+localhost=localhost
--- /dev/null
+import ConfigParser
+import copy
+import logging
+import logging.handlers
+import os
+import re
+import shlex
+import subprocess
+import sys
+import time
+import traceback
+
+from benderjab import rpc
+
+def runfolder_validate(fname):
+ """
+ Return True if fname looks like a runfolder name
+ """
+ if re.match("^[0-9]{6}_[-A-Za-z0-9_]*$", fname):
+ return True
+ else:
+ return False
+
+class rsync(object):
+ def __init__(self, sources, dest, pwfile):
+ self.cmd = ['/usr/bin/rsync', ]
+ self.pwfile = os.path.expanduser(pwfile)
+ self.cmd.append('--password-file=%s' % (self.pwfile))
+ self.source_base_list = [ self._normalize_rsync_source(x) for x in sources]
+ self.dest_base = dest
+ self.processes = {}
+ self.exit_code = None
+
+ def list(self):
+ """
+ Get a directory listing for all our sources
+ """
+ logging.debug("searching for entries in: %s" % (self.source_base_list,))
+ entries = []
+ for source in self.source_base_list:
+ logging.debug("Scanning %s" % (source,))
+ args = copy.copy(self.cmd)
+ args.append(source)
+
+ logging.debug("Rsync cmd:" + " ".join(args))
+ short_process = subprocess.Popen(args, stdout=subprocess.PIPE)
+ exit_code = short_process.wait()
+ stdout = short_process.stdout
+ # We made sure source ends in a / earlier
+ cur_list = [ source+subdir for subdir in self.list_filter(stdout)]
+ entries.extend(cur_list)
+ logging.debug(u"Found the following: %s" % (unicode(entries)))
+ return entries
+
+ def list_filter(self, lines):
+ """
+ parse rsync directory listing
+ """
+ dirs_to_copy = []
+ direntries = [ x[0:42].split() + [x[43:-1]] for x in lines ]
+ logging.debug(u'direntries: %s' % (unicode(direntries),))
+ for permissions, size, filedate, filetime, filename in direntries:
+ if permissions[0] == 'd':
+ # hey its a directory, the first step to being something we want to
+ # copy
+ if re.match("[0-9]{6}", filename):
+ # it starts with something that looks like a 6 digit date
+ # aka good enough for me
+ dirs_to_copy.append(filename)
+ return dirs_to_copy
+
+ def create_copy_process(self, urlname):
+ args = copy.copy(self.cmd)
+ # args.append('--dry-run') # Makes testing easier
+ # we want to copy everything
+ args.append('-rlt')
+ # from here
+ args.append(urlname)
+ # to here
+ args.append(self.dest_base)
+ logging.debug("Rsync cmd:" + " ".join(args))
+ return subprocess.Popen(args)
+
+ def copy(self):
+ """
+ copy any interesting looking directories over
+ return list of items that we started copying.
+ """
+ # clean up any lingering non-running processes
+ self.poll()
+
+ # what's available to copy?
+ dirs_to_copy = self.list()
+
+ # lets start copying
+ started = []
+ for d in dirs_to_copy:
+ process = self.processes.get(d, None)
+
+ if process is None:
+ # we don't have a process, so make one
+ logging.info("rsyncing %s" % (d))
+ self.processes[d] = self.create_copy_process(d)
+ started.append(d)
+ return started
+
+ def _normalize_rsync_source(self, source):
+ """
+ Make sure that we have a reasonable looking source
+ a source must be a directory/collection.
+ """
+ # we must be a directory
+ if source[-1] != '/':
+ source += '/'
+ # I suppose we could check to see if we start with rsync:// or something
+ return source
+
+ def poll(self):
+ """
+ check currently running processes to see if they're done
+
+ return path roots that have finished.
+ """
+ for dir_key, proc_value in self.processes.items():
+ retcode = proc_value.poll()
+ if retcode is None:
+ # process hasn't finished yet
+ pass
+ elif retcode == 0:
+ logging.info("finished rsyncing %s, exitcode %d" %( dir_key, retcode))
+ del self.processes[dir_key]
+ else:
+ logging.error("rsync failed for %s, exit code %d" % (dir_key, retcode))
+
+ def __len__(self):
+ """
+ Return how many active rsync processes we currently have
+
+ Call poll first to close finished processes.
+ """
+ return len(self.processes)
+
+ def keys(self):
+ """
+ Return list of current run folder names
+ """
+ return self.processes.keys()
+
+class CopierBot(rpc.XmlRpcBot):
+ def __init__(self, section=None, configfile=None):
+ #if configfile is None:
+ # configfile = '~/.htsworkflow'
+
+ super(CopierBot, self).__init__(section, configfile)
+
+ # options for rsync command
+ self.cfg['rsync_password_file'] = None
+ self.cfg['rsync_source'] = None
+ self.cfg['rsync_destination'] = None
+
+ # options for reporting we're done
+ self.cfg['notify_users'] = None
+ self.cfg['notify_runner'] = None
+
+ self.pending = []
+ self.rsync = None
+ self.notify_users = None
+ self.notify_runner = None
+
+ self.register_function(self.startCopy)
+ self.register_function(self.sequencingFinished)
+ self.eventTasks.append(self.update)
+
+ def _init_rsync(self):
+ """
+ Initalize rsync class
+
+ This is only accessible for test purposes.
+ """
+ # we can't call any logging function until after start finishes.
+ # this got moved to a seperate function from run to help with test code
+ if self.rsync is None:
+ self.rsync = rsync(self.sources, self.destination, self.password)
+
+ def read_config(self, section=None, configfile=None):
+ """
+ read the config file
+ """
+ super(CopierBot, self).read_config(section, configfile)
+
+ self.sources = shlex.split(self._check_required_option('rsync_sources'))
+ self.password = self._check_required_option('rsync_password_file')
+ self.destination = self._check_required_option('rsync_destination')
+
+ self.notify_users = self._parse_user_list(self.cfg['notify_users'])
+ try:
+ self.notify_runner = \
+ self._parse_user_list(self.cfg['notify_runner'],
+ require_resource=True)
+ except bot.JIDMissingResource:
+ msg = 'need a full jabber ID + resource for xml-rpc destinations'
+ print >>sys.stderr, msg
+ raise bot.JIDMissingResource(msg)
+
+ def run(self):
+ """
+ Start application
+ """
+ self._init_rsync()
+ super(CopierBot, self).run()
+
+ def startCopy(self, *args):
+ """
+ start our copy
+ """
+ logging.info("starting copy scan, %s" % (args,))
+ started = self.rsync.copy()
+ logging.info("copying:" + " ".join(started)+".")
+ return started
+
+ def sequencingFinished(self, runDir, *args):
+ """
+ The run was finished, if we're done copying, pass the message on
+ """
+ # close any open processes
+ self.rsync.poll()
+
+ # see if we're still copying
+ if runfolder_validate(runDir):
+ logging.info("recevied sequencing finshed for %s" % (runDir))
+ self.pending.append(runDir)
+ self.startCopy()
+ return "PENDING"
+ else:
+ errmsg = "received bad runfolder name (%s)" % (runDir)
+ logging.warning(errmsg)
+ # maybe I should use a different error message
+ raise RuntimeError(errmsg)
+
+ def reportSequencingFinished(self, runDir):
+ """
+ Send the sequencingFinished message to the interested parties
+ """
+ if self.notify_users is not None:
+ for u in self.notify_users:
+ self.send(u, 'Sequencing run %s finished' % (runDir))
+ if self.notify_runner is not None:
+ for r in self.notify_runner:
+ self.rpc_send(r, (runDir,), 'sequencingFinished')
+ logging.info("forwarding sequencingFinshed message for %s" % (runDir))
+
+ def update(self, *args):
+ """
+ Update our current status.
+ Report if we've finished copying files.
+ """
+ self.rsync.poll()
+ for p in self.pending:
+ if p not in self.rsync.keys():
+ self.reportSequencingFinished(p)
+ self.pending.remove(p)
+
+ def _parser(self, msg, who):
+ """
+ Parse xmpp chat messages
+ """
+ help = u"I can [copy], or report current [status]"
+ if re.match(u"help", msg):
+ reply = help
+ elif re.match("copy", msg):
+ started = self.startCopy()
+ reply = u"started copying " + ", ".join(started)
+ elif re.match(u"status", msg):
+ msg = [u"Currently %d rsync processes are running." % (len(self.rsync))]
+ for d in self.rsync.keys():
+ msg.append(u" " + d)
+ reply = os.linesep.join(msg)
+ else:
+ reply = u"I didn't understand '%s'" % (unicode(msg))
+ return reply
+
+def main(args=None):
+ bot = CopierBot()
+ bot.main(args)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
+
--- /dev/null
+#!/usr/bin/env python
+from glob import glob
+import logging
+import os
+import re
+import sys
+import time
+import threading
+
+from benderjab import rpc
+
+from htsworkflow.pipelines.configure_run import *
+
+#s_fc = re.compile('FC[0-9]+')
+s_fc = re.compile('_[0-9a-zA-Z]*$')
+
+
+def _get_flowcell_from_rundir(run_dir):
+ """
+ Returns flowcell string based on run_dir.
+ Returns None and logs error if flowcell can't be found.
+ """
+ junk, dirname = os.path.split(run_dir)
+ mo = s_fc.search(dirname)
+ if not mo:
+ logging.error('RunDir 2 FlowCell error: %s' % (run_dir))
+ return None
+
+ return dirname[mo.start()+1:]
+
+
+
+class Runner(rpc.XmlRpcBot):
+ """
+ Manage running pipeline jobs.
+ """
+ def __init__(self, section=None, configfile=None):
+ #if configfile is None:
+ # self.configfile = "~/.htsworkflow"
+ super(Runner, self).__init__(section, configfile)
+
+ self.cfg['notify_users'] = None
+ self.cfg['genome_dir'] = None
+ self.cfg['base_analysis_dir'] = None
+
+ self.cfg['notify_users'] = None
+ self.cfg['notify_postanalysis'] = None
+
+ self.conf_info_dict = {}
+
+ self.register_function(self.sequencingFinished)
+ #self.eventTasks.append(self.update)
+
+
+ def read_config(self, section=None, configfile=None):
+ super(Runner, self).read_config(section, configfile)
+
+ self.genome_dir = self._check_required_option('genome_dir')
+ self.base_analysis_dir = self._check_required_option('base_analysis_dir')
+
+ self.notify_users = self._parse_user_list(self.cfg['notify_users'])
+ #FIXME: process notify_postpipeline cfg
+
+
+ def _parser(self, msg, who):
+ """
+ Parse xmpp chat messages
+ """
+ help = u"I can send [start] a run, or report [status]"
+ if re.match(u"help", msg):
+ reply = help
+ elif re.match("status", msg):
+ words = msg.split()
+ if len(words) == 2:
+ reply = self.getStatusReport(words[1])
+ else:
+ reply = u"Status available for: %s" \
+ % (', '.join([k for k in self.conf_info_dict.keys()]))
+ elif re.match(u"start", msg):
+ words = msg.split()
+ if len(words) == 2:
+ self.sequencingFinished(words[1])
+ reply = u"starting run for %s" % (words[1])
+ else:
+ reply = u"need runfolder name"
+ elif re.match(u"path", msg):
+ reply = u"My path is: " + unicode(os.environ['PATH'])
+ else:
+ reply = u"I didn't understand '%s'" %(msg)
+
+ logging.debug("reply: " + str(reply))
+ return reply
+
+
+ def getStatusReport(self, fc_num):
+ """
+ Returns text status report for flow cell number
+ """
+ if fc_num not in self.conf_info_dict:
+ return "No record of a %s run." % (fc_num)
+
+ status = self.conf_info_dict[fc_num].status
+
+ if status is None:
+ return "No status information for %s yet." \
+ " Probably still in configure step. Try again later." % (fc_num)
+
+ output = status.statusReport()
+
+ return '\n'.join(output)
+
+
+ def sequencingFinished(self, run_dir):
+ """
+ Sequenceing (and copying) is finished, time to start pipeline
+ """
+ logging.debug("received sequencing finished message")
+
+ # Setup config info object
+ ci = ConfigInfo()
+ ci.base_analysis_dir = self.base_analysis_dir
+ ci.analysis_dir = os.path.join(self.base_analysis_dir, run_dir)
+
+ # get flowcell from run_dir name
+ flowcell = _get_flowcell_from_rundir(run_dir)
+
+ # Store ci object in dictionary
+ self.conf_info_dict[flowcell] = ci
+
+
+ # Launch the job in it's own thread and turn.
+ self.launchJob(run_dir, flowcell, ci)
+ return "started"
+
+
+ def pipelineFinished(self, run_dir):
+ # need to strip off self.watch_dir from rundir I suspect.
+ logging.info("pipeline finished in" + str(run_dir))
+ #pattern = self.watch_dir
+ #if pattern[-1] != os.path.sep:
+ # pattern += os.path.sep
+ #stripped_run_dir = re.sub(pattern, "", run_dir)
+ #logging.debug("stripped to " + stripped_run_dir)
+
+ # Notify each user that the run has finished.
+ if self.notify_users is not None:
+ for u in self.notify_users:
+ self.send(u, 'Pipeline run %s finished' % (run_dir))
+
+ #if self.notify_runner is not None:
+ # for r in self.notify_runner:
+ # self.rpc_send(r, (stripped_run_dir,), 'sequencingFinished')
+
+ def reportMsg(self, msg):
+
+ if self.notify_users is not None:
+ for u in self.notify_users:
+ self.send(u, msg)
+
+
+ def _runner(self, run_dir, flowcell, conf_info):
+
+ # retrieve config step
+ cfg_filepath = os.path.join(conf_info.analysis_dir,
+ 'config-auto.txt')
+ status_retrieve_cfg = retrieve_config(conf_info,
+ flowcell,
+ cfg_filepath,
+ self.genome_dir)
+ if status_retrieve_cfg:
+ logging.info("Runner: Retrieve config: success")
+ self.reportMsg("Retrieve config (%s): success" % (run_dir))
+ else:
+ logging.error("Runner: Retrieve config: failed")
+ self.reportMsg("Retrieve config (%s): FAILED" % (run_dir))
+
+
+ # configure step
+ if status_retrieve_cfg:
+ status = configure(conf_info)
+ if status:
+ logging.info("Runner: Configure: success")
+ self.reportMsg("Configure (%s): success" % (run_dir))
+ self.reportMsg(
+ os.linesep.join(glob(os.path.join(run_dir,'Data','C*')))
+ )
+ else:
+ logging.error("Runner: Configure: failed")
+ self.reportMsg("Configure (%s): FAILED" % (run_dir))
+
+ #if successful, continue
+ if status:
+ # Setup status cmdline status monitor
+ #startCmdLineStatusMonitor(ci)
+
+ # running step
+ print 'Running pipeline now!'
+ run_status = run_pipeline(conf_info)
+ if run_status is True:
+ logging.info('Runner: Pipeline: success')
+ self.reportMsg("Pipeline run (%s): Finished" % (run_dir,))
+ else:
+ logging.info('Runner: Pipeline: failed')
+ self.reportMsg("Pipeline run (%s): FAILED" % (run_dir))
+
+
+ def launchJob(self, run_dir, flowcell, conf_info):
+ """
+ Starts up a thread for running the pipeline
+ """
+ t = threading.Thread(target=self._runner,
+ args=[run_dir, flowcell, conf_info])
+ t.setDaemon(True)
+ t.start()
+
+
+
+def main(args=None):
+ bot = Runner()
+ return bot.main(args)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
+
--- /dev/null
+#!/usr/bin/env python
+import logging
+import os
+import re
+import shlex
+import sys
+import time
+
+from htsworkflow.util import mount
+
+# this uses pyinotify
+import pyinotify
+from pyinotify import EventsCodes
+
+from benderjab import rpc
+
+def get_top_dir(root, path):
+ """
+ Return the directory in path that is a subdirectory of root.
+ e.g.
+
+ >>> print get_top_dir('/a/b/c', '/a/b/c/d/e/f')
+ d
+ >>> print get_top_dir('/a/b/c/', '/a/b/c/d/e/f')
+ d
+ >>> print get_top_dir('/a/b/c', '/g/e/f')
+ None
+ >>> print get_top_dir('/a/b/c', '/a/b/c')
+ <BLANKLINE>
+ """
+ if path.startswith(root):
+ subpath = path[len(root):]
+ if subpath.startswith('/'):
+ subpath = subpath[1:]
+ return subpath.split(os.path.sep)[0]
+ else:
+ return None
+
+class WatcherEvents(object):
+ # two events need to be tracked
+ # one to send startCopy
+ # one to send OMG its broken
+ # OMG its broken needs to stop when we've seen enough
+ # cycles
+ # this should be per runfolder.
+ # read the xml files
+ def __init__(self):
+ pass
+
+
+class Handler(pyinotify.ProcessEvent):
+ def __init__(self, watchmanager, bot, ipar=False):
+ """
+ ipar flag indicates we should wait for ipar to finish, instead of
+ just the run finishing
+ """
+ self.last_event = {}
+ self.watchmanager = watchmanager
+ self.bot = bot
+ self.ipar_mode = ipar
+ if self.ipar_mode:
+ self.last_file = 'IPAR_Netcopy_Complete.txt'.lower()
+ else:
+ self.last_file = "run.completed".lower()
+
+ def process_IN_CREATE(self, event):
+ for wdd in self.bot.wdds:
+ for watch_path in self.bot.watchdirs:
+ if event.path.startswith(watch_path):
+ target = get_top_dir(watch_path, event.path)
+ self.last_event.setdefault(watch_path, {})[target] = time.time()
+
+ msg = "Create: %s %s %s" % (event.path, event.name, target)
+
+ if event.name.lower() == self.last_file:
+ try:
+ self.bot.sequencingFinished(event.path)
+ except IOError, e:
+ logging.error("Couldn't send sequencingFinished")
+ logging.debug(msg)
+
+ def process_IN_DELETE(self, event):
+ logging.debug("Remove: %s" % os.path.join(event.path, event.name))
+ pass
+
+ def process_IN_UNMOUNT(self, event):
+ pathname = os.path.join(event.path, event.name)
+ logging.debug("IN_UNMOUNT: %s" % (pathname,))
+ self.bot.unmount_watch(event.path)
+
+class SpoolWatcher(rpc.XmlRpcBot):
+ """
+ Watch a directory and send a message when another process is done writing.
+
+ This monitors a directory tree using inotify (linux specific) and
+ after some files having been written will send a message after <timeout>
+ seconds of no file writing.
+
+ (Basically when the solexa machine finishes dumping a round of data
+ this'll hopefully send out a message saying hey look theres data available
+
+ """
+ # these params need to be in the config file
+ # I wonder where I should put the documentation
+ #:Parameters:
+ # `watchdirs` - list of directories to monitor for modifications
+ # `profile` - specify which .htsworkflow profile to use
+ # `write_timeout` - how many seconds to wait for writes to finish to
+ # the spool
+ # `notify_timeout` - how often to timeout from notify
+
+ def __init__(self, section=None, configfile=None):
+ #if configfile is None:
+ # self.configfile = "~/.htsworkflow"
+ super(SpoolWatcher, self).__init__(section, configfile)
+
+ self.cfg['watchdirs'] = None
+ self.cfg['write_timeout'] = 10
+ self.cfg['notify_users'] = None
+ self.cfg['notify_runner'] = None
+ self.cfg['wait_for_ipar'] = 0
+
+ self.watchdirs = []
+ self.watchdir_url_map = {}
+ self.notify_timeout = 0.001
+
+ self.wm = None
+ self.notify_users = None
+ self.notify_runner = None
+ self.wdds = []
+
+ # keep track if the specified mount point is currently mounted
+ self.mounted_points = {}
+ # keep track of which mount points tie to which watch directories
+ # so maybe we can remount them.
+ self.mounts_to_watches = {}
+
+ self.eventTasks.append(self.process_notify)
+
+ def read_config(self, section=None, configfile=None):
+ # Don't give in to the temptation to use logging functions here,
+ # need to wait until after we detach in start
+ super(SpoolWatcher, self).read_config(section, configfile)
+
+ self.watchdirs = shlex.split(self._check_required_option('watchdirs'))
+ # see if there's an alternate url that should be used for the watchdir
+ for watchdir in self.watchdirs:
+ self.watchdir_url_map[watchdir] = self.cfg.get(watchdir, watchdir)
+
+ self.write_timeout = int(self.cfg['write_timeout'])
+ self.wait_for_ipar = int(self.cfg['wait_for_ipar'])
+
+ self.notify_users = self._parse_user_list(self.cfg['notify_users'])
+ try:
+ self.notify_runner = \
+ self._parse_user_list(self.cfg['notify_runner'],
+ require_resource=True)
+ except bot.JIDMissingResource:
+ msg = 'need a full jabber ID + resource for xml-rpc destinations'
+ raise bot.JIDMissingResource(msg)
+
+ self.handler = None
+ self.notifier = None
+
+ def add_watch(self, watchdirs=None):
+ """
+ start watching watchdir or self.watchdir
+ we're currently limited to watching one directory tree.
+ """
+ # create the watch managers if we need them
+ if self.wm is None:
+ self.wm = pyinotify.WatchManager()
+ self.handler = Handler(self.wm, self, self.wait_for_ipar)
+ self.notifier = pyinotify.Notifier(self.wm, self.handler)
+
+ # the one tree limit is mostly because self.wdd is a single item
+ # but managing it as a list might be a bit more annoying
+ if watchdirs is None:
+ watchdirs = self.watchdirs
+
+ mask = EventsCodes.IN_CREATE | EventsCodes.IN_UNMOUNT
+ # rec traverses the tree and adds all the directories that are there
+ # at the start.
+ # auto_add will add in new directories as they are created
+ for w in watchdirs:
+ mount_location = mount.find_mount_point_for(w)
+ self.mounted_points[mount_location] = True
+ mounts = self.mounts_to_watches.get(mount_location, [])
+ if w not in mounts:
+ mounts.append(w)
+ self.mounts_to_watches[mount_location] = mounts
+
+ logging.info(u"Watching:"+unicode(w))
+ self.wdds.append(self.wm.add_watch(w, mask, rec=True, auto_add=True))
+
+ def unmount_watch(self, event_path):
+ # remove backwards so we don't get weirdness from
+ # the list getting shorter
+ for i in range(len(self.wdds),0, -1):
+ wdd = self.wdds[i]
+ logging.info(u'unmounting: '+unicode(wdd.items()))
+ self.wm.rm_watch(wdd.values())
+ del self.wdds[i]
+ self.mounted = False
+
+ def make_copy_url(self, watchdir, list_event_dir):
+ root_copy_url = self.watchdir_url_map[watchdir]
+ if root_copy_url[-1] != '/':
+ root_copy_url += '/'
+ copy_url = root_copy_url + list_event_dir
+ logging.debug('Copy url: %s' % (copy_url,))
+ return copy_url
+
+ def process_notify(self, *args):
+ if self.notifier is None:
+ # nothing to do yet
+ return
+ # process the queue of events as explained above
+ self.notifier.process_events()
+ #check events waits timeout
+ if self.notifier.check_events(self.notify_timeout):
+ # read notified events and enqeue them
+ self.notifier.read_events()
+ # should we do something?
+ # has something happened?
+ for watchdir, last_events in self.handler.last_event.items():
+ for last_event_dir, last_event_time in last_events.items():
+ time_delta = time.time() - last_event_time
+ if time_delta > self.write_timeout:
+ copy_url = self.make_copy_url(watchdir, last_event_dir)
+ self.startCopy(copy_url)
+ self.handler.last_event[watchdir] = {}
+ # handle unmounted filesystems
+ for mount_point, was_mounted in self.mounted_points.items():
+ if not was_mounted and mount.is_mounted(mount_point):
+ # we've been remounted. Huzzah!
+ # restart the watch
+ for watch in self.mounts_to_watches[mount_point]:
+ self.add_watch(watch)
+ logging.info(
+ "%s was remounted, restarting watch" % \
+ (mount_point)
+ )
+ self.mounted_points[mount_point] = True
+
+ def _parser(self, msg, who):
+ """
+ Parse xmpp chat messages
+ """
+ help = u"I can send [copy] message, or squencer [finished]"
+ if re.match(u"help", msg):
+ reply = help
+ elif re.match("copy", msg):
+ self.startCopy()
+ reply = u"sent copy message"
+ elif re.match(u"finished", msg):
+ words = msg.split()
+ if len(words) == 2:
+ self.sequencingFinished(words[1])
+ reply = u"sending sequencing finished for %s" % (words[1])
+ else:
+ reply = u"need runfolder name"
+ else:
+ reply = u"I didn't understand '%s'" %(msg)
+ return reply
+
+ def run(self):
+ """
+ Start application
+ """
+ # we have to configure pyinotify after BenderJab.start is called
+ # as weird things happen to pyinotify if the stdio is closed
+ # after it's initialized.
+ self.add_watch()
+ super(SpoolWatcher, self).run()
+
+ def stop(self):
+ """
+ shutdown application
+ """
+ # destroy the inotify's instance on this interrupt (stop monitoring)
+ if self.notifier is not None:
+ self.notifier.stop()
+ super(SpoolWatcher, self).stop()
+
+ def startCopy(self, copy_url=None):
+ logging.debug("writes seem to have stopped")
+ if self.notify_runner is not None:
+ for r in self.notify_runner:
+ self.rpc_send(r, tuple(), 'startCopy')
+ if self.notify_users is not None:
+ for u in self.notify_users:
+ self.send(u, 'startCopy %s.' % (copy_url,))
+
+ def sequencingFinished(self, run_dir):
+ # need to strip off self.watchdirs from rundir I suspect.
+ logging.info("run.completed in " + str(run_dir))
+ pattern = self.watch_dir
+ if pattern[-1] != os.path.sep:
+ pattern += os.path.sep
+ stripped_run_dir = re.sub(pattern, "", run_dir)
+ logging.debug("stripped to " + stripped_run_dir)
+ if self.notify_users is not None:
+ for u in self.notify_users:
+ self.send(u, 'Sequencing run %s finished' % (stripped_run_dir))
+ if self.notify_runner is not None:
+ for r in self.notify_runner:
+ self.rpc_send(r, (stripped_run_dir,), 'sequencingFinished')
+
+def main(args=None):
+ bot = SpoolWatcher()
+ return bot.main(args)
+
+if __name__ == "__main__":
+ ret = main(sys.argv[1:])
+ #sys.exit(ret)
+
+# TODO:
+# send messages to copier specifying which mount to copy
--- /dev/null
+import unittest
+
+
+import os
+from htsworkflow.automation.copier import runfolder_validate
+
+def extract_runfolder_path(watchdir, event):
+ runfolder_path = watchdir
+ path = event.path
+ if not path.startswith(watchdir):
+ return None
+
+ fragments = path[len(watchdir):].split(os.path.sep)
+ for f in fragments:
+ runfolder_path = os.path.join(runfolder_path, f)
+ if runfolder_validate(f):
+ return runfolder_path
+ return None
+
+class Event(object):
+ def __init__(self, path=None, name=None):
+ self.path = path
+ self.name = name
+
+class testRunner(unittest.TestCase):
+
+ def test_extract_runfolder(self):
+ watchdir = os.path.join('root', 'server', 'mount')
+ runfolder = os.path.join(watchdir, '080909_HWI-EAS229_0052_1234ABCD')
+ ipar = os.path.join(runfolder, 'Data', 'IPAR_1.01')
+ other = os.path.join(watchdir, 'other')
+
+ event = Event( path=runfolder )
+ self.failUnlessEqual(extract_runfolder_path(watchdir, event), runfolder)
+
+ event = Event( path=ipar )
+ self.failUnlessEqual(extract_runfolder_path(watchdir, event), runfolder)
+
+ event = Event( path=other)
+ self.failUnlessEqual(extract_runfolder_path(watchdir, event), None )
+
+def suite():
+ return unittest.makeSuite(testRunner,'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="suite")
--- /dev/null
+from htsworkflow.frontend.analysis.models import Task, Project
+from django.contrib import admin
+from django.utils.translation import ugettext_lazy as _
+
+class ProjectOptions(admin.ModelAdmin):
+ list_display = ('ProjTitle','ProjectTasks')
+ list_filter = ()
+ search_fieldsets = ['project_name','=tasks__subject1__library_id','=tasks__subject2__library_id','tasks__subject1__library_name','tasks__subject2__library_name','project_notes']
+ fieldsets = (
+ (None, {
+ 'fields': (('project_name'),('tasks'),('project_notes'))}),
+ )
+ filter_horizontal = ('tasks',)
+
+class TaskOptions(admin.ModelAdmin):
+ list_display = ('task_name','apply_calc','subject1','subject2','task_params','InProjects','submitted_on','task_status')
+ list_filter = ('apply_calc',)
+ search_fieldsets = ['task_name','id','=subject1__library_id','=subject2__library_id']
+ fieldsets = (
+ (None, {
+ 'fields': (('task_name'),('apply_calc'),('subject1'),('subject2'),('task_params'))
+ }),
+ ('system fields', {
+ 'classes': ('collapse',),
+ 'fields': (('submitted_on'),('task_status','run_note'))
+ }),
+ )
+
+admin.site.register(Project, ProjectOptions)
+admin.site.register(Task, TaskOptions)
+
--- /dev/null
+# some core functions of analysis manager module
+from django.http import HttpResponse
+from datetime import datetime
+from string import *
+import re
+from htsworkflow.frontend import settings
+from htsworkflow.frontend.analysis.models import Task, Project
+from django.core.exceptions import ObjectDoesNotExist
+
+def updStatus(request):
+ ClIP = request.META['REMOTE_ADDR']
+ #Check client access permission
+ granted = False
+ if (settings.ALLOWED_ANALYS_IPS.has_key(ClIP)): granted = True
+ if not granted: return HttpResponse("access denied.")
+
+ output=''
+ taskid=-1;
+ # Check required param
+ if request.has_key('taskid'): taskid = request['taskid']
+ else: return HttpResponse('missing param task id')
+
+ try:
+ rec = Task.objects.get(id=taskid)
+ mytimestamp = datetime.now().__str__()
+ mytimestamp = re.sub(pattern=":[^:]*$",repl="",string=mytimestamp)
+ if request.has_key('msg'):
+ rec.task_status += ", "+request['msg']+" ("+mytimestamp+")"
+ else :
+ rec.task_status = "Registered ("+mytimestamp+")"
+ rec.save()
+ output = "Hello "+settings.ALLOWED_ANALYS_IPS[ClIP]+". Updated status for task "+taskid
+ except ObjectDoesNotExist:
+ output = "entry not found: taskid="+taskid
+
+ return HttpResponse(output)
+
+
+def getProjects(request):
+ ClIP = request.META['REMOTE_ADDR']
+ #Check client access permission
+ granted = False
+ if (settings.ALLOWED_ANALYS_IPS.has_key(ClIP)): granted = True
+ if not granted: return HttpResponse("access denied.")
+
+ outputfile = ''
+
+ All=False
+ if (request.has_key('mode')):
+ if request['mode']=='all':
+ All=True
+
+ try:
+ if(All):
+ rec = Project.objects.all().distinct()
+ else:
+ rec = Project.objects.filter(tasks__task_status__exact='defined').distinct()
+
+ outputfile = '<?xml version="1.0" ?>'
+ outputfile += '\n<Projects Client="'+settings.ALLOWED_ANALYS_IPS[ClIP]+'">'
+ for p in rec:
+ outputfile += '\n'
+ outputfile += '\n<Project ProjectId="'+p.id.__str__()+'" Name="'+p.project_name+'">'
+ prj_tasks = p.tasks.all()
+ for t in prj_tasks:
+ outputfile += '\n'
+ if (t.apply_calc == 'QuEST' or t.apply_calc == 'WingPeaks' or t.apply_calc == 'MACS'):
+ outputfile += '\n<PeakCalling TaskId="'+t.id.__str__()+'" Name="'+t.task_name+'" Caller="'+t.apply_calc+'" Genome="'+t.subject1.library_species.use_genome_build+'">'
+ if t.subject1:
+ outputfile += '\n<Signal Library="'+t.subject1.library_id+'"/>'
+ if t.subject2:
+ outputfile += '\n<Background Library="'+t.subject2.library_id+'"/>'
+ else:
+ outputfile += '\n<Err>Background Library Missing</Err>'
+ else:
+ outputfile += '\n<Err>Signal Library Missing</Err>'
+ outputfile += '\n<params>'+t.task_params.__str__()+'</params>'
+ outputfile += '\n</PeakCalling>'
+
+ if (t.apply_calc == 'Methylseq'):
+ outputfile += '\n<Methylseq TaskId="'+t.id.__str__()+'" Name="'+t.task_name+'" Genome="'+t.subject1.library_species.use_genome_build+'">'
+ if t.subject1:
+ outputfile += '\n<Hpa2 Library="'+t.subject1.library_id+'"/>'
+ if t.subject2:
+ outputfile += '\n<Msp1 Library="'+t.subject2.library_id+'"/>'
+ else:
+ outputfile += '\n<Err>Msp1 Library Missing</Err>'
+ else:
+ outputfile += '\n<Err>Hpa2 Library Missing</Err>'
+ outputfile += '\n<params>'+t.task_params.__str__()+'</params>'
+ outputfile += '\n</Methylseq>'
+
+ if (t.apply_calc == 'ProfileReads' or t.apply_calc == 'qPCR'):
+ outputfile += '\n<'+t.apply_calc+' TaskId="'+t.id.__str__()+'" Name="'+t.task_name+'" Genome="'+t.subject1.library_species.use_genome_build+'" Library="'+t.subject1.library_id+'"/>'
+
+ if (t.apply_calc == 'CompareLibs'):
+ outputfile += '\n<CompareLibraries TaskId="'+t.id.__str__()+'" TF="'+t.task_name+'" Genome="'+t.subject1.library_species.use_genome_build+'">'
+ if t.subject1:
+ outputfile += '\n<Library Library="'+t.subject1.library_id+'"/>'
+ else:
+ outputfile += '\n<Err>Library Missing</Err>'
+ if t.subject2:
+ outputfile += '\n<Library Library="'+t.subject2.library_id+'"/>'
+ else:
+ outputfile += '\n<Err>Library Missing</Err>'
+ outputfile += '\n<params>'+t.task_params.__str__()+'</params>'
+ outputfile += '\n</CompareLibraries>'
+
+ #if (t.apply_calc == 'ComparePeakCalls'):
+ # <ComparePeakCalls Genome="hg18" Caller1="QuEST" Set1="A549 GR Dex ChIP" Caller2="QuEST" Set2="A549 GR EtOH ChIP" />
+ # outputfile += '\n<ComparePeakCalls TaskId='+t.id.__str__()+' Genome="'+t.subject1.library_species.use_genome_build+'" Caller1="'+t.pcaller1+'" Caller1="'+t.pcaller1+'" Caller2="'+t.pcaller2+'" Set1="'+t.set1+'" Set1="'+t.set2+'"/>'
+ # TO DO: Define these new fields in Task: PCaller1 (QuEST,WingPeaks), PCaller2, Set1(FK to self), Set2 (FK..) ALL NULL=TRUE
+ outputfile += '\n</Project>'
+ outputfile += '\n</Projects>'
+ except ObjectDoesNotExist:
+ outputfile = "<?xml version='1.0' ?><Projects></Projects>"
+
+ return HttpResponse(outputfile, mimetype='text/plain')
--- /dev/null
+from django.db import models
+from datetime import datetime
+from htsworkflow.frontend import settings
+from htsworkflow.frontend.samples.models import Library
+from string import *
+
+class Task(models.Model):
+ task_name = models.CharField(max_length=50,unique=True, db_index=True)
+ subject1 = models.ForeignKey(Library,related_name='sbj1_library',verbose_name="Subject1 (Signal/Hpa2)")
+ subject2 = models.ForeignKey(Library,related_name='sbj2_library',verbose_name="Subject2 (Control/Msp1)",blank=True,null=True)
+ CALCS = (
+ ('QuEST', 'QuEST Peak Calling'),
+ ('WingPeaks', 'Wing Peak Calling'),
+ ('MACS', 'MACS Peak Calling'),
+ ('qPCR', 'In Silico qPCR'),
+ ('CompareLibs', 'Compare Libaraies'),
+ ('ComparePeakCalls','Compare Peak Calls'),
+ ('ProfileReads','Profile Reads'),
+ ('Methylseq','Methylseq'),
+ )
+ apply_calc = models.CharField(max_length=50,choices=CALCS,verbose_name='Applied Calculation')
+ ## userid = # logged in user
+ task_params = models.CharField(max_length=200,blank=True,null=True,default="")
+ task_status = models.CharField(max_length=500,blank=True,null=True,default='defined')
+ results_location = models.CharField(max_length=2000,blank=True,null=True)
+ submitted_on = models.DateTimeField(default=datetime.now())
+ run_note = models.CharField(max_length=500,blank=True,null=True)
+
+ def __str__(self):
+ return '"%s" - %s on [%s]/[%s]' % (self.task_name,self.apply_calc,self.subject1,self.subject2)
+
+ def InProjects(self):
+ return '...'
+ ps = self.project_set.all()
+ pstr = 'In '
+ return pstr
+ for p in ps:
+ pstr += '%s, ' % (p.project_name)
+ return pstr
+
+class Project(models.Model):
+ project_name = models.CharField(max_length=50,unique=True, db_index=True)
+ tasks = models.ManyToManyField(Task,related_name='project_tasks',null=True)
+ project_notes = models.CharField(max_length=500,blank=True,null=True)
+
+ def __str__(self):
+ return '%s' % (self.project_name)
+
+ def ProjectTasks(self):
+ ptasks = self.tasks.all().order_by('id')
+ surl = settings.TASKS_PROJS_SERVER+'/projects/'
+ tstr = '<script>'
+ tstr += 'function togView(eid){'
+ tstr += 'f=document.getElementById(eid);'
+ tstr += 'if(f.height==0){'
+ tstr += 'f.height=600;'
+ tstr += 'f.style.border=\'solid #cccccc 3px\';'
+ tstr += '}else{'
+ tstr += 'f.height=0;'
+ tstr += 'f.style.border=\'none\';'
+ tstr += '}'
+ tstr += '}'
+ tstr += '</script>'
+ Style = ''
+ if len(ptasks) > 8: Style = ' style="height:200px;overflow:auto" '
+ tstr += '<div '+Style+'>'
+ tstr += '<table><tr><th>Tasks</th><th>Job Status</th>'
+ isregistered = False
+ for t in ptasks:
+ taskdesc = t.task_name+'<div style="font-size:80%">Details: '+t.apply_calc+' on '+t.subject1.library_id
+ if t.subject2 is not None:
+ taskdesc += ' and '+t.subject2.library_id
+ taskdesc += ' (TaskId:'+t.id.__str__()+')'
+ tstr += '<tr><td width=250>%s</td><td>%s</td></tr>' % (taskdesc,replace(t.task_status,'Complete','<span style="color:green;font-weight:bolder">Complete</span>'))
+ if t.task_status != 'defined': isregistered = True
+
+ tstr += '</table>'
+ tstr += '</div>'
+ tstr += '<div>'
+ tstr += '<div align=center>'
+ if isregistered:
+ tstr += '<a onClick="togView(\'RFrame'+self.id.__str__()+'\');" href="'+surl+self.id.__str__()+'/" title="View Results Page" target="RFrame'+self.id.__str__()+'">VIEW PROJECT RESULTS</a>'
+ tstr += '<a href="'+surl+self.id.__str__()+'/" title="View Results Page" target="_blank" style="margin-left:10px">(view in new window)</a>'
+ else:
+ tstr += 'REGISTERING ...'
+
+ tstr += '</div>'
+ tstr += '<iframe width="100%" height="0" frameborder="0" style="background-color:#ffffff" name="RFrame'+self.id.__str__()+'" id="RFrame'+self.id.__str__()+'"/></iframe>'
+ tstr += '</div>'
+ return tstr
+
+ ProjectTasks.allow_tags = True
+
+ def ProjTitle(self):
+ ptasks = self.tasks.all().order_by('id')
+ tasks_counter = '<span style="color:#666666;font-size:85%">('+len(ptasks).__str__() + ' tasks)</span>'
+ htmlstr = '%s<br/>%s' % (self.project_name,tasks_counter)
+ return htmlstr
+
+ ProjTitle.allow_tags = True
+
--- /dev/null
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('',
+ (r'^updStatus$', 'htsworkflow.frontend.analysis.main.updStatus'),
+ (r'^getProjects/$', 'htsworkflow.frontend.analysis.main.getProjects'),
+)
--- /dev/null
+from django.contrib import admin
+from django.utils.translation import ugettext_lazy as _
+
+
--- /dev/null
+from django import forms
+from django.forms.util import ErrorList
+
+
+SPECIES_LIST = [#('--choose--', '--Choose--'),
+ ('hg18', 'Homo sapiens (Hg18)'),
+ ('Mm8', 'Mus musculus (Mm8)'),
+ ('arabv6', 'Arabadopsis Thaliana v6'),
+ ('other', 'Other species (Include in description)')]
+
+
+class DivErrorList(ErrorList):
+ def __unicode__(self):
+ return self.as_divs()
+
+ def as_divs(self):
+ if not self: return u''
+ return u'<div class="errorlist">%s</div>' % (''.join([u'<div class="error">%s</div>' % e for e in self]))
+
+
+
+class ConfigForm(forms.Form):
+
+ flow_cell_number = forms.CharField(min_length=2)
+ run_date = forms.DateTimeField()
+ advanced_run = forms.BooleanField(required=False)
+ read_length = forms.IntegerField(min_value=1, initial=32)
+ #eland_repeat = forms.BooleanField()
+
+ #needs a for loop or something to allow for n configurations
+ #analysis_type = forms.ChoiceField(choices=[('eland','eland')])
+ lane1_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane1_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane2_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane2_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane3_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane3_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane4_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane4_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane5_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane5_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane6_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane6_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane7_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane7_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ lane8_species = forms.ChoiceField(choices=SPECIES_LIST)
+ lane8_description = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
+
+ notes = forms.CharField(widget=forms.Textarea(attrs={'cols':'70'}), required=False)
+
+ #lane_specific_read_length = forms.IntegerField(min_value=1)
+
+ #eland_genome_lanes = forms.MultipleChoiceField(choices=[('lane1','1'),
+ # ('lane2','2'),
+ # ('lane3','3'),
+ # ('lane4','4'),
+ # ('lane5','5'),
+ # ('lane6','6'),
+ # ('lane7','7'),
+ # ('lane8','8') ])
+
+ #eland_genome = forms.ChoiceField(choices=)
+
+ #use_bases_lanes = forms.MultipleChoiceField(choices=[('lane1','1'),
+ # ('lane2','2'),
+ # ('lane3','3'),
+ # ('lane4','4'),
+ # ('lane5','5'),
+ # ('lane6','6'),
+ # ('lane7','7'),
+ # ('lane8','8') ])
+
+ #use_bases_mask = forms.CharField()
+
+ #sequence_format = forms.ChoiceField(choices=[('scarf', 'scarf')])
+
+
+
+ #subject = forms.CharField(max_length=100)
+ #message = forms.CharField()
+ #sender = forms.EmailField()
+ #cc_myself = forms.BooleanField()
+
+ def as_custom(self):
+ """
+ Displays customized html output
+ """
+ html = []
+
+ fcn = self['flow_cell_number']
+
+ html.append(fcn.label_tag() + ': ' + str(fcn) + str(fcn.errors) + '<br />')
+
+ run_date = self['run_date']
+ html.append(run_date.label_tag() + ': ' + str(run_date) + str(run_date.errors) + '<br />')
+
+ arun = self['advanced_run']
+ html.append(arun.label_tag() + ': ' + str(arun) + str(arun.errors) + '<br />')
+
+ rl = self['read_length']
+ html.append(rl.label_tag() + ': ' + str(rl) + str(rl.errors) + '<br /><br />')
+
+ html.append('<table border="0">')
+ html.append(' <tr><td>%s</td><td>%s</td><td>%s</td></tr>' \
+ % ('Lane', 'Species', 'Description'))
+
+ l1s = self['lane1_species']
+ l1d = self['lane1_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('1', str(l1s), str(l1s.errors), str(l1d), str(l1d.errors)))
+
+ l2s = self['lane2_species']
+ l2d = self['lane2_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('2', str(l2s), str(l2s.errors), str(l2d), str(l2d.errors)))
+
+ l3s = self['lane3_species']
+ l3d = self['lane3_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('3', str(l3s), str(l3s.errors), str(l3d), str(l3d.errors)))
+
+ l4s = self['lane4_species']
+ l4d = self['lane4_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('4', str(l4s), str(l4s.errors), str(l4d), str(l4d.errors)))
+
+ l5s = self['lane5_species']
+ l5d = self['lane5_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('5', str(l5s), str(l5s.errors), str(l5d), str(l5d.errors)))
+
+ l6s = self['lane6_species']
+ l6d = self['lane6_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('6', str(l6s), str(l6s.errors), str(l6d), str(l6d.errors)))
+
+ l7s = self['lane7_species']
+ l7d = self['lane7_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('7', str(l7s), str(l7s.errors), str(l7d), str(l7d.errors)))
+
+ l8s = self['lane8_species']
+ l8d = self['lane8_description']
+ html.append(' <tr><td>%s</td><td>%s %s</td><td>%s %s</td></tr>' \
+ % ('8', str(l8s), str(l8s.errors), str(l8d), str(l8d.errors)))
+
+ html.append('</table><br />')
+
+ notes = self['notes']
+ html.append('<p>Notes:</p>')
+ html.append(' %s<br />' % (str(notes)))
+
+ return '\n'.join(html)
+
+
+
--- /dev/null
+from django.db import models
+
+# Create your models here.
--- /dev/null
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('',
+ # Example:
+
+ (r'^(?P<flowcell>\w+)/$', 'htsworkflow.frontend.eland_config.views.config'),
+ (r'^$', 'htsworkflow.frontend.eland_config.views.config'),
+ #(r'^$', 'htsworkflow.frontend.eland_config.views.index')
+
+)
--- /dev/null
+from django.http import HttpResponse
+from django.shortcuts import render_to_response
+from django.core.exceptions import ObjectDoesNotExist
+
+from htsworkflow.frontend.eland_config import forms
+from htsworkflow.frontend import settings
+from htsworkflow.frontend.experiments import models
+
+import os
+import glob
+# Create your views here.
+
+
+def _validate_input(data):
+ #if data.find('..') == -1 or data.find('/') == -1 or data.find('\\') == -1:
+ return data.replace('..', '').replace('/', '_').replace('\\', '_')
+
+#def contact(request):
+# if request.method == 'POST':
+# form = ContactForm(request.POST)
+# if form.is_valid():
+# # Do form processing here...
+# return HttpResponseRedirect('/url/on_success/')
+# else:
+# form = ContactForm()
+# return
+
+
+
+#def _saveConfigFile(form):
+# """
+# Given a valid form, save eland config to file based on flowcell number.
+# """
+# assert form.is_valid()
+#
+# clean_data = form.cleaned_data
+# flowcell = clean_data['flow_cell_number'].replace('/','_').replace('..', '__')
+#
+# file_path = os.path.join(settings.UPLOADTO_CONFIG_FILE, flowcell)
+#
+# f = open(file_path, 'w')
+# cfg = generateElandConfig(form)
+# f.write(cfg)
+# f.close()
+#
+#
+#def _saveToDb(form):
+# """
+# Save info to the database.
+# """
+# clean_data = form.cleaned_data
+#
+# fc_id = clean_data['flow_cell_number']
+#
+# try:
+# fc = models.FlowCell.objects.get(flowcell_id=fc_id)
+# except models.FlowCell.DoesNotExist:
+# fc = models.FlowCell()
+#
+# fc.flowcell_id = fc_id
+# fc.run_date = clean_data['run_date']
+#
+# #LANE 1
+# fc.lane1_sample = clean_data['lane1_description']
+# species_name = clean_data['lane1_species']
+# try:
+# specie = models.Specie.objects.get(scientific_name=species_name)
+# except models.Specie.DoesNotExist:
+# specie = models.Specie(scientific_name=species_name)
+# specie.save()
+# fc.lane1_species = specie
+#
+# #LANE 2
+# fc.lane2_sample = clean_data['lane2_description']
+# species_name = clean_data['lane2_species']
+# try:
+# specie = models.Specie.objects.get(scientific_name=species_name)
+# except models.Specie.DoesNotExist:
+# specie = models.Specie(scientific_name=species_name)
+# specie.save()
+# fc.lane2_species = specie
+#
+# #LANE 3
+# fc.lane3_sample = clean_data['lane3_description']
+# species_name = clean_data['lane3_species']
+# try:
+# specie = models.Specie.objects.get(scientific_name=species_name)
+# except models.Specie.DoesNotExist:
+# specie = models.Specie(scientific_name=species_name)
+# specie.save()
+# fc.lane3_species = specie
+#
+# #LANE 4
+# fc.lane4_sample = clean_data['lane4_description']
+# species_name = clean_data['lane4_species']
+# try:
+# specie = models.Specie.objects.get(scientific_name=species_name)
+# except models.Specie.DoesNotExist:
+# specie = models.Specie(scientific_name=species_name)
+# specie.save()
+# fc.lane4_species = specie
+#
+# #LANE 5
+# fc.lane5_sample = clean_data['lane5_description']
+# species_name = clean_data['lane5_species']
+# try:
+# specie = models.Specie.objects.get(scientific_name=species_name)
+# except models.Specie.DoesNotExist:
+# specie = models.Specie(scientific_name=species_name)
+# specie.save()
+# fc.lane5_species = specie
+#
+# #LANE 6
+# fc.lane6_sample = clean_data['lane6_description']
+# species_name = clean_data['lane6_species']
+# try:
+# specie = models.Specie.objects.get(scientific_name=species_name)
+# except models.Specie.DoesNotExist:
+# specie = models.Specie(scientific_name=species_name)
+# specie.save()
+# fc.lane6_species = specie
+#
+# #LANE 7
+# fc.lane7_sample = clean_data['lane7_description']
+# species_name = clean_data['lane7_species']
+# try:
+# specie = models.Specie.objects.get(scientific_name=species_name)
+# except models.Specie.DoesNotExist:
+# specie = models.Specie(scientific_name=species_name)
+# specie.save()
+# fc.lane7_species = specie
+#
+# #LANE 8
+# fc.lane8_sample = clean_data['lane8_description']
+# species_name = clean_data['lane8_species']
+# try:
+# specie = models.Specie.objects.get(scientific_name=species_name)
+# except models.Specie.DoesNotExist:
+# specie = models.Specie(scientific_name=species_name)
+# specie.save()
+# fc.lane8_species = specie
+#
+# fc.notes = clean_data['notes']
+#
+# fc.save()
+#
+# return fc
+#
+#
+#def generateElandConfig(form):
+# data = []
+#
+# form = form.cleaned_data
+#
+# BASE_DIR = '/data-store01/compbio/genomes'
+#
+# data.append("# FLOWCELL: %s" % (form['flow_cell_number']))
+# data.append("#")
+#
+# notes = form['notes'].replace('\r\n', '\n').replace('\r', '\n')
+# notes = notes.replace('\n', '\n# ')
+# data.append("# NOTES:")
+# data.append("# %s\n#" % (notes))
+#
+# #Convert all newline conventions to unix style
+# l1d = form['lane1_description'].replace('\r\n', '\n').replace('\r', '\n')
+# l2d = form['lane2_description'].replace('\r\n', '\n').replace('\r', '\n')
+# l3d = form['lane3_description'].replace('\r\n', '\n').replace('\r', '\n')
+# l4d = form['lane4_description'].replace('\r\n', '\n').replace('\r', '\n')
+# l5d = form['lane5_description'].replace('\r\n', '\n').replace('\r', '\n')
+# l6d = form['lane6_description'].replace('\r\n', '\n').replace('\r', '\n')
+# l7d = form['lane7_description'].replace('\r\n', '\n').replace('\r', '\n')
+# l8d = form['lane8_description'].replace('\r\n', '\n').replace('\r', '\n')
+#
+# # Turn new lines into indented commented newlines
+# l1d = l1d.replace('\n', '\n# ')
+# l2d = l2d.replace('\n', '\n# ')
+# l3d = l3d.replace('\n', '\n# ')
+# l4d = l4d.replace('\n', '\n# ')
+# l5d = l5d.replace('\n', '\n# ')
+# l6d = l6d.replace('\n', '\n# ')
+# l7d = l7d.replace('\n', '\n# ')
+# l8d = l8d.replace('\n', '\n# ')
+#
+# data.append("# Lane1: %s" % (l1d))
+# data.append("# Lane2: %s" % (l2d))
+# data.append("# Lane3: %s" % (l3d))
+# data.append("# Lane4: %s" % (l4d))
+# data.append("# Lane5: %s" % (l5d))
+# data.append("# Lane6: %s" % (l6d))
+# data.append("# Lane7: %s" % (l7d))
+# data.append("# Lane8: %s" % (l8d))
+#
+# #data.append("GENOME_DIR %s" % (BASE_DIR))
+# #data.append("CONTAM_DIR %s" % (BASE_DIR))
+# read_length = form['read_length']
+# data.append("READ_LENGTH %d" % (read_length))
+# #data.append("ELAND_REPEAT")
+# data.append("ELAND_MULTIPLE_INSTANCES 8")
+#
+# #Construct genome dictionary to figure out what lanes to put
+# # in the config file.
+# genome_dict = {}
+# l1s = form['lane1_species']
+# genome_dict.setdefault(l1s, []).append('1')
+# l2s = form['lane2_species']
+# genome_dict.setdefault(l2s, []).append('2')
+# l3s = form['lane3_species']
+# genome_dict.setdefault(l3s, []).append('3')
+# l4s = form['lane4_species']
+# genome_dict.setdefault(l4s, []).append('4')
+# l5s = form['lane5_species']
+# genome_dict.setdefault(l5s, []).append('5')
+# l6s = form['lane6_species']
+# genome_dict.setdefault(l6s, []).append('6')
+# l7s = form['lane7_species']
+# genome_dict.setdefault(l7s, []).append('7')
+# l8s = form['lane8_species']
+# genome_dict.setdefault(l8s, []).append('8')
+#
+# genome_list = genome_dict.keys()
+# genome_list.sort()
+#
+# #Loop through and create entries for each species.
+# for genome in genome_list:
+# lanes = ''.join(genome_dict[genome])
+# data.append('%s:ANALYSIS eland' % (lanes))
+# data.append('%s:READ_LENGTH %s' % (lanes, read_length))
+# data.append('%s:ELAND_GENOME %s' % (lanes, os.path.join(BASE_DIR, genome)))
+# data.append('%s:USE_BASES %s' % (lanes, 'Y'*int(read_length)))
+#
+# data.append('SEQUENCE_FORMAT --scarf')
+#
+# return '\n'.join(data)
+
+
+def getElandConfig(flowcell, regenerate=False):
+
+ file_path = os.path.join(settings.UPLOADTO_CONFIG_FILE, flowcell)
+
+ #If we are regenerating the config file, skip
+ # reading of existing file. If the file doesn't
+ # exist, try to generate it form the DB.
+ if not regenerate and os.path.isfile(file_path):
+ f = open(file_path, 'r')
+ data = f.read()
+ f.close()
+ return data
+
+ try:
+ fcObj = models.FlowCell.objects.get(flowcell_id__iexact=flowcell)
+ except ObjectDoesNotExist:
+ return None
+
+ data = []
+
+ #form = form.cleaned_data
+
+ BASE_DIR = '/data-store01/compbio/genomes'
+
+ data.append("# FLOWCELL: %s" % (fcObj.flowcell_id))
+ data.append("#")
+
+ notes = fcObj.notes.replace('\r\n', '\n').replace('\r', '\n')
+ notes = notes.replace('\n', '\n# ')
+ data.append("# NOTES:")
+ data.append("# %s\n#" % (notes))
+
+ #Convert all newline conventions to unix style
+ l1d = str(fcObj.lane_1_library.library_id) + '|' \
+ + fcObj.lane_1_library.library_name.replace('\r\n', '\n').replace('\r', '\n').replace('%', '%%')
+ l2d = str(fcObj.lane_2_library.library_id) + '|' \
+ + fcObj.lane_2_library.library_name.replace('\r\n', '\n').replace('\r', '\n').replace('%', '%%')
+ l3d = str(fcObj.lane_3_library.library_id) + '|' \
+ + fcObj.lane_3_library.library_name.replace('\r\n', '\n').replace('\r', '\n').replace('%', '%%')
+ l4d = str(fcObj.lane_4_library.library_id) + '|' \
+ + fcObj.lane_4_library.library_name.replace('\r\n', '\n').replace('\r', '\n').replace('%', '%%')
+
+ l5d = str(fcObj.lane_5_library.library_id) + '|' \
+ + fcObj.lane_5_library.library_name.replace('\r\n', '\n').replace('\r', '\n').replace('%', '%%')
+ l6d = str(fcObj.lane_6_library.library_id) + '|' \
+ + fcObj.lane_6_library.library_name.replace('\r\n', '\n').replace('\r', '\n').replace('%', '%%')
+ l7d = str(fcObj.lane_7_library.library_id) + '|' \
+ + fcObj.lane_7_library.library_name.replace('\r\n', '\n').replace('\r', '\n').replace('%', '%%')
+ l8d = str(fcObj.lane_8_library.library_id) + '|' \
+ + fcObj.lane_8_library.library_name.replace('\r\n', '\n').replace('\r', '\n').replace('%', '%%')
+
+ # Turn new lines into indented commented newlines
+ l1d = l1d.replace('\n', '\n# ')
+ l2d = l2d.replace('\n', '\n# ')
+ l3d = l3d.replace('\n', '\n# ')
+ l4d = l4d.replace('\n', '\n# ')
+ l5d = l5d.replace('\n', '\n# ')
+ l6d = l6d.replace('\n', '\n# ')
+ l7d = l7d.replace('\n', '\n# ')
+ l8d = l8d.replace('\n', '\n# ')
+
+ data.append("# Lane1: %s" % (l1d))
+ data.append("# Lane2: %s" % (l2d))
+ data.append("# Lane3: %s" % (l3d))
+ data.append("# Lane4: %s" % (l4d))
+ data.append("# Lane5: %s" % (l5d))
+ data.append("# Lane6: %s" % (l6d))
+ data.append("# Lane7: %s" % (l7d))
+ data.append("# Lane8: %s" % (l8d))
+
+ #data.append("GENOME_DIR %s" % (BASE_DIR))
+ #data.append("CONTAM_DIR %s" % (BASE_DIR))
+ read_length = fcObj.read_length
+ #data.append("ELAND_REPEAT")
+ data.append("ELAND_MULTIPLE_INSTANCES 8")
+
+ #Construct genome dictionary to figure out what lanes to put
+ # in the config file.
+ genome_dict = {}
+
+ #l1s = form['lane1_species']
+ l1s = fcObj.lane_1_library.library_species.scientific_name #+ '|' + \
+ #fcObj.lane_1_library.library_species.use_genome_build
+ genome_dict.setdefault(l1s, []).append('1')
+ l2s = fcObj.lane_2_library.library_species.scientific_name #+ '|' + \
+ #fcObj.lane_2_library.library_species.use_genome_build
+ genome_dict.setdefault(l2s, []).append('2')
+ l3s = fcObj.lane_3_library.library_species.scientific_name #+ '|' + \
+ #fcObj.lane_3_library.library_species.use_genome_build
+ genome_dict.setdefault(l3s, []).append('3')
+ l4s = fcObj.lane_4_library.library_species.scientific_name #+ '|' + \
+ #fcObj.lane_4_library.library_species.use_genome_build
+ genome_dict.setdefault(l4s, []).append('4')
+ l5s = fcObj.lane_5_library.library_species.scientific_name #+ '|' + \
+ #fcObj.lane_5_library.library_species.use_genome_build
+ genome_dict.setdefault(l5s, []).append('5')
+ l6s = fcObj.lane_6_library.library_species.scientific_name #+ '|' + \
+ #fcObj.lane_6_library.library_species.use_genome_build
+ genome_dict.setdefault(l6s, []).append('6')
+ l7s = fcObj.lane_7_library.library_species.scientific_name #+ '|' + \
+ #fcObj.lane_7_library.library_species.use_genome_build
+ genome_dict.setdefault(l7s, []).append('7')
+ l8s = fcObj.lane_8_library.library_species.scientific_name #+ '|' + \
+ #fcObj.lane_8_library.library_species.use_genome_build
+ genome_dict.setdefault(l8s, []).append('8')
+
+ genome_list = genome_dict.keys()
+ genome_list.sort()
+
+ #Loop through and create entries for each species.
+ for genome in genome_list:
+ lanes = ''.join(genome_dict[genome])
+ if fcObj.paired_end:
+ data.append('%s:ANALYSIS eland_pair' % (lanes))
+ else:
+ data.append('%s:ANALYSIS eland_extended' % (lanes))
+ data.append('%s:READ_LENGTH %s' % (lanes, read_length))
+ data.append('%s:ELAND_GENOME %s' % (lanes, '%%(%s)s' % (genome)))
+ data.append('%s:USE_BASES %s' % (lanes, 'Y'*int(read_length)))
+
+ data.append('SEQUENCE_FORMAT --fastq')
+
+ data = '\n'.join(data)
+
+ f = open(file_path, 'w')
+ f.write(data)
+ f.close()
+
+ return data
+
+
+
+def config(request, flowcell=None):
+ """
+ Returns eland config file for a given flowcell number,
+ or returns a list of available flowcell numbers.
+ """
+
+ # Provide INDEX of available Flowcell config files.
+ if flowcell is None:
+ #Find all FC* config files and report an index html file
+ #fc_list = [ os.path.split(file_path)[1] for file_path in glob.glob(os.path.join(settings.UPLOADTO_CONFIG_FILE, 'FC*')) ]
+ fc_list = [ fc.flowcell_id for fc in models.FlowCell.objects.all() ]
+
+ #Convert FC* list to html links
+ fc_html = [ '<a href="/eland_config/%s/">%s</a>' % (fc_name, fc_name) for fc_name in fc_list ]
+
+ return HttpResponse('<br />'.join(fc_html))
+
+ #FIXME: Should validate flowcell input before using.
+ flowcell = _validate_input(flowcell)
+ cfg = getElandConfig(flowcell, regenerate=True)
+
+ if not cfg:
+ return HttpResponse("Hmm, config file for %s does not seem to exist." % (flowcell))
+
+
+ return HttpResponse(cfg, mimetype="text/plain")
+
+
+
+
+#def index(request):
+# """
+# Return a form for filling out information about the flowcell
+# """
+# if request.method == 'POST':
+# form = forms.ConfigForm(request.POST, error_class=forms.DivErrorList)
+# if form.is_valid():
+# #cfg = generateElandConfig(form)
+# _saveConfigFile(form)
+# _saveToDb(form)
+# return HttpResponse("Eland Config Saved!", mimetype="text/plain")
+# else:
+# return render_to_response('config_form.html', {'form': form })
+#
+# else:
+# fm = forms.ConfigForm(error_class=forms.DivErrorList)
+# return render_to_response('config_form.html', {'form': fm })
--- /dev/null
+from htsworkflow.frontend.experiments.models import FlowCell, DataRun, ClusterStation, Sequencer
+from django.contrib import admin
+from django.utils.translation import ugettext_lazy as _
+
+class DataRunOptions(admin.ModelAdmin):
+ search_fields = [
+ 'run_folder',
+ 'run_note',
+ 'config_params',
+ '=fcid__lane_1_library__library_id',
+ '=fcid__lane_2_library__library_id',
+ '=fcid__lane_3_library__library_id',
+ '=fcid__lane_4_library__library_id',
+ '=fcid__lane_5_library__library_id',
+ '=fcid__lane_6_library__library_id',
+ '=fcid__lane_7_library__library_id',
+ '=fcid__lane_8_library__library_id'
+ 'fcid__lane_1_library__library_name',
+ 'fcid__lane_2_library__library_name',
+ 'fcid__lane_3_library__library_name',
+ 'fcid__lane_4_library__library_name',
+ 'fcid__lane_5_library__library_name',
+ 'fcid__lane_6_library__library_name',
+ 'fcid__lane_7_library__library_name',
+ 'fcid__lane_8_library__library_name' ]
+ list_display = [
+ 'run_folder',
+ 'Flowcell_Info',
+ 'run_start_time',
+ 'main_status',
+ 'run_note',
+ ]
+ list_filter = ('run_status', 'run_start_time')
+
+class FlowCellOptions(admin.ModelAdmin):
+ date_hierarchy = "run_date"
+ save_on_top = True
+ search_fields = ('flowcell_id',
+ 'sequencer__name',
+ 'cluster_station__name',
+ '=lane_1_library__library_id',
+ '=lane_2_library__library_id',
+ '=lane_3_library__library_id',
+ '=lane_4_library__library_id',
+ '=lane_5_library__library_id',
+ '=lane_6_library__library_id',
+ '=lane_7_library__library_id',
+ '=lane_8_library__library_id',
+ 'lane_1_library__library_name',
+ 'lane_2_library__library_name',
+ 'lane_3_library__library_name',
+ 'lane_4_library__library_name',
+ 'lane_5_library__library_name',
+ 'lane_6_library__library_name',
+ 'lane_7_library__library_name',
+ 'lane_8_library__library_name')
+ list_display = ('flowcell_id','run_date','Lanes')
+ list_filter = ('sequencer','cluster_station')
+ fieldsets = (
+ (None, {
+ 'fields': ('run_date', ('flowcell_id','cluster_station','sequencer'), ('read_length', 'paired_end'),)
+ }),
+ ('Lanes:', {
+ 'fields' : (('lane_1_library', 'lane_1_pM', 'lane_1_cluster_estimate'), ('lane_2_library', 'lane_2_pM', 'lane_2_cluster_estimate'), ('lane_3_library', 'lane_3_pM', 'lane_3_cluster_estimate'), ('lane_4_library', 'lane_4_pM', 'lane_4_cluster_estimate'), ('lane_5_library', 'lane_5_pM', 'lane_5_cluster_estimate'), ('lane_6_library', 'lane_6_pM', 'lane_6_cluster_estimate'), ('lane_7_library', 'lane_7_pM', 'lane_7_cluster_estimate'), ('lane_8_library', 'lane_8_pM', 'lane_8_cluster_estimate'),)
+ }),
+ ('Notes:', { 'fields': ('notes',),}),
+ )
+
+class ClusterStationOptions(admin.ModelAdmin):
+ list_display = ('name', )
+ fieldsets = ( ( None, { 'fields': ( 'name', ) } ), )
+
+class SequencerOptions(admin.ModelAdmin):
+ list_display = ('name', )
+ fieldsets = ( ( None, { 'fields': ( 'name', ) } ), )
+
+admin.site.register(DataRun, DataRunOptions)
+admin.site.register(FlowCell, FlowCellOptions)
+admin.site.register(ClusterStation, ClusterStationOptions)
+admin.site.register(Sequencer, SequencerOptions)
--- /dev/null
+# some core functions of the exp tracker module
+from django.http import HttpResponse
+from datetime import datetime
+from string import *
+import re
+from htsworkflow.frontend import settings
+from htsworkflow.frontend.experiments.models import FlowCell, DataRun
+from htsworkflow.frontend.samples.models import Library
+from django.core.exceptions import ObjectDoesNotExist
+from django.core.mail import send_mail, mail_admins
+
+def updStatus(request):
+ output=''
+ user = 'none'
+ pswd = ''
+ UpdatedStatus = 'unknown'
+ fcid = 'none'
+ runfolder = 'unknown'
+ ClIP = request.META['REMOTE_ADDR']
+ granted = False
+
+ if request.has_key('user'):
+ user = request['user']
+
+ #Check access permission
+ if (user == 'rami' and settings.ALLOWED_IPS.has_key(ClIP)): granted = True
+ if not granted: return HttpResponse("access denied.")
+
+
+ # ~~~~~~Parameters for the job ~~~~
+ if request.has_key('fcid'):
+ fcid = request['fcid']
+ else:
+ return HttpResponse('missing fcid')
+
+ if request.has_key('runf'):
+ runfolder = request['runf']
+ else:
+ return HttpResponse('missing runf')
+
+
+ if request.has_key('updst'):
+ UpdatedStatus = request['updst']
+ else:
+ return HttpResponse('missing status')
+
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ # Update Data Run status in DB
+ # Try get rec. If not found return 'entry not found + <fcid><runfolder>', if found try update and return updated
+ try:
+ rec = DataRun.objects.get(run_folder=runfolder)
+ rec.run_status = UpdatedStatus
+
+ #if there's a message update that too
+ mytimestamp = datetime.now().__str__()
+ mytimestamp = re.sub(pattern=":[^:]*$",repl="",string=mytimestamp)
+ if request.has_key('msg'):
+ rec.run_note += ", "+request['msg']+" ("+mytimestamp+")"
+ else :
+ if UpdatedStatus == '1':
+ rec.run_note = "Started ("+mytimestamp+")"
+
+ rec.save()
+ output = "Hello "+settings.ALLOWED_IPS[ClIP]+". Updated to:'"+DataRun.RUN_STATUS_CHOICES[int(UpdatedStatus)][1].__str__()+"'"
+ except ObjectDoesNotExist:
+ output = "entry not found: "+fcid+", "+runfolder
+
+
+ #Notify researcher by email
+ # Doesn't work
+ #send_mail('Exp Tracker', 'Data Run Status '+output, 'rrauch@stanford.edu', ['rrrami@gmail.com'], fail_silently=False)
+ #mail_admins("test subject", "testing , testing", fail_silently=False)
+ # gives error: (49, "Can't assign requested address")
+ return HttpResponse(output)
+
+def generateConfile(request,fcid):
+ #granted = False
+ #ClIP = request.META['REMOTE_ADDR']
+ #if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
+
+ #if not granted: return HttpResponse("access denied.")
+
+ cnfgfile = 'READ_LENGTH 25\n'
+ cnfgfile += 'ANALYSIS eland\n'
+ cnfgfile += 'GENOME_FILE all_chr.fa\n'
+ cnfgfile += 'ELAND_MULTIPLE_INSTANCES 8\n'
+ genome_dir = 'GENOME_DIR /Volumes/Genomes/'
+ eland_genome = 'ELAND_GENOME /Volumes/Genomes/'
+
+ try:
+ rec = FlowCell.objects.get(flowcell_id=fcid)
+
+ cnfgfile += '1:'+genome_dir+rec.lane_1_library.library_species.use_genome_build+'\n'
+ cnfgfile += '1:'+eland_genome+rec.lane_1_library.library_species.use_genome_build+'\n'
+
+ cnfgfile += '2:'+genome_dir+rec.lane_2_library.library_species.use_genome_build+'\n'
+ cnfgfile += '2:'+eland_genome+rec.lane_2_library.library_species.use_genome_build+'\n'
+
+ cnfgfile += '3:'+genome_dir+rec.lane_3_library.library_species.use_genome_build+'\n'
+ cnfgfile += '3:'+eland_genome+rec.lane_3_library.library_species.use_genome_build+'\n'
+
+ cnfgfile += '4:'+genome_dir+rec.lane_4_library.library_species.use_genome_build+'\n'
+ cnfgfile += '4:'+eland_genome+rec.lane_4_library.library_species.use_genome_build+'\n'
+
+ cnfgfile += '5:'+genome_dir+rec.lane_5_library.library_species.use_genome_build+'\n'
+ cnfgfile += '5:'+eland_genome+rec.lane_5_library.library_species.use_genome_build+'\n'
+
+ cnfgfile += '6:'+genome_dir+rec.lane_6_library.library_species.use_genome_build+'\n'
+ cnfgfile += '6:'+eland_genome+rec.lane_6_library.library_species.use_genome_build+'\n'
+
+ cnfgfile += '7:'+genome_dir+rec.lane_7_library.library_species.use_genome_build+'\n'
+ cnfgfile += '7:'+eland_genome+rec.lane_7_library.library_species.use_genome_build+'\n'
+
+ cnfgfile += '8:'+genome_dir+rec.lane_8_library.library_species.use_genome_build+'\n'
+ cnfgfile += '8:'+eland_genome+rec.lane_8_library.library_species.use_genome_build
+
+ except ObjectDoesNotExist:
+ cnfgfile = 'Entry not found for fcid = '+fcid
+
+ return cnfgfile
+
+def getConfile(req):
+ granted = False
+ ClIP = req.META['REMOTE_ADDR']
+ if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
+
+ if not granted: return HttpResponse("access denied. IP: "+ClIP)
+
+ fcid = 'none'
+ cnfgfile = 'Nothing found'
+ runfolder = 'unknown'
+ request = req.REQUEST
+ print request, dir(request)
+ print request['fcid'], request.has_key('fcid')
+ print request['runf']
+ if request.has_key('fcid'):
+ fcid = request['fcid']
+ if request.has_key('runf'):
+ runfolder = request['runf']
+ try:
+ rec = DataRun.objects.get(run_folder=runfolder) #,flowcell_id=fcid)
+ cnfgfile = rec.config_params
+ #match_str = re.compile(r"READ_LENGTH.+$")
+ match_str = re.compile('^READ_LENGTH.+')
+ if not match_str.search(cnfgfile):
+ cnfgfile = generateConfile(request,fcid)
+ if match_str.search(cnfgfile):
+ rec = DataRun.objects.get(run_folder=runfolder) #,flowcell_id=fcid)
+ rec.config_params = cnfgfile
+ rec.save()
+ else:
+ cnfgfile = 'Failed generating config params for RunFolder = '+runfolder +', Flowcell id = '+ fcid+ ' Config Text:\n'+cnfgfile
+
+ except ObjectDoesNotExist:
+ cnfgfile = 'Entry not found for RunFolder = '+runfolder
+
+ return HttpResponse(cnfgfile, mimetype='text/plain')
+
+def getLaneLibs(req):
+ granted = False
+ ClIP = req.META['REMOTE_ADDR']
+ if (settings.ALLOWED_IPS.has_key(ClIP)): granted = True
+
+ if not granted: return HttpResponse("access denied.")
+
+ request = req.REQUEST
+ fcid = 'none'
+ outputfile = ''
+ if request.has_key('fcid'):
+ fcid = request['fcid']
+ try:
+ rec = FlowCell.objects.get(flowcell_id=fcid)
+ #Ex: 071211
+ year = datetime.today().year.__str__()
+ year = replace(year,'20','')
+ month = datetime.today().month
+ if month < 10: month = "0"+month.__str__()
+ else: month = month.__str__()
+ day = datetime.today().day
+ if day < 10: day = "0"+day.__str__()
+ else: day = day.__str__()
+ mydate = year+month+day
+ outputfile = '<?xml version="1.0" ?>'
+ outputfile += '\n<SolexaResult Date="'+mydate+'" Flowcell="'+fcid+'" Client="'+settings.ALLOWED_IPS[ClIP]+'">'
+ outputfile += '\n<Lane Index="1" Name="'+rec.lane_1_library.library_name+'" Library="'+rec.lane_1_library.library_id+'" Genome="'+rec.lane_1_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="2" Name="'+rec.lane_2_library.library_name+'" Library="'+rec.lane_2_library.library_id+'" Genome="'+rec.lane_2_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="3" Name="'+rec.lane_3_library.library_name+'" Library="'+rec.lane_3_library.library_id+'" Genome="'+rec.lane_3_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="4" Name="'+rec.lane_4_library.library_name+'" Library="'+rec.lane_4_library.library_id+'" Genome="'+rec.lane_4_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="5" Name="'+rec.lane_5_library.library_name+'" Library="'+rec.lane_5_library.library_id+'" Genome="'+rec.lane_5_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="6" Name="'+rec.lane_6_library.library_name+'" Library="'+rec.lane_6_library.library_id+'" Genome="'+rec.lane_6_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="7" Name="'+rec.lane_7_library.library_name+'" Library="'+rec.lane_7_library.library_id+'" Genome="'+rec.lane_7_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n<Lane Index="8" Name="'+rec.lane_8_library.library_name+'" Library="'+rec.lane_8_library.library_id+'" Genome="'+rec.lane_8_library.library_species.use_genome_build+'" PrimerName="" PrimerSeq=""/>'
+ outputfile += '\n</SolexaResult>'
+ except ObjectDoesNotExist:
+ outputfile = 'Flowcell entry not found for: '+fcid
+ else: outputfile = 'Missing input: flowcell id'
+
+ return HttpResponse(outputfile, mimetype='text/plain')
--- /dev/null
+from django.db import models
+from htsworkflow.frontend.samples.models import *
+from htsworkflow.frontend.settings import options
+from django.core.exceptions import ObjectDoesNotExist
+import logging
+
+class ClusterStation(models.Model):
+ name = models.CharField(max_length=50, unique=True)
+
+ def __unicode__(self):
+ return unicode(self.name)
+
+class Sequencer(models.Model):
+ name = models.CharField(max_length=50, unique=True)
+
+ def __unicode__(self):
+ return unicode(self.name)
+
+default_pM = 5
+try:
+ default_pM = int(options.get('frontend', 'default_pm'))
+except ValueError,e:
+ logging.error("invalid value for frontend.default_pm")
+
+class FlowCell(models.Model):
+
+ flowcell_id = models.CharField(max_length=20, unique=True, db_index=True)
+ run_date = models.DateTimeField()
+ advanced_run = models.BooleanField(default=False)
+ paired_end = models.BooleanField(default=False)
+ read_length = models.IntegerField(default=32) #Stanford is currenlty 25
+
+ lane_1_library = models.ForeignKey(Library, related_name="lane_1_library")
+ lane_2_library = models.ForeignKey(Library, related_name="lane_2_library")
+ lane_3_library = models.ForeignKey(Library, related_name="lane_3_library")
+ lane_4_library = models.ForeignKey(Library, related_name="lane_4_library")
+ lane_5_library = models.ForeignKey(Library, related_name="lane_5_library")
+ lane_6_library = models.ForeignKey(Library, related_name="lane_6_library")
+ lane_7_library = models.ForeignKey(Library, related_name="lane_7_library")
+ lane_8_library = models.ForeignKey(Library, related_name="lane_8_library")
+
+ lane_1_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
+ lane_2_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
+ lane_3_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
+ lane_4_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
+ lane_5_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
+ lane_6_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
+ lane_7_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
+ lane_8_pM = models.DecimalField(max_digits=5, decimal_places=2,blank=False, null=False,default=default_pM)
+
+ lane_1_cluster_estimate = models.IntegerField(blank=True, null=True)
+ lane_2_cluster_estimate = models.IntegerField(blank=True, null=True)
+ lane_3_cluster_estimate = models.IntegerField(blank=True, null=True)
+ lane_4_cluster_estimate = models.IntegerField(blank=True, null=True)
+ lane_5_cluster_estimate = models.IntegerField(blank=True, null=True)
+ lane_6_cluster_estimate = models.IntegerField(blank=True, null=True)
+ lane_7_cluster_estimate = models.IntegerField(blank=True, null=True)
+ lane_8_cluster_estimate = models.IntegerField(blank=True, null=True)
+
+ # lane_1_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_1_primer")
+ # lane_2_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_2_primer")
+ # lane_3_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_3_primer")
+ # lane_4_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_4_primer")
+ # lane_5_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_5_primer")
+ # lane_6_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_6_primer")
+ # lane_7_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_7_primer")
+ # lane_8_primer = models.ForeignKey(Primer,blank=True,null=True,related_name="lane_8_primer")
+
+ cluster_station = models.ForeignKey(ClusterStation, default=1)
+ sequencer = models.ForeignKey(Sequencer, default=1)
+
+ notes = models.TextField(blank=True)
+
+ def __unicode__(self):
+ return unicode(self.flowcell_id)
+
+ def Create_LOG(self):
+ str = ''
+ str +='<a target=_balnk href="/experiments/'+self.flowcell_id+'" title="Create XLS like sheet for this Flowcell ..." ">Create LOG</a>'
+ try:
+ t = DataRun.objects.get(fcid=self.id)
+ str +='<br/><a target=_self href="/admin/experiments/datarun/?q='+self.flowcell_id+'" title="Check Data Runs ..." ">DataRun ..</a>'
+ except ObjectDoesNotExist:
+ str += '<br/><span style="color:red">not sequenced</span>'
+ return str
+ Create_LOG.allow_tags = True
+
+ def Lanes(self):
+ library_url = '/admin/samples/library/%s'
+ html = ['<table>']
+ for i in range(1,9):
+ cluster_estimate = getattr(self, 'lane_%d_cluster_estimate' % (i,))
+ if cluster_estimate is not None:
+ cluster_estimate = "%s k" % ((int(cluster_estimate)/1000), )
+ else:
+ cluster_estimate = 'None'
+ library_id = getattr(self, 'lane_%d_library_id' % (i,))
+ library = getattr(self, 'lane_%d_library' % i)
+ element = '<tr><td>%d</td><td><a href="%s">%s</a></td><td>%s</td></tr>'
+ expanded_library_url = library_url %(library_id,)
+ html.append(element % (i, expanded_library_url, library, cluster_estimate))
+ html.append('</table>')
+ return "\n".join(html)
+ Lanes.allow_tags = True
+
+ class Meta:
+ ordering = ["-run_date"]
+
+### -----------------------
+class DataRun(models.Model):
+ ConfTemplate = "CONFIG PARAMS WILL BE GENERATED BY THE PIPELINE SCRIPT.\nYOU'LL BE ABLE TO EDIT AFTER IF NEEDED."
+ run_folder = models.CharField(max_length=50,unique=True, db_index=True)
+ fcid = models.ForeignKey(FlowCell,verbose_name="Flowcell Id")
+ config_params = models.TextField(default=ConfTemplate)
+ run_start_time = models.DateTimeField()
+ RUN_STATUS_CHOICES = (
+ (0, 'Sequencer running'), ##Solexa Data Pipeline Not Yet Started'),
+ (1, 'Data Pipeline Started'),
+ (2, 'Data Pipeline Interrupted'),
+ (3, 'Data Pipeline Finished'),
+ (4, 'CollectReads Started'),
+ (5, 'CollectReads Finished'),
+ (6, 'QC Finished'),
+ (7, 'DONE'),
+ )
+ run_status = models.IntegerField(choices=RUN_STATUS_CHOICES, default=0)
+ run_note = models.TextField(blank=True)
+
+
+ def main_status(self):
+ str = '<div'
+ if self.run_status >= 5:
+ str += ' style="color:green">'
+ str += '<b>'+self.RUN_STATUS_CHOICES[self.run_status][1]+'</b>'
+ str += '<br/><br/>' #<span style="color:red;font-size:80%;">New!</span>'
+ str +='<br/><a target=_balnk href="'+settings.TASKS_PROJS_SERVER+'/Flowcells/'+self.fcid.flowcell_id+'/'+self.fcid.flowcell_id+'_QC_Summary.html" title="View QC Summaries of this run ..." ">View QC Page</a>'
+ else:
+ str += '>'+self.RUN_STATUS_CHOICES[self.run_status][1]
+
+ str += '</div>'
+ return str
+ main_status.allow_tags = True
+
+ main_status.allow_tags = True
+
+ def Flowcell_Info(self):
+ str = '<b>'+self.fcid.__str__()+'</b>'
+ str += ' (c: '+self.fcid.cluster_mac_id+', s: '+self.fcid.seq_mac_id+')'
+ str += '<div style="margin-top:5px;">'
+ str +='<a title="View Lane List here ..." onClick="el = document.getElementById(\'LanesOf'+self.fcid.__str__()+'\');if(el) (el.style.display==\'none\'?el.style.display=\'block\':el.style.display=\'none\')" style="cursor:pointer;color: #5b80b2;">View/hide lanes</a>'
+ str += '<div id="LanesOf'+self.fcid.__str__()+'" style="display:block;border:solid #cccccc 1px;width:350px">'
+ LanesList = '1: '+self.fcid.lane_1_library.__str__()+' ('+self.fcid.lane_1_library.library_species.use_genome_build+')<br/>2: '+self.fcid.lane_2_library.__str__()+' ('+self.fcid.lane_2_library.library_species.use_genome_build+')<br/>3: '+self.fcid.lane_3_library.__str__()+' ('+self.fcid.lane_3_library.library_species.use_genome_build+')<br/>4: '+self.fcid.lane_4_library.__str__()+' ('+self.fcid.lane_4_library.library_species.use_genome_build+')<br/>5: '+self.fcid.lane_5_library.__str__()+' ('+self.fcid.lane_5_library.library_species.use_genome_build+')<br/>6: '+self.fcid.lane_6_library.__str__()+' ('+self.fcid.lane_6_library.library_species.use_genome_build+')<br/>7: '+self.fcid.lane_7_library.__str__()+' ('+self.fcid.lane_7_library.library_species.use_genome_build+')<br/>8: '+self.fcid.lane_8_library.__str__()+' ('+self.fcid.lane_8_library.library_species.use_genome_build+')'
+ str += LanesList ## self.fcid.Lanes()
+ str += '</div>'
+ str += '<div><a title="open Flowcell record" href="/admin/exp_track/flowcell/'+self.fcid.id.__str__()+'/" target=_self>Edit Flowcell record</a>'
+ #str += '<span style="color:red;font-size:80%;margin-left:15px;margin-right:3px">New!</span>'
+ str +='<a style="margin-left:15px;" target=_balnk href="/exp_track/'+self.fcid.flowcell_id+'" title="View XLS like sheet for this Flowcell LOG ..." ">GA LOG Page</a>'
+ str += '</div>'
+ str += '</div>'
+ return str
+ Flowcell_Info.allow_tags = True
--- /dev/null
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('',
+
+ (r'^$', 'htsworkflow.frontend.experiments.views.index'),
+ #(r'^liblist$', 'htsworkflow.frontend.experiments.views.test_Libs'),
+ #(r'^(?P<run_folder>.+)/$', 'gaworkflow.frontend.experiments.views.detail'),
+ (r'^(?P<fcid>.+)/$', 'htsworkflow.frontend.experiments.views.makeFCSheet'),
+ (r'^updStatus$', 'htsworkflow.frontend.experiments.experiments.updStatus'),
+ (r'^getConfile$', 'htsworkflow.frontend.experiments.experiments.getConfile'),
+ (r'^getLanesNames$', 'htsworkflow.frontend.experiments.experiments.getLaneLibs')
+)
--- /dev/null
+# Create your views here.
+#from django.template import Context, loader
+#shortcut to the above modules
+from django.shortcuts import render_to_response, get_object_or_404
+from htsworkflow.frontend.experiments.models import *
+from django.http import HttpResponse
+from django.core.exceptions import ObjectDoesNotExist
+
+def index(request):
+ all_runs = DataRun.objects.order_by('-run_start_time')
+ #t = loader.get_template('experiments/index.html')
+ #c = Context({
+ # 'data_run_list': all_runs,
+ #})
+ #return HttpResponse(t.render(c))
+ # shortcut to the above module usage
+ return render_to_response('experiments/index.html',{'data_run_list': all_runs})
+
+def detail(request, run_folder):
+ html_str = '<h2>Exp Track Details Page</h2>'
+ html_str += 'Run Folder: '+run_folder
+ r = get_object_or_404(DataRun,run_folder=run_folder)
+ return render_to_response('experiments/detail.html',{'run_f': r})
+
+def makeFCSheet(request,fcid):
+ # get Flowcell by input fcid
+ # ...
+ rec = None
+ try:
+ rec = FlowCell.objects.get(flowcell_id=fcid)
+ except ObjectDoesNotExist:
+ pass
+ lanes = ['1','2','3','4','5','6','7','8']
+ return render_to_response('experiments/flowcellSheet.html',{'fc': rec})
--- /dev/null
+from django.contrib import admin
+
+from htsworkflow.frontend.inventory.models import Item, ItemInfo, ItemType, Vendor, Location, LongTermStorage, ItemStatus
+
+class ItemAdmin(admin.ModelAdmin):
+ list_display = ('uuid', 'barcode_id','item_type', 'item_info', 'location', 'force_use_uuid', 'creation_date')
+ list_filter = (
+ 'item_type',
+ )
+
+class ItemInfoAdmin(admin.ModelAdmin):
+ pass
+
+class ItemTypeAdmin(admin.ModelAdmin):
+ pass
+
+class VendorAdmin(admin.ModelAdmin):
+ pass
+
+class LocationAdmin(admin.ModelAdmin):
+ pass
+
+class LongTermStorageAdmin(admin.ModelAdmin):
+ pass
+
+class ItemStatusAdmin(admin.ModelAdmin):
+ pass
+
+admin.site.register(Item, ItemAdmin)
+admin.site.register(ItemInfo, ItemInfoAdmin)
+admin.site.register(ItemType, ItemTypeAdmin)
+admin.site.register(Vendor, VendorAdmin)
+admin.site.register(Location, LocationAdmin)
+admin.site.register(LongTermStorage, LongTermStorageAdmin)
+admin.site.register(ItemStatus, ItemStatusAdmin)
--- /dev/null
+from django.db import models
+from django.db.models.signals import pre_save
+
+from htsworkflow.frontend.samples.models import Library
+from htsworkflow.frontend.experiments.models import FlowCell
+
+
+import uuid
+
+def _assign_uuid(sender, instance, **kwargs):
+ """
+ Assigns a UUID to model on save
+ """
+ print 'Entered _assign_uuid'
+ if instance.uuid is None or len(instance.uuid) != 32:
+ instance.uuid = uuid.uuid1().hex
+
+
+class Vendor(models.Model):
+ name = models.CharField(max_length=256)
+ url = models.URLField(blank=True, null=True)
+
+ def __unicode__(self):
+ return u"%s" % (self.name)
+
+
+class Location(models.Model):
+
+ name = models.CharField(max_length=256, unique=True)
+ location_description = models.TextField()
+
+ uuid = models.CharField(max_length=32, blank=True, help_text="Leave blank for automatic UUID generation")
+
+ notes = models.TextField(blank=True, null=True)
+
+ def __unicode__(self):
+ if len(self.location_description) > 16:
+ return u"%s: %s" % (self.name, self.location_description[0:16]+u"...")
+ else:
+ return u"%s: %s" % (self.name, self.location_description)
+
+pre_save.connect(_assign_uuid, sender=Location)
+
+class ItemInfo(models.Model):
+ model_id = models.CharField(max_length=256, blank=True, null=True)
+ part_number = models.CharField(max_length=256, blank=True, null=True)
+ lot_number = models.CharField(max_length=256, blank=True, null=True)
+
+ url = models.URLField(blank=True, null=True)
+
+ qty_purchased = models.IntegerField(default=1)
+
+ vendor = models.ForeignKey(Vendor)
+ purchase_date = models.DateField(blank=True, null=True)
+ warranty_months = models.IntegerField(blank=True, null=True)
+
+ notes = models.TextField(blank=True, null=True)
+
+ def __unicode__(self):
+ name = u''
+ if self.model_id:
+ name += u"model:%s " % (self.model_id)
+ if self.part_number:
+ name += u"part:%s " % (self.part_number)
+ if self.lot_number:
+ name += u"lot:%s " % (self.lot_number)
+
+ return u"%s: %s" % (name, self.purchase_date)
+
+
+class ItemType(models.Model):
+
+ name = models.CharField(max_length=64, unique=True)
+ description = models.TextField(blank=True, null=True)
+
+ def __unicode__(self):
+ return u"%s" % (self.name)
+
+class ItemStatus(models.Model):
+ name = models.CharField(max_length=64, unique=True)
+ notes = models.TextField(blank=True, null=True)
+
+ def __unicode__(self):
+ return self.name
+
+class Item(models.Model):
+
+ item_type = models.ForeignKey(ItemType)
+
+ #Automatically assigned uuid; used for barcode if one is not provided in
+ # barcode_id
+ uuid = models.CharField(max_length=32, blank=True, help_text="Leave blank for automatic UUID generation")
+
+ # field for existing barcodes; used instead of uuid if provided
+ barcode_id = models.CharField(max_length=256, blank=True, null=True)
+ force_use_uuid = models.BooleanField(default=False)
+
+ item_info = models.ForeignKey(ItemInfo)
+
+ location = models.ForeignKey(Location)
+
+ status = models.ForeignKey(ItemStatus, blank=True, null=True)
+
+ creation_date = models.DateTimeField(auto_now_add=True)
+ modified_date = models.DateTimeField(auto_now=True)
+
+ notes = models.TextField(blank=True, null=True)
+
+ def __unicode__(self):
+ if self.barcode_id is None or len(self.barcode_id) == 0:
+ return u"invu|%s" % (self.uuid)
+ else:
+ return u"invb|%s" % (self.barcode_id)
+
+pre_save.connect(_assign_uuid, sender=Item)
+
+
+class LongTermStorage(models.Model):
+
+ flowcell = models.ForeignKey(FlowCell)
+ libraries = models.ManyToManyField(Library)
+
+ storage_devices = models.ManyToManyField(Item)
+
+ def __unicode__(self):
+ return u"%s: %s" % (str(self.flowcell), ', '.join([ str(s) for s in self.storage_devices.iterator() ]))
\ No newline at end of file
--- /dev/null
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('',
+ (r'^lts/link/(?P<flowcell>.+)/(?P<serial>.+)/$', 'htsworkflow.frontend.inventory.views.link_flowcell_and_device'),
+ )
--- /dev/null
+from htsworkflow.frontend.inventory.models import Item, LongTermStorage
+from htsworkflow.frontend.experiments.models import FlowCell
+
+from django.core.exceptions import ObjectDoesNotExist
+from django.http import HttpResponse
+
+
+def link_flowcell_and_device(request, flowcell, serial):
+ """
+ Updates database records of a flowcell being archived on a device with a particular serial #
+ """
+ assert flowcell is not None
+ assert serial is not None
+
+ LTS_UPDATED = False
+ SD_UPDATED = False
+ LIBRARY_UPDATED = False
+
+ ###########################################
+ # Retrieve Storage Device
+ try:
+ sd = Item.objects.get(barcode_id=serial)
+ except ObjectDoesNotExist, e:
+ msg = "Item with barcode_id of %s not found." % (serial)
+ raise ObjectDoesNotExist(msg)
+
+ ###########################################
+ # Retrieve FlowCell
+ try:
+ fc = FlowCell.objects.get(flowcell_id=flowcell)
+ except ObjectDoesNotExist, e:
+ msg = "FlowCell with flowcell_id of %s not found." % (flowcell)
+ raise ObjectDoesNotExist(msg)
+
+ ###########################################
+ # Retrieve or create LongTermStorage Object
+ count = fc.longtermstorage_set.count()
+ lts = None
+ if count > 1:
+ msg = "There really should only be one longtermstorage object per flowcell"
+ raise ValueError, msg
+ elif count == 1:
+ # lts already attached to flowcell
+ lts = fc.longtermstorage_set.all()[0]
+ else:
+ lts = LongTermStorage()
+ # Attach flowcell
+ lts.flowcell = fc
+ # Need a primary keey before linking to storage devices
+ lts.save()
+ LTS_UPDATED = True
+
+
+ ############################################
+ # Link Storage to Flowcell
+
+ # Add a link to this storage device if it is not already linked.
+ if sd not in lts.storage_devices.all():
+ lts.storage_devices.add(sd)
+ SD_UPDATED = True
+
+ ###########################################
+ # Add Library Links to LTS
+
+ if fc.lane_1_library not in lts.libraries.all():
+ lts.libraries.add(fc.lane_1_library)
+ LIBRARY_UPDATED = True
+ print 1
+
+ if fc.lane_2_library not in lts.libraries.all():
+ lts.libraries.add(fc.lane_2_library)
+ LIBRARY_UPDATED = True
+ print 2
+
+ if fc.lane_3_library not in lts.libraries.all():
+ lts.libraries.add(fc.lane_3_library)
+ LIBRARY_UPDATED = True
+ print 3
+
+ if fc.lane_4_library not in lts.libraries.all():
+ lts.libraries.add(fc.lane_4_library)
+ LIBRARY_UPDATED = True
+ print 4
+
+
+ if fc.lane_5_library not in lts.libraries.all():
+ lts.libraries.add(fc.lane_5_library)
+ LIBRARY_UPDATED = True
+ print 5
+
+ if fc.lane_6_library not in lts.libraries.all():
+ lts.libraries.add(fc.lane_6_library)
+ LIBRARY_UPDATED = True
+ print 6
+
+ if fc.lane_7_library not in lts.libraries.all():
+ lts.libraries.add(fc.lane_7_library)
+ LIBRARY_UPDATED = True
+ print 7
+
+ if fc.lane_8_library not in lts.libraries.all():
+ lts.libraries.add(fc.lane_8_library)
+ LIBRARY_UPDATED = True
+ print 8
+
+ # Save Changes
+ lts.save()
+
+ msg = ['Success:']
+ if LTS_UPDATED or SD_UPDATED or LIBRARY_UPDATED:
+ msg.append(' LongTermStorage (LTS) Created: %s' % (LTS_UPDATED))
+ msg.append(' Storage Device Linked to LTS: %s' % (SD_UPDATED))
+ msg.append(' Libraries updated in LTS: %s' % (LIBRARY_UPDATED))
+ else:
+ msg.append(' No Updates Needed.')
+
+ return HttpResponse('\n'.join(msg))
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+ import settings # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ execute_manager(settings)
--- /dev/null
+<?xml version="1.0" ?>
+<Libraries>
+<Library Name="SL3">
+<Track Flowcell="FC11862" Lane="2" Filename="Flowcells/FC11862/070919_FC11862_s2_NRSF_monoclonal_Jurkat_rep2_SL3.align_25.hg18.txt" Count=" 1423565" Date="070919" />
+</Library>
+<Library Name="SL4">
+<Track Flowcell="FC10073" Lane="3" Filename="Flowcells/FC10073/070821_FC10073_s3_mock_IP_Jurkat_rep1_SL4.align_25.hg18.txt" Count=" 2132972" Date="070821" />
+<Track Flowcell="FC10182" Lane="18" Filename="Flowcells/FC10182/070925_FC10182_s18_mock_IP_Jurkat_rep1_SL4.align_25.hg18.txt" Count=" 4061515" Date="070925" />
+<Track Flowcell="FC11862" Lane="6" Filename="Flowcells/FC11862/070919_FC11862_s6_Mock_IP_Jurkat_rep1_SL4.align_25.hg18.txt" Count=" 2397558" Date="070919" />
+<Track Flowcell="FC11977" Lane="8" Filename="Flowcells/FC11977/070928_FC11977_s8_mock_IP_Jurkat_rep1_SL4.align_25.hg18.txt" Count=" 1088135" Date="070928" />
+<Track Flowcell="FC8053" Lane="78" Filename="Flowcells/FC8053/070724_FC8053_s78_mock_IP_Jurkat_rep1_SL4.align_25.hg18.txt" Count=" 3583766" Date="070724" />
+<Track Flowcell="FC8883" Lane="78" Filename="Flowcells/FC8883/070720_FC8883_s78_mock_IP_Jurkat_rep1_SL4.align_25.hg18.txt" Count=" 5491316" Date="070720" />
+<Track Flowcell="FC8886" Lane="7" Filename="Flowcells/FC8886/070802_FC8886_s7_mock_IP_Jurkat_rep1_SL4.align_25.hg18.txt" Count=" 2417786" Date="070802" />
+</Library>
+<Library Name="SL10">
+<Track Flowcell="FC11977" Lane="7" Filename="Flowcells/FC11977/070928_FC11977_s7_hct_1_msp_SL10.align_25.hg18.txt" Count=" 1801596" Date="070928" />
+<Track Flowcell="FC13593" Lane="678" Filename="Flowcells/FC13593/071002_FC13593_s678_hct_1_msp_SL10.align_25.hg18.txt" Count=" 7978981" Date="071002" />
+</Library>
+<Library Name="SL11">
+<Track Flowcell="FCOLD1" Lane="1" Filename="Flowcells/FCOLD1/070000_FCOLD1_s1_SRF_ChIP_Jurkat_Rep1_SL11.align_25.hg18.txt" Count=" 8721730" Date="070000" />
+</Library>
+<Library Name="SL13">
+<Track Flowcell="FC7225" Lane="67" Filename="Flowcells/FCSL13/070629_FC7225_s67_FoxP2_PFSK1_SL13.align_25.hg18.txt" Count=" 3830788" Date="070629" />
+<Track Flowcell="FC5507" Lane="67" Filename="Flowcells/FCSL13/070703_FC5507_s67_FoxP2_PFSK1_SL13.align_25.hg18.txt" Count=" 2694525" Date="070703" />
+<Track Flowcell="FC8053" Lane="56" Filename="Flowcells/FCSL13/070724_FC8053_s56_FoxP2_PFSK1_SL13.align_25.hg18.txt" Count=" 2214065" Date="070724" />
+<Track Flowcell="FC7857" Lane="8" Filename="Flowcells/FCSL13/070807_FC7857_s8_FoxP2_PFSK1_SL13.align_25.hg18.txt" Count=" 1273565" Date="070807" />
+</Library>
+<Library Name="SL14">
+<Track Flowcell="FC10135" Lane="4" Filename="Flowcells/FC10135/071005_FC10135_s4_FoxP2_polyclonal_pfsk1_SL14.align_25.hg18.txt" Count=" 2438679" Date="071005" />
+<Track Flowcell="FC11977" Lane="6" Filename="Flowcells/FC11977/070928_FC11977_s6_FoxP2_polyclonal_pfsk1_SL14.align_25.hg18.txt" Count=" 2007880" Date="070928" />
+<Track Flowcell="FC13593" Lane="5" Filename="Flowcells/FC13593/071002_FC13593_s5_FoxP2_polyclonal_pfsk1_SL14.align_25.hg18.txt" Count=" 2533720" Date="071002" />
+</Library>
+<Library Name="SL16">
+<Track Flowcell="FC201U7" Lane="12345678" Filename="Flowcells/FC201U7/071205_FC201U7_s12345678_mock_IP_PFSK1_SL16.align_25.hg.txt" Count=" 23476737" Date="071205" />
+</Library>
+<Library Name="SL24">
+<Track Flowcell="FC5512" Lane="123" Filename="Flowcells/FC5512/070609_FC5512_s123_d5_C_hpa_SL24.align_25.hg18.txt" Count=" 1534145" Date="070609" />
+<Track Flowcell="FC5738" Lane="12" Filename="Flowcells/FC5738/070605_FC5738_s12_d5_C_hpa_SL24.align_25.hg18.txt" Count=" 267543" Date="070605" />
+<Track Flowcell="FC6058" Lane="6" Filename="Flowcells/FC6058/070608_FC6058_s6_d5_C_hpa_SL24.align_25.hg18.txt" Count=" 2174107" Date="070608" />
+</Library>
+<Library Name="SL26">
+<Track Flowcell="FC5512" Lane="45" Filename="Flowcells/FC5512/070609_FC5512_s45_ES_E_hpa_SL26.align_25.hg18.txt" Count=" 833887" Date="070609" />
+<Track Flowcell="FC5738" Lane="4" Filename="Flowcells/FC5738/070605_FC5738_s4_d0_ES_E_hpa_SL26.align_25.hg18.txt" Count=" 324128" Date="070605" />
+<Track Flowcell="FC6058" Lane="3" Filename="Flowcells/FC6058/070608_FC6058_s3_ES_E_hpa_SL26.align_25.hg18.txt" Count=" 2385605" Date="070608" />
+<Track Flowcell="FC8880" Lane="78" Filename="Flowcells/FC8880/070810_FC8880_s78_d0_ES_E_hpa_SL26.align_25.hg18.txt" Count=" 29965" Date="070810" />
+</Library>
+<Library Name="SL28">
+<Track Flowcell="FC6058" Lane="78" Filename="Flowcells/FC6058/070608_FC6058_s78_d5_D_hpa_SL28.align_25.hg18.txt" Count=" 4785632" Date="070608" />
+</Library>
+<Library Name="SL30">
+<Track Flowcell="FC6058" Lane="4" Filename="Flowcells/FC6058/070608_FC6058_s4_ES_F_hpa_SL30.align_25.hg18.txt" Count=" 2383276" Date="070608" />
+</Library>
+<Library Name="SL33">
+<Track Flowcell="FC10182" Lane="3" Filename="Flowcells/FC10182/070925_FC10182_s3_hct_2_hpa_SL33.align_25.hg18.txt" Count=" 740316" Date="070925" />
+<Track Flowcell="FC5399" Lane="3" Filename="Flowcells/FC5399/070713_FC5399_s3_hct_2_hpa_SL33.align_25.hg18.txt" Count=" 554691" Date="070713" />
+<Track Flowcell="FC7853" Lane="3" Filename="Flowcells/FC7853/070709_FC7853_s3_hct_2_hpa_SL33.align_25.hg18.txt" Count=" 734854" Date="070709" />
+<Track Flowcell="FC8880" Lane="34" Filename="Flowcells/FC8880/070810_FC8880_s34_hct_2_hpa_SL33.align_25.hg18.txt" Count=" 1360438" Date="070810" />
+</Library>
+<Library Name="SL37">
+<Track Flowcell="FC5399" Lane="2" Filename="Flowcells/FC5399/070713_FC5399_s2_liver_2_hpa_SL37.align_25.hg18.txt" Count=" 374553" Date="070713" />
+<Track Flowcell="FC7853" Lane="2" Filename="Flowcells/FC7853/070709_FC7853_s2_liver_2_hpa_SL37.align_25.hg18.txt" Count=" 1100144" Date="070709" />
+<Track Flowcell="FC8883" Lane="3" Filename="Flowcells/FC8883/070720_FC8883_s3_liver_2_hpa_SL37.align_25.hg18.txt" Count=" 1276813" Date="070720" />
+</Library>
+<Library Name="SL38">
+<Track Flowcell="FC10182" Lane="7" Filename="Flowcells/FC10182/070925_FC10182_s7_liver_1_msp_SL38.align_25.hg18.txt" Count=" 1039338" Date="070925" />
+<Track Flowcell="FC11977" Lane="34" Filename="Flowcells/FC11977/070928_FC11977_s34_liver_1_msp_SL38.align_25.hg18.txt" Count=" 2094254" Date="070928" />
+<Track Flowcell="FC7857" Lane="5" Filename="Flowcells/FC7857/070807_FC7857_s5_liver_1_msp_SL38.align_25.hg18.txt" Count=" 1075706" Date="070807" />
+</Library>
+<Library Name="SL39">
+<Track Flowcell="FC5399" Lane="1" Filename="Flowcells/FC5399/070713_FC5399_s1_liver_1_hpa_SL39.align_25.hg18.txt" Count=" 336859" Date="070713" />
+<Track Flowcell="FC7853" Lane="1" Filename="Flowcells/FC7853/070709_FC7853_s1_liver_1_hpa_SL39.align_25.hg18.txt" Count=" 973571" Date="070709" />
+<Track Flowcell="FC8880" Lane="56" Filename="Flowcells/FC8880/070810_FC8880_s56_liver_1_hpa_SL39.align_25.hg18.txt" Count=" 876351" Date="070810" />
+<Track Flowcell="FC8883" Lane="4" Filename="Flowcells/FC8883/070720_FC8883_s4_liver_1_hpa_SL39.align_25.hg18.txt" Count=" 1316822" Date="070720" />
+</Library>
+<Library Name="SL40">
+<Track Flowcell="FC11862" Lane="7" Filename="Flowcells/FC11862/070919_FC11862_s7_RNAseq_skeletal_muscle_human_rep1_SL40.align_25.hg18.txt" Count=" 1613090" Date="070919" />
+</Library>
+<Library Name="SL41">
+<Track Flowcell="FC11862" Lane="8" Filename="Flowcells/FC11862/070919_FC11862_s8_RNAseq_skeletal_muscle_human_rep2_SL41.align_25.hg18.txt" Count=" 1036954" Date="070919" />
+</Library>
+<Library Name="SL42">
+<Track Flowcell="FC5507" Lane="12" Filename="Flowcells/FC5507/070703_FC5507_s12_AFP+_1_hpa_SL42.align_25.hg18.txt" Count=" 2297609" Date="070703" />
+<Track Flowcell="FC7225" Lane="1" Filename="Flowcells/FC7225/070629_FC7225_s1_AFP+_1_hpa_SL42.align_25.hg18.txt" Count=" 921537" Date="070629" />
+<Track Flowcell="FC7225" Lane="2" Filename="Flowcells/FC7225/070629_FC7225_s2_AFP+_1_hpa_SL42.align_25.hg18.txt" Count=" 1042305" Date="070629" />
+</Library>
+<Library Name="SL43">
+<Track Flowcell="FC5507" Lane="3" Filename="Flowcells/FC5507/070703_FC5507_s3_AFP-_1_hpa_SL43.align_25.hg18.txt" Count=" 1351625" Date="070703" />
+</Library>
+<Library Name="SL44">
+<Track Flowcell="FC5507" Lane="4" Filename="Flowcells/FC5507/070703_FC5507_s4_EB_1_hpa_SL44.align_25.hg18.txt" Count=" 1269627" Date="070703" />
+<Track Flowcell="FC7225" Lane="4" Filename="Flowcells/FC7225/070629_FC7225_s4_EB_1_hpa_SL44.align_25.hg18.txt" Count=" 1681253" Date="070629" />
+</Library>
+<Library Name="SL46">
+<Track Flowcell="FC5507" Lane="5" Filename="Flowcells/FC5507/070703_FC5507_s5_CM_1_hpa_SL46.align_25.hg18.txt" Count=" 1473405" Date="070703" />
+<Track Flowcell="FC7225" Lane="5" Filename="Flowcells/FC7225/070629_FC7225_s5_CM_1_hpa_SL46.align_25.hg18.txt" Count=" 1875969" Date="070629" />
+</Library>
+<Library Name="SL48">
+<Track Flowcell="FC8053" Lane="3" Filename="Flowcells/FC8053/070724_FC8053_s3_sperm_A_hpa_SL48.align_25.hg18.txt" Count=" 364972" Date="070724" />
+<Track Flowcell="FC8883" Lane="1" Filename="Flowcells/FC8883/070720_FC8883_s1_sperm_A_hpa_SL48.align_25.hg18.txt" Count=" 642474" Date="070720" />
+<Track Flowcell="FC8886" Lane="12" Filename="Flowcells/FC8886/070802_FC8886_s12_sperm_A_hpa_SL48.align_25.hg18.txt" Count=" 1589274" Date="070802" />
+</Library>
+<Library Name="SL49">
+<Track Flowcell="FC8053" Lane="4" Filename="Flowcells/FC8053/070724_FC8053_s4_sperm_B_hpa_SL49.align_25.hg18.txt" Count=" 426192" Date="070724" />
+<Track Flowcell="FC8883" Lane="2" Filename="Flowcells/FC8883/070720_FC8883_s2_sperm_B_hpa_SL49.align_25.hg18.txt" Count=" 956543" Date="070720" />
+<Track Flowcell="FC8886" Lane="34" Filename="Flowcells/FC8886/070802_FC8886_s34_sperm_B_hpa_SL49.align_25.hg18.txt" Count=" 1697031" Date="070802" />
+</Library>
+<Library Name="SL50">
+<Track Flowcell="FC8879" Lane="3" Filename="Flowcells/FC8879/070717_FC8879_s3_sperm_A_msp_SL50.align_25.hg18.txt" Count=" 249065" Date="070717" />
+</Library>
+<Library Name="SL53">
+<Track Flowcell="FC10073" Lane="2" Filename="Flowcells/FC10073/070821_FC10073_s2_d0_ES_C_msp_SL53.align_25.hg18.txt" Count=" 459147" Date="070821" />
+<Track Flowcell="FC10182" Lane="2" Filename="Flowcells/FC10182/070925_FC10182_s2_d0_ES_C_msp_SL53.align_25.hg18.txt" Count=" 513510" Date="070925" />
+<Track Flowcell="FC11862" Lane="345" Filename="Flowcells/FC11862/070919_FC11862_s345_d0_ES_C_msp_SL53.align_25.hg18.txt" Count=" 1650605" Date="070919" />
+</Library>
+<Library Name="SL54">
+<Track Flowcell="FC10073" Lane="456" Filename="Flowcells/FC10073/070821_FC10073_s456_pancreas_1_hpa_SL54.align_25.hg18.txt" Count=" 4352582" Date="070821" />
+<Track Flowcell="FC10182" Lane="4" Filename="Flowcells/FC10182/070925_FC10182_s4_pancreas_1_hpa_SL54.align_25.hg18.txt" Count=" 1136630" Date="070925" />
+</Library>
+<Library Name="SL56">
+<Track Flowcell="FC11862" Lane="1" Filename="Flowcells/FC11862/070919_FC11862_s1_pancreas_2_hpa_SL56.align_25.hg18.txt" Count=" 1359802" Date="070919" />
+<Track Flowcell="FC11977" Lane="2" Filename="Flowcells/FC11977/070928_FC11977_s2_pancreas_2_hpa_SL56.align_25.hg18.txt" Count=" 1120271" Date="070928" />
+</Library>
+<Library Name="SL58">
+<Track Flowcell="FC10073" Lane="78" Filename="Flowcells/FC10073/070821_FC10073_s78_jurkat_1_hpa_SL58.align_25.hg18.txt" Count=" 276664" Date="070821" />
+<Track Flowcell="FC10132" Lane="4" Filename="Flowcells/FC10132/070817_FC10132_s4_jurkat_1_hpa_SL58.align_25.hg18.txt" Count=" 1326942" Date="070817" />
+<Track Flowcell="FC10182" Lane="6" Filename="Flowcells/FC10182/070925_FC10182_s6_jurkat_1_hpa_SL58.align_25.hg18.txt" Count=" 1162424" Date="070925" />
+<Track Flowcell="FC11977" Lane="5" Filename="Flowcells/FC11977/070928_FC11977_s5_jurkat_1_hpa_SL58.align_25.hg18.txt" Count=" 904205" Date="070928" />
+</Library>
+<Library Name="SL80">
+<Track Flowcell="FC10170" Lane="3" Filename="Flowcells/FC10170/071010_FC10170_s3_WOL3_cervical_RNA_human_SL80.align_25.hg18.txt" Count=" 189349" Date="071010" />
+</Library>
+<Library Name="SL81">
+<Track Flowcell="FC10170" Lane="4" Filename="Flowcells/FC10170/071010_FC10170_s4_WOL4_cervical_RNA_human_SL81.align_25.hg18.txt" Count=" 208690" Date="071010" />
+</Library>
+<Library Name="SL82">
+<Track Flowcell="FC12673" Lane="4" Filename="Flowcells/FC12673/071023_FC12673_s4_WOL6_cervical_RNA_human_SL82.align_25.hg18.txt" Count=" 8190" Date="071023" />
+</Library>
+<Library Name="SL83">
+<Track Flowcell="30DAGAAXX" Lane="1" Filename="Flowcells/30DAGAAXX/080826_30DAGAAXX_s1_HTB-11_NRSF_ChIP_Rep1_SL83.align_25.hg18.txt" Count=" 3016467" Date="080826" />
+<Track Flowcell="FC10182" Lane="5" Filename="Flowcells/FC10182/070925_FC10182_s5_NRSF_monoclonal_HTB11_SL83.align_25.hg18.txt" Count=" 918491" Date="070925" />
+<Track Flowcell="FC11977" Lane="1" Filename="Flowcells/FC11977/070928_FC11977_s1_NRSF_monoclonal_HTB11_SL83.align_25.hg18.txt" Count=" 932151" Date="070928" />
+<Track Flowcell="FC14428" Lane="3" Filename="Flowcells/FC14428/071102_FC14428_s3_NRSF_monoclonal_HTB11_SL83.align_25.hgt18.txt" Count=" 987885" Date="071102" />
+<Track Flowcell="FC14432" Lane="2" Filename="Flowcells/FC14432/071026_FC14432_s2_NRSF_monoclonal_HTB11_SL83.align_25.hg18.txt" Count=" 1052331" Date="071026" />
+<Track Flowcell="FC6420" Lane="678" Filename="Flowcells/FC6420/080212_FC6420_s678_NRSF_ChIP_HTB-11_SL83.align_25.hg18.txt" Count=" 3489053" Date="080212" />
+</Library>
+<Library Name="SL84">
+<Track Flowcell="FC10135" Lane="1" Filename="Flowcells/FC10135/071005_FC10135_s1_BG02_ES_A_hpa_SL84.align_25.hg18.txt" Count=" 1908138" Date="071005" />
+<Track Flowcell="FC12563" Lane="1" Filename="Flowcells/FC12563/071016_FC12563_s1_BG02_ES_A_hpa_SL84.align_25.hg18.txt" Count=" 1319454" Date="071016" />
+</Library>
+<Library Name="SL85">
+<Track Flowcell="FC10135" Lane="2" Filename="Flowcells/FC10135/071005_FC10135_s2_BG02_ES_B_hpa_SL85.align_25.hg18.txt" Count=" 2046898" Date="071005" />
+<Track Flowcell="FC12563" Lane="2" Filename="Flowcells/FC12563/071016_FC12563_s2_BG02_ES_B_hpa_SL85.align_25.hg18.txt" Count=" 1576213" Date="071016" />
+</Library>
+<Library Name="SL86">
+<Track Flowcell="FC10135" Lane="7" Filename="Flowcells/FC10135/071005_FC10135_s7_H9_hepato_B_hpa_SL86.align_25.hg18.txt" Count=" 1645814" Date="071005" />
+<Track Flowcell="FC12673" Lane="6" Filename="Flowcells/FC12673/071023_FC12673_s6_H9_hepato_B_hpa_SL86.align_25.hg18.txt" Count=" 581257" Date="071023" />
+</Library>
+<Library Name="SL87">
+<Track Flowcell="FC10135" Lane="8" Filename="Flowcells/FC10135/071005_FC10135_s8_H9_hepato_D_hpa_SL87.align_25.hg18.txt" Count=" 894069" Date="071005" />
+<Track Flowcell="FC12673" Lane="7" Filename="Flowcells/FC12673/071023_FC12673_s7_H9_hepato_D_hpa_SL87.align_25.hg18.txt" Count=" 410824" Date="071023" />
+</Library>
+<Library Name="SL88">
+<Track Flowcell="30DAGAAXX" Lane="3" Filename="Flowcells/30DAGAAXX/080826_30DAGAAXX_s3_U87_monoclonal_NRSF_ChIP_Rep1_SL88.align_25.hg18.txt" Count=" 2910545" Date="080826" />
+<Track Flowcell="FC10135" Lane="3" Filename="Flowcells/FC10135/071005_FC10135_s3_NRSF_monoclonal_U87_SL88.align_25.hg18.txt" Count=" 1240914" Date="071005" />
+<Track Flowcell="FC12565" Lane="5" Filename="Flowcells/FC12565/071019_FC12565_s5_NRSF_monoclonal_U87_SL88.align_25.hg18.txt" Count=" 571952" Date="071019" />
+<Track Flowcell="FC14428" Lane="4" Filename="Flowcells/FC14428/071102_FC14428_s4_NRSF_monoclonal_U87_SL88.align_25.hg18.txt" Count=" 1114155" Date="071102" />
+<Track Flowcell="FC14432" Lane="4" Filename="Flowcells/FC14432/071026_FC14432_s4_NRSF_monoclonal_U87_SL88.align_25.hg18.txt" Count=" 914576" Date="071026" />
+<Track Flowcell="FC2057R" Lane="6" Filename="Flowcells/FC2057R/071211_FC2057R_s6_U87_monoclonal_NRSF_ChIP_SL88.align_25.hg18.txt" Count=" 172579" Date="071211" />
+<Track Flowcell="FC6192" Lane="345" Filename="Flowcells/FC6192/080212_FC6192_s345_NRSF_ChIP_UB7_SL88.align_25.hg18.txt" Count=" 3307816" Date="080212" />
+</Library>
+<Library Name="SL89">
+<Track Flowcell="FC10135" Lane="5" Filename="Flowcells/FC10135/071005_FC10135_s5_FoxP2_polyclonal_pfsk1_SL89.align_25.hg18.txt" Count=" 1992055" Date="071005" />
+<Track Flowcell="FC10170" Lane="56" Filename="Flowcells/FC10170/071010_FC10170_s56_FoxP2_polyclonal_pfsk1_SL89.align_25.hg18.txt" Count=" 2332472" Date="071010" />
+<Track Flowcell="FC12673" Lane="5" Filename="Flowcells/FC12673/071023_FC12673_s5_FoxP2_polyclonal_pfsk1_SL89.align_25.hg18.txt" Count=" 754441" Date="071023" />
+<Track Flowcell="FC14432" Lane="5678" Filename="Flowcells/FC14432/071026_FC14432_s5678_FoxP2_polyclonal_pfsk1_SL89.align_25.hg18.txt" Count=" 4136620" Date="071026" />
+</Library>
+<Library Name="SL90">
+<Track Flowcell="FC10135" Lane="6" Filename="Flowcells/FC10135/071005_FC10135_s6_NlaIII_18_mouse_SL90.align_25.hg18.txt" Count=" 925114" Date="071005" />
+</Library>
+<Library Name="SL91">
+<Track Flowcell="FC10170" Lane="1" Filename="Flowcells/FC10170/071010_FC10170_s1_BG02_hepato_B_hpa_SL91.align_25.hg18.txt" Count=" 53593" Date="071010" />
+<Track Flowcell="FC12673" Lane="3" Filename="Flowcells/FC12673/071023_FC12673_s3_BG02_hepato_B_hpa_SL91.align_25.hg18.txt" Count=" 34104" Date="071023" />
+</Library>
+<Library Name="SL92">
+<Track Flowcell="FC10170" Lane="2" Filename="Flowcells/FC10170/071010_FC10170_s2_BG02_hepato_C_hpa_SL92.align_25.hg18.txt" Count=" 101462" Date="071010" />
+</Library>
+<Library Name="SL93">
+<Track Flowcell="FC10170" Lane="7" Filename="Flowcells/FC10170/071010_FC10170_s7_HCT_mCIP_1_SL93.align_25.hg18.txt" Count=" 1110620" Date="071010" />
+<Track Flowcell="FC12673" Lane="8" Filename="Flowcells/FC12673/071023_FC12673_s8_HCT_mCIP_1_SL93.align_25.hg18.txt" Count=" 348238" Date="071023" />
+<Track Flowcell="FC14430" Lane="78" Filename="Flowcells/FC14430/071030_FC14430_s78_HCT_mCIP_1_SL93.align_25.hg18.txt" Count=" 1271501" Date="071030" />
+</Library>
+<Library Name="SL94">
+<Track Flowcell="FC10170" Lane="8" Filename="Flowcells/FC10170/071010_FC10170_s8_HCT_unbound_mCIP_1_SL94.align_25.hg18.txt" Count=" 926056" Date="071010" />
+</Library>
+<Library Name="SL98">
+<Track Flowcell="FC12563" Lane="3" Filename="Flowcells/FC12563/071016_FC12563_s3_fetal_liver_11weeks_1_hpa_SL98.align_25.hg18.txt" Count=" 199565" Date="071016" />
+<Track Flowcell="FC12565" Lane="12" Filename="Flowcells/FC12565/071019_FC12565_s12_fetal_liver_11weeks_1_hpa_SL98.align_25.hg18.txt" Count=" 764623" Date="071019" />
+<Track Flowcell="FC12673" Lane="1" Filename="Flowcells/FC12673/071023_FC12673_s1_fetal_liver_11weeks_1_hpa_SL98.align_25.hg18.txt" Count=" 97009" Date="071023" />
+</Library>
+<Library Name="SL99">
+<Track Flowcell="FC12563" Lane="4" Filename="Flowcells/FC12563/071016_FC12563_s4_fetal_liver_24weeks_1_hpa_SL99.align_25.hg18.txt" Count=" 101572" Date="071016" />
+<Track Flowcell="FC12565" Lane="34" Filename="Flowcells/FC12565/071019_FC12565_s34_fetal_liver_24weeks_1_hpa_SL99.align_25.hg18.txt" Count=" 315747" Date="071019" />
+<Track Flowcell="FC12673" Lane="2" Filename="Flowcells/FC12673/071023_FC12673_s2_fetal_liver_24weeks_1_hpa_SL99.align_25.hg18.txt" Count=" 64593" Date="071023" />
+</Library>
+<Library Name="SL100">
+<Track Flowcell="FC12563" Lane="5" Filename="Flowcells/FC12563/071016_FC12563_s5_Y157SL_genomic_yeast_SL100.align_25.hg18.txt" Count=" 316612" Date="071016" />
+</Library>
+<Library Name="SL101">
+<Track Flowcell="FC12565" Lane="78" Filename="Flowcells/FC12565/071019_FC12565_s78_FoxP2_polyclonal_SK_N_MC_SL101.align_25.hg18.txt" Count=" 2344547" Date="071019" />
+</Library>
+<Library Name="SL102">
+<Track Flowcell="FC20162" Lane="4" Filename="Flowcells/FC20162/080111_FC20162_s4_SK-N-MC_TotalChromatin_SL102.align_25.hg18.txt" Count=" 3103385" Date="080111" />
+<Track Flowcell="FC202W1" Lane="1234" Filename="Flowcells/FC202W1/080116_FC202W1_s1234_SK-N-MC_total_chromatin_SL102.align_25.hg18.txt" Count=" 6381095" Date="080116" />
+<Track Flowcell="FC2057R" Lane="4" Filename="Flowcells/FC2057R/071211_FC2057R_s4_SK_N_MC_control_SL102.align_25.hg18.txt" Count=" 247103" Date="071211" />
+<Track Flowcell="FC2057R" Lane="5" Filename="Flowcells/FC2057R/071211_FC2057R_s5_SK_N_MC_control_SL102.align_25.hg18.txt" Count=" 285363" Date="071211" />
+</Library>
+<Library Name="SL103">
+<Track Flowcell="30DAGAAXX" Lane="4" Filename="Flowcells/30DAGAAXX/080826_30DAGAAXX_s4_U87_Control_SL103.align_25.hg18.txt" Count=" 5805925" Date="080826" />
+<Track Flowcell="FC12565" Lane="6" Filename="Flowcells/FC12565/071019_FC12565_s6_mock_IP_U87_SL103.align_25.hg18.txt" Count=" 1642558" Date="071019" />
+<Track Flowcell="FC14428" Lane="5" Filename="Flowcells/FC14428/071102_FC14428_s5_mock_IP_U87_SL103.align_25.hg18.txt" Count=" 44271" Date="071102" />
+<Track Flowcell="FC14432" Lane="3" Filename="Flowcells/FC14432/071026_FC14432_s3_mock_IP_U87_SL103.align_25.hg18.txt" Count=" 2246689" Date="071026" />
+<Track Flowcell="FC6420" Lane="45" Filename="Flowcells/FC6420/080212_FC6420_s45_UB7_Control_SL103.align_25.hg18.txt" Count=" 7268724" Date="080212" />
+</Library>
+<Library Name="SL104">
+<Track Flowcell="FC14426" Lane="3" Filename="Flowcells/FC14426/071106_FC14426_s3_WOL9_small_RNA_human_SL104.align_25.hg18.txt" Count=" 104372" Date="071106" />
+</Library>
+<Library Name="SL105">
+<Track Flowcell="FC14426" Lane="4" Filename="Flowcells/FC14426/071106_FC14426_s4_WOL8_small_RNA_human_SL105.align_25.hg18.txt" Count=" 433070" Date="071106" />
+</Library>
+<Library Name="SL108">
+<Track Flowcell="30DAGAAXX" Lane="2" Filename="Flowcells/30DAGAAXX/080826_30DAGAAXX_s2_HTB-11_Control_SL108.align_25.hg18.txt" Count=" 6550943" Date="080826" />
+<Track Flowcell="FC14428" Lane="6" Filename="Flowcells/FC14428/071102_FC14428_s6_mock_IP_HTB11_SL108.align_25.hg18.txt" Count=" 201318" Date="071102" />
+<Track Flowcell="FC14432" Lane="1" Filename="Flowcells/FC14432/071026_FC14432_s1_mock_IP_HTB11_SL108.align_25.hg18.txt" Count=" 2525735" Date="071026" />
+<Track Flowcell="FC6420" Lane="123" Filename="Flowcells/FC6420/080212_FC6420_s123_HTB-11_Control_SL108.align_25.hg18.txt" Count=" 9532996" Date="080212" />
+</Library>
+<Library Name="SL109">
+<Track Flowcell="FC14428" Lane="7" Filename="Flowcells/FC14428/071102_FC14428_s7_RNAseq_liver_human_rep1_SL109.align_25.hg18.txt" Count=" 755566" Date="071102" />
+</Library>
+<Library Name="SL110">
+<Track Flowcell="FC14428" Lane="8" Filename="Flowcells/FC14428/071102_FC14428_s8_RNAseq_liver_human_rep2_SL110.align_25.hg18.txt" Count=" 515935" Date="071102" />
+<Track Flowcell="FC14763" Lane="4" Filename="Flowcells/FC14763/071129_FC14763_s4_RNAseq_liver_human_rep2_SL110.align_25.hg18.txt" Count=" 501659" Date="071129" />
+</Library>
+<Library Name="SL111">
+<Track Flowcell="FC14426" Lane="1" Filename="Flowcells/FC14426/071106_FC14426_s1_BG02_hepato_B2_hpa_SL111.align_25.hg18.txt" Count=" 1878793" Date="071106" />
+<Track Flowcell="FC14430" Lane="1" Filename="Flowcells/FC14430/071030_FC14430_s1_BG02_hepato_B2_hpa_SL111.align_25.hg18.txt" Count=" 1172349" Date="071030" />
+</Library>
+<Library Name="SL112">
+<Track Flowcell="FC14426" Lane="2" Filename="Flowcells/FC14426/071106_FC14426_s2_BG02_hepato_C2_hpa_SL112.align_25.hg18.txt" Count=" 2107429" Date="071106" />
+<Track Flowcell="FC14430" Lane="2" Filename="Flowcells/FC14430/071030_FC14430_s2_BG02_hepato_C2_hpa_SL112.align_25.hg18.txt" Count=" 1447587" Date="071030" />
+</Library>
+<Library Name="SL113">
+<Track Flowcell="FC14420" Lane="1" Filename="Flowcells/FC14420/071113_FC14420_s1_fetal_liver_11weeks2_hpa_SL113.align_25.hg18.txt" Count=" 1250091" Date="071113" />
+<Track Flowcell="FC14428" Lane="1" Filename="Flowcells/FC14428/071102_FC14428_s1_fetal_liver_11weeks2_hpa_SL113.align_25.hgt18.txt" Count=" 1172349" Date="071102" />
+<Track Flowcell="FC14430" Lane="3" Filename="Flowcells/FC14430/071030_FC14430_s3_fetal_liver_11weeks2_hpa_SL113.align_25.hg18.txt" Count=" 987885" Date="071030" />
+</Library>
+<Library Name="SL114">
+<Track Flowcell="FC14420" Lane="2" Filename="Flowcells/FC14420/071113_FC14420_s2_fetal_liver_24weeks2_hpa_SL114.align_25.hg18.txt" Count=" 1805836" Date="071113" />
+<Track Flowcell="FC14428" Lane="2" Filename="Flowcells/FC14428/071102_FC14428_s2_fetal_liver_24weeks2_hpa_SL114.align_25.hgt18.txt" Count=" 1447587" Date="071102" />
+<Track Flowcell="FC14430" Lane="4" Filename="Flowcells/FC14430/071030_FC14430_s4_fetal_liver_24weeks2_hpa_SL114.align_25.hg18.txt" Count=" 1114155" Date="071030" />
+</Library>
+<Library Name="SL115">
+<Track Flowcell="FC202VW" Lane="1234" Filename="Flowcells/FC202VW/071218_FC202VW_s1234_cat_x_chromosome_SL115.align_25.catGar12.txt" Count=" 5488573" Date="071218" />
+</Library>
+<Library Name="SL116">
+<Track Flowcell="FC12472" Lane="12" Filename="Flowcells/FC12472/071116_FC12472_s12_NRSF_monoclonal_PANC1_SL116.align_25.hg18.txt" Count=" 1924940" Date="071116" />
+<Track Flowcell="FC14420" Lane="5" Filename="Flowcells/FC14420/071113_FC14420_s5_NRSF_monoclonal_PANC1_SL116.align_25.hg18.txt" Count=" 1037723" Date="071113" />
+<Track Flowcell="FC14426" Lane="5" Filename="Flowcells/FC14426/071106_FC14426_s5_NRSF_monoclonal_PANC1_SL116.align_25.hg18.txt" Count=" 961751" Date="071106" />
+<Track Flowcell="FC6192" Lane="678" Filename="Flowcells/FC6192/080212_FC6192_s678_NRSF_ChIP_PANC1_SL116.align_25.hg18.txt" Count=" 4075003" Date="080212" />
+</Library>
+<Library Name="SL117">
+<Track Flowcell="FC14420" Lane="6" Filename="Flowcells/FC14420/071113_FC14420_s6_mock_IP_PANC1_SL117.align_25.hg18.txt" Count=" 2462518" Date="071113" />
+<Track Flowcell="FC14426" Lane="6" Filename="Flowcells/FC14426/071106_FC14426_s6_mock_IP_PANC1_SL117.align_25.hg18.txt" Count=" 2214338" Date="071106" />
+<Track Flowcell="FC6192" Lane="12" Filename="Flowcells/FC6192/080212_FC6192_s12_PANC1_Control_SL117.align_25.hg18.txt" Count=" 6046619" Date="080212" />
+</Library>
+<Library Name="SL118">
+<Track Flowcell="FC12472" Lane="34" Filename="Flowcells/FC12472/071116_FC12472_s34_NRSF_monoclonal_HTB187_SL118.align_25.hg18.txt" Count=" 2520211" Date="071116" />
+<Track Flowcell="FC14420" Lane="7" Filename="Flowcells/FC14420/071113_FC14420_s7_NRSF_monoclonal_HTB187_SL118.align_25.hg18.txt" Count=" 1183349" Date="071113" />
+<Track Flowcell="FC14426" Lane="7" Filename="Flowcells/FC14426/071106_FC14426_s7_NRSF_monoclonal_HTB187_SL118.align_25.hg18.txt" Count=" 998104" Date="071106" />
+</Library>
+<Library Name="SL119">
+<Track Flowcell="FC14420" Lane="8" Filename="Flowcells/FC14420/071113_FC14420_s8_mock_IP_HTB187_SL119.align_25.hg18.txt" Count=" 2376268" Date="071113" />
+<Track Flowcell="FC14426" Lane="8" Filename="Flowcells/FC14426/071106_FC14426_s8_mock_IP_HTB187_SL119.align_25.hg18.txt" Count=" 1606271" Date="071106" />
+</Library>
+<Library Name="SL120">
+<Track Flowcell="FC13512" Lane="1" Filename="Flowcells/FC13512/071109_FC13512_s1_NRSF_monoclonal_Jurkat_SL120.align_25.hg18.txt" Count=" 1285225" Date="071109" />
+<Track Flowcell="FC14420" Lane="3" Filename="Flowcells/FC14420/071113_FC14420_s3_NRSF_monoclonal_Jurkat_SL120.align_25.hg18.txt" Count=" 2130283" Date="071113" />
+</Library>
+<Library Name="SL121">
+<Track Flowcell="FC13512" Lane="2" Filename="Flowcells/FC13512/071109_FC13512_s2_GAPB_monoclonal_Jurkat_SL121.align_25.hg18.txt" Count=" 1512986" Date="071109" />
+<Track Flowcell="FC14420" Lane="4" Filename="Flowcells/FC14420/071113_FC14420_s4_GAPB_monoclonal_Jurkat_SL121.align_25.hg18.txt" Count=" 2069705" Date="071113" />
+<Track Flowcell="FC207CF" Lane="4" Filename="Flowcells/FC207CF/080207_FC207CF_s4_Jurkat_GABP_ChIP_SL121.align_25.hg18.txt" Count=" 11127549" Date="080207" />
+<Track Flowcell="FC20AJ4" Lane="2" Filename="Flowcells/FC20AJ4/080312_FC20AJ4_s2_Jurkat_GABP_ChIP_SL121.align_25.hg18.txt" Count=" 3288504" Date="080312" />
+</Library>
+<Library Name="SL127">
+<Track Flowcell="FC12472" Lane="7" Filename="Flowcells/FC12472/071116_FC12472_s7_RNA_Pol_Jurkat_SL127.align_25.hg18.txt" Count=" 1744821" Date="071116" />
+<Track Flowcell="FC2057R" Lane="7" Filename="Flowcells/FC2057R/071211_FC2057R_s7_RNA_PoI_II_ChIP_Jurkat_SL127.align_25.hg18.txt" Count=" 245677" Date="071211" />
+<Track Flowcell="FC2057R" Lane="8" Filename="Flowcells/FC2057R/071211_FC2057R_s8_RNA_PoI_II_ChIP_Jurkat_SL127.align_25.hg18.txt" Count=" 124585" Date="071211" />
+<Track Flowcell="FC2057R" Lane="4" Filename="Flowcells/FC2057R/080118_FC2057R_s4_RNApol2_ChIP_Jurkat_SL127.align_25.hg18.txt" Count=" 2876921" Date="080118" />
+<Track Flowcell="FC20686" Lane="4" Filename="Flowcells/FC20686/080221_FC20686_s4_RNApol2_ChIP_Jurkat_SL127.align_25.hg18.txt" Count=" 15232" Date="080221" />
+<Track Flowcell="FC207CF" Lane="5" Filename="Flowcells/FC207CF/080207_FC207CF_s5_RNApol2_ChIP_Jurkat_SL127.align_25.hg18.txt" Count=" 14282376" Date="080207" />
+<Track Flowcell="FC20AN8" Lane="4" Filename="Flowcells/FC20AN8/080310_FC20AN8_s4_RNApol2_ChIP_Jurkat_SL127.align_25.hg18.txt" Count=" 804871" Date="080310" />
+</Library>
+<Library Name="SL128">
+<Track Flowcell="FC12472" Lane="8" Filename="Flowcells/FC12472/071116_FC12472_s8_MsMeCP2_Jurkat_SL128.align_25.hg18.txt" Count=" 1441721" Date="071116" />
+<Track Flowcell="FC204PR" Lane="8" Filename="Flowcells/FC204PR/080520_FC204PR_s8_MeCP2_ChIP_Jurkat_SL128.align_25.hg18.txt" Count=" 3300096" Date="080520" />
+<Track Flowcell="FC2057R" Lane="5" Filename="Flowcells/FC2057R/080118_FC2057R_s5_MeCP2_ChIP_Jurkat_SL128.align_25.hg18.txt" Count=" 2246279" Date="080118" />
+</Library>
+<Library Name="SL129">
+<Track Flowcell="FC14763" Lane="1" Filename="Flowcells/FC14763/071129_FC14763_s1_dko_1_hpa_SL129.align_25.hg18.txt" Count=" 1039877" Date="071129" />
+<Track Flowcell="FC20162" Lane="16" Filename="Flowcells/FC20162/080111_FC20162_s16_dko_1_hpa_SL129.align_25.hg18.txt" Count=" 3270592" Date="080111" />
+<Track Flowcell="FC2057R" Lane="1" Filename="Flowcells/FC2057R/071211_FC2057R_s1_dko_1_hpa_SL129.align_25.hg18.txt" Count=" 246639" Date="071211" />
+<Track Flowcell="FC2057R" Lane="12" Filename="Flowcells/FC2057R/080118_FC2057R_s12_dko_1_hpa_SL129.align_25.hg18.txt" Count=" 5238922" Date="080118" />
+</Library>
+<Library Name="SL130">
+<Track Flowcell="FC14763" Lane="2" Filename="Flowcells/FC14763/071129_FC14763_s2_dnmt1_1_hpa_SL130.align_25.hg18.txt" Count=" 1224247" Date="071129" />
+<Track Flowcell="FC20162" Lane="27" Filename="Flowcells/FC20162/080111_FC20162_s27_dnmt1_1_hpa_SL130.align_25.hg18.txt" Count=" 3592097" Date="080111" />
+<Track Flowcell="FC2057R" Lane="2" Filename="Flowcells/FC2057R/071211_FC2057R_s2_dnmt1_1_hpa_SL130.align_25.hg18.txt" Count=" 417799" Date="071211" />
+</Library>
+<Library Name="SL131">
+<Track Flowcell="FC14763" Lane="3" Filename="Flowcells/FC14763/071129_FC14763_s3_dnmt3b_1_hpa_SL131.align_25.hg18.txt" Count=" 1328448" Date="071129" />
+<Track Flowcell="FC20162" Lane="38" Filename="Flowcells/FC20162/080111_FC20162_s38_dmnt3b_1_hpa_SL131.align_25.hg18.txt" Count=" 3486008" Date="080111" />
+<Track Flowcell="FC2057R" Lane="3" Filename="Flowcells/FC2057R/071211_FC2057R_s3_dnmt3b_1_hpa_SL131.align_25.hg18.txt" Count=" 501842" Date="071211" />
+</Library>
+<Library Name="SL138">
+<Track Flowcell="FC2057U" Lane="1" Filename="Flowcells/FC2057U/080220_FC2057U_s1_e_7_75_Embryo_hpa_1_SL138.align_25.hg18.txt" Count=" 3235636" Date="080220" />
+<Track Flowcell="FC205DP" Lane="3" Filename="Flowcells/FC205DP/080118_FC205DP_s3_e_7_75_Embryo_hpa_SL138.align_25.mm9.txt" Count=" 3251998" Date="080118" />
+</Library>
+<Library Name="SL139">
+<Track Flowcell="FC2057U" Lane="2" Filename="Flowcells/FC2057U/080220_FC2057U_s2_e_7_75_Extra_Em_hpa_1_SL139.align_25.hg18.txt" Count=" 3408585" Date="080220" />
+<Track Flowcell="FC205DP" Lane="6" Filename="Flowcells/FC205DP/080118_FC205DP_s6_e_7_75_Extra_Em_hpa_1_SL139.align_25.mm9.txt" Count=" 3017471" Date="080118" />
+</Library>
+<Library Name="SL140">
+<Track Flowcell="FC2057U" Lane="7" Filename="Flowcells/FC2057U/080220_FC2057U_s7_e_8_5_Unturned_hpa_1_SL140.align_25.hg18.txt" Count=" 4152706" Date="080220" />
+<Track Flowcell="FC205DP" Lane="7" Filename="Flowcells/FC205DP/080118_FC205DP_s7_e_8_5_Unturned_hpa_SL140.align_25.mm9.txt" Count=" 2924215" Date="080118" />
+</Library>
+<Library Name="SL141">
+<Track Flowcell="FC20678" Lane="1" Filename="Flowcells/FC20678/080214_FC20678_s1_e11_5_SL141.align_25.hg18.txt" Count=" 288210" Date="080214" />
+<Track Flowcell="FC20AJ6" Lane="7" Filename="Flowcells/FC20AJ6/080318_FC20AJ6_s7_e11.5_Fet-Plac_hpa_SL141.align_25.mm9.txt" Count=" 3531295" Date="080318" />
+</Library>
+<Library Name="SL142">
+<Track Flowcell="FC20678" Lane="2" Filename="Flowcells/FC20678/080214_FC20678_s2_e15_5_SL142.align_25.hg18.txt" Count=" 610226" Date="080214" />
+<Track Flowcell="FC20AJ6" Lane="8" Filename="Flowcells/FC20AJ6/080318_FC20AJ6_s8_e1.5_Fet-Plac_hpa_SL142.align_25.mm9.txt" Count=" 3896266" Date="080318" />
+</Library>
+<Library Name="SL143">
+<Track Flowcell="FC2057U" Lane="8" Filename="Flowcells/FC2057U/080220_FC2057U_s8_e_15_5_Fet_Plac_msp_1_SL143.align_25.hg18.txt" Count=" 2901012" Date="080220" />
+<Track Flowcell="FC205DP" Lane="8" Filename="Flowcells/FC205DP/080118_FC205DP_s8_e_15_5_Fet_Plac_msp_1_SL143.align_25.mm9.txt" Count=" 2661896" Date="080118" />
+</Library>
+<Library Name="SL144">
+<Track Flowcell="FC20162" Lane="5" Filename="Flowcells/FC20162/080111_FC20162_s5_SK-N-MC_FOXP2_ChIP_SL144.align_25.hg18.txt" Count=" 2578704" Date="080111" />
+<Track Flowcell="FC202W1" Lane="5678" Filename="Flowcells/FC202W1/080116_FC202W1_s5678_SK-N-MC_FOXP2_ChIP_SL144.align_25.hg18.txt" Count=" 10867872" Date="080116" />
+</Library>
+<Library Name="SL147">
+<Track Flowcell="FC2065U" Lane="12" Filename="Flowcells/FC2065U/080226_FC2065U_s12_BE2_C_NRSF_ChIP_SL147.align_25.hg18.txt" Count=" 5768434" Date="080226" />
+<Track Flowcell="FC20686" Lane="5" Filename="Flowcells/FC20686/080221_FC20686_s5_BE2_C_NRSF_ChIP_SL147.align_25.hg18.txt" Count=" 327" Date="080221" />
+<Track Flowcell="FC20AJ4" Lane="3" Filename="Flowcells/FC20AJ4/080312_FC20AJ4_s3_BE_2_-C_NRSF_ChIP_SL147.align_25.hg18.txt" Count=" 3022727" Date="080312" />
+</Library>
+<Library Name="SL148">
+<Track Flowcell="FC2065U" Lane="3" Filename="Flowcells/FC2065U/080226_FC2065U_s3_Input_BE2_C_SL148.align_25.hg18.txt" Count=" 4076715" Date="080226" />
+<Track Flowcell="FC2079B" Lane="5" Filename="Flowcells/FC2079B/080129_FC2079B_s5_Input_BE2-C_SL148.align_25.hg18.txt" Count=" 3917265" Date="080129" />
+<Track Flowcell="FC20AJ6" Lane="4" Filename="Flowcells/FC20AJ6/080318_FC20AJ6_s4_Input_control_BE2-C_SL148.align_25.hg18.txt" Count=" 4103876" Date="080318" />
+</Library>
+<Library Name="SL149">
+<Track Flowcell="FC2065U" Lane="45" Filename="Flowcells/FC2065U/080226_FC2065U_s45_PFSK1_NRSF_ChIP_SL149.align_25.hg18.txt" Count=" 5690999" Date="080226" />
+<Track Flowcell="FC20678" Lane="6" Filename="Flowcells/FC20678/080214_FC20678_s6_NRSF_ChIP_PFSK-1_SL149.align_25.hg18.txt" Count=" 976436" Date="080214" />
+<Track Flowcell="FC20686" Lane="6" Filename="Flowcells/FC20686/080221_FC20686_s6_PFSK1_NRSF_ChIP_SL149.align_25.hg18.txt" Count=" 17027" Date="080221" />
+<Track Flowcell="FC20AJ4" Lane="4" Filename="Flowcells/FC20AJ4/080312_FC20AJ4_s4_PFSK1_NRSF_ChIP_SL149.align_25.hg18.txt" Count=" 2779349" Date="080312" />
+</Library>
+<Library Name="SL150">
+<Track Flowcell="FC2065U" Lane="6" Filename="Flowcells/FC2065U/080226_FC2065U_s6_Input_PFSK1_SL150.align_25.hg18.txt" Count=" 3558958" Date="080226" />
+<Track Flowcell="FC2079B" Lane="6" Filename="Flowcells/FC2079B/080129_FC2079B_s6_Input_PFSK-1_SL150.align_25.hg18.txt" Count=" 3864147" Date="080129" />
+<Track Flowcell="FC20AJ6" Lane="5" Filename="Flowcells/FC20AJ6/080318_FC20AJ6_s5_Input_control_PSF-1_SL150.align_25.hg18.txt" Count=" 4013975" Date="080318" />
+</Library>
+<Library Name="SL152">
+<Track Flowcell="FC2079B" Lane="4" Filename="Flowcells/FC2079B/080129_FC2079B_s4_scer_rnaseq_SL152.align_25.scer.txt" Count=" 3578645" Date="080129" />
+</Library>
+<Library Name="SL153">
+<Track Flowcell="FC207CF" Lane="2" Filename="Flowcells/FC207CF/080207_FC207CF_s2_InputControl_SL153.align_25.hg18.txt" Count=" 0" Date="080207" />
+</Library>
+<Library Name="SL154">
+<Track Flowcell="FC207CF" Lane="3" Filename="Flowcells/FC207CF/080207_FC207CF_s3_PSTAT_ChIP_SL154.align_25.hg18.txt" Count=" 0" Date="080207" />
+</Library>
+<Library Name="SL155">
+<Track Flowcell="FC20678" Lane="3" Filename="Flowcells/FC20678/080214_FC20678_s3_WL_GCT3_RNAseq_SL155.align_25.hg18.txt" Count=" 90301" Date="080214" />
+</Library>
+<Library Name="SL156">
+<Track Flowcell="FC20678" Lane="4" Filename="Flowcells/FC20678/080214_FC20678_s4_WL_GCT4_RNAseq_SL156.align_25.hg18.txt" Count=" 5791" Date="080214" />
+</Library>
+<Library Name="SL157">
+<Track Flowcell="FC2057U" Lane="3" Filename="Flowcells/FC2057U/080220_FC2057U_s3_Input_mouse_neurons_SL157.align_25.hg18.txt" Count=" 4030470" Date="080220" />
+</Library>
+<Library Name="SL158">
+<Track Flowcell="FC2057U" Lane="4" Filename="Flowcells/FC2057U/080220_FC2057U_s4_MeCP2_ChIP_SL158.align_25.hg18.txt" Count=" 2669313" Date="080220" />
+</Library>
+<Library Name="SL159">
+<Track Flowcell="FC2057U" Lane="5" Filename="Flowcells/FC2057U/080220_FC2057U_s5_Input_mouse_neurons_SL159.align_25.hg18.txt" Count=" 1776966" Date="080220" />
+</Library>
+<Library Name="SL160">
+<Track Flowcell="FC2057U" Lane="6" Filename="Flowcells/FC2057U/080220_FC2057U_s6_MEF2_ChIP_SL160.align_25.hg18.txt" Count=" 3568746" Date="080220" />
+</Library>
+<Library Name="SL161">
+<Track Flowcell="FC2064D" Lane="1" Filename="Flowcells/FC2064D/080208_FC2064D_s1_GABP_1x_K562_ChIP_SL161.align_25.hg18.txt" Count=" 1337451" Date="080208" />
+<Track Flowcell="FC20ANBA" Lane="4" Filename="Flowcells/FC20ANBA/080321_FC20ANBA_s4_GABP_ChIP_1x_K562_SL161.align_25.hg18.txt" Count=" 1933407" Date="080321" />
+</Library>
+<Library Name="SL162">
+<Track Flowcell="FC2064D" Lane="2" Filename="Flowcells/FC2064D/080208_FC2064D_s2_GABP_4x_K562_ChIP_SL162.align_25.hg18.txt" Count=" 1581402" Date="080208" />
+<Track Flowcell="FC20ANBA" Lane="5" Filename="Flowcells/FC20ANBA/080321_FC20ANBA_s5_GABP_ChIP_4x_K562_SL162.align_25.hg18.txt" Count=" 1981536" Date="080321" />
+</Library>
+<Library Name="SL163">
+<Track Flowcell="FC2064D" Lane="3" Filename="Flowcells/FC2064D/080208_FC2064D_s3_Input_K562_1_SL163.align_25.hg18.txt" Count=" 2506864" Date="080208" />
+</Library>
+<Library Name="SL164">
+<Track Flowcell="FC2064D" Lane="6" Filename="Flowcells/FC2064D/080208_FC2064D_s6_PolII_1x_K562_ChIP_SL164.align_25.hg18.txt" Count=" 2542107" Date="080208" />
+</Library>
+<Library Name="SL165">
+<Track Flowcell="FC2064D" Lane="7" Filename="Flowcells/FC2064D/080208_FC2064D_s7_PolII_4x_K562_ChIP_SL165.align_25.hg18.filter.txt" Count=" 2887076" Date="080208" />
+<Track Flowcell="FC2064D" Lane="7" Filename="Flowcells/FC2064D/080208_FC2064D_s7_PolII_4x_K562_ChIP_SL165.align_25.hg18.txt" Count=" 2890553" Date="080208" />
+<Track Flowcell="FC20ANBA" Lane="6" Filename="Flowcells/FC20ANBA/080321_FC20ANBA_s6_RNApol2_ChIP_4x_K562_SL165.align_25.hg18.txt" Count=" 2938622" Date="080321" />
+</Library>
+<Library Name="SL166">
+<Track Flowcell="FC2064D" Lane="8" Filename="Flowcells/FC2064D/080208_FC2064D_s8_Input_K562_2_SL166.align_25.hg18.txt" Count=" 2704047" Date="080208" />
+</Library>
+<Library Name="SL167">
+<Track Flowcell="FC2065U" Lane="78" Filename="Flowcells/FC2065U/080226_FC2065U_s78_FOXP2_ChIP_SKNMC_SL167.align_25.hg18.txt" Count=" 7161740" Date="080226" />
+<Track Flowcell="FC20678" Lane="78" Filename="Flowcells/FC20678/080214_FC20678_s78_FOXP2_ChIP_SK-N-MC_SL167.align_25.hg18.txt" Count=" 2037766" Date="080214" />
+<Track Flowcell="FC20686" Lane="78" Filename="Flowcells/FC20686/080221_FC20686_s78_FOXP2_ChIP_SKNMC_SL167.align_25.hg18.txt" Count=" 35763" Date="080221" />
+<Track Flowcell="FC20AJ4" Lane="5" Filename="Flowcells/FC20AJ4/080312_FC20AJ4_s5_FOXP2_ChIP_SK-N-MC_SL167.align_25.hg18.txt" Count=" 3185960" Date="080312" />
+</Library>
+<Library Name="SL168">
+<Track Flowcell="FC207CF" Lane="6" Filename="Flowcells/FC207CF/080207_FC207CF_s6_RNASeq_muscle_1_SL168.align_25.hg18.txt" Count=" 1531101" Date="080207" />
+</Library>
+<Library Name="SL169">
+<Track Flowcell="FC207CF" Lane="7" Filename="Flowcells/FC207CF/080207_FC207CF_s7_RNASeq_muscle_2_SL169.align_25.hg18.txt" Count=" 89434" Date="080207" />
+</Library>
+<Library Name="SL170">
+<Track Flowcell="FC20686" Lane="1" Filename="Flowcells/FC20686/080221_FC20686_s1_Methyl_ChIP_K562_SL170.align_25.hg18.txt" Count=" 9738" Date="080221" />
+<Track Flowcell="FC209RM" Lane="12" Filename="Flowcells/FC209RM/080325_FC209RM_s12_Input_Control_K562_SL170.align_25.hg18.txt" Count=" 5950898" Date="080325" />
+<Track Flowcell="FC20AJB" Lane="7" Filename="Flowcells/FC20AJB/080411_FC20AJB_s7_Input_Control_K562_SL170.align_25.hg18.txt" Count=" 2808114" Date="080411" />
+<Track Flowcell="FC20AN8" Lane="1" Filename="Flowcells/FC20AN8/080310_FC20AN8_s1_Input_Control_K562_SL170.align_25.hg18.txt" Count=" 2366449" Date="080310" />
+</Library>
+<Library Name="SL171">
+<Track Flowcell="FC20686" Lane="2" Filename="Flowcells/FC20686/080221_FC20686_s2_Input_K562_SL171.align_25.hg18.txt" Count=" 5745" Date="080221" />
+<Track Flowcell="FC209RM" Lane="34" Filename="Flowcells/FC209RM/080325_FC209RM_s34_MethylC_ChIP_K562_SL171.align_25.hg18.txt" Count=" 2019575" Date="080325" />
+<Track Flowcell="FC20AJB" Lane="8" Filename="Flowcells/FC20AJB/080411_FC20AJB_s8_MethylC_ChIP_K562_SL171.align_25.hg18.txt" Count=" 1109615" Date="080411" />
+<Track Flowcell="FC20AN8" Lane="2" Filename="Flowcells/FC20AN8/080310_FC20AN8_s2_MethylC_ChIP_K562_SL171.align_25.hg18.txt" Count=" 3470047" Date="080310" />
+<Track Flowcell="FC20AN8" Lane="4" Filename="Flowcells/FC20AN8/080310_FC20AN8_s4_MethylC_ChIP_K562_SL171.align_25.hg18.txt" Count=" 804871" Date="080310" />
+</Library>
+<Library Name="SL172">
+<Track Flowcell="FC20686" Lane="3" Filename="Flowcells/FC20686/080221_FC20686_s3_Histone_Mod_ChIP_HESC_SL172.align_25.hg18.txt" Count=" 6153" Date="080221" />
+<Track Flowcell="FC20AJB" Lane="23" Filename="Flowcells/FC20AJB/080411_FC20AJB_s23_Histone_Mod_ChIP_HESC_SL172.align_25.hg18.txt" Count=" 6025511" Date="080411" />
+<Track Flowcell="FC20AN8" Lane="3" Filename="Flowcells/FC20AN8/080310_FC20AN8_s3_Histone_Mod_ChIP_HESC_SL172.align_25.hg18.txt" Count=" 1662103" Date="080310" />
+</Library>
+<Library Name="SL173">
+<Track Flowcell="FC207CF" Lane="1" Filename="Flowcells/FC207CF/080207_FC207CF_s1_RNASeq_WOL_GCT6_SL173.align_25.hg18.txt" Count=" 458511" Date="080207" />
+<Track Flowcell="FC20AUF" Lane="1" Filename="Flowcells/FC20AUF/080418_FC20AUF_s1_RNAseq_WOL_GCT6_SL173.align_25.hg18.txt" Count=" 192208" Date="080418" />
+</Library>
+<Library Name="SL174">
+<Track Flowcell="FC207CF" Lane="8" Filename="Flowcells/FC207CF/080207_FC207CF_s8_RNAseq_WOL_GCT5_SL174.align_25.hg18.txt" Count=" 419076" Date="080207" />
+<Track Flowcell="FC20AUF" Lane="2" Filename="Flowcells/FC20AUF/080418_FC20AUF_s2_RNAseq_WOL_GCT5_SL174.align_25.hg18.txt" Count=" 277173" Date="080418" />
+</Library>
+<Library Name="SL180">
+<Track Flowcell="FC20AJ4" Lane="6" Filename="Flowcells/FC20AJ4/080312_FC20AJ4_s6_genomic_DNA_SL180.align_25.hg18.txt" Count=" 2947761" Date="080312" />
+</Library>
+<Library Name="SL182">
+<Track Flowcell="FC20AJ4" Lane="8" Filename="Flowcells/FC20AJ4/080312_FC20AJ4_s8_N_pound_124_SL182.align_25.hg18.txt" Count=" 744786" Date="080312" />
+</Library>
+<Library Name="SL183">
+<Track Flowcell="FC20AN8" Lane="5" Filename="Flowcells/FC20AN8/080310_FC20AN8_s5_K27_ChIP_HESC_SL183.align_25.hg18.txt" Count=" 1323849" Date="080310" />
+</Library>
+<Library Name="SL184">
+<Track Flowcell="FC20AN8" Lane="6" Filename="Flowcells/FC20AN8/080310_FC20AN8_s6_K36_ChIP_HESC_SL184.align_25.hg18.txt" Count=" 1416960" Date="080310" />
+</Library>
+<Library Name="SL185">
+<Track Flowcell="FC20AN8" Lane="7" Filename="Flowcells/FC20AN8/080310_FC20AN8_s7_RNAPol2_ChIP_HESC_SL185.align_25.hg18.txt" Count=" 303217" Date="080310" />
+</Library>
+<Library Name="SL186">
+<Track Flowcell="FC20AN8" Lane="8" Filename="Flowcells/FC20AN8/080310_FC20AN8_s8_Input_Control_HESC_SL186.align_25.hg18.txt" Count=" 524314" Date="080310" />
+</Library>
+<Library Name="SL187">
+<Track Flowcell="FC204TE" Lane="4" Filename="Flowcells/FC204TE/080401_FC204TE_s4_RNApol2_ChIP_Jurkat_Rep2_SL187.align_25.hg18.txt" Count=" 3439954" Date="080401" />
+<Track Flowcell="FC209TN" Lane="4" Filename="Flowcells/FC209TN/080320_FC209TN_s4_RNApol2_ChIP_Jurkat_Rep2_SL187.align_25.hg18.txt" Count=" 2798720" Date="080320" />
+<Track Flowcell="FC20AJ6" Lane="3" Filename="Flowcells/FC20AJ6/080318_FC20AJ6_s3_RNApol2_ChIP_Jurkat_Rep2_SL187.align_25.hg18.txt" Count=" 2842778" Date="080318" />
+<Track Flowcell="FC20AJB" Lane="6" Filename="Flowcells/FC20AJB/080411_FC20AJB_s6_RNApol2_ChIP_Jurkat_Rep2_SL187.align_25.hg18.txt" Count=" 3636448" Date="080411" />
+</Library>
+<Library Name="SL189">
+<Track Flowcell="FC20AJ6" Lane="6" Filename="Flowcells/FC20AJ6/080318_FC20AJ6_s6_RNAseq_yeast_SL189.align_25.scer.txt" Count=" 262855" Date="080318" />
+</Library>
+<Library Name="SL190">
+<Track Flowcell="FC20AJ6" Lane="1" Filename="Flowcells/FC20AJ6/080318_FC20AJ6_s1_YX271_nucleosomal_DNA_SL190.align_25.cel.txt" Count=" 3261307" Date="080318" />
+</Library>
+<Library Name="SL191">
+<Track Flowcell="FC20AJ6" Lane="2" Filename="Flowcells/FC20AJ6/080318_FC20AJ6_s2_YX213_nucleosomal_DNA_SL191.align_25.cel.txt" Count=" 1400954" Date="080318" />
+</Library>
+<Library Name="SL192">
+<Track Flowcell="FC20ANBA" Lane="1" Filename="Flowcells/FC20ANBA/080321_FC20ANBA_s1_DKO_2_hpa_SL192.align_25.hg18.txt" Count=" 2724639" Date="080321" />
+</Library>
+<Library Name="SL193">
+<Track Flowcell="FC20AJD" Lane="123" Filename="Flowcells/FC20AJD/080516_FC20AJD_s123_DKO_2_msp_SL193.align_25.hg18.txt" Count=" 10254337" Date="080516" />
+<Track Flowcell="FC20ANBA" Lane="2" Filename="Flowcells/FC20ANBA/080321_FC20ANBA_s2_DKO_2_msp_SL193.align_25.hg18.txt" Count=" 2748790" Date="080321" />
+</Library>
+<Library Name="SL194">
+<Track Flowcell="FC20ANBA" Lane="3" Filename="Flowcells/FC20ANBA/080321_FC20ANBA_s3_colon_A_hpa_SL194.align_25.hg18.txt" Count=" 3041571" Date="080321" />
+</Library>
+<Library Name="SL195">
+<Track Flowcell="FC204TE" Lane="1" Filename="Flowcells/FC204TE/080401_FC204TE_s1_colon_B_hpa_SL195.align_25.hg18.txt" Count=" 3349137" Date="080401" />
+<Track Flowcell="FC209TN" Lane="1" Filename="Flowcells/FC209TN/080320_FC209TN_s1_colon_B_hpa_SL195.align_25.hg18.txt" Count=" 3403447" Date="080320" />
+</Library>
+<Library Name="SL196">
+<Track Flowcell="FC204TE" Lane="2" Filename="Flowcells/FC204TE/080401_FC204TE_s2_colon_C_hpa_SL196.align_25.hg18.txt" Count=" 3827859" Date="080401" />
+<Track Flowcell="FC209TN" Lane="2" Filename="Flowcells/FC209TN/080320_FC209TN_s2_colon_C_hpa_SL196.align_25.hg18.txt" Count=" 3640251" Date="080320" />
+</Library>
+<Library Name="SL197">
+<Track Flowcell="FC204TE" Lane="3" Filename="Flowcells/FC204TE/080401_FC204TE_s3_colon_A_msp_SL197.align_25.hg18.txt" Count=" 2691934" Date="080401" />
+<Track Flowcell="FC209TN" Lane="3" Filename="Flowcells/FC209TN/080320_FC209TN_s3_colon_A_msp_SL197.align_25.hg18.txt" Count=" 2795747" Date="080320" />
+<Track Flowcell="FC20AJD" Lane="678" Filename="Flowcells/FC20AJD/080516_FC20AJD_s678_colon_A_msp_SL197.align_25.hg18.txt" Count=" 10383564" Date="080516" />
+</Library>
+<Library Name="SL199">
+<Track Flowcell="FC20AME" Lane="1" Filename="Flowcells/FC20AME/080327_FC20AME_s1_RIBO-XRLP_SL199.align_25.scer.txt" Count=" 700987" Date="080327" />
+</Library>
+<Library Name="SL200">
+<Track Flowcell="FC20ANBA" Lane="7" Filename="Flowcells/FC20ANBA/080321_FC20ANBA_s7_K562_Rep2_Hpa_SL200.align_25.hg18.txt" Count=" 1655989" Date="080321" />
+</Library>
+<Library Name="SL201">
+<Track Flowcell="FC20ANBA" Lane="8" Filename="Flowcells/FC20ANBA/080321_FC20ANBA_s8_K562_Rep2_Msp_SL201.align_25.hg18.txt" Count=" 1438074" Date="080321" />
+</Library>
+<Library Name="SL202">
+<Track Flowcell="FC204PT" Lane="1234" Filename="Flowcells/FC204PT/080408_FC204PT_s1234_NRSF_ChIP_GM12878_Rep1_SL202.align_25.hg18.txt" Count=" 7274643" Date="080408" />
+<Track Flowcell="FC204TE" Lane="5" Filename="Flowcells/FC204TE/080401_FC204TE_s5_NRSF_ChIP_GM12878_Rep1_SL202.align_25.hg18.txt" Count=" 2247042" Date="080401" />
+<Track Flowcell="FC209TN" Lane="5" Filename="Flowcells/FC209TN/080320_FC209TN_s5_NRSF_ChIP_GM12878_Rep1_SL202.align_25.hg18.txt" Count=" 1576307" Date="080320" />
+</Library>
+<Library Name="SL203">
+<Track Flowcell="FC204PT" Lane="5678" Filename="Flowcells/FC204PT/080408_FC204PT_s5678_GABP_ChIP_GM12878_Rep1_SL203.align_25.hg18.txt" Count=" 7887093" Date="080408" />
+<Track Flowcell="FC204TE" Lane="6" Filename="Flowcells/FC204TE/080401_FC204TE_s6_GABP_ChIP_GM12878_Rep2_SL203.align_25.hg18.txt" Count=" 2373273" Date="080401" />
+<Track Flowcell="FC209TN" Lane="6" Filename="Flowcells/FC209TN/080320_FC209TN_s6_GABP_ChIP_GM12878_Rep1_SL203.align_25.hg18.txt" Count=" 1701737" Date="080320" />
+</Library>
+<Library Name="SL204">
+<Track Flowcell="FC204GV" Lane="123" Filename="Flowcells/FC204GV/080429_FC204GV_s123_NRSF_ChIP_GM12878_Rep2_SL204.align_25.hg18.txt" Count=" 3577884" Date="080429" />
+<Track Flowcell="FC209TN" Lane="7" Filename="Flowcells/FC209TN/080320_FC209TN_s7_NRSF_ChIP_GM12878_Rep2_SL204.align_25.hg18.txt" Count=" 1896929" Date="080320" />
+<Track Flowcell="FC20ATL" Lane="3" Filename="Flowcells/FC20ATL/080527_FC20ATL_s3_NRSF_ChIP_GM12878_Rep2_SL204.align_25.hg18.txt" Count=" 3115234" Date="080527" />
+<Track Flowcell="FC20ATL" Lane="4" Filename="Flowcells/FC20ATL/080527_FC20ATL_s4_NRSF_ChIP_GM12878_Rep2_SL204.align_25.hg18.txt" Count=" 3154935" Date="080527" />
+</Library>
+<Library Name="SL205">
+<Track Flowcell="FC204PR" Lane="1" Filename="Flowcells/FC204PR/080520_FC204PR_s1_GABP_ChIP_GM12878_Rep2_SL205.align_25.hg18.txt" Count=" 2655501" Date="080520" />
+<Track Flowcell="FC204TD" Lane="3" Filename="Flowcells/FC204TD/080509_FC204TD_s3_GABP_ChIP_GM12878_Rep2_SL205.align_25.hg18.txt" Count=" 3057775" Date="080509" />
+<Track Flowcell="FC209TN" Lane="8" Filename="Flowcells/FC209TN/080320_FC209TN_s8_GABP_ChIP_GM12878_Rep2_SL205.align_25.hg18.txt" Count=" 2362256" Date="080320" />
+<Track Flowcell="FC20ATL" Lane="1" Filename="Flowcells/FC20ATL/080527_FC20ATL_s1_GABP_ChIP_GM12878_Rep2_SL205.align_25.hg18.txt" Count=" 3517050" Date="080527" />
+</Library>
+<Library Name="SL206">
+<Track Flowcell="FC209RM" Lane="5" Filename="Flowcells/FC209RM/080325_FC209RM_s5_RNAPol2_ChIP_GM12878_Rep1_R1_SL206.align_25.hg18.txt" Count=" 2140588" Date="080325" />
+</Library>
+<Library Name="SL207">
+<Track Flowcell="FC204GW" Lane="12" Filename="Flowcells/FC204GW/080503_FC204GW_s12_RNAPol2_ChIP_GM12878_Rep1_R2_SL207.align_25.hg18.txt" Count=" 4626454" Date="080503" />
+<Track Flowcell="FC204TD" Lane="4" Filename="Flowcells/FC204TD/080509_FC204TD_s4_RNAPol2_ChIP_GM12878_Rep1_R2_SL207.align_25.hg18.txt" Count=" 2702184" Date="080509" />
+<Track Flowcell="FC209RM" Lane="6" Filename="Flowcells/FC209RM/080325_FC209RM_s6_RNAPol2_ChIP_GM12878_Rep1_R2_SL207.align_25.hg18.txt" Count=" 2332288" Date="080325" />
+<Track Flowcell="FC20AJB" Lane="4" Filename="Flowcells/FC20AJB/080411_FC20AJB_s4_RNAPol2_ChIP_GM12878_Rep1_R2_SL207.align_25.hg18.txt" Count=" 2615980" Date="080411" />
+</Library>
+<Library Name="SL208">
+<Track Flowcell="FC209RM" Lane="7" Filename="Flowcells/FC209RM/080325_FC209RM_s7_RNAPol2_ChIP_GM12878_Rep2_R1_SL208.align_25.hg18.txt" Count=" 2045107" Date="080325" />
+</Library>
+<Library Name="SL209">
+<Track Flowcell="FC204GW" Lane="34" Filename="Flowcells/FC204GW/080503_FC204GW_s34_RNAPol2_ChIP_GM12878_Rep2_R2_SL209.align_25.hg18.txt" Count=" 6350506" Date="080503" />
+<Track Flowcell="FC204TD" Lane="5" Filename="Flowcells/FC204TD/080509_FC204TD_s5_RNAPol2_ChIP_GM12878_Rep2_R2_SL209.align_25.hg18.txt" Count=" 2519907" Date="080509" />
+<Track Flowcell="FC209RM" Lane="8" Filename="Flowcells/FC209RM/080325_FC209RM_s8_RNAPol2_ChIP_GM12878_Rep2_R2_SL209.align_25.hg18.txt" Count=" 2375516" Date="080325" />
+<Track Flowcell="FC20AJB" Lane="5" Filename="Flowcells/FC20AJB/080411_FC20AJB_s5_RNAPol2_ChIP_GM12878_Rep2_R2_SL209.align_25.hg18.txt" Count=" 3527877" Date="080411" />
+</Library>
+<Library Name="SL210">
+<Track Flowcell="FC20AME" Lane="6" Filename="Flowcells/FC20AME/080327_FC20AME_s6_hESC_K27_New_SL210.align_25.hg18.txt" Count=" 422900" Date="080327" />
+</Library>
+<Library Name="SL211">
+<Track Flowcell="FC20AME" Lane="7" Filename="Flowcells/FC20AME/080327_FC20AME_s7_hESC_Pol2_New_SL211.align_25.hg18.txt" Count=" 805937" Date="080327" />
+</Library>
+<Library Name="SL212">
+<Track Flowcell="FC20AJB" Lane="1" Filename="Flowcells/FC20AJB/080411_FC20AJB_s1_hESC_input_New_SL212.align_25.hg18.txt" Count=" 1721512" Date="080411" />
+<Track Flowcell="FC20AME" Lane="8" Filename="Flowcells/FC20AME/080327_FC20AME_s8_hESC_input_New_SL212.align_25.hg18.txt" Count=" 2225791" Date="080327" />
+</Library>
+<Library Name="SL213">
+<Track Flowcell="FC204GW" Lane="7" Filename="Flowcells/FC204GW/080503_FC204GW_s7_day5_K4_SL213.align_25.hg18.txt" Count=" 619689" Date="080503" />
+</Library>
+<Library Name="SL214">
+<Track Flowcell="FC204GW" Lane="8" Filename="Flowcells/FC204GW/080503_FC204GW_s8_day5_input_SL214.align_25.hg18.txt" Count=" 1212965" Date="080503" />
+</Library>
+<Library Name="SL217">
+<Track Flowcell="FC20ATK" Lane="1234" Filename="Flowcells/FC20ATK/080404_FC20ATK_s1234_GM12878_input_Ctrl_Rep1_SL217.align_25.hg18.txt" Count=" 14209973" Date="080404" />
+</Library>
+<Library Name="SL218">
+<Track Flowcell="FC20ATK" Lane="5678" Filename="Flowcells/FC20ATK/080404_FC20ATK_s5678_GM12878_input_Ctrl_Rep2_SL218.align_25.hg18.txt" Count=" 11888537" Date="080404" />
+</Library>
+<Library Name="SL219">
+<Track Flowcell="FC204TE" Lane="7" Filename="Flowcells/FC204TE/080401_FC204TE_s7_RNAPol2_ChIP_K562_Dex_rep1_SL219.align_25.hg18.txt" Count=" 3414718" Date="080401" />
+</Library>
+<Library Name="SL220">
+<Track Flowcell="FC204TE" Lane="8" Filename="Flowcells/FC204TE/080401_FC204TE_s8_RNAPol2_ChIP_K562_EtOH_rep1_SL220.align_25.hg18.txt" Count=" 3318493" Date="080401" />
+</Library>
+<Library Name="SL221">
+<Track Flowcell="FC209VL" Lane="12" Filename="Flowcells/FC209VL/080409_FC209VL_s12_NRSF_ChIP-K562_Rep1_SL221.align_25.hg18.txt" Count=" 5557080" Date="080409" />
+<Track Flowcell="FC20AJD" Lane="4" Filename="Flowcells/FC20AJD/080516_FC20AJD_s4_NRSF_ChIP-K562_Rep1_SL221.align_25.hg18.txt" Count=" 3599218" Date="080516" />
+<Track Flowcell="FC20ATL" Lane="5" Filename="Flowcells/FC20ATL/080527_FC20ATL_s5_NRSF_ChIP-K562_Rep1_SL221.align_25.hg18.txt" Count=" 4360336" Date="080527" />
+<Track Flowcell="FC20ATL" Lane="6" Filename="Flowcells/FC20ATL/080527_FC20ATL_s6_NRSF_ChIP-K562_Rep1_SL221.align_25.hg18.txt" Count=" 4414231" Date="080527" />
+</Library>
+<Library Name="SL222">
+<Track Flowcell="FC209VL" Lane="34" Filename="Flowcells/FC209VL/080409_FC209VL_s34_NRSF_ChIP_K562_Rep2_SL222.align_25.hg18.txt" Count=" 5104501" Date="080409" />
+<Track Flowcell="FC20AJD" Lane="5" Filename="Flowcells/FC20AJD/080516_FC20AJD_s5_NRSF_ChIP_K562_Rep2_SL222.align_25.hg18.txt" Count=" 3449963" Date="080516" />
+<Track Flowcell="FC20ATL" Lane="7" Filename="Flowcells/FC20ATL/080527_FC20ATL_s7_NRSF_ChIP_K562_Rep2_SL222.align_25.hg18.txt" Count=" 3722128" Date="080527" />
+<Track Flowcell="FC20ATL" Lane="8" Filename="Flowcells/FC20ATL/080527_FC20ATL_s8_NRSF_ChIP_K562_Rep2_SL222.align_25.hg18.txt" Count=" 3947293" Date="080527" />
+</Library>
+<Library Name="SL223">
+<Track Flowcell="FC204PR" Lane="2" Filename="Flowcells/FC204PR/080520_FC204PR_s2_GABP_ChIP_K562_Rep1_SL223.align_25.hg18.txt" Count=" 2860313" Date="080520" />
+<Track Flowcell="FC209VL" Lane="56" Filename="Flowcells/FC209VL/080409_FC209VL_s56_GABP_ChIP_K562_Rep1_SL223.align_25.hg18.txt" Count=" 4864011" Date="080409" />
+<Track Flowcell="FC20AJ8" Lane="4" Filename="Flowcells/FC20AJ8/080523_FC20AJ8_s4_GABP_ChIP_K562_Rep1_SL223.align_25.hg18.txt" Count=" 3540087" Date="080523" />
+</Library>
+<Library Name="SL224">
+<Track Flowcell="FC204PR" Lane="3" Filename="Flowcells/FC204PR/080520_FC204PR_s3_GABP_ChIP_K562_Rep2_SL224.align_25.hg18.txt" Count=" 17" Date="080520" />
+<Track Flowcell="FC209VL" Lane="78" Filename="Flowcells/FC209VL/080409_FC209VL_s78_GABP_ChIP_K562_Rep2_SL224.align_25.hg18.txt" Count=" 4173297" Date="080409" />
+<Track Flowcell="FC20AJ8" Lane="1" Filename="Flowcells/FC20AJ8/080523_FC20AJ8_s1_GABP_ChIP_K562_Rep2_SL224.align_25.hg18.txt" Count=" 3048516" Date="080523" />
+<Track Flowcell="FC20AJ8" Lane="5" Filename="Flowcells/FC20AJ8/080523_FC20AJ8_s5_GABP_ChIP_K562_Rep2_SL224.align_25.hg18.txt" Count=" 3259099" Date="080523" />
+</Library>
+<Library Name="SL225">
+<Track Flowcell="FC209VY" Lane="1" Filename="Flowcells/FC209VY/080415_FC209VY_s1_MeC_DIP_GM12878_Rep1_SL225.align_25.hg18.txt" Count=" 596256" Date="080415" />
+</Library>
+<Library Name="SL226">
+<Track Flowcell="FC209VY" Lane="2" Filename="Flowcells/FC209VY/080415_FC209VY_s2_MeC_DIP_GM12878_Rep2_SL226.align_25.hg18.txt" Count=" 267004" Date="080415" />
+</Library>
+<Library Name="SL227">
+<Track Flowcell="FC209VY" Lane="3" Filename="Flowcells/FC209VY/080415_FC209VY_s3_MeC_DIP_Input_GM12878_Rep1_SL227.align_25.hg18.txt" Count=" 2207861" Date="080415" />
+</Library>
+<Library Name="SL228">
+<Track Flowcell="FC209VY" Lane="6" Filename="Flowcells/FC209VY/080415_FC209VY_s6_MeC_DIP_Input_GM12878_Rep2_SL228.align_25.hg18.txt" Count=" 2130348" Date="080415" />
+</Library>
+<Library Name="SL229">
+<Track Flowcell="306WNAAXX" Lane="1" Filename="Flowcells/306WNAAXX/080731_306WNAAXX_s1_Methylseq_K562_R1_hpa_SL229.align_25.hg18.txt" Count=" 2789078" Date="080731" />
+<Track Flowcell="30EGGAAXX" Lane="4" Filename="Flowcells/30EGGAAXX/080910_30EGGAAXX_s4_Methylseq_K562_R1_hpa_SL229.align_25.hg18.txt" Count=" 340831" Date="080910" />
+<Track Flowcell="FC204TD" Lane="6" Filename="Flowcells/FC204TD/080509_FC204TD_s6_Methylseq_K562_R1_hpa_SL229.align_25.hg18.txt" Count=" 1710215" Date="080509" />
+</Library>
+<Library Name="SL230">
+<Track Flowcell="306WNAAXX" Lane="2" Filename="Flowcells/306WNAAXX/080731_306WNAAXX_s2_Methylseq_K562_R1_msp_SL230.align_25.hg18.txt" Count=" 3452680" Date="080731" />
+<Track Flowcell="FC204TD" Lane="7" Filename="Flowcells/FC204TD/080509_FC204TD_s7_Methylseq_K562_R1_msp_SL230.align_25.hg18.txt" Count=" 1645339" Date="080509" />
+</Library>
+<Library Name="SL231">
+<Track Flowcell="306WNAAXX" Lane="3" Filename="Flowcells/306WNAAXX/080731_306WNAAXX_s3_Methylseq_K562_R2_hpa_SL231.align_25.hg18.txt" Count=" 3339995" Date="080731" />
+<Track Flowcell="30EGGAAXX" Lane="5" Filename="Flowcells/30EGGAAXX/080910_30EGGAAXX_s5_Methylseq_K562_R2_hpa_SL231.align_25.hg18.txt" Count=" 508537" Date="080910" />
+<Track Flowcell="FC204TD" Lane="8" Filename="Flowcells/FC204TD/080509_FC204TD_s8_Methylseq_K562_R2_hpa_SL231.align_25.hg18.txt" Count=" 1671255" Date="080509" />
+</Library>
+<Library Name="SL232">
+<Track Flowcell="306WNAAXX" Lane="4" Filename="Flowcells/306WNAAXX/080731_306WNAAXX_s4_Methylseq_K562_R2_msp_SL232.align_25.hg18.txt" Count=" 2608243" Date="080731" />
+<Track Flowcell="FC209VY" Lane="7" Filename="Flowcells/FC209VY/080415_FC209VY_s7_Methylseq_K562_msp_SL232.align_25.hg18.txt" Count=" 1996275" Date="080415" />
+</Library>
+<Library Name="SL233">
+<Track Flowcell="30DCTAAXX" Lane="1" Filename="Flowcells/30DCTAAXX/080904_30DCTAAXX_s1_Input_Control_K562_Rep1_SL233.align_25.hg18.txt" Count=" 2724511" Date="080904" />
+<Track Flowcell="FC209VY" Lane="4" Filename="Flowcells/FC209VY/080415_FC209VY_s4_Input_Control_K562_Rep1_SL233.align_25.hg18.txt" Count=" 2749243" Date="080415" />
+<Track Flowcell="FC20E3HAAXX" Lane="4" Filename="Flowcells/FC20E3HAAXX/080502_FC20E3HAAXX_s4_Input_Control_K562_Rep1_SL233.align_25.hg18.txt" Count=" 1825060" Date="080502" />
+<Track Flowcell="FC303PRAAXX" Lane="4" Filename="Flowcells/FC303PRAAXX/080523_FC303PRAAXX_s4_Input_Control_K562_Rep1_SL233.align_25.hg18.txt" Count=" 2792190" Date="080523" />
+</Library>
+<Library Name="SL234">
+<Track Flowcell="30DCTAAXX" Lane="2" Filename="Flowcells/30DCTAAXX/080904_30DCTAAXX_s2_Input_Control_K562_Rep2_SL234.align_25.hg18.txt" Count=" 3602099" Date="080904" />
+<Track Flowcell="30EFCAAXX" Lane="1" Filename="Flowcells/30EFCAAXX/080910_30EFCAAXX_s1_Input_Control_K562_Rep2_SL234.align_25.hg18.txt" Count=" 569875" Date="080910" />
+<Track Flowcell="30EFCAAXX" Lane="2" Filename="Flowcells/30EFCAAXX/080910_30EFCAAXX_s2_Input_Control_K562_Rep2_SL234.align_25.hg18.txt" Count=" 1955971" Date="080910" />
+<Track Flowcell="FC209VY" Lane="5" Filename="Flowcells/FC209VY/080415_FC209VY_s5_Input_Control_K562_Rep2_SL234.align_25.hg18.txt" Count=" 2190280" Date="080415" />
+<Track Flowcell="FC20E3HAAXX" Lane="5" Filename="Flowcells/FC20E3HAAXX/080502_FC20E3HAAXX_s5_Input_Control_K562_Rep2_SL234.align_25.hg18.txt" Count=" 1592799" Date="080502" />
+</Library>
+<Library Name="SL235">
+<Track Flowcell="FC209VY" Lane="8" Filename="Flowcells/FC209VY/080415_FC209VY_s8_RNAseq_AF_sol_101_SL235.align_25.cel.txt" Count=" 2172789" Date="080415" />
+</Library>
+<Library Name="SL236">
+<Track Flowcell="FC20AUF" Lane="3" Filename="Flowcells/FC20AUF/080418_FC20AUF_s3_RNASeq_SL236.align_25.hg18.txt" Count=" 334732" Date="080418" />
+</Library>
+<Library Name="SL237">
+<Track Flowcell="FC20AUF" Lane="6" Filename="Flowcells/FC20AUF/080418_FC20AUF_s6_DNA_nucleosomes_SL237.align_25.mm9.txt" Count=" 2337360" Date="080418" />
+</Library>
+<Library Name="SL238">
+<Track Flowcell="FC20AUF" Lane="7" Filename="Flowcells/FC20AUF/080418_FC20AUF_s7_AF_SOL_104_SL238.align_25.hg18.txt" Count=" 2960999" Date="080418" />
+</Library>
+<Library Name="SL239">
+<Track Flowcell="FC20AUF" Lane="8" Filename="Flowcells/FC20AUF/080418_FC20AUF_s8_AF_SOL_105_SL239.align_25.hg18.txt" Count=" 3601304" Date="080418" />
+</Library>
+<Library Name="SL240">
+<Track Flowcell="30DCTAAXX" Lane="3" Filename="Flowcells/30DCTAAXX/080904_30DCTAAXX_s3_K562_RNApol2_rep1_SL240.align_25.hg18.txt" Count=" 4391389" Date="080904" />
+<Track Flowcell="FC20E3HAAXX" Lane="1" Filename="Flowcells/FC20E3HAAXX/080502_FC20E3HAAXX_s1_K562_RNApol2_rep1_SL240.align_25.hg18.txt" Count=" 1666658" Date="080502" />
+<Track Flowcell="FC303PRAAXX" Lane="12" Filename="Flowcells/FC303PRAAXX/080523_FC303PRAAXX_s12_K562_RNApol2_rep1_SL240.align_25.hg18.txt" Count=" 6613625" Date="080523" />
+</Library>
+<Library Name="SL241">
+<Track Flowcell="30DCTAAXX" Lane="4" Filename="Flowcells/30DCTAAXX/080904_30DCTAAXX_s4_K562_RNApol2_rep2_SL241.align_25.hg18.txt" Count=" 3497136" Date="080904" />
+<Track Flowcell="FC20E3HAAXX" Lane="2" Filename="Flowcells/FC20E3HAAXX/080502_FC20E3HAAXX_s2_K562_RNApol2_rep2_SL241.align_25.hg18.txt" Count=" 2005718" Date="080502" />
+<Track Flowcell="FC303PRAAXX" Lane="36" Filename="Flowcells/FC303PRAAXX/080523_FC303PRAAXX_s36_K562_RNApol2_rep2_SL241.align_25.hg18.txt" Count=" 5690721" Date="080523" />
+</Library>
+<Library Name="SL242">
+<Track Flowcell="306WPAAXX" Lane="1" Filename="Flowcells/306WPAAXX/080731_306WPAAXX_s1_K562_TAF250_Rep1_SL242.align_25.hg18.txt" Count=" 2063352" Date="080731" />
+<Track Flowcell="30DCTAAXX" Lane="5" Filename="Flowcells/30DCTAAXX/080904_30DCTAAXX_s5_K562_TAF250_Rep1_SL242.align_25.hg18.txt" Count=" 1499911" Date="080904" />
+<Track Flowcell="30EFCAAXX" Lane="3" Filename="Flowcells/30EFCAAXX/080910_30EFCAAXX_s3_K562_TAF250_Rep1_SL242.align_25.hg18.txt" Count=" 1802228" Date="080910" />
+<Track Flowcell="FC20E3HAAXX" Lane="36" Filename="Flowcells/FC20E3HAAXX/080502_FC20E3HAAXX_s36_K562_TAF250_Rep1_SL242.align_25.hg18.txt" Count=" 3378725" Date="080502" />
+<Track Flowcell="FC303PRAAXX" Lane="7" Filename="Flowcells/FC303PRAAXX/080523_FC303PRAAXX_s7_K562_TAF250_Rep1_SL242.align_25.hg18.txt" Count=" 1171122" Date="080523" />
+</Library>
+<Library Name="SL243">
+<Track Flowcell="306WPAAXX" Lane="2" Filename="Flowcells/306WPAAXX/080731_306WPAAXX_s2_K562_TAF250_Rep2_SL243.align_25.hg18.txt" Count=" 4389115" Date="080731" />
+<Track Flowcell="FC20E3HAAXX" Lane="78" Filename="Flowcells/FC20E3HAAXX/080502_FC20E3HAAXX_s78_K562_TAF250_Rep2_SL243.align_25.hg18.txt" Count=" 4628303" Date="080502" />
+<Track Flowcell="FC303PRAAXX" Lane="8" Filename="Flowcells/FC303PRAAXX/080523_FC303PRAAXX_s8_K562_TAF250_Rep2_SL243.align_25.hg18.txt" Count=" 2228574" Date="080523" />
+</Library>
+<Library Name="SL244">
+<Track Flowcell="303y5aaxx" Lane="3" Filename="Flowcells/303y5aaxx/080715_303y5aaxx_s3_ChIPseq_A549_Pol2_Dex_SL244.align_25.hg18.txt" Count=" 4670412" Date="080715" />
+<Track Flowcell="FC204GV" Lane="4" Filename="Flowcells/FC204GV/080429_FC204GV_s4_ChIPseq_A549_Pol2_Dex_SL244.align_25.hg18.txt" Count=" 1143215" Date="080429" />
+<Track Flowcell="FC204GW" Lane="5" Filename="Flowcells/FC204GW/080503_FC204GW_s5_ChIPseq_A549_Pol2_Dex_SL244.align_25.hg18.txt" Count=" 2893570" Date="080503" />
+<Track Flowcell="FC204PR" Lane="4" Filename="Flowcells/FC204PR/080520_FC204PR_s4_ChIPseq_A549_Pol2_Dex_SL244.align_25.hg18.txt" Count=" 2984654" Date="080520" />
+</Library>
+<Library Name="SL245">
+<Track Flowcell="303y5aaxx" Lane="4" Filename="Flowcells/303y5aaxx/080715_303y5aaxx_s4_ChIPSeq_A549_Pol2_EtOH_SL245.align_25.hg18.txt" Count=" 5705811" Date="080715" />
+<Track Flowcell="FC204GV" Lane="5" Filename="Flowcells/FC204GV/080429_FC204GV_s5_ChIPSeq_A549_Pol2_EtOH_SL245.align_25.hg18.txt" Count=" 1331975" Date="080429" />
+<Track Flowcell="FC204GW" Lane="6" Filename="Flowcells/FC204GW/080503_FC204GW_s6_ChIPSeq_A549_Pol2_EtOH_SL245.align_25.hg18.txt" Count=" 3378626" Date="080503" />
+<Track Flowcell="FC204PR" Lane="5" Filename="Flowcells/FC204PR/080520_FC204PR_s5_ChIPSeq_A549_Pol2_EtOH_SL245.align_25.hg18.txt" Count=" 3137998" Date="080520" />
+</Library>
+<Library Name="SL246">
+<Track Flowcell="303y5aaxx" Lane="1" Filename="Flowcells/303y5aaxx/080715_303y5aaxx_s1_ChIPSeq_A549_M20_GR_Dex_SL246.align_25.hg18.txt" Count=" 2056910" Date="080715" />
+<Track Flowcell="FC204JB" Lane="2" Filename="Flowcells/FC204JB/080507_FC204JB_s2_ChIPSeq_A549_M20_GR_Dex_SL246.align_25.hg18.txt" Count=" 1321687" Date="080507" />
+<Track Flowcell="FC204PR" Lane="6" Filename="Flowcells/FC204PR/080520_FC204PR_s6_ChIPSeq_A549_M20_GR_Dex_SL246.align_25.hg18.txt" Count=" 1321643" Date="080520" />
+<Track Flowcell="FC20AUF" Lane="4" Filename="Flowcells/FC20AUF/080418_FC20AUF_s4_ChIPSeq_A549_M20_GR_Dex_SL246.align_25.hg18.txt" Count=" 1236139" Date="080418" />
+<Track Flowcell="FC20AUM" Lane="6" Filename="Flowcells/FC20AUM/080616_FC20AUM_s6_ChIPSeq_A549_M20_GR_Dex_SL246.align_25.hg18.txt" Count=" 1449936" Date="080616" />
+<Track Flowcell="FC20AUM" Lane="7" Filename="Flowcells/FC20AUM/080616_FC20AUM_s7_ChIPSeq_A549_M20_GR_Dex_SL246.align_25.hg18.txt" Count=" 1599501" Date="080616" />
+<Track Flowcell="FC20AUM" Lane="8" Filename="Flowcells/FC20AUM/080616_FC20AUM_s8_ChIPSeq_A549_M20_GR_Dex_SL246.align_25.hg18.txt" Count=" 1605226" Date="080616" />
+</Library>
+<Library Name="SL247">
+<Track Flowcell="303y5aaxx" Lane="2" Filename="Flowcells/303y5aaxx/080715_303y5aaxx_s2_ChIPSeq_A549_M20_GR_EtOH_SL247.align_25.hg18.txt" Count=" 3710876" Date="080715" />
+<Track Flowcell="FC204JB" Lane="4" Filename="Flowcells/FC204JB/080507_FC204JB_s4_ChIPSeq_A549_M20_GR_EtOH_SL247.align_25.hg18.txt" Count=" 2448458" Date="080507" />
+<Track Flowcell="FC204PR" Lane="7" Filename="Flowcells/FC204PR/080520_FC204PR_s7_ChIPSeq_A549_M20_GR_EtOH_SL247.align_25.hg18.txt" Count=" 2346726" Date="080520" />
+<Track Flowcell="FC20AUF" Lane="5" Filename="Flowcells/FC20AUF/080418_FC20AUF_s5_ChIPSeq_A549_M20_GR_EtOH_SL247.align_25.hg18.txt" Count=" 2148284" Date="080418" />
+</Library>
+<Library Name="SL248">
+<Track Flowcell="FC204GV" Lane="6" Filename="Flowcells/FC204GV/080429_FC204GV_s6_XRLP_041408_SL248.align_25.scer.txt" Count=" 2411445" Date="080429" />
+</Library>
+<Library Name="SL249">
+<Track Flowcell="FC204GV" Lane="7" Filename="Flowcells/FC204GV/080429_FC204GV_s7_NaCl_041408_SL249.align_25.scer.txt" Count=" 2433903" Date="080429" />
+</Library>
+<Library Name="SL250">
+<Track Flowcell="FC204GV" Lane="8" Filename="Flowcells/FC204GV/080429_FC204GV_s8_WT_041408_SL250.align_25.scer.txt" Count=" 2135397" Date="080429" />
+</Library>
+<Library Name="SL259">
+<Track Flowcell="FC204JB" Lane="3" Filename="Flowcells/FC204JB/080507_FC204JB_s3_Input_Control_Namwala_RX_Ch_SL259.align_25.hg18.txt" Count=" 3608279" Date="080507" />
+</Library>
+<Library Name="SL260">
+<Track Flowcell="FC204JB" Lane="5" Filename="Flowcells/FC204JB/080507_FC204JB_s5_Input_Control_MNase_UB_SL260.align_25.hg18.txt" Count=" 2239155" Date="080507" />
+</Library>
+<Library Name="SL261">
+<Track Flowcell="FC204JB" Lane="6" Filename="Flowcells/FC204JB/080507_FC204JB_s6_Input_Control_MNase_LB_SL261.align_25.hg18.txt" Count=" 4413501" Date="080507" />
+</Library>
+<Library Name="SL262">
+<Track Flowcell="FC204JB" Lane="7" Filename="Flowcells/FC204JB/080507_FC204JB_s7_ChIPSeq_Namwala_Pol2_MNase_UB_SL262.align_25.hg18.txt" Count=" 2135250" Date="080507" />
+</Library>
+<Library Name="SL263">
+<Track Flowcell="FC204JB" Lane="8" Filename="Flowcells/FC204JB/080507_FC204JB_s8_ChIPSeq_Namwala_Pol2_MNase_LB_SL263.align_25.hg18.txt" Count=" 4570064" Date="080507" />
+</Library>
+<Library Name="SL264">
+<Track Flowcell="FC204JB" Lane="1" Filename="Flowcells/FC204JB/080507_FC204JB_s1_RNASeq_GM12878_Rep1_SL264.align_25.hg18.txt" Count=" 3546913" Date="080507" />
+</Library>
+<Library Name="SL265">
+<Track Flowcell="FC204TD" Lane="1" Filename="Flowcells/FC204TD/080509_FC204TD_s1_RNASeq_K562_Rep1_SL265.align_25.hg18.txt" Count=" 3677080" Date="080509" />
+</Library>
+<Library Name="SL266">
+<Track Flowcell="FC204TD" Lane="2" Filename="Flowcells/FC204TD/080509_FC204TD_s2_RNASeq_K562_Rep2_SL266.align_25.hg18.txt" Count=" 3565092" Date="080509" />
+</Library>
+<Library Name="SL269">
+<Track Flowcell="FC204MT" Lane="1" Filename="Flowcells/FC204MT/080512_FC204MT_s1_MCF7_ChIPSeq_GR_Dex_SL269.align_25.hg18.txt" Count=" 2282494" Date="080512" />
+</Library>
+<Library Name="SL270">
+<Track Flowcell="FC204MT" Lane="2" Filename="Flowcells/FC204MT/080512_FC204MT_s2_MCF7_ChIPSeq_GR_EtOH_SL270.align_25.hg18.txt" Count=" 2399296" Date="080512" />
+</Library>
+<Library Name="SL271">
+<Track Flowcell="FC204MT" Lane="3" Filename="Flowcells/FC204MT/080512_FC204MT_s3_MCF7_ChIPSeq_Pol2_Dex_SL271.align_25.hg18.txt" Count=" 2884011" Date="080512" />
+</Library>
+<Library Name="SL272">
+<Track Flowcell="FC204MT" Lane="4" Filename="Flowcells/FC204MT/080512_FC204MT_s4_ChIPSeq_MCF7_Pol2_EtOH_SL272.align_25.hg18.txt" Count=" 3016679" Date="080512" />
+</Library>
+<Library Name="SL273">
+<Track Flowcell="209UKAAXX" Lane="1" Filename="Flowcells/209UKAAXX/080528_209UKAAXX_s1_ChIPSeq_HepG2_Rep1_NRSF_SL273.align_25.hg18.txt" Count=" 1096000" Date="080528" />
+<Track Flowcell="209UKAAXX" Lane="2" Filename="Flowcells/209UKAAXX/080528_209UKAAXX_s2_ChIPSeq_HepG2_Rep1_NRSF_SL273.align_25.hg18.txt" Count=" 1197533" Date="080528" />
+<Track Flowcell="209UKAAXX" Lane="3" Filename="Flowcells/209UKAAXX/080528_209UKAAXX_s3_ChIPSeq_HepG2_Rep1_NRSF_SL273.align_25.hg18.txt" Count=" 1437394" Date="080528" />
+<Track Flowcell="209UKAAXX" Lane="4" Filename="Flowcells/209UKAAXX/080528_209UKAAXX_s4_ChIPSeq_HepG2_Rep1_NRSF_SL273.align_25.hg18.txt" Count=" 1523562" Date="080528" />
+<Track Flowcell="306P2AAXX" Lane="4" Filename="Flowcells/306P2AAXX/080722_306P2AAXX_s4_ChIPSeq_HepG2_Rep1_NRSF_SL273.align_25.hg18.txt" Count=" 3111388" Date="080722" />
+<Track Flowcell="FC204MT" Lane="5" Filename="Flowcells/FC204MT/080512_FC204MT_s5_ChIPSeq_HepG2_Rep1_NRSF_SL273.align_25.hg18.txt" Count=" 2875972" Date="080512" />
+</Library>
+<Library Name="SL274">
+<Track Flowcell="209UKAAXX" Lane="5" Filename="Flowcells/209UKAAXX/080528_209UKAAXX_s5_ChIPSeq_HepG2_Rep2_NRSF_SL274.align_25.hg18.txt" Count=" 1726267" Date="080528" />
+<Track Flowcell="209UKAAXX" Lane="6" Filename="Flowcells/209UKAAXX/080528_209UKAAXX_s6_ChIPSeq_HepG2_Rep2_NRSF_SL274.align_25.hg18.txt" Count=" 1693140" Date="080528" />
+<Track Flowcell="209UKAAXX" Lane="7" Filename="Flowcells/209UKAAXX/080528_209UKAAXX_s7_ChIPSeq_HepG2_Rep2_NRSF_SL274.align_25.hg18.txt" Count=" 1537265" Date="080528" />
+<Track Flowcell="209UKAAXX" Lane="8" Filename="Flowcells/209UKAAXX/080528_209UKAAXX_s8_ChIPSeq_HepG2_Rep2_NRSF_SL274.align_25.hg18.txt" Count=" 1364998" Date="080528" />
+<Track Flowcell="306P2AAXX" Lane="3" Filename="Flowcells/306P2AAXX/080722_306P2AAXX_s3_ChIPSeq_HepG2_Rep2_NRSF_SL274.align_25.hg18.txt" Count=" 3945743" Date="080722" />
+<Track Flowcell="FC204MT" Lane="6" Filename="Flowcells/FC204MT/080512_FC204MT_s6_ChIPSeq_HepG2_Rep2_NRSF_SL274.align_25.hg18.txt" Count=" 2969609" Date="080512" />
+</Library>
+<Library Name="SL275">
+<Track Flowcell="306P2AAXX" Lane="2" Filename="Flowcells/306P2AAXX/080722_306P2AAXX_s2_ChIPSeq_HepG2_Rep1_GABP_SL275.align_25.hg18.txt" Count=" 4599829" Date="080722" />
+<Track Flowcell="30DCTAAXX" Lane="7" Filename="Flowcells/30DCTAAXX/080904_30DCTAAXX_s7_ChIPSeq_HepG2_Rep1_GABP_SL275.align_25.hg18.txt" Count=" 677714" Date="080904" />
+<Track Flowcell="FC204MT" Lane="7" Filename="Flowcells/FC204MT/080512_FC204MT_s7_ChIPSeq_HepG2_Rep1_GABP_SL275.align_25.hg18.txt" Count=" 3373373" Date="080512" />
+</Library>
+<Library Name="SL276">
+<Track Flowcell="306P2AAXX" Lane="1" Filename="Flowcells/306P2AAXX/080722_306P2AAXX_s1_ChIPSeq_HepG2_Rep2_GABP_SL276.align_25.hg18.txt" Count=" 4297640" Date="080722" />
+<Track Flowcell="30DCTAAXX" Lane="8" Filename="Flowcells/30DCTAAXX/080904_30DCTAAXX_s8_ChIPSeq_HepG2_Rep2_GABP_SL276.align_25.hg18.txt" Count=" 604582" Date="080904" />
+<Track Flowcell="FC204MT" Lane="8" Filename="Flowcells/FC204MT/080512_FC204MT_s8_ChIPSeq_HepG2_Rep2_GABP_SL276.align_25.hg18.txt" Count=" 3252004" Date="080512" />
+</Library>
+<Library Name="SL277">
+<Track Flowcell="FC20ATL" Lane="2" Filename="Flowcells/FC20ATL/080527_FC20ATL_s2_ChIPSeq_Jurkat_S_S_Rep1_SRF_SL277.align_25.hg18.txt" Count=" 3716401" Date="080527" />
+</Library>
+<Library Name="SL280">
+<Track Flowcell="FC20AJ8" Lane="2" Filename="Flowcells/FC20AJ8/080523_FC20AJ8_s2_RNASeq_HepG2_Rep1_SL280.align_25.hg18.txt" Count=" 194175" Date="080523" />
+</Library>
+<Library Name="SL281">
+<Track Flowcell="FC20AJ8" Lane="3" Filename="Flowcells/FC20AJ8/080523_FC20AJ8_s3_RNASeq_HepG2_Rep2_SL281.align_25.hg18.txt" Count=" 421392" Date="080523" />
+</Library>
+<Library Name="SL288">
+<Track Flowcell="306P2AAXX" Lane="8" Filename="Flowcells/306P2AAXX/080722_306P2AAXX_s8_ChIPSeq_GM12878_Rep1_TAF250_SL288.align_25.hg18.txt" Count=" 2153614" Date="080722" />
+<Track Flowcell="30DBLAAXX" Lane="1" Filename="Flowcells/30DBLAAXX/080815_30DBLAAXX_s1_ChIPSeq_GM12878_Rep1_TAF250_SL288.align_25.hg18.txt" Count=" 3958844" Date="080815" />
+<Track Flowcell="30DCTAAXX" Lane="6" Filename="Flowcells/30DCTAAXX/080904_30DCTAAXX_s6_ChIPSeq_GM12878_Rep1_TAF250_SL288.align_25.hg18.txt" Count=" 1715117" Date="080904" />
+<Track Flowcell="FC20AJ8" Lane="6" Filename="Flowcells/FC20AJ8/080523_FC20AJ8_s6_ChIPSeq_GM12878_Rep1_TAF250_SL288.align_25.hg18.txt" Count=" 3168587" Date="080523" />
+</Library>
+<Library Name="SL289">
+<Track Flowcell="30DBLAAXX" Lane="5" Filename="Flowcells/30DBLAAXX/080815_30DBLAAXX_s5_ChIPSeq_K562_Rep1_SRF_SL289.align_25.hg18.txt" Count=" 3892910" Date="080815" />
+<Track Flowcell="30DBLAAXX" Lane="6" Filename="Flowcells/30DBLAAXX/080815_30DBLAAXX_s6_ChIPSeq_K562_Rep1_SRF_SL289.align_25.hg18.txt" Count=" 3749795" Date="080815" />
+<Track Flowcell="FC20AJ8" Lane="7" Filename="Flowcells/FC20AJ8/080523_FC20AJ8_s7_ChIPSeq_K562_Rep1_SRF_SL289.align_25.hg18.txt" Count=" 2705050" Date="080523" />
+</Library>
+<Library Name="SL290">
+<Track Flowcell="30DBLAAXX" Lane="7" Filename="Flowcells/30DBLAAXX/080815_30DBLAAXX_s7_ChIPSeq_K562_Rep2_SRF_SL290.align_25.hg18.txt" Count=" 4165480" Date="080815" />
+<Track Flowcell="30DBLAAXX" Lane="8" Filename="Flowcells/30DBLAAXX/080815_30DBLAAXX_s8_ChIPSeq_K562_Rep2_SRF_SL290.align_25.hg18.txt" Count=" 2870741" Date="080815" />
+<Track Flowcell="FC20AJ8" Lane="8" Filename="Flowcells/FC20AJ8/080523_FC20AJ8_s8_ChIPSeq_K562_Rep2_SRF_SL290.align_25.hg18.txt" Count=" 2889602" Date="080523" />
+</Library>
+<Library Name="SL291">
+<Track Flowcell="2087VAAXX" Lane="1" Filename="Flowcells/2087VAAXX/080611_2087VAAXX_s1_ChIPSeq_GM12878_Rep1_SRF_SL291.align_25.hg18.txt" Count=" 2326626" Date="080611" />
+<Track Flowcell="2087VAAXX" Lane="5" Filename="Flowcells/2087VAAXX/080611_2087VAAXX_s5_ChIPSeq_GM12878_Rep1_SRF_SL291.align_25.hg18.txt" Count=" 2283483" Date="080611" />
+<Track Flowcell="30DBLAAXX" Lane="3" Filename="Flowcells/30DBLAAXX/080815_30DBLAAXX_s3_ChIP-seq_SRF_GM12878_Rep1_SL291.align_25.hg18.txt" Count=" 4312781" Date="080815" />
+<Track Flowcell="FC20ATH" Lane="1" Filename="Flowcells/FC20ATH/080602_FC20ATH_s1_ChIP-seq_SRF_GM12878_Rep1_SL291.align_25.hg18.txt" Count=" 1165384" Date="080602" />
+</Library>
+<Library Name="SL292">
+<Track Flowcell="2087VAAXX" Lane="2" Filename="Flowcells/2087VAAXX/080611_2087VAAXX_s2_ChIPSeq_GM12878_Rep2_SRF_SL292.align_25.hg18.txt" Count=" 2117859" Date="080611" />
+<Track Flowcell="2087VAAXX" Lane="6" Filename="Flowcells/2087VAAXX/080611_2087VAAXX_s6_ChIPSeq_GM12878_Rep2_SRF_SL292.align_25.hg18.txt" Count=" 2135165" Date="080611" />
+<Track Flowcell="30DBLAAXX" Lane="4" Filename="Flowcells/30DBLAAXX/080815_30DBLAAXX_s4_ChIP-seq_SRF_GM12878_Rep2_SL292.align_25.hg18.txt" Count=" 4481065" Date="080815" />
+<Track Flowcell="FC20ATH" Lane="2" Filename="Flowcells/FC20ATH/080602_FC20ATH_s2_ChIP-seq_SRF_GM12878_Rep2_SL292.align_25.hg18.txt" Count=" 2027947" Date="080602" />
+</Library>
+<Library Name="SL293">
+<Track Flowcell="2087VAAXX" Lane="3" Filename="Flowcells/2087VAAXX/080611_2087VAAXX_s3_ChIPSeq_GM12878_Rep2_TAF250_SL293.align_25.hg18.txt" Count=" 2598142" Date="080611" />
+<Track Flowcell="2087VAAXX" Lane="7" Filename="Flowcells/2087VAAXX/080611_2087VAAXX_s7_ChIPSeq_GM12878_Rep2_TAF250_SL293.align_25.hg18.txt" Count=" 2556642" Date="080611" />
+<Track Flowcell="30DBLAAXX" Lane="2" Filename="Flowcells/30DBLAAXX/080815_30DBLAAXX_s2_ChIP-seq_TAF250_GM12878_Rep2_SL293.align_25.hg18.txt" Count=" 4857889" Date="080815" />
+<Track Flowcell="FC20ATH" Lane="3" Filename="Flowcells/FC20ATH/080602_FC20ATH_s3_ChIP-seq_TAF250_GM12878_Rep2_SL293.align_25.hg18.txt" Count=" 2398112" Date="080602" />
+</Library>
+<Library Name="SL294">
+<Track Flowcell="2087VAAXX" Lane="8" Filename="Flowcells/2087VAAXX/080611_2087VAAXX_s8_ChIPSeq_HepG2_Rep1_InputControl_RXLCh_SL294.align_25.hg18.txt" Count=" 2190318" Date="080611" />
+<Track Flowcell="306P2AAXX" Lane="7" Filename="Flowcells/306P2AAXX/080722_306P2AAXX_s7_Input_Control_HepG2_Rep1_SL294.align_25.hg18.txt" Count=" 1918136" Date="080722" />
+<Track Flowcell="30CLAAXX" Lane="7" Filename="Flowcells/30CLAAXX/080815_30CLAAXX_s7_Input_Control_HepG2_Rep1_SL294.align_25.hg18.txt" Count=" 5027019" Date="080815" />
+<Track Flowcell="30EFCAAXX" Lane="4" Filename="Flowcells/30EFCAAXX/080910_30EFCAAXX_s4_Input_Control_HepG2_Rep1_SL294.align_25.hg18.txt" Count=" 1919675" Date="080910" />
+<Track Flowcell="30EFCAAXX" Lane="5" Filename="Flowcells/30EFCAAXX/080910_30EFCAAXX_s5_Input_Control_HepG2_Rep1_SL294.align_25.hg18.txt" Count=" 1999038" Date="080910" />
+<Track Flowcell="FC20ATH" Lane="4" Filename="Flowcells/FC20ATH/080602_FC20ATH_s4_Input_Control_HepG2_Rep1_SL294.align_25.hg18.txt" Count=" 2168270" Date="080602" />
+</Library>
+<Library Name="SL295">
+<Track Flowcell="306P2AAXX" Lane="5" Filename="Flowcells/306P2AAXX/080722_306P2AAXX_s5_Input_Control_HepG2_Rep2_SL295.align_25.hg18.txt" Count=" 2771168" Date="080722" />
+<Track Flowcell="306P2AAXX" Lane="6" Filename="Flowcells/306P2AAXX/080722_306P2AAXX_s6_Input_Control_HepG2_Rep2_SL295.align_25.hg18.txt" Count=" 1633531" Date="080722" />
+<Track Flowcell="30CLAAXX" Lane="8" Filename="Flowcells/30CLAAXX/080815_30CLAAXX_s8_Input_Control_HepG2_Rep2_SL295.align_25.hg18.txt" Count=" 3842145" Date="080815" />
+<Track Flowcell="30EFCAAXX" Lane="7" Filename="Flowcells/30EFCAAXX/080910_30EFCAAXX_s7_Input_Control_HepG2_Rep2_SL295.align_25.hg18.txt" Count=" 2989786" Date="080910" />
+<Track Flowcell="30EFCAAXX" Lane="8" Filename="Flowcells/30EFCAAXX/080910_30EFCAAXX_s8_Input_Control_HepG2_Rep2_SL295.align_25.hg18.txt" Count=" 2811384" Date="080910" />
+<Track Flowcell="FC20ATH" Lane="5" Filename="Flowcells/FC20ATH/080602_FC20ATH_s5_Input_Control_HepG2_Rep2_SL295.align_25.hg18.txt" Count=" 1970158" Date="080602" />
+</Library>
+<Library Name="SL296">
+<Track Flowcell="30DDDAAXX" Lane="4" Filename="Flowcells/30DDDAAXX/080826_30DDDAAXX_s4_Methylseq_GM12878_R1_hpa_1pcr_SL296.align_25.hg18.txt" Count=" 5963498" Date="080826" />
+<Track Flowcell="30EGGAAXX" Lane="1" Filename="Flowcells/30EGGAAXX/080910_30EGGAAXX_s1_Methylseq_GM12878_R1_hpa_1pcr_SL296.align_25.hg18.txt" Count=" 977352" Date="080910" />
+<Track Flowcell="30EGGAAXX" Lane="2" Filename="Flowcells/30EGGAAXX/080910_30EGGAAXX_s2_Methylseq_GM12878_R1_hpa_1pcr_SL296.align_25.hg18.txt" Count=" 687356" Date="080910" />
+<Track Flowcell="30EGGAAXX" Lane="3" Filename="Flowcells/30EGGAAXX/080910_30EGGAAXX_s3_Methylseq_GM12878_R1_hpa_1pcr_SL296.align_25.hg18.txt" Count=" 488635" Date="080910" />
+<Track Flowcell="FC209TJ" Lane="5" Filename="Flowcells/FC209TJ/080606_FC209TJ_s5_Methylseq_GM12878_R1_hpa_1pcr_SL296.align_25.hg18.txt" Count=" 2940725" Date="080606" />
+</Library>
+<Library Name="SL297">
+<Track Flowcell="30DDDAAXX" Lane="3" Filename="Flowcells/30DDDAAXX/080826_30DDDAAXX_s3_Methylseq_GM12878_R2_hpa_2pcr_SL297.align_25.hg18.txt" Count=" 5868879" Date="080826" />
+<Track Flowcell="30EGGAAXX" Lane="6" Filename="Flowcells/30EGGAAXX/080910_30EGGAAXX_s6_Methylseq_GM12878_R2_hpa_2pcr_SL297.align_25.hg18.txt" Count=" 326483" Date="080910" />
+<Track Flowcell="30EGGAAXX" Lane="7" Filename="Flowcells/30EGGAAXX/080910_30EGGAAXX_s7_Methylseq_GM12878_R2_hpa_2pcr_SL297.align_25.hg18.txt" Count=" 397246" Date="080910" />
+<Track Flowcell="30EGGAAXX" Lane="8" Filename="Flowcells/30EGGAAXX/080910_30EGGAAXX_s8_Methylseq_GM12878_R2_hpa_2pcr_SL297.align_25.hg18.txt" Count=" 646888" Date="080910" />
+<Track Flowcell="FC209TJ" Lane="6" Filename="Flowcells/FC209TJ/080606_FC209TJ_s6_Methylseq_GM12878_R2_hpa_2pcr_SL297.align_25.hg18.txt" Count=" 2634191" Date="080606" />
+</Library>
+<Library Name="SL298">
+<Track Flowcell="30DDDAAXX" Lane="2" Filename="Flowcells/30DDDAAXX/080826_30DDDAAXX_s2_Methylseq_GM12878_R1_msp_1pcr_SL298.align_25.hg18.txt" Count=" 4205665" Date="080826" />
+<Track Flowcell="FC209TJ" Lane="7" Filename="Flowcells/FC209TJ/080606_FC209TJ_s7_Methylseq_GM12878_R1_msp_1pcr_SL298.align_25.hg18.txt" Count=" 2516383" Date="080606" />
+</Library>
+<Library Name="SL299">
+<Track Flowcell="30DDDAAXX" Lane="1" Filename="Flowcells/30DDDAAXX/080826_30DDDAAXX_s1_Methylseq_GM12878_R2_msp_2pcr_SL299.align_25.hg18.txt" Count=" 3481486" Date="080826" />
+<Track Flowcell="FC209TJ" Lane="8" Filename="Flowcells/FC209TJ/080606_FC209TJ_s8_Methylseq_GM12878_R2_msp_2pcr_SL299.align_25.hg18.txt" Count=" 1951342" Date="080606" />
+</Library>
+<Library Name="SL300">
+<Track Flowcell="306WNAAXX" Lane="5" Filename="Flowcells/306WNAAXX/080731_306WNAAXX_s5_Methyl-seq_HepG2__rep1_hpa_1PCR_SL300.align_25.hg18.txt" Count=" 1404807" Date="080731" />
+<Track Flowcell="30DDDAAXX" Lane="5" Filename="Flowcells/30DDDAAXX/080826_30DDDAAXX_s5_Methyl-seq_HepG2__rep1_hpa_1PCR_SL300.align_25.hg18.txt" Count=" 5941690" Date="080826" />
+</Library>
+<Library Name="SL301">
+<Track Flowcell="306WNAAXX" Lane="6" Filename="Flowcells/306WNAAXX/080731_306WNAAXX_s6_Methyl-seq_HepG2__rep2_hpa_2PCR_SL301.align_25.hg18.txt" Count=" 1216872" Date="080731" />
+<Track Flowcell="30DDDAAXX" Lane="6" Filename="Flowcells/30DDDAAXX/080826_30DDDAAXX_s6_Methyl-seq_HepG2__rep2_hpa_2PCR_SL301.align_25.hg18.txt" Count=" 6122369" Date="080826" />
+</Library>
+<Library Name="SL302">
+<Track Flowcell="306WNAAXX" Lane="7" Filename="Flowcells/306WNAAXX/080731_306WNAAXX_s7_Methyl-seq_HepG2__rep2_msp_1PCR_SL302.align_25.hg18.txt" Count=" 1205138" Date="080731" />
+<Track Flowcell="30DDDAAXX" Lane="7" Filename="Flowcells/30DDDAAXX/080826_30DDDAAXX_s7_Methyl-seq_HepG2__rep2_msp_1PCR_SL302.align_25.hg18.txt" Count=" 4609878" Date="080826" />
+</Library>
+<Library Name="SL303">
+<Track Flowcell="306WNAAXX" Lane="8" Filename="Flowcells/306WNAAXX/080731_306WNAAXX_s8_Methyl-seq_HepG2__rep2_msp_2PCR_SL303.align_25.hg18.txt" Count=" 856073" Date="080731" />
+<Track Flowcell="30DDDAAXX" Lane="8" Filename="Flowcells/30DDDAAXX/080826_30DDDAAXX_s8_Methyl-seq_HepG2__rep2_msp_2PCR_SL303.align_25.hg18.txt" Count=" 4337314" Date="080826" />
+</Library>
+<Library Name="SL304">
+<Track Flowcell="3072MAAXX" Lane="3" Filename="Flowcells/3072MAAXX/080722_3072MAAXX_s3_A549_Rep2_GR_Dex_ChIP_SL304.align_25.hg18.txt" Count=" 3036609" Date="080722" />
+<Track Flowcell="3072MAAXX" Lane="4" Filename="Flowcells/3072MAAXX/080722_3072MAAXX_s4_A549_Rep2_GR_Dex_ChIP_SL304.align_25.hg18.txt" Count=" 2826138" Date="080722" />
+<Track Flowcell="30DC1AAXX" Lane="1" Filename="Flowcells/30DC1AAXX/080826_30DC1AAXX_s1_A549_Rep2_GR_Dex_ChIP_SL304.align_25.hg18.txt" Count=" 2155855" Date="080826" />
+<Track Flowcell="FC20AUG" Lane="5" Filename="Flowcells/FC20AUG/080612_FC20AUG_s5_A549_Rep2_GR_Dex_ChIP_SL304.align_25.hg18.txt" Count=" 2357287" Date="080612" />
+</Library>
+<Library Name="SL305">
+<Track Flowcell="30DAGAAXX" Lane="7" Filename="Flowcells/30DAGAAXX/080826_30DAGAAXX_s7_A549_Rep2_GR_EtOH_ChIP_SL305.align_25.hg18.txt" Count=" 3119566" Date="080826" />
+<Track Flowcell="30DC1AAXX" Lane="2" Filename="Flowcells/30DC1AAXX/080826_30DC1AAXX_s2_A549_Rep2_GR_EtOH_ChIP_SL305.align_25.hg18.txt" Count=" 2437734" Date="080826" />
+<Track Flowcell="30DC1AAXX" Lane="3" Filename="Flowcells/30DC1AAXX/080826_30DC1AAXX_s3_A549_Rep2_GR_EtOH_ChIP_SL305.align_25.hg18.txt" Count=" 2429901" Date="080826" />
+<Track Flowcell="FC20AUG" Lane="6" Filename="Flowcells/FC20AUG/080612_FC20AUG_s6_A549_Rep2_GR_EtOH_ChIP_SL305.align_25.hg18.txt" Count=" 2182536" Date="080612" />
+</Library>
+<Library Name="SL306">
+<Track Flowcell="3072MAAXX" Lane="5" Filename="Flowcells/3072MAAXX/080722_3072MAAXX_s5_A549_Rep2_Pol2_Dex_ChIP_SL306.align_25.hg18.txt" Count=" 3787015" Date="080722" />
+<Track Flowcell="3072MAAXX" Lane="6" Filename="Flowcells/3072MAAXX/080722_3072MAAXX_s6_A549_Rep2_Pol2_Dex_ChIP_SL306.align_25.hg18.txt" Count=" 3262311" Date="080722" />
+<Track Flowcell="3072MAAXX" Lane="7" Filename="Flowcells/3072MAAXX/080722_3072MAAXX_s7_A549_Rep2_Pol2_Dex_ChIP_SL306.align_25.hg18.txt" Count=" 2664712" Date="080722" />
+<Track Flowcell="3072MAAXX" Lane="8" Filename="Flowcells/3072MAAXX/080722_3072MAAXX_s8_A549_Rep2_Pol2_Dex_ChIP_SL306.align_25.hg18.txt" Count=" 2082693" Date="080722" />
+<Track Flowcell="FC20AUG" Lane="7" Filename="Flowcells/FC20AUG/080612_FC20AUG_s7_A549_Rep2_Pol2_Dex_ChIP_SL306.align_25.hg18.txt" Count=" 4246636" Date="080612" />
+</Library>
+<Library Name="SL307">
+<Track Flowcell="3072MAAXX" Lane="1" Filename="Flowcells/3072MAAXX/080722_3072MAAXX_s1_A549_EtOH_RX_noIP_SL307.align_25.hg18.txt" Count=" 3727098" Date="080722" />
+<Track Flowcell="3072MAAXX" Lane="2" Filename="Flowcells/3072MAAXX/080722_3072MAAXX_s2_A549_EtOH_RX_noIP_SL307.align_25.hg18.txt" Count=" 4398655" Date="080722" />
+<Track Flowcell="FC20AUG" Lane="8" Filename="Flowcells/FC20AUG/080612_FC20AUG_s8_A549_EtOH_RX_noIP_SL307.align_25.hg18.txt" Count=" 3738550" Date="080612" />
+</Library>
+<Library Name="SL310">
+<Track Flowcell="FC20ATH" Lane="6" Filename="Flowcells/FC20ATH/080602_FC20ATH_s6_RNA-seq_GM12878_Rep2_SL310.align_25.hg18.txt" Count=" 3087245" Date="080602" />
+</Library>
+<Library Name="SL311">
+<Track Flowcell="FC20AUM" Lane="1" Filename="Flowcells/FC20AUM/080616_FC20AUM_s1_RNASeq_BJ_rep1_SL311.align_25.hg18.txt" Count=" 3688931" Date="080616" />
+</Library>
+<Library Name="SL312">
+<Track Flowcell="30EG4AAXX" Lane="8" Filename="Flowcells/30EG4AAXX/080916_30EG4AAXX_s8_RNA-seq_HepG2_Rep1_SL312.align_25.hg18.txt" Count=" 4776370" Date="080916" />
+<Track Flowcell="FC20ATH" Lane="7" Filename="Flowcells/FC20ATH/080602_FC20ATH_s7_RNA-seq_HepG2_Rep1_SL312.align_25.hg18.txt" Count=" 3535250" Date="080602" />
+</Library>
+<Library Name="SL313">
+<Track Flowcell="FC20ATH" Lane="8" Filename="Flowcells/FC20ATH/080602_FC20ATH_s8_RNA-seq_HepG2_Rep2_SL313.align_25.hg18.txt" Count=" 3462781" Date="080602" />
+</Library>
+<Library Name="SL314">
+<Track Flowcell="FC20AUM" Lane="2" Filename="Flowcells/FC20AUM/080616_FC20AUM_s2_RNA-seq_HMEC_rep1_SL314.align_25.hg18.txt" Count=" 4056466" Date="080616" />
+</Library>
+<Library Name="SL315">
+<Track Flowcell="FC20AUM" Lane="3" Filename="Flowcells/FC20AUM/080616_FC20AUM_s3_RNA-seq_HMEC_rep2_SL315.align_25.hg18.txt" Count=" 3958633" Date="080616" />
+</Library>
+<Library Name="SL316">
+<Track Flowcell="306WKAAXX" Lane="5" Filename="Flowcells/306WKAAXX/080728_306WKAAXX_s5_RNAseq_Jurkat_rep1_SL316.align_25.hg18.txt" Count=" 2116970" Date="080728" />
+<Track Flowcell="306WKAAXX" Lane="6" Filename="Flowcells/306WKAAXX/080728_306WKAAXX_s6_RNAseq_Jurkat_rep1_SL316.align_25.hg18.txt" Count=" 3213207" Date="080728" />
+<Track Flowcell="30DAGAAXX" Lane="8" Filename="Flowcells/30DAGAAXX/080826_30DAGAAXX_s8_RNAseq_Jurkat_rep1_SL316.align_25.hg18.txt" Count=" 4938781" Date="080826" />
+<Track Flowcell="FC20AUM" Lane="4" Filename="Flowcells/FC20AUM/080616_FC20AUM_s4_RNAseq_Jurkat_rep1_SL316.align_25.hg18.txt" Count=" 3926383" Date="080616" />
+</Library>
+<Library Name="SL317">
+<Track Flowcell="306WKAAXX" Lane="7" Filename="Flowcells/306WKAAXX/080728_306WKAAXX_s7_RNAseq_Jurkat_rep2_SL317.align_25.hg18.txt" Count=" 4116201" Date="080728" />
+<Track Flowcell="306WKAAXX" Lane="8" Filename="Flowcells/306WKAAXX/080728_306WKAAXX_s8_RNAseq_Jurkat_rep2_SL317.align_25.hg18.txt" Count=" 3689888" Date="080728" />
+<Track Flowcell="FC20AUM" Lane="5" Filename="Flowcells/FC20AUM/080616_FC20AUM_s5_RNAseq_Jurkat_rep2_SL317.align_25.hg18.txt" Count=" 4104444" Date="080616" />
+</Library>
+<Library Name="SL318">
+<Track Flowcell="FC20AMC" Lane="1" Filename="Flowcells/FC20AMC/080609_FC20AMC_s1_ChIP-seq_hESC_K36_repurified_SL318.align_25.hg18.txt" Count=" 971624" Date="080609" />
+</Library>
+<Library Name="SL319">
+<Track Flowcell="FC20AMC" Lane="2" Filename="Flowcells/FC20AMC/080609_FC20AMC_s2_ChIP-seq_hESC_K27_repurified_SL319.align_25.hg18.txt" Count=" 365209" Date="080609" />
+</Library>
+<Library Name="SL320">
+<Track Flowcell="FC20AMC" Lane="3" Filename="Flowcells/FC20AMC/080609_FC20AMC_s3_ChIP-seq_hESC_Pol2_repurified_SL320.align_25.hg18.txt" Count=" 643582" Date="080609" />
+</Library>
+<Library Name="SL321">
+<Track Flowcell="FC20AMC" Lane="4" Filename="Flowcells/FC20AMC/080609_FC20AMC_s4_Input_Control_hESC_Repurified_SL321.align_25.hg18.txt" Count=" 1384822" Date="080609" />
+</Library>
+<Library Name="SL322">
+<Track Flowcell="FC209TJ" Lane="1" Filename="Flowcells/FC209TJ/080606_FC209TJ_s1_ChIpSeq_hESCday5_K4_SL322.align_25.hg18.txt" Count=" 578452" Date="080606" />
+</Library>
+<Library Name="SL323">
+<Track Flowcell="FC209TJ" Lane="2" Filename="Flowcells/FC209TJ/080606_FC209TJ_s2_Input_Control_hESCday5_SL323.align_25.hg18.txt" Count=" 1756643" Date="080606" />
+</Library>
+<Library Name="SL324">
+<Track Flowcell="FC209TJ" Lane="3" Filename="Flowcells/FC209TJ/080606_FC209TJ_s3_ChIpSeq_hESCday5_K27_SL324.align_25.hg18.txt" Count=" 1306396" Date="080606" />
+</Library>
+<Library Name="SL325">
+<Track Flowcell="FC209TJ" Lane="4" Filename="Flowcells/FC209TJ/080606_FC209TJ_s4_ChIpSeq_hESCday5_K36_SL325.align_25.hg18.txt" Count=" 478866" Date="080606" />
+</Library>
+<Library Name="SL326">
+<Track Flowcell="FC20AUG" Lane="1" Filename="Flowcells/FC20AUG/080612_FC20AUG_s1_RNA-seq_BJ_Rep2_75_SL326.align_25.hg18.txt" Count=" 3188417" Date="080612" />
+</Library>
+<Library Name="SL327">
+<Track Flowcell="FC20AUG" Lane="2" Filename="Flowcells/FC20AUG/080612_FC20AUG_s2_RNA-seq_K562_Rep3_75_SL327.align_25.hg18.txt" Count=" 3717306" Date="080612" />
+</Library>
+<Library Name="SL328">
+<Track Flowcell="FC20AUG" Lane="3" Filename="Flowcells/FC20AUG/080612_FC20AUG_s3_RNA-seq_BJ_Rep2_7_5_SL328.align_25.hg18.txt" Count=" 3864656" Date="080612" />
+</Library>
+<Library Name="SL329">
+<Track Flowcell="FC20AUG" Lane="4" Filename="Flowcells/FC20AUG/080612_FC20AUG_s4_RNA-seq_K562_Rep3_7_5_SL329.align_25.hg18.txt" Count=" 3915270" Date="080612" />
+</Library>
+<Library Name="SL330">
+<Track Flowcell="303n0aaxx" Lane="1" Filename="Flowcells/303n0aaxx/080715_303n0aaxx_s1_RNA-seq_A549_Rep1_Dex_SL330.align_25.hg18.txt" Count=" 1006721" Date="080715" />
+<Track Flowcell="303n0aaxx" Lane="2" Filename="Flowcells/303n0aaxx/080715_303n0aaxx_s2_RNA-seq_A549_Rep1_Dex_SL330.align_25.hg18.txt" Count=" 1140136" Date="080715" />
+<Track Flowcell="306WKAAXX" Lane="1" Filename="Flowcells/306WKAAXX/080728_306WKAAXX_s1_RNA-seq_A549_Rep1_Dex_SL330.align_25.hg18.txt" Count=" 3860069" Date="080728" />
+<Track Flowcell="30DC1AAXX" Lane="4" Filename="Flowcells/30DC1AAXX/080826_30DC1AAXX_s4_RNA-seq_A549_Rep1_Dex_SL330.align_25.hg18.txt" Count=" 5037938" Date="080826" />
+<Track Flowcell="FC20AMC" Lane="5" Filename="Flowcells/FC20AMC/080609_FC20AMC_s5_RNA-seq_A549_Rep1_Dex_SL330.align_25.hg18.txt" Count=" 2586689" Date="080609" />
+<Track Flowcell="FC306VCAAXX" Lane="1" Filename="Flowcells/FC306VCAAXX/080725_FC306VCAAXX_s1_RNA-seq_A549_Rep1_Dex_SL330.align_25.hg18.txt" Count=" 2607495" Date="080725" />
+<Track Flowcell="FC306VCAAXX" Lane="2" Filename="Flowcells/FC306VCAAXX/080725_FC306VCAAXX_s2_RNA-seq_A549_Rep1_Dex_SL330.align_25.hg18.txt" Count=" 2538777" Date="080725" />
+</Library>
+<Library Name="SL331">
+<Track Flowcell="303n0aaxx" Lane="5" Filename="Flowcells/303n0aaxx/080715_303n0aaxx_s5_RNA-seq_A549_Rep1_EtOH_SL331.align_25.hg18.txt" Count=" 2173243" Date="080715" />
+<Track Flowcell="303n0aaxx" Lane="6" Filename="Flowcells/303n0aaxx/080715_303n0aaxx_s6_RNA-seq_A549_Rep1_EtOH_SL331.align_25.hg18.txt" Count=" 2197491" Date="080715" />
+<Track Flowcell="306WKAAXX" Lane="2" Filename="Flowcells/306WKAAXX/080728_306WKAAXX_s2_RNA-seq_A549_Rep1_EtOH_SL331.align_25.hg18.txt" Count=" 3706943" Date="080728" />
+<Track Flowcell="30DC1AAXX" Lane="5" Filename="Flowcells/30DC1AAXX/080826_30DC1AAXX_s5_RNA-seq_A549_Rep1_EtOH_SL331.align_25.hg18.txt" Count=" 5087597" Date="080826" />
+<Track Flowcell="FC20AMC" Lane="6" Filename="Flowcells/FC20AMC/080609_FC20AMC_s6_RNA-seq_A549_Rep1_EtOH_SL331.align_25.hg18.txt" Count=" 2877770" Date="080609" />
+<Track Flowcell="FC306VCAAXX" Lane="5" Filename="Flowcells/FC306VCAAXX/080725_FC306VCAAXX_s5_RNA-seq_A549_Rep1_EtOH_SL331.align_25.hg18.txt" Count=" 1159780" Date="080725" />
+<Track Flowcell="FC306VCAAXX" Lane="6" Filename="Flowcells/FC306VCAAXX/080725_FC306VCAAXX_s6_RNA-seq_A549_Rep1_EtOH_SL331.align_25.hg18.txt" Count=" 1488352" Date="080725" />
+</Library>
+<Library Name="SL332">
+<Track Flowcell="303n0aaxx" Lane="3" Filename="Flowcells/303n0aaxx/080715_303n0aaxx_s3_RNA-seq_A549_Rep2_Dex_SL332.align_25.hg18.txt" Count=" 1087155" Date="080715" />
+<Track Flowcell="303n0aaxx" Lane="4" Filename="Flowcells/303n0aaxx/080715_303n0aaxx_s4_RNA-seq_A549_Rep2_Dex_SL332.align_25.hg18.txt" Count=" 1070083" Date="080715" />
+<Track Flowcell="306WKAAXX" Lane="3" Filename="Flowcells/306WKAAXX/080728_306WKAAXX_s3_RNA-seq_A549_Rep2_Dex_SL332.align_25.hg18.txt" Count=" 4289055" Date="080728" />
+<Track Flowcell="30DC1AAXX" Lane="6" Filename="Flowcells/30DC1AAXX/080826_30DC1AAXX_s6_RNA-seq_A549_Rep2_Dex_SL332.align_25.hg18.txt" Count=" 5053382" Date="080826" />
+<Track Flowcell="30DC1AAXX" Lane="7" Filename="Flowcells/30DC1AAXX/080826_30DC1AAXX_s7_RNA-seq_A549_Rep2_Dex_SL332.align_25.hg18.txt" Count=" 4921156" Date="080826" />
+<Track Flowcell="FC20AMC" Lane="7" Filename="Flowcells/FC20AMC/080609_FC20AMC_s7_RNA-seq_A549_Rep2_Dex_SL332.align_25.hg18.txt" Count=" 2950811" Date="080609" />
+<Track Flowcell="FC306VCAAXX" Lane="3" Filename="Flowcells/FC306VCAAXX/080725_FC306VCAAXX_s3_RNA-seq_A549_Rep2_Dex_SL332.align_25.hg18.txt" Count=" 1260681" Date="080725" />
+</Library>
+<Library Name="SL333">
+<Track Flowcell="303n0aaxx" Lane="7" Filename="Flowcells/303n0aaxx/080715_303n0aaxx_s7_RNA-seq_A549_Rep2_EtOH_SL333.align_25.hg18.txt" Count=" 1479883" Date="080715" />
+<Track Flowcell="303n0aaxx" Lane="8" Filename="Flowcells/303n0aaxx/080715_303n0aaxx_s8_RNA-seq_A549_Rep2_EtOH_SL333.align_25.hg18.txt" Count=" 1429681" Date="080715" />
+<Track Flowcell="306WKAAXX" Lane="4" Filename="Flowcells/306WKAAXX/080728_306WKAAXX_s4_RNA-seq_A549_Rep2_EtOH_SL333.align_25.hg18.txt" Count=" 3317843" Date="080728" />
+<Track Flowcell="30DC1AAXX" Lane="8" Filename="Flowcells/30DC1AAXX/080826_30DC1AAXX_s8_RNA-seq_A549_Rep2_EtOH_SL333.align_25.hg18.txt" Count=" 4215546" Date="080826" />
+<Track Flowcell="FC20AMC" Lane="8" Filename="Flowcells/FC20AMC/080609_FC20AMC_s8_RNA-seq_A549_Rep2_EtOH_SL333.align_25.hg18.txt" Count=" 2863677" Date="080609" />
+<Track Flowcell="FC306VCAAXX" Lane="7" Filename="Flowcells/FC306VCAAXX/080725_FC306VCAAXX_s7_RNA-seq_A549_Rep2_EtOH_SL333.align_25.hg18.txt" Count=" 3146212" Date="080725" />
+<Track Flowcell="FC306VCAAXX" Lane="8" Filename="Flowcells/FC306VCAAXX/080725_FC306VCAAXX_s8_RNA-seq_A549_Rep2_EtOH_SL333.align_25.hg18.txt" Count=" 2107413" Date="080725" />
+</Library>
+<Library Name="SL334">
+<Track Flowcell="303y5aaxx" Lane="5" Filename="Flowcells/303y5aaxx/080715_303y5aaxx_s5_Pol2_EtOH_chIP_Rep1_SL334.align_25.hg18.txt" Count=" 4221253" Date="080715" />
+<Track Flowcell="303y5aaxx" Lane="6" Filename="Flowcells/303y5aaxx/080715_303y5aaxx_s6_Pol2_EtOH_chIP_Rep1_SL334.align_25.hg18.txt" Count=" 4389966" Date="080715" />
+<Track Flowcell="30DAGAAXX" Lane="5" Filename="Flowcells/30DAGAAXX/080826_30DAGAAXX_s5_A549_Pol2_EtOH_chIP_Rep2_SL334.align_25.hg18.txt" Count=" 6048948" Date="080826" />
+</Library>
+<Library Name="SL335">
+<Track Flowcell="303y5aaxx" Lane="7" Filename="Flowcells/303y5aaxx/080715_303y5aaxx_s7_Input_RXLCh_+Dex_SL335.align_25.hg18.txt" Count=" 4320528" Date="080715" />
+<Track Flowcell="303y5aaxx" Lane="8" Filename="Flowcells/303y5aaxx/080715_303y5aaxx_s8_Input_RXLCh_+Dex_SL335.align_25.hg18.txt" Count=" 3212232" Date="080715" />
+<Track Flowcell="30DAGAAXX" Lane="6" Filename="Flowcells/30DAGAAXX/080826_30DAGAAXX_s6_Input_RXLCh_Dex_SL335.align_25.hg18.txt" Count=" 5399341" Date="080826" />
+</Library>
+<Library Name="SL336">
+<Track Flowcell="303PNAXX" Lane="1" Filename="Flowcells/303PNAXX/080718_303PNAXX_s1_Input_Control_RXLCh_Neuro2A_Rep1_SL336.align_25.mm9.txt" Count=" 4919007" Date="080718" />
+</Library>
+<Library Name="SL337">
+<Track Flowcell="303PNAXX" Lane="2" Filename="Flowcells/303PNAXX/080718_303PNAXX_s2_Input_Control_RXLCh_CAD_Rep1_SL337.align_25.mm9.txt" Count=" 5960847" Date="080718" />
+</Library>
+<Library Name="SL338">
+<Track Flowcell="303PNAXX" Lane="3" Filename="Flowcells/303PNAXX/080718_303PNAXX_s3_Neuro2A_CTCF_Rep1_SL338.align_25.mm9.txt" Count=" 5871158" Date="080718" />
+</Library>
+<Library Name="SL339">
+<Track Flowcell="303PNAXX" Lane="4" Filename="Flowcells/303PNAXX/080718_303PNAXX_s4_CAD_CTCF_Rep1_SL339.align_25.mm9.txt" Count=" 5226675" Date="080718" />
+</Library>
+<Library Name="SL340">
+<Track Flowcell="303PNAXX" Lane="5" Filename="Flowcells/303PNAXX/080718_303PNAXX_s5_Neuro2A_USF1_Rep1_SL340.align_25.mm9.txt" Count=" 5113687" Date="080718" />
+</Library>
+<Library Name="SL341">
+<Track Flowcell="303PNAXX" Lane="6" Filename="Flowcells/303PNAXX/080718_303PNAXX_s6_CAD_USF1_Rep1_SL341.align_25.mm9.txt" Count=" 5580547" Date="080718" />
+</Library>
+<Library Name="SL342">
+<Track Flowcell="303PNAXX" Lane="7" Filename="Flowcells/303PNAXX/080718_303PNAXX_s7_Neuro2A_USF2_Rep1_SL342.align_25.mm9.txt" Count=" 4845266" Date="080718" />
+</Library>
+<Library Name="SL343">
+<Track Flowcell="303PNAXX" Lane="8" Filename="Flowcells/303PNAXX/080718_303PNAXX_s8_CAD_USF2_Rep1_SL343.align_25.mm9.txt" Count=" 4722617" Date="080718" />
+</Library>
+<Library Name="SL344">
+<Track Flowcell="FC20AUL" Lane="5" Filename="Flowcells/FC20AUL/080621_FC20AUL_s5_Input_Control_HMEC_rep1_SL344.align_25.hg18.txt" Count=" 1854345" Date="080621" />
+<Track Flowcell="FC20AUL" Lane="6" Filename="Flowcells/FC20AUL/080621_FC20AUL_s6_Input_Control_HMEC_rep1_SL344.align_25.hg18.txt" Count=" 2139393" Date="080621" />
+</Library>
+<Library Name="SL345">
+<Track Flowcell="FC20AUL" Lane="7" Filename="Flowcells/FC20AUL/080621_FC20AUL_s7_Input_Control_HMEC_rep2_SL345.align_25.hg18.txt" Count=" 1981441" Date="080621" />
+<Track Flowcell="FC20AUL" Lane="8" Filename="Flowcells/FC20AUL/080621_FC20AUL_s8_Input_Control_HMEC_rep2_SL345.align_25.hg18.txt" Count=" 2279789" Date="080621" />
+</Library>
+<Library Name="SL346">
+<Track Flowcell="306WPAAXX" Lane="7" Filename="Flowcells/306WPAAXX/080731_306WPAAXX_s7_ChIP-seq_HepG2_Rep1_SRF_SL346.align_25.hg18.txt" Count=" 2030668" Date="080731" />
+<Track Flowcell="30EFCAAXX" Lane="6" Filename="Flowcells/30EFCAAXX/080910_30EFCAAXX_s6_ChIP-seq_HepG2_Rep1_SRF_SL346.align_25.hg18.txt" Count=" 1131395" Date="080910" />
+<Track Flowcell="30EH5AAXX" Lane="3" Filename="Flowcells/30EH5AAXX/080910_30EH5AAXX_s3_ChIP-seq_HepG2_Rep1_SRF_SL346.align_25.hg18.txt" Count=" 656597" Date="080910" />
+</Library>
+<Library Name="SL347">
+<Track Flowcell="306WPAAXX" Lane="8" Filename="Flowcells/306WPAAXX/080731_306WPAAXX_s8_ChIP-seq_HepG2_Rep2_SRF_SL347.align_25.hg18.txt" Count=" 1645829" Date="080731" />
+</Library>
+<Library Name="SL348">
+<Track Flowcell="306WPAAXX" Lane="5" Filename="Flowcells/306WPAAXX/080731_306WPAAXX_s5_ChIP-seq_HepG2_Rep1_RNA_Pol2_SL348.align_25.hg18.txt" Count=" 3221651" Date="080731" />
+</Library>
+<Library Name="SL349">
+<Track Flowcell="306WPAAXX" Lane="6" Filename="Flowcells/306WPAAXX/080731_306WPAAXX_s6_ChIP-seq_HepG2_Rep2_RNA_Pol2_SL349.align_25.hg18.txt" Count=" 3150928" Date="080731" />
+</Library>
+<Library Name="SL350">
+<Track Flowcell="FC20AUL" Lane="1" Filename="Flowcells/FC20AUL/080621_FC20AUL_s1_ChIPSeq_HMEC_Rep1_RNApol2_SL350.align_25.hg18.txt" Count=" 1211303" Date="080621" />
+<Track Flowcell="FC20AUL" Lane="2" Filename="Flowcells/FC20AUL/080621_FC20AUL_s2_ChIPSeq_HMEC_Rep1_RNApol2_SL350.align_25.hg18.txt" Count=" 1646993" Date="080621" />
+</Library>
+<Library Name="SL351">
+<Track Flowcell="FC20AUL" Lane="3" Filename="Flowcells/FC20AUL/080621_FC20AUL_s3_chIPSeq_HMEC_Rep2_RNApol2_SL351.align_25.hg18.txt" Count=" 1810613" Date="080621" />
+<Track Flowcell="FC20AUL" Lane="4" Filename="Flowcells/FC20AUL/080621_FC20AUL_s4_chIPSeq_HMEC_Rep1_RNApol2_SL351.align_25.hg18.txt" Count=" 1866673" Date="080621" />
+</Library>
+<Library Name="SL352">
+<Track Flowcell="30CLAAXX" Lane="1" Filename="Flowcells/30CLAAXX/080815_30CLAAXX_s1_RNAseq_mouse_skin_gb1_SL352.align_25.mm9.txt" Count=" 3921939" Date="080815" />
+<Track Flowcell="30CLAAXX" Lane="1" Filename="Flowcells/DATA_FROM_HA/080815_30CLAAXX_s1_RNAseq_mouse_skin_gb1_SL352.align_25.mm9.txt" Count=" 1224253" Date="080815" />
+</Library>
+<Library Name="SL353">
+<Track Flowcell="30CLAAXX" Lane="2" Filename="Flowcells/30CLAAXX/080815_30CLAAXX_s2_RNAseq_mouse_skin_gb2_SL353.align_25.mm9.txt" Count=" 4617024" Date="080815" />
+</Library>
+<Library Name="SL354">
+<Track Flowcell="30CLAAXX" Lane="3" Filename="Flowcells/30CLAAXX/080815_30CLAAXX_s3_RNAseq_mouse_skin_gb3_SL354.align_25.mm9.txt" Count=" 4018744" Date="080815" />
+</Library>
+<Library Name="SL355">
+<Track Flowcell="30CLAAXX" Lane="4" Filename="Flowcells/30CLAAXX/080815_30CLAAXX_s4_RNAseq_mouse_skin_gb4_SL355.align_25.mm9.txt" Count=" 3719245" Date="080815" />
+</Library>
+<Library Name="SL356">
+<Track Flowcell="30CLAAXX" Lane="5" Filename="Flowcells/30CLAAXX/080815_30CLAAXX_s5_Input_Control_ChIP-seq_protocadherin_tagged_SL356.align_25.hg18.txt" Count=" 6608872" Date="080815" />
+</Library>
+<Library Name="SL357">
+<Track Flowcell="30CLAAXX" Lane="6" Filename="Flowcells/30CLAAXX/080815_30CLAAXX_s6_ChIP-seq_protocadherin_alpha6_tagged_SL357.align_25.hg18.txt" Count=" 6057062" Date="080815" />
+</Library>
+<Library Name="SL358">
+<Track Flowcell="306WDAAXX" Lane="1" Filename="Flowcells/306WDAAXX/080725_306WDAAXX_s1_ChIP-seq_HepG2_Rep1_TAF250_SL358.align_25.hg18.txt" Count=" 3950828" Date="080725" />
+<Track Flowcell="306WDAAXX" Lane="2" Filename="Flowcells/306WDAAXX/080725_306WDAAXX_s2_ChIP-seq_HepG2_Rep1_TAF250_SL358.align_25.hg18.txt" Count=" 4064007" Date="080725" />
+<Track Flowcell="306WPAAXX" Lane="3" Filename="Flowcells/306WPAAXX/080731_306WPAAXX_s3_ChIP-seq_HepG2_Rep1_TAF250_SL358.align_25.hg18.txt" Count=" 3307317" Date="080731" />
+</Library>
+<Library Name="SL359">
+<Track Flowcell="306WDAAXX" Lane="3" Filename="Flowcells/306WDAAXX/080725_306WDAAXX_s3_ChIP-seq_HepG2_Rep2_TAF250_SL359.align_25.hg18.txt" Count=" 2721181" Date="080725" />
+<Track Flowcell="306WDAAXX" Lane="4" Filename="Flowcells/306WDAAXX/080725_306WDAAXX_s4_ChIP-seq_HepG2_Rep2_TAF250_SL359.align_25.hg18.txt" Count=" 3705820" Date="080725" />
+<Track Flowcell="306WPAAXX" Lane="4" Filename="Flowcells/306WPAAXX/080731_306WPAAXX_s4_ChIP-seq_HepG2_Rep2_TAF250_SL359.align_25.hg18.txt" Count=" 3232318" Date="080731" />
+<Track Flowcell="30EG4AAXX" Lane="7" Filename="Flowcells/30EG4AAXX/080916_30EG4AAXX_s7_ChIP-seq_HepG2_Rep2_TAF250_SL359.align_25.hg18.txt" Count=" 4307991" Date="080916" />
+</Library>
+<Library Name="SL360">
+<Track Flowcell="306WDAAXX" Lane="5" Filename="Flowcells/306WDAAXX/080725_306WDAAXX_s5_ChIP-seq_BJ_Fibroblast_Rep1_RNAPol2_SL360.align_25.hg18.txt" Count=" 3104910" Date="080725" />
+</Library>
+<Library Name="SL361">
+<Track Flowcell="306WDAAXX" Lane="6" Filename="Flowcells/306WDAAXX/080725_306WDAAXX_s6_ChIP-seq_BJ_Fibroblast_Rep2_RNAPol2_SL361.align_25.hg18.txt" Count=" 2279682" Date="080725" />
+</Library>
+<Library Name="SL362">
+<Track Flowcell="306WDAAXX" Lane="7" Filename="Flowcells/306WDAAXX/080725_306WDAAXX_s7_Input_Control_BJ_Fibroblast_Rep1_SL362.align_25.hg18.txt" Count=" 1305197" Date="080725" />
+</Library>
+<Library Name="SL363">
+<Track Flowcell="306WDAAXX" Lane="8" Filename="Flowcells/306WDAAXX/080725_306WDAAXX_s8_Input_Control_BJ_Fibroblast_Rep2_SL363.align_25.hg18.txt" Count=" 1981571" Date="080725" />
+</Library>
+<Library Name="SL368">
+<Track Flowcell="30DRRAAXX" Lane="8" Filename="Flowcells/30DRRAAXX/080919_30DRRAAXX_s8_Input_Control_RXLCh_Neuro2A_Rep2_SL368.align_25.mm9.txt" Count=" 2783931" Date="080919" />
+</Library>
+<Library Name="SL369">
+<Track Flowcell="30DRRAAXX" Lane="7" Filename="Flowcells/30DRRAAXX/080919_30DRRAAXX_s7_Input_Control_RXLCh_CAD_Rep2_SL369.align_25.mm9.txt" Count=" 2520025" Date="080919" />
+</Library>
+<Library Name="SL370">
+<Track Flowcell="30DRRAAXX" Lane="6" Filename="Flowcells/30DRRAAXX/080919_30DRRAAXX_s6_Neuro2A_CTCF_Rep2_SL370.align_25.mm9.txt" Count=" 3046099" Date="080919" />
+</Library>
+<Library Name="SL371">
+<Track Flowcell="30DRRAAXX" Lane="5" Filename="Flowcells/30DRRAAXX/080919_30DRRAAXX_s5_CAD_CTCF_Rep2_SL371.align_25.mm9.txt" Count=" 3466060" Date="080919" />
+</Library>
+<Library Name="SL372">
+<Track Flowcell="30DRRAAXX" Lane="4" Filename="Flowcells/30DRRAAXX/080919_30DRRAAXX_s4_Neuro2A_USF1_Rep2_SL372.align_25.mm9.txt" Count=" 2857481" Date="080919" />
+</Library>
+<Library Name="SL373">
+<Track Flowcell="30DRRAAXX" Lane="3" Filename="Flowcells/30DRRAAXX/080919_30DRRAAXX_s3_CAD_USF1_Rep2_SL373.align_25.mm9.txt" Count=" 3741192" Date="080919" />
+</Library>
+<Library Name="SL374">
+<Track Flowcell="30DRRAAXX" Lane="2" Filename="Flowcells/30DRRAAXX/080919_30DRRAAXX_s2_Neuro2A_USF2_Rep2_SL374.align_25.mm9.txt" Count=" 4160807" Date="080919" />
+</Library>
+<Library Name="SL375">
+<Track Flowcell="30DRRAAXX" Lane="1" Filename="Flowcells/30DRRAAXX/080919_30DRRAAXX_s1_CAD_USF2_Rep2_SL375.align_25.mm9.txt" Count=" 2005344" Date="080919" />
+</Library>
+<Library Name="SL376">
+<Track Flowcell="30CUNAAXX" Lane="1" Filename="Flowcells/30CUNAAXX/080918_30CUNAAXX_s1_A549_P65_Dex_Rep2_SL376.align_25.hg18.txt" Count=" 506090" Date="080918" />
+</Library>
+<Library Name="SL377">
+<Track Flowcell="30CUNAAXX" Lane="2" Filename="Flowcells/30CUNAAXX/080918_30CUNAAXX_s2_A549_P65_EtOH_Rep2_SL377.align_25.hg18.txt" Count=" 1618541" Date="080918" />
+</Library>
+<Library Name="SL378">
+<Track Flowcell="30CUNAAXX" Lane="3" Filename="Flowcells/30CUNAAXX/080918_30CUNAAXX_s3_A549_Pol2Ser2_Dex_Rep2_SL378.align_25.hg18.txt" Count=" 2773966" Date="080918" />
+<Track Flowcell="30CUNAAXX" Lane="7" Filename="Flowcells/30CUNAAXX/080918_30CUNAAXX_s7_A549_Pol2Ser2_Dex_Rep2_SL378.align_25.hg18.txt" Count=" 3050258" Date="080918" />
+</Library>
+<Library Name="SL379">
+<Track Flowcell="30CUNAAXX" Lane="4" Filename="Flowcells/30CUNAAXX/080918_30CUNAAXX_s4_A549_Pol2Ser2_EtOH_Rep2_SL379.align_25.hg18.txt" Count=" 1315068" Date="080918" />
+<Track Flowcell="30CUNAAXX" Lane="8" Filename="Flowcells/30CUNAAXX/080918_30CUNAAXX_s8_A549_Pol2Ser2_EtOH_Rep2_SL379.align_25.hg18.txt" Count=" 2957711" Date="080918" />
+</Library>
+<Library Name="SL388">
+<Track Flowcell="30EF9AAXX" Lane="8" Filename="Flowcells/30EF9AAXX/080916_30EF9AAXX_s8_RNAseq_mtN_mtG_7d_SL388.align_25.mm9.txt" Count=" 4555457" Date="080916" />
+</Library>
+<Library Name="SL389">
+<Track Flowcell="30EF9AAXX" Lane="7" Filename="Flowcells/30EF9AAXX/080916_30EF9AAXX_s7_RNAseq_mtN_WTG_7d_SL389.align_25.mm9.txt" Count=" 2247" Date="080916" />
+</Library>
+<Library Name="SL390">
+<Track Flowcell="30EF9AAXX" Lane="6" Filename="Flowcells/30EF9AAXX/080916_30EF9AAXX_s6_RNAseq_WTN_mtG_7d_SL390.align_25.mm9.txt" Count=" 5472114" Date="080916" />
+</Library>
+<Library Name="SL391">
+<Track Flowcell="30EF9AAXX" Lane="5" Filename="Flowcells/30EF9AAXX/080916_30EF9AAXX_s5_RNAseq_WTN_WTG_7d_SL391.align_25.mm9.txt" Count=" 6010993" Date="080916" />
+</Library>
+<Library Name="SL392">
+<Track Flowcell="30EF9AAXX" Lane="4" Filename="Flowcells/30EF9AAXX/080916_30EF9AAXX_s4_RNAseq_mtG_mtN_7d_SL392.align_25.mm9.txt" Count=" 5573656" Date="080916" />
+</Library>
+<Library Name="SL393">
+<Track Flowcell="30EF9AAXX" Lane="3" Filename="Flowcells/30EF9AAXX/080916_30EF9AAXX_s3_RNAseq_WTG_mtN_7d_SL393.align_25.mm9.txt" Count=" 5993678" Date="080916" />
+</Library>
+<Library Name="SL394">
+<Track Flowcell="30EF9AAXX" Lane="2" Filename="Flowcells/30EF9AAXX/080916_30EF9AAXX_s2_RNAseq_mtG_WTN_7d_SL394.align_25.mm9.txt" Count=" 5988007" Date="080916" />
+</Library>
+<Library Name="SL395">
+<Track Flowcell="30EF9AAXX" Lane="1" Filename="Flowcells/30EF9AAXX/080916_30EF9AAXX_s1_RNAseq_WTG_WTN_7d_SL395.align_25.mm9.txt" Count=" 5716492" Date="080916" />
+</Library>
+<Library Name="SL396">
+<Track Flowcell="30EG4AAXX" Lane="6" Filename="Flowcells/30EG4AAXX/080916_30EG4AAXX_s6_RNAseq_4484-17_occipital_cortex_SL396.align_25.hg18.txt" Count=" 5908254" Date="080916" />
+</Library>
+<Library Name="SL397">
+<Track Flowcell="30EG4AAXX" Lane="5" Filename="Flowcells/30EG4AAXX/080916_30EG4AAXX_s5_RNAseq_4484-6_basal_ganglia_SL397.align_25.hg18.txt" Count=" 5949974" Date="080916" />
+</Library>
+<Library Name="SL398">
+<Track Flowcell="30CUNAAXX" Lane="5" Filename="Flowcells/30CUNAAXX/080918_30CUNAAXX_s5_A549_Pol2Ser2_Dex_Rep3_SL398.align_25.hg18.txt" Count=" 1352310" Date="080918" />
+<Track Flowcell="30EH5AAXX" Lane="1" Filename="Flowcells/30EH5AAXX/080910_30EH5AAXX_s1_A549_Pol2Ser2_Dex_Rep3_SL398.align_25.hg18.txt" Count=" 2249460" Date="080910" />
+</Library>
+<Library Name="SL399">
+<Track Flowcell="30CUNAAXX" Lane="6" Filename="Flowcells/30CUNAAXX/080918_30CUNAAXX_s6_A549_Pol2Ser2_EtOH_Rep3_SL399.align_25.hg18.txt" Count=" 1475564" Date="080918" />
+<Track Flowcell="30EH5AAXX" Lane="2" Filename="Flowcells/30EH5AAXX/080910_30EH5AAXX_s2_A549_Pol2Ser2_EtOH_Rep3_SL399.align_25.hg18.txt" Count=" 2020061" Date="080910" />
+</Library>
+<Library Name="SL415">
+<Track Flowcell="30EH5AAXX" Lane="4" Filename="Flowcells/30EH5AAXX/080910_30EH5AAXX_s4_A549_ChIP_NFkB_Dex_R3_SL415.align_25.hg18.txt" Count=" 1605808" Date="080910" />
+</Library>
+<Library Name="SL419">
+<Track Flowcell="30EG4AAXX" Lane="1" Filename="Flowcells/30EG4AAXX/080916_30EG4AAXX_s1_GM12878_Rep1_NFATc1_SL419.align_25.hg18.txt" Count=" 3203524" Date="080916" />
+</Library>
+<Library Name="SL420">
+<Track Flowcell="30EG4AAXX" Lane="2" Filename="Flowcells/30EG4AAXX/080916_30EG4AAXX_s2_K562_Rep1_NFATc1_SL420.align_25.hg18.txt" Count=" 4198383" Date="080916" />
+</Library>
+<Library Name="SL421">
+<Track Flowcell="30EG4AAXX" Lane="3" Filename="Flowcells/30EG4AAXX/080916_30EG4AAXX_s3_GM12878_Dex_Rep1_GR_ChIP_SL421.align_25.hg18.txt" Count=" 5259681" Date="080916" />
+</Library>
+<Library Name="SL422">
+<Track Flowcell="30EG4AAXX" Lane="4" Filename="Flowcells/30EG4AAXX/080916_30EG4AAXX_s4_GM12878_EtOH_Rep1_GR_ChIP_SL422.align_25.hg18.txt" Count=" 3451771" Date="080916" />
+</Library>
+</Libraries>
--- /dev/null
+from htsworkflow.frontend.reports.models import ProgressReport
+from django.contrib import admin
+from django.utils.translation import ugettext_lazy as _
+
+class ProgressReportOptions(admin.ModelAdmin):
+ list_display = ('Study','ab_batch','cell_line','library','sequencing','aligned_reads','QPCR','submit_to_DCC','submit_to_NCBI','interactome_complete')
+ ## list_filter = ('interactome_complete')
+
+admin.site.register(ProgressReport, ProgressReportOptions)
+
--- /dev/null
+from htsworkflow.frontend import settings
+from django.http import HttpResponse
+from datetime import datetime
+from string import *
+import re
+from xml.sax import make_parser
+from xml.sax.handler import ContentHandler
+import urllib
+import urllib2
+import os
+
+'''
+Example library node from LibraryInfo.xml:
+<Library Name="SL14">
+<Track Flowcell="FC10135" Lane="4" Filename="071005_FC10135_s4_FoxP2_polyclonal_pfsk1_SL14.align_25.hg18.txt" Count=" 2438679" Complexity="4.51989e-06"/>
+<Track Flowcell="FC11977" Lane="6" Filename="070928_FC11977_s6_FoxP2_polyclonal_pfsk1_SL14.align_25.hg18.txt" Count=" 2007880" Complexity="0"/>
+<Track Flowcell="FC13593" Lane="5" Filename="071002_FC13593_s5_FoxP2_polyclonal_pfsk1_SL14.align_25.hg18.txt" Count=" 2533720" Complexity="1.97771e-06"/>
+</Library>
+'''
+class LibInfoHandler(ContentHandler):
+
+ def __init__ (self, searchTerm):
+ self.searchTerm= searchTerm
+ self.currlibid = ''
+ self.LanesCount, self.ReadsCount = 0, 0
+ self.Msg = 'OK'
+
+ def startElement(self, name, attrs):
+ try:
+ if name == 'Library':
+ self.currlibid = attrs.get('Name',"")
+ elif name == 'Track' and self.searchTerm == self.currlibid:
+ self.LanesCount += len(attrs.get('Lane',""))
+ self.ReadsCount += int(attrs.get('Count',""))
+ #else:
+ # self.Msg += ' | name = '+name+', currlibid = '+ self.currlibid
+ except:
+ self.Msg = 'failed parsing xml file'
+ return
+
+ #def characters (self, ch):
+ # return ..
+
+ #def endElement(self, name):
+ # return ..
+
+
+## TO DO: Change this to read the LibraryInfo.xml only ONCE per ReoprtRequest (do it in the models.py). + Read it directly from the analysis_server
+
+def getLibReads(libid):
+ searchTerm= libid
+ parser = make_parser()
+ curHandler = LibInfoHandler(searchTerm)
+ parser.setContentHandler(curHandler)
+ reports_dir = os.path.split(__file__)[0]
+ library_info = os.path.join(reports_dir, 'LibraryInfo.xml')
+ parser.parse(open(library_info))
+ arRes = []
+ arRes.append(curHandler.LanesCount)
+ arRes.append(curHandler.ReadsCount)
+ arRes.append(curHandler.Msg)
+
+ return arRes
+
+def getWebPage(url,params):
+ pdata = urllib.urlencode(params)
+ req = urllib2.Request(url,pdata)
+ wpage = urllib2.urlopen(req)
+ restext = wpage.read()
+ wpage.close()
+ return restext
+
+def refreshLibInfoFile(request):
+ varStatus = 'getting conf file from exp trac server'
+ url = settings.TASKS_PROJS_SERVER+'/LibraryInfo.xml'
+ params = {}
+ readw = getWebPage(url,params)
+ # make sure file content starts as xml
+ match_str = re.compile('^<\?xml.+')
+ if match_str.search(readw): ##tempstr):
+ # Rename current file with timestamp
+ year = datetime.today().year.__str__()
+ year = replace(year,'20','')
+ month = datetime.today().month
+ if month < 10: month = "0"+month.__str__()
+ else: month = month.__str__()
+ day = datetime.today().day
+ if day < 10: day = "0"+day.__str__()
+ else: day = day.__str__()
+ mydate = year+month+day
+ folder_loc = '/htsworkflow/htswfrontend/htswfrontend' # DEV
+ #folder_loc = '/Library/WebServer/gaworkflow/gaworkflow/frontend' # PROD
+ folder = folder_loc+'/htsw_reports/LibInfo/'
+ os.rename(folder+'LibraryInfo.xml',folder+mydate+'_LibraryInfo.xml')
+ # create file in curret folder
+ file_path = os.path.join(folder,'LibraryInfo.xml')
+ f = open(file_path, 'w')
+ f.write(readw)
+ f.close()
+ varStatus = 'OK. LibraryInfo.xml refreshed at Web server.'
+ else:
+ varStatus = 'Failed reading valid LibraryInfo.xml server reply:\n'+readw
+ return HttpResponse(varStatus)
--- /dev/null
+from django.db import models
+from django.db.models import Q
+from django.core.exceptions import ObjectDoesNotExist
+from datetime import datetime
+from htsworkflow.frontend.samples.models import *
+from htsworkflow.frontend.analysis.models import *
+from htsworkflow.frontend.experiments.models import *
+from string import *
+from htsworkflow.frontend.reports.utils import *
+import re
+##from p1 import LibInfo
+from libinfopar import *
+
+## This is a table based REPORT generator. The goal is to display a Progress Report for all the ENCODE projects, based on Study Name (e.g. NRSF, FOXP2, Methy-Seq on .. etc).
+
+class ProgressReport(models.Model):
+ st_sbj = models.ForeignKey(Project,limit_choices_to = Q(project_name__startswith='ENCODE '),related_name='project',db_index=True,verbose_name="Studied Subject")
+ interactome_complete = models.BooleanField(default=False)
+
+ def Study(self):
+ str = self.st_sbj.__str__()
+ str += '<br/><br/>'
+ str += '<a title="open Project record" href="/admin/analys_track/project/'+self.st_sbj.id.__str__()+'/" target=_self style="font-size:85%">Edit Project</a>'
+ return str
+ Study.allow_tags = True
+
+ def submit_to_DCC(self):
+ varText = ''
+ if self.note_about_DCC:
+ varText += '<br/><u>Note:</u><br/>'+self.note_about_DCC
+ return '%s<br/>%s' % (self.submitted_to_DCC,varText)
+ submit_to_DCC.allow_tags = True
+
+ def submit_to_NCBI(self):
+ varText = ''
+ if self.note_about_NCBI:
+ varText += '<br/><u>Note:</u><br/>'+self.note_about_NCBI
+ return '%s<br/>%s' % (self.submitted_to_NCBI,varText)
+ submit_to_NCBI.allow_tags = True
+
+ ## -- Utility functions <-- This method was transfered to untils.py
+
+ ## --- LIBARAY PREPARATION SECTION
+ def getLibIds(self):
+ ptasks = self.st_sbj.tasks.distinct()
+ arLibs = []
+ for t in ptasks:
+ if t.subject1 is not None:
+ arLibs.append(t.subject1.library_id)
+ if t.subject2 is not None:
+ arLibs.append(t.subject2.library_id)
+ arLibs = unique(arLibs)
+ return arLibs #.sort()
+
+ def getFCInfo(self,libid): ## This is the haviest function
+ arFCLanes = []
+ ##Test return arFCLanes
+ # can't get this to work: FC_L1 = FlowCell.objects.filter(lane_5_library__exact=libid)
+ allFCs = FlowCell.objects.all()
+ for f in allFCs:
+ entry = ''
+ lanes = []
+ #found = False
+# for i in range(1,9):
+# if eval('f.lane_'+i.__str__()+'_library.library_id==libid'):
+# lanes.append(i.__str__())
+# found = True
+
+# maybe a bit faster this way:
+ if f.lane_1_library.library_id==libid:
+ lanes.append('1')
+ #found = True
+ if f.lane_2_library.library_id==libid:
+ lanes.append('2')
+ #found = True
+ if f.lane_3_library.library_id==libid:
+ lanes.append('3')
+ #found = True
+ if f.lane_4_library.library_id==libid:
+ lanes.append('4')
+ #found = True
+ if f.lane_5_library.library_id==libid:
+ lanes.append('5')
+ #found = True
+ if f.lane_6_library.library_id==libid:
+ lanes.append('6')
+ #found = True
+ if f.lane_7_library.library_id==libid:
+ lanes.append('7')
+ #found = True
+ if f.lane_8_library.library_id==libid:
+ lanes.append('8')
+ #found = True
+
+
+ #if found:
+ if len(lanes)>0:
+ rundate = re.sub(pattern="\s.*$",repl="",string=f.run_date.__str__())
+ entry = '<b>'+f.flowcell_id + '</b> Lanes No.: '+','.join(lanes)+' ('+rundate+')'
+ arFCLanes.append(entry)
+ if len(arFCLanes)==0:
+ arFCLanes.append('<font color=red>Flowcell not found.</font>')
+ return arFCLanes
+
+ def ab_batch(self):
+ ## To have the Company's lot number, apearing on the (source) tube, we need to add new Field in Library.
+ arlibs = self.getLibIds()
+ tstr = '<ul>' ##<u><b>Ab</b> from '+len(arlibs).__str__()+' libs</u>: '
+ arRows = []
+ for l in arlibs:
+ try:
+ rec = Library.objects.get(library_id=l,antibody__isnull=False)
+ arRows.append('<li>'+rec.antibody.antibodies+' for <b>'+rec.antibody.antigene+'</b> (src:'+rec.antibody.source+', cat:'+rec.antibody.catalog+')</li>')
+ except ObjectDoesNotExist:
+ tstr += ""
+ tstr += "".join(unique(arRows))+'</ul>'
+ return tstr
+ ab_batch.allow_tags = True
+
+ def cell_line(self):
+ arlibs = self.getLibIds()
+ tstr = '<ul>'
+ arRows = []
+ for l in arlibs:
+ try:
+ rec = Library.objects.get(library_id=l)
+ arRows.append('<li><b>'+rec.cell_line.cellline_name+'</b> ('+rec.condition.condition_name+')</li>')
+ except ObjectDoesNotExist:
+ tstr += ""
+ tstr += "".join(unique(arRows))+'</ul>'
+ return tstr
+ cell_line.allow_tags = True
+
+ def cell_harvest_batch(self): # <- data now displayed in "cell_line"
+ ## name + date
+ arlibs = self.getLibIds()
+ tstr = '<ul>'
+ arRows = []
+ for l in arlibs:
+ try:
+ rec = Library.objects.get(library_id=l)
+ arRows.append('<li><b>'+rec.condition.condition_name+'</b></li>')
+ except ObjectDoesNotExist:
+ tstr += ""
+ tstr += "".join(unique(arRows))+'</ul>'
+ return tstr
+ cell_harvest_batch.allow_tags = True
+
+ def ChIP_made(self):
+ ## person + date
+ return '...'
+
+ def library(self):
+ ## Lib Id + Date + Person
+ tstr = '<script>'
+ tstr += 'function togit(eid){'
+ tstr += 'f=document.getElementById(eid);'
+ tstr += 'if(f.style.display==\'none\'){'
+ tstr += 'f.style.display=\'block\';'
+ tstr += '}else{'
+ tstr += 'f.style.display=\'none\';'
+ tstr += '}'
+ tstr += '}'
+ tstr += '</script>'
+ arlibs = self.getLibIds() ##.sort()
+ arlibs = arlibs
+ tstr +='<a href=# onClick="togit(\'libInfo'+self.st_sbj.project_name+'\')">view /hide</a>'
+ tstr += '<div id="libInfo'+self.st_sbj.project_name+'" style="display:block;border:solid #cccccc 1px;width:200px;height:300px;overflow:auto"><ul>'
+ arRows = []
+ for l in arlibs:
+ try:
+ rec = Library.objects.get(library_id=l)
+ arRows.append('<li><b>'+rec.library_id+'</b>: '+rec.library_name+'.<br/>Made By: '+rec.made_by+', On: '+ rec.creation_date.__str__()+'</li>')
+ except ObjectDoesNotExist:
+ tstr += ""
+ tstr += "".join(unique(arRows))+'</ul></div>'
+ return tstr
+ library.allow_tags = True
+
+
+ ## -- SEQUENCING SECTION
+ def sequencing(self):
+ ## FCId + Lane + Date
+ arlibs = self.getLibIds()
+ tstr ='<a href=# onClick="togit(\'seqInfo'+self.st_sbj.project_name+'\')">view /hide</a>'
+ tstr += '<div id="seqInfo'+self.st_sbj.project_name+'" style="display:block;border:solid #cccccc 1px;width:200px;height:300px;overflow:auto"><ul>'
+ for l in arlibs:
+ tstr += '<li><b>'+l+'</b>:<br/>'+(' / '.join(self.getFCInfo(l)))+'</li>'
+ tstr += '</ul></div>'
+ return tstr
+ sequencing.allow_tags = True
+
+ def aligned_reads(self):
+ ## Mega reads/lane
+ arlibs = self.getLibIds()
+ tstr = '<a href=# onClick="togit(\'readsInfo'+self.st_sbj.project_name+'\')">view /hide</a>'
+ tstr += '<div id="readsInfo'+self.st_sbj.project_name+'" style="display:block;border:solid #cccccc 1px;width:200px;height:300px;overflow:auto">'
+ tstr += '<table><tr><td>Library Id</td><td>Total Lanes</td><td>M Reads</td></tr>'
+ LanesCnt, ReadsCnt = 0, 0
+ for l in arlibs:
+ res = getLibReads(l)
+ LanesCnt += res[0]
+ ReadsCnt += res[1]
+ rc = "%1.2f" % (res[1]/1000000.0)
+ tstr += '<tr><td><b>'+l+'</b></td><td>'+res[0].__str__()+'</td></td><td>'+rc+'</td></tr>'
+ tstr += '</table>'
+ #tstr += '<a target=_blank href="'+settings.TASKS_PROJS_SERVER+'/projects/'+self.st_sbj.id.__str__()+'">Project results page</a>'
+ tstr += '</div>'
+ myNum = (ReadsCnt/1000000.0)
+ myNum = "%1.2f" % (myNum)
+ tstr += '<div>Total: <b>'+LanesCnt.__str__()+'</b> lanes and <b>'+myNum+'</b> M Reads</div>'
+ tstr += '<a target=_blank href="'+settings.TASKS_PROJS_SERVER+'/projects/'+self.st_sbj.id.__str__()+'">Project results page</a>'
+ return tstr
+ aligned_reads.allow_tags = True
+
+ def peak_calling(self):
+ # date + what etc..
+ return 'coming up ..'
+
+ QPCR = models.CharField(max_length=500,blank=True,null=True)
+ submitted_to_DCC = models.DateTimeField(blank=True,null=True)
+ submitted_to_NCBI = models.DateTimeField(blank=True,null=True)
+ note_about_DCC = models.TextField(blank=True)
+ note_about_NCBI = models.TextField(blank=True)
+
+ def __str__(self):
+ return '"%s" - %s' % (self.st_sbj,self.interactome_complete)
+
+ class Meta:
+ #verbose_name_plural = "Reports"
+ ordering = ["id"]
+
+ class Admin:
+ list_display = ('Study','ab_batch','cell_line','library','sequencing','aligned_reads','QPCR','submit_to_DCC','submit_to_NCBI','interactome_complete')
+ ## list_filter = ('interactome_complete')
+
+
+#############################################
--- /dev/null
+from htsworkflow.frontend.experiments.models import *
+from django.http import HttpResponse
+from django.core.exceptions import ObjectDoesNotExist
+from django.shortcuts import render_to_response, get_object_or_404
+
+def getBgColor(reads_cnt,exp_type):
+ # Color Scheme: green is more than 12M, blue is more than 5M, orange is more than 3M and red is less. For RNAseq, all those thresholds are ~ double
+ bgcolor = '#ff3300' # Red is the color for minimum read counts
+ rc_thr = [12000000,5000000,3000000] # Default for ChIP-Seq and Methyl-Seq
+ if exp_type == 'RNA-seq':
+ rc_thr = [20000000,10000000,6000000]
+
+ if reads_cnt > rc_thr[0]:
+ bgcolor = '#66ff66' # Green
+ else:
+ if reads_cnt > rc_thr[1]:
+ bgcolor ='#00ccff' # Blue
+ else:
+ if reads_cnt > rc_thr[2]:
+ bgcolor ='#ffcc33' # Orange
+ #tstr = '<div style="background-color:'+bgcolor+';color:black">'
+ #tstr += res[0].__str__()+' Lanes, '+rc+' M Reads'
+ #tstr += '</div>'
+
+ return bgcolor
+
+def report1(request):
+ EXP = 'ChIP-seq'
+
+ if request.GET.has_key('aflid'):
+ AFL_Id = request.GET['aflid']
+ try:
+ AFL = Affiliation.objects.get(id=AFL_Id).name
+ AFL_CNT = Affiliation.objects.get(id=AFL_Id).contact
+ except ObjectDoesNotExist:
+ return HttpResponse("ERROR: Affiliation Record Not Found for: '"+AFL_ID+"'")
+ else:
+ AFL = 'ENCODE_Tier1'
+ AFL_CNT = ''
+ try:
+ AFL_Id = Affiliation.objects.get(name=AFL,contact=AFL_CNT).id.__str__()
+ except ObjectDoesNotExist:
+ return HttpResponse("ERROR: Affiliation Record Not Found for: '"+AFL+"'")
+
+ TFall = Library.objects.values('antibody').order_by('antibody').distinct()
+ CLLall = Library.objects.values('cell_line').order_by('cell_line').distinct()
+
+ TFs = TFall.filter(experiment_type=EXP,affiliations__name=AFL,affiliations__contact=AFL_CNT)
+ CLLs = CLLall.filter(experiment_type=EXP,affiliations__name=AFL,affiliations__contact=AFL_CNT)
+
+ # Check Replicate numbers
+ Reps = 1
+ RepRecs = Library.objects.filter(experiment_type=EXP,affiliations__name=AFL,affiliations__contact=AFL_CNT).order_by('-replicate')
+ if len(RepRecs) > 0: Reps = RepRecs[0].replicate
+
+ ########
+ str = ''
+ str += '<span style="margin-right:20px"><a target=_self href="/admin" target=_self">Main Page</a></span>'
+ ##str += '<span style="margin-right:20px">Max Replicates: '+MaxRep.replicate.__str__()+'</span>'
+ str += '<span>Select another <b>'+EXP+'</b> Report:</span> <select>'
+ for af in Affiliation.objects.distinct():
+ str += '<option value='+af.id.__str__()
+ if AFL_Id == af.id.__str__():
+ str += ' selected'
+ str += ' onclick="window.location=\'/reports/report?aflid='+af.id.__str__()+'\'; return false;">'+af.name+' '+af.contact+'</option>'
+ str += '</select>'
+
+ str += '<span style="margin-left:20px;padding:1px;border:solid #cccccc 1px">color scheme: <span style="margin-left:5px;background-color:#66ff66"> > 12 M</span><span style="margin-left:5px;background-color:#00ccff"> > 5 M</span><span style="margin-left:5px;background-color:#ffcc33"> > 3 M</span><span style="margin-left:5px;background-color:#ff3300"> < 3 M</span></span>'
+
+ str += '<span style="margin-left:20px">'
+ str += '<u>Switch to:</u> '+AFL+' '+AFL_CNT+' <a target=_self href="/reports/report_RM?exp=RNA-seq&aflid='+AFL_Id+'"><b>RNA-Seq</b> Report</a>'
+ str += ' | '
+ str += '<a target=_self href="/reports/report_RM?exp=Methyl-seq&aflid='+AFL_Id+'"><b>Methyl-Seq</b> Report</a>'
+
+ bgc = '#ffffff'
+ pbgc = '#f7f7f7'
+ str += '<br/><br/><table border=1 cellspacing="2">'
+ str += '<tr><th style="text-align:right">PROJECT</th><th colspan='+(Reps*len(CLLs)).__str__()+' style="text-align:center">'+AFL+' '+AFL_CNT+' <span style="font-size:140%">'+EXP+'</span></th></tr>'
+ str += '<tr><th style="text-align:right">CELL LINE</th>'
+ for H in CLLs:
+ str += '<th colspan='+Reps.__str__()+' style="text-align:center;background-color:'+bgc+'">'+Cellline.objects.get(id=H['cell_line']).cellline_name+'</th>'
+ tbgc = bgc
+ bgc = pbgc
+ pbgc = tbgc
+ str += '</tr><tr><th style="text-align:left">TF</th>'
+ bgc = '#ffffff'
+ pbgc = '#f7f7f7'
+ for H in CLLs:
+ for r in range(1,Reps+1):
+ str += '<th style="text-align:center;background-color:'+bgc+'">Rep. '+r.__str__()+'</th>'
+ tbgc = bgc
+ bgc = pbgc
+ pbgc = tbgc
+ str += '</tr>'
+ str += '<tr><td align=right><a title="View Libraries Records" target=_self href=/admin/fctracker/library/?affiliations__id__exact='+AFL_Id+'&experiment_type__exact=INPUT_RXLCh>Total Chromatin</a></td>'
+ bgc = '#ffffff'
+ pbgc = '#f7f7f7'
+ for H in CLLs:
+ for r in range(1,Reps+1):
+ repReads = Library.objects.filter(experiment_type='INPUT_RXLCh',affiliations__name=AFL,affiliations__contact=AFL_CNT,cell_line=H['cell_line'].__str__(),replicate=r)
+ str += "<td align=center style='background-color:"+bgc+"'>"
+ if len(repReads) == 0:
+ str += 'No Libraries'
+ else:
+ cnt = 0
+ for R1 in repReads:
+ rres = R1.aligned_m_reads()
+ # Check data sanlty
+ if rres[2] != 'OK':
+ str += '<div style="border:solid red 2px">'+rres[2]
+ else:
+ cnt = rres[1]
+ if cnt > 0:
+ str += "<div style='background-color:"+getBgColor(cnt,EXP)+";font-size:140%'>"
+ str += "%1.2f" % (cnt/1000000.0)+" M"
+ else: str += "<div style='background-color:#ff3300;width:100%;font-size:140%'>0 Reads"
+ str += "<div style='font-size:70%'>"+R1.library_id+", "+R1.condition.nickname+"</div>"
+ str += "</div>"
+ str += '</td>'
+ tbgc = bgc
+ bgc = pbgc
+ pbgc = tbgc
+ str += '</tr>'
+
+ for T in TFs:
+ str += '<tr>'
+ try:
+ if T['antibody']:
+ str += '<td><a title="View Libraries Records" target=_self href=/admin/fctracker/library/?affiliations__id__exact='+AFL_Id+'&antibody__id__exact='+T['antibody'].__str__()+'>'+Antibody.objects.get(id=T['antibody']).nickname+'</a></td>'
+ except Antibody.DoesNotExist:
+ str += '<td>n/a</td>'
+
+ bgc = '#ffffff'
+ pbgc = '#f7f7f7'
+ for H in CLLs:
+ for r in range(1,Reps+1):
+ repReads = Library.objects.filter(experiment_type=EXP,affiliations__name=AFL,affiliations__contact=AFL_CNT,cell_line=H['cell_line'].__str__(),antibody=T['antibody'].__str__(),replicate=r)
+ str += "<td align=center style='background-color:"+bgc+"'>"
+ if len(repReads) == 0:
+ str += 'No Libraries'
+ else:
+ cnt = 0
+ for R1 in repReads:
+ rres = R1.aligned_m_reads()
+ # Check data sanlty
+ if rres[2] != 'OK':
+ str += '<div style="border:solid red 2px">'+rres[2]
+ else:
+ cnt = rres[1]
+ if cnt > 0:
+ str += "<div style='background-color:"+getBgColor(cnt,EXP)+";font-size:140%'>"
+ str += "%1.2f" % (cnt/1000000.0)+" M"
+ else: str += "<div style='background-color:#ff3300;width:100%;font-size:140%'>0 Reads"
+ str += "<div style='font-size:70%'>"+R1.library_id+", "+R1.condition.nickname+"</div>"
+ str += "</div>"
+ str += '</td>'
+ tbgc = bgc
+ bgc = pbgc
+ pbgc = tbgc
+ str += '</tr>'
+ str += '</table>'
+
+ return render_to_response('reports/report.html',{'main': str})
+
+
+def report_RM(request): #for RNA-Seq and Methyl-Seq
+ EXP = 'RNA-seq'
+
+ if request.GET.has_key('exp'):
+ EXP = request.GET['exp'] # Methyl-seq
+
+ if request.GET.has_key('aflid'):
+ AFL_Id = request.GET['aflid']
+ try:
+ AFL = Affiliation.objects.get(id=AFL_Id).name
+ AFL_CNT = Affiliation.objects.get(id=AFL_Id).contact
+ except ObjectDoesNotExist:
+ return HttpResponse("ERROR: Affiliation Record Not Found for: '"+AFL_ID+"'")
+ else:
+ AFL = 'ENCODE_Tier1'
+ AFL_CNT = ''
+ try:
+ AFL_Id = Affiliation.objects.get(name=AFL,contact=AFL_CNT).id.__str__()
+ except ObjectDoesNotExist:
+ return HttpResponse("ERROR: Affiliation Record Not Found for: '"+AFL+"'")
+
+ CLLall = Library.objects.values('cell_line').order_by('cell_line').distinct()
+ CLLs = CLLall.filter(experiment_type=EXP,affiliations__name=AFL,affiliations__contact=AFL_CNT)
+
+ ########
+ # Check Replicate numbers
+ Reps = 1
+ RepRecs = Library.objects.filter(experiment_type=EXP,affiliations__name=AFL,affiliations__contact=AFL_CNT).order_by('-replicate')
+ if len(RepRecs) > 0: Reps = RepRecs[0].replicate
+
+ str = ''
+ str += '<span style="margin-right:20px"><a target=_self href="/admin" target=_self">Main Page</a></span>'
+ str += '<span>Select another <b>'+EXP+'</b> Report:</span> <select>'
+ for af in Affiliation.objects.distinct():
+ str += '<option value='+af.id.__str__()
+ if AFL_Id == af.id.__str__():
+ str += ' selected'
+ str += ' onclick="window.location=\'/reports/report_RM?exp='+EXP+'&aflid='+af.id.__str__()+'\'; return false;">'+af.name+' '+af.contact+'</option>'
+ str += '</select>'
+
+ if EXP == 'RNA-seq':
+ str += '<span style="margin-left:20px;padding:1px;border:solid #cccccc 1px">color scheme: <span style="margin-left:5px;background-color:#66ff66"> > 20 M</span><span style="margin-left:5px;background-color:#00ccff"> > 10 M</span><span style="margin-left:5px;background-color:#ffcc33"> > 6 M</span><span style="margin-left:5px;background-color:#ff3300"> < 6 M</span></span>'
+ str += '<span style="margin-left:20px">'
+ str += '<u>Switch to:</u> '+AFL+' '+AFL_CNT+' <a target=_self href="/reports/report?exp=RNA-seq&aflid='+AFL_Id+'"><b>ChIP-Seq</b> Report</a>'
+ str += ' | '
+ str += '<a target=_self href="/reports/report_RM?exp=Methyl-seq&aflid='+AFL_Id+'"><b>Methyl-Seq</b> Report</a>'
+ else:
+ str += '<span style="margin-left:20px;padding:1px;border:solid #cccccc 1px">color scheme: <span style="margin-left:5px;background-color:#66ff66"> > 12 M</span><span style="margin-left:5px;background-color:#00ccff"> > 5 M</span><span style="margin-left:5px;background-color:#ffcc33"> > 3 M</span><span style="margin-left:5px;background-color:#ff3300"> < 3 M</span></span>'
+ str += '<span style="margin-left:20px">'
+ str += '<u>Switch to:</u> '+AFL+' '+AFL_CNT+' <a target=_self href="/reports/report?exp=RNA-seq&aflid='+AFL_Id+'"><b>ChIP-Seq</b> Report</a>'
+ str += ' | '
+ str += '<a target=_self href="/reports/report_RM?exp=RNA-seq&aflid='+AFL_Id+'"><b>RNA-Seq</b> Report</a>'
+
+ str += '<br/><br/><table border=1 cellspacing="2">'
+ str += '<tr><th colspan='+(Reps*len(CLLs)).__str__()+' style="text-align:center">'+AFL+' '+AFL_CNT+' <span style="font-size:140%">'+EXP+'</span></th></tr>'
+ str += '<tr>'
+ bgc = '#ffffff'
+ pbgc = '#f7f7f7'
+ for H in CLLs:
+ str += '<th colspan='+Reps.__str__()+' style="text-align:center;background-color:'+bgc+'">'+Cellline.objects.get(id=H['cell_line']).cellline_name+'</th>'
+ tbgc = bgc
+ bgc = pbgc
+ pbgc = tbgc
+ str += '</tr><tr>'
+ bgc = '#ffffff'
+ pbgc = '#f7f7f7'
+ for H in CLLs:
+ for r in range(1,Reps+1):
+ str += '<th style="text-align:center;background-color:'+bgc+'">Rep. '+r.__str__()+'</th>'
+ tbgc = bgc
+ bgc = pbgc
+ pbgc = tbgc
+ str += '</tr>'
+
+ str += '<tr>'
+ bgc = '#ffffff'
+ pbgc = '#f7f7f7'
+ for H in CLLs:
+ for r in range(1,Reps+1):
+ repReads = Library.objects.filter(experiment_type=EXP,affiliations__name=AFL,affiliations__contact=AFL_CNT,cell_line=H['cell_line'],replicate=r)
+ str += "<td align=center valign=top style='background-color:"+bgc+"'>"
+ if len(repReads) == 0:
+ str += 'No Libraries'
+ else:
+ cnt = 0
+ for R1 in repReads:
+ rres = R1.aligned_m_reads()
+ # Check data sanlty
+ if rres[2] != 'OK':
+ str += '<div style="border:solid red 2px">'+rres[2]
+ else:
+ cnt = rres[1]
+ if cnt > 0:
+ str += "<div style='background-color:"+getBgColor(cnt,EXP)+";border:solid #cccccc 1px;font-size:140%'>"
+ str += "%1.2f" % (cnt/1000000.0)+" M"
+ else: str += "<div style='background-color:#ff3300;border:solid #cccccc 1px;width:100%;font-size:140%'>0 Reads"
+ str += "<div style='font-size:80%'><a title='View Record' target=_self href=/admin/fctracker/library/?q="+R1.library_id+">"+R1.library_id+"</a>, "+R1.condition.nickname+", "+R1.library_species.common_name+"</div>"
+ str += "<div style='font-size:70%'>\""+R1.library_name+"\"</div"
+ str += "</div>"
+ str += '</td>'
+ tbgc = bgc
+ bgc = pbgc
+ pbgc = tbgc
+ str += '</tr>'
+ str += '</table>'
+
+ return render_to_response('reports/report.html',{'main': str})
+
+def getNotRanFCs(request):
+ FCall = FlowCell.objects.order_by('-run_date').distinct()
+ str = '<table><tr><th>FlowCell</th><th>Lanes</th><th>Creation Date</th></tr>'
+ for f in FCall:
+ try:
+ t = DataRun.objects.get(fcid=f.id)
+ except ObjectDoesNotExist:
+ str += '<tr><td>'+f.flowcell_id+'</td><td>'+f.Lanes()+'</td><td>'+f.run_date.__str__()+'</td></tr>'
+ str += "</table>"
+ return render_to_response('reports/report.html',{'main':str})
+
+def test_Libs(request):
+ str = ''
+ str += '<table border=1><tr><th>Lib ID</th><th>Current Libaray Name (Free Text)</th><th>Auto-composed Libaray Name (antibody + celline + libid + species + [replicate])</th></tr>'
+ allLibs = Library.objects.all()
+ #allLibs = Library.objects.filter(antibody__isnull=False)
+ for L in allLibs:
+ str += '<tr>'
+ str += '<td>'+L.library_id+'</td><td>'+L.library_name+'</td>'
+ str += '<td>'
+ str += L.experiment_type+'_'
+ if L.cell_line.cellline_name != 'Unknown':
+ str += L.cell_line.cellline_name+'_'
+
+ try:
+ if L.antibody is not None:
+ str += L.antibody.nickname + '_'
+ except Antibody.DoesNotExist:
+ pass
+
+ str += 'Rep'+L.replicate.__str__()
+ str += '</td></tr>'
+
+ str += '</table>'
+ return HttpResponse(str)
--- /dev/null
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('',
+ (r'^updLibInfo$', 'htsworkflow.frontend.reports.libinfopar.refreshLibInfoFile'),
+ (r'^report$', 'htsworkflow.frontend.reports.reports.report1'),
+ (r'^report_RM$', 'htsworkflow.frontend.reports.reports.report_RM'),
+ (r'^report_FCs$', 'htsworkflow.frontend.reports.reports.getNotRanFCs'),
+ (r'^liblist$', 'htsworkflow.frontend.reports.reports.test_Libs')
+)
--- /dev/null
+def unique(s):
+ """Return a list of the elements in s, but without duplicates.
+ For example, unique([1,2,3,1,2,3]) is some permutation of [1,2,3],
+ unique("abcabc") some permutation of ["a", "b", "c"], and
+ unique(([1, 2], [2, 3], [1, 2])) some permutation of
+ [[2, 3], [1, 2]].
+ For best speed, all sequence elements should be hashable. Then
+ unique() will usually work in linear time.
+ If not possible, the sequence elements should enjoy a total
+ ordering, and if list(s).sort() doesn't raise TypeError it's
+ assumed that they do enjoy a total ordering. Then unique() will
+ usually work in O(N*log2(N)) time.
+ If that's not possible either, the sequence elements must support
+ equality-testing. Then unique() will usually work in quadratic
+ time.
+ """
+
+ n = len(s)
+ if n == 0:
+ return []
+
+ # Try using a dict first, as that's the fastest and will usually
+ # work. If it doesn't work, it will usually fail quickly, so it
+ # usually doesn't cost much to *try* it. It requires that all the
+ # sequence elements be hashable, and support equality comparison.
+ u = {}
+ try:
+ for x in s:
+ u[x] = 1
+ except TypeError:
+ del u # move on to the next method
+ else:
+ return u.keys()
+ # We can't hash all the elements. Second fastest is to sort,
+ # which brings the equal elements together; then duplicates are
+ # easy to weed out in a single pass.
+ # NOTE: Python's list.sort() was designed to be efficient in the
+ # presence of many duplicate elements. This isn't true of all
+ # sort functions in all languages or libraries, so this approach
+ # is more effective in Python than it may be elsewhere.
+ try:
+ t = list(s)
+ t.sort()
+ except TypeError:
+ del t # move on to the next method
+ else:
+ assert n > 0
+ last = t[0]
+ lasti = i = 1
+ while i < n:
+ if t[i] != last:
+ t[lasti] = last = t[i]
+ lasti += 1
+ i += 1
+ return t[:lasti]
+ # Brute force is all that's left.
+ u = []
+ for x in s:
+ if x not in u:
+ u.append(x)
+ return u
--- /dev/null
+from django.contrib import admin
+from django.contrib.admin import widgets
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+
+from htsworkflow.frontend.samples.models import Antibody, Cellline, Condition, ExperimentType, Species, Affiliation, Library, Tag
+
+class Library_Inline(admin.TabularInline):
+ model = Library
+
+class CelllineOptions(admin.ModelAdmin):
+ list_display = ('cellline_name', 'nickname', 'notes')
+ search_fields = ('cellline_name', 'nickname', 'notes')
+ fieldsets = (
+ (None, {
+ 'fields': (('cellline_name'),('notes'),)
+ }),
+ )
+
+class ExperimentTypeOptions(admin.ModelAdmin):
+ model = ExperimentType
+ #list_display = ('name',)
+ #fieldsets = ( (None, { 'fields': ('name',) }), )
+
+class LibraryOptions(admin.ModelAdmin):
+ date_hierarchy = "creation_date"
+ save_as = True
+ save_on_top = True
+ search_fields = (
+ 'library_id',
+ 'library_name',
+ 'cell_line__cellline_name',
+ 'library_species__scientific_name',
+ 'library_species__common_name',
+ )
+ list_display = (
+ 'library_id',
+ #'aligned_reads',
+ #'DataRun',
+ 'library_name',
+ 'public',
+ #'experiment_type',
+ #'organism',
+ #'antibody_name',
+ #'cell_line',
+ #'libtags',
+ #'made_for',
+ 'affiliation',
+ #'made_by',
+ 'undiluted_concentration',
+ 'creation_date',
+ 'stopping_point',
+ #'condition',
+
+ )
+ list_filter = (
+ 'experiment_type',
+ 'library_species',
+ 'tags',
+ #'made_for',
+ 'affiliations',
+ 'made_by',
+ 'antibody',
+ 'cell_line',
+ 'condition',
+ 'stopping_point',
+ 'hidden')
+ list_display_links = ('library_id', 'library_name',)
+ fieldsets = (
+ (None, {
+ 'fields': (
+ ('library_id','library_name','hidden'),
+ ('library_species'),
+ ('experiment_type', 'replicate'),
+ ('cell_line','condition','antibody'),)
+ }),
+ ('Creation Information:', {
+ 'fields' : (('made_for', 'made_by', 'creation_date'), ('stopping_point', 'amplified_from_sample'), ('avg_lib_size','undiluted_concentration', 'ten_nM_dilution', 'successful_pM'), 'notes',)
+ }),
+ ('Library/Project Affiliation:', {
+ 'fields' : (('affiliations'), ('tags'),)
+ }),
+ )
+
+ # some post 1.0.2 version of django has formfield_overrides
+ # which would replace this code with:
+ # formfield_overrids = {
+ # models.ManyToMany: { 'widget': widgets.FilteredSelectMultiple }
+ # }
+ def formfield_for_dbfield(self, db_field, **kwargs):
+ if db_field.name == 'affiliations':
+ kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
+ rv = super(LibraryOptions, self).formfield_for_dbfield(db_field, **kwargs)
+ print db_field.name, kwargs
+ return rv
+
+class AffiliationOptions(admin.ModelAdmin):
+ list_display = ('name','contact','email')
+ fieldsets = (
+ (None, {
+ 'fields': (('name','contact','email'))
+ }),
+ )
+
+# class UserOptions(admin.ModelAdmin):
+# inlines = [Library_Inline]
+
+class AntibodyOptions(admin.ModelAdmin):
+ search_fields = ('antigene','nickname','catalog','antibodies','source','biology','notes')
+ list_display = ('antigene','nickname','antibodies','catalog','source','biology','notes')
+ list_filter = ('antibodies','source')
+ fieldsets = (
+ (None, {
+ 'fields': (('antigene','nickname','antibodies'),('catalog','source'),('biology'),('notes'))
+ }),
+ )
+
+class SpeciesOptions(admin.ModelAdmin):
+ fieldsets = (
+ (None, {
+ 'fields': (('scientific_name', 'common_name'),)
+ }),
+ )
+
+class ConditionOptions(admin.ModelAdmin):
+ list_display = (('condition_name'), ('notes'),)
+ fieldsets = (
+ (None, {
+ 'fields': (('condition_name'),('nickname'),('notes'),)
+ }),
+ )
+
+class TagOptions(admin.ModelAdmin):
+ list_display = ('tag_name', 'context')
+ fieldsets = (
+ (None, {
+ 'fields': ('tag_name', 'context')
+ }),
+ )
+
+admin.site.register(Affiliation, AffiliationOptions)
+admin.site.register(Antibody, AntibodyOptions)
+admin.site.register(Cellline, CelllineOptions)
+admin.site.register(Condition, ConditionOptions)
+admin.site.register(ExperimentType, ExperimentTypeOptions)
+admin.site.register(Library, LibraryOptions)
+admin.site.register(Species, SpeciesOptions)
+admin.site.register(Tag, TagOptions)
--- /dev/null
+"""
+Slightly modified version of the django admin component that handles filters and searches
+"""
+from django.contrib.admin.filterspecs import FilterSpec
+from django.contrib.admin.options import IncorrectLookupParameters
+from django.core.paginator import Paginator, InvalidPage, EmptyPage
+from django.db import models
+from django.db.models.query import QuerySet
+from django.utils.encoding import smart_str
+from django.utils.http import urlencode
+
+import operator
+
+MAX_SHOW_ALL_ALLOWED = 20000
+
+#change list settings
+ALL_VAR = 'all'
+ORDER_VAR = 'o'
+ORDER_TYPE_VAR = 'ot'
+PAGE_VAR = 'p'
+SEARCH_VAR = 'q'
+IS_POPUP_VAR = 'pop'
+ERROR_FLAG = 'e'
+
+class ChangeList(object):
+ def __init__(self, request, model, list_filter, search_fields, list_per_page, queryset=None):
+ self.model = model
+ self.opts = model._meta
+ self.lookup_opts = self.opts
+ if queryset is None:
+ self.root_query_set = model.objects
+ else:
+ self.root_query_set = queryset
+ self.list_display = []
+ self.list_display_links = None
+ self.list_filter = list_filter
+
+ self.search_fields = search_fields
+ self.list_select_related = None
+ self.list_per_page = list_per_page
+ self.model_admin = None
+
+ try:
+ self.page_num = int(request.GET.get(PAGE_VAR,'0'))
+ except ValueError:
+ self.page_num = 0
+ self.show_all = 'all' in request.GET
+ self.params = dict(request.GET.items())
+ if PAGE_VAR in self.params:
+ del self.params[PAGE_VAR]
+ if ERROR_FLAG in self.params:
+ del self.params[ERROR_FLAG]
+
+ self.multi_page = True
+ self.can_show_all = False
+
+ self.order_field, self.order_type = self.get_ordering()
+ self.query = request.GET.get(SEARCH_VAR, '')
+ self.query_set = self.get_query_set()
+ self.get_results(request)
+ self.filter_specs, self.has_filters = self.get_filters(request)
+
+ #self.result_count = 'result count'
+ #self.full_result_count = 'full result count'
+
+ def get_filters(self, request):
+ filter_specs = []
+ if self.list_filter:
+ filter_fields = [self.lookup_opts.get_field(field_name) for field_name in self.list_filter]
+ for f in filter_fields:
+ spec = FilterSpec.create(f, request, self.params, self.model, self.model_admin)
+ if spec and spec.has_output():
+ filter_specs.append(spec)
+ return filter_specs, bool(filter_specs)
+
+ def get_query_string(self, new_params=None, remove=None):
+ if new_params is None: new_params = {}
+ if remove is None: remove = []
+ p = self.params.copy()
+ for r in remove:
+ for k in p.keys():
+ if k.startswith(r):
+ del p[k]
+ for k, v in new_params.items():
+ if v is None:
+ if k in p:
+ del p[k]
+ else:
+ p[k] = v
+ return '?%s' % urlencode(p)
+
+ def get_results(self, request):
+ paginator = Paginator(self.query_set, self.list_per_page)
+ # Get the number of objects, with admin filters applied.
+ result_count = paginator.count
+
+ # Get the total number of objects, with no admin filters applied.
+ # Perform a slight optimization: Check to see whether any filters were
+ # given. If not, use paginator.hits to calculate the number of objects,
+ # because we've already done paginator.hits and the value is cached.
+ if not self.query_set.query.where:
+ full_result_count = result_count
+ else:
+ full_result_count = self.root_query_set.count()
+
+ can_show_all = result_count <= MAX_SHOW_ALL_ALLOWED
+ multi_page = result_count > self.list_per_page
+
+ # Get the list of objects to display on this page.
+ if (self.show_all and can_show_all) or not multi_page:
+ result_list = list(self.query_set)
+ else:
+ try:
+ result_list = paginator.page(self.page_num+1).object_list
+ except InvalidPage:
+ result_list = ()
+
+ self.result_count = result_count
+ self.full_result_count = full_result_count
+ self.result_list = result_list
+ self.can_show_all = can_show_all
+ self.multi_page = multi_page
+ self.paginator = paginator
+
+ def get_ordering(self):
+ lookup_opts, params = self.lookup_opts, self.params
+ # For ordering, first check the "ordering" parameter in the admin
+ # options, then check the object's default ordering. If neither of
+ # those exist, order descending by ID by default. Finally, look for
+ # manually-specified ordering from the query string.
+ ordering = lookup_opts.ordering or ['-' + lookup_opts.pk.name]
+
+ if ordering[0].startswith('-'):
+ order_field, order_type = ordering[0][1:], 'desc'
+ else:
+ order_field, order_type = ordering[0], 'asc'
+ if ORDER_VAR in params:
+ try:
+ field_name = self.list_display[int(params[ORDER_VAR])]
+ try:
+ f = lookup_opts.get_field(field_name)
+ except models.FieldDoesNotExist:
+ # See whether field_name is a name of a non-field
+ # that allows sorting.
+ try:
+ if callable(field_name):
+ attr = field_name
+ elif hasattr(self.model_admin, field_name):
+ attr = getattr(self.model_admin, field_name)
+ else:
+ attr = getattr(self.model, field_name)
+ order_field = attr.admin_order_field
+ except AttributeError:
+ pass
+ else:
+ order_field = f.name
+ except (IndexError, ValueError):
+ pass # Invalid ordering specified. Just use the default.
+ if ORDER_TYPE_VAR in params and params[ORDER_TYPE_VAR] in ('asc', 'desc'):
+ order_type = params[ORDER_TYPE_VAR]
+ return order_field, order_type
+
+ def get_query_set(self):
+ qs = self.root_query_set
+ lookup_params = self.params.copy() # a dictionary of the query string
+ for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR):
+ if i in lookup_params:
+ del lookup_params[i]
+ for key, value in lookup_params.items():
+ if not isinstance(key, str):
+ # 'key' will be used as a keyword argument later, so Python
+ # requires it to be a string.
+ del lookup_params[key]
+ lookup_params[smart_str(key)] = value
+
+ # if key ends with __in, split parameter into separate values
+ if key.endswith('__in'):
+ lookup_params[key] = value.split(',')
+
+ # Apply lookup parameters from the query string.
+ try:
+ qs = qs.filter(**lookup_params)
+ # Naked except! Because we don't have any other way of validating "params".
+ # They might be invalid if the keyword arguments are incorrect, or if the
+ # values are not in the correct type, so we might get FieldError, ValueError,
+ # ValicationError, or ? from a custom field that raises yet something else
+ # when handed impossible data.
+ except Exception, e:
+ print e
+ raise IncorrectLookupParameters
+
+ # Use select_related() if one of the list_display options is a field
+ # with a relationship.
+ if self.list_select_related:
+ qs = qs.select_related()
+ else:
+ for field_name in self.list_display:
+ try:
+ f = self.lookup_opts.get_field(field_name)
+ except models.FieldDoesNotExist:
+ pass
+ else:
+ if isinstance(f.rel, models.ManyToOneRel):
+ qs = qs.select_related()
+ break
+
+ # Set ordering.
+ if self.order_field:
+ qs = qs.order_by('%s%s' % ((self.order_type == 'desc' and '-' or ''), self.order_field))
+
+ # Apply keyword searches.
+ def construct_search(field_name):
+ if field_name.startswith('^'):
+ return "%s__istartswith" % field_name[1:]
+ elif field_name.startswith('='):
+ return "%s__iexact" % field_name[1:]
+ elif field_name.startswith('@'):
+ return "%s__search" % field_name[1:]
+ else:
+ return "%s__icontains" % field_name
+
+ if self.search_fields and self.query:
+ for bit in self.query.split():
+ or_queries = [models.Q(**{construct_search(field_name): bit}) for field_name in self.search_fields]
+ other_qs = QuerySet(self.model)
+ other_qs.dup_select_related(qs)
+ other_qs = other_qs.filter(reduce(operator.or_, or_queries))
+ qs = qs & other_qs
+ for field_name in self.search_fields:
+ if '__' in field_name:
+ qs = qs.distinct()
+ break
+
+ if self.opts.one_to_one_field:
+ qs = qs.complex_filter(self.opts.one_to_one_field.rel.limit_choices_to)
+
+ return qs
+
+
--- /dev/null
+import urlparse
+from django.db import models
+from django.contrib.auth.models import User
+from htsworkflow.frontend import settings
+from htsworkflow.frontend.reports.libinfopar import *
+
+# Create your models here.
+
+class Antibody(models.Model):
+ antigene = models.CharField(max_length=500, db_index=True)
+ # New field Aug/20/08
+ # SQL to add column:
+ # alter table fctracker_antibody add column "nickname" varchar(20) NULL;
+ nickname = models.CharField(
+ max_length=20,
+ blank=True,
+ null=True,
+ db_index=True,
+ verbose_name = 'Short Name'
+ )
+ catalog = models.CharField(max_length=50, unique=True, db_index=True)
+ antibodies = models.CharField(max_length=500, db_index=True)
+ source = models.CharField(max_length=500, blank=True, db_index=True)
+ biology = models.TextField(blank=True)
+ notes = models.TextField(blank=True)
+ def __unicode__(self):
+ return u'%s - %s (%s)' % (self.antigene, self.antibodies, self.catalog)
+ class Meta:
+ verbose_name_plural = "antibodies"
+ ordering = ["antigene"]
+
+class Cellline(models.Model):
+ cellline_name = models.CharField(max_length=100, unique=True, db_index=True)
+ nickname = models.CharField(max_length=20,
+ blank=True,
+ null=True,
+ db_index=True,
+ verbose_name = 'Short Name')
+ notes = models.TextField(blank=True)
+ def __unicode__(self):
+ return unicode(self.cellline_name)
+
+ class Meta:
+ ordering = ["cellline_name"]
+
+class Condition(models.Model):
+ condition_name = models.CharField(
+ max_length=2000, unique=True, db_index=True)
+ nickname = models.CharField(max_length=20,
+ blank=True,
+ null=True,
+ db_index=True,
+ verbose_name = 'Short Name')
+ notes = models.TextField(blank=True)
+
+ def __unicode__(self):
+ return unicode(self.condition_name)
+
+ class Meta:
+ ordering = ["condition_name"]
+
+class ExperimentType(models.Model):
+ name = models.CharField(max_length=50, unique=True)
+
+ def __unicode__(self):
+ return unicode(self.name)
+
+class Tag(models.Model):
+ tag_name = models.CharField(max_length=100, db_index=True,blank=False,null=False)
+ TAG_CONTEXT = (
+ #('Antibody','Antibody'),
+ #('Cellline', 'Cellline'),
+ #('Condition', 'Condition'),
+ ('Library', 'Library'),
+ ('ANY','ANY'),
+ )
+ context = models.CharField(max_length=50,
+ choices=TAG_CONTEXT, default='Library')
+
+ def __unicode__(self):
+ return u'%s' % (self.tag_name)
+
+ class Meta:
+ ordering = ["context","tag_name"]
+
+class Species(models.Model):
+ scientific_name = models.CharField(max_length=256,
+ unique=False,
+ db_index=True
+ )
+ common_name = models.CharField(max_length=256, blank=True)
+ #use_genome_build = models.CharField(max_length=100, blank=False, null=False)
+
+ def __unicode__(self):
+ return u'%s (%s)' % (self.scientific_name, self.common_name)
+
+ class Meta:
+ verbose_name_plural = "species"
+ ordering = ["scientific_name"]
+
+class Affiliation(models.Model):
+ name = models.CharField(max_length=256, db_index=True, verbose_name='Name')
+ contact = models.CharField(max_length=256, null=True, blank=True,verbose_name='Lab Name')
+ email = models.EmailField(null=True,blank=True)
+
+ def __unicode__(self):
+ str = unicode(self.name)
+ if self.contact is not None and len(self.contact) > 0:
+ str += u' ('+self.contact+u')'
+ return str
+
+ class Meta:
+ ordering = ["name","contact"]
+ unique_together = (("name", "contact"),)
+
+class Library(models.Model):
+ id = models.AutoField(primary_key=True)
+ library_id = models.CharField(max_length=30, db_index=True, unique=True)
+ library_name = models.CharField(max_length=100, unique=True)
+ library_species = models.ForeignKey(Species)
+ # new field 2008 Mar 5, alter table samples_library add column "hidden" NOT NULL default 0;
+ hidden = models.BooleanField()
+ cell_line = models.ForeignKey(Cellline, null=True)
+ condition = models.ForeignKey(Condition, null=True)
+ antibody = models.ForeignKey(Antibody,blank=True,null=True)
+ # New field Aug/25/08. SQL: alter table fctracker_library add column "lib_affiliation" varchar(256) NULL;
+ affiliations = models.ManyToManyField(Affiliation,related_name='library_affiliations',null=True)
+ # new field Nov/14/08
+ tags = models.ManyToManyField(Tag,related_name='library_tags',blank=True,null=True)
+ # New field Aug/19/08
+ # SQL to add column: alter table fctracker_library add column "replicate" smallint unsigned NULL;
+ REPLICATE_NUM = ((1,1),(2,2),(3,3),(4,4))
+ replicate = models.PositiveSmallIntegerField(choices=REPLICATE_NUM,default=1)
+ experiment_type = models.ForeignKey(ExperimentType)
+ creation_date = models.DateField(blank=True, null=True)
+ made_for = models.CharField(max_length=50, blank=True,
+ verbose_name='ChIP/DNA/RNA Made By')
+ made_by = models.CharField(max_length=50, blank=True, default="Lorian")
+
+ PROTOCOL_END_POINTS = (
+ ('?', 'Unknown'),
+ ('Sample', 'Raw sample'),
+ ('Progress', 'In progress'),
+ ('1A', 'Ligation, then gel'),
+ ('PCR', 'Ligation, then PCR'),
+ ('1Ab', 'Ligation, PCR, then gel'),
+ ('1Aa', 'Ligation, gel, then PCR'),
+ ('2A', 'Ligation, PCR, gel, PCR'),
+ ('Done', 'Completed'),
+ )
+ stopping_point = models.CharField(max_length=25, choices=PROTOCOL_END_POINTS, default='Done')
+ amplified_from_sample = models.ForeignKey('self', blank=True, null=True, related_name='amplified_into_sample')
+
+ undiluted_concentration = models.DecimalField("Concentration",
+ max_digits=5, decimal_places=2, blank=True, null=True,
+ help_text=u"Undiluted concentration (ng/\u00b5l)")
+ # note \u00b5 is the micro symbol in unicode
+ successful_pM = models.DecimalField(max_digits=9, decimal_places=1, blank=True, null=True)
+ ten_nM_dilution = models.BooleanField()
+ avg_lib_size = models.IntegerField(default=225, blank=True, null=True)
+ notes = models.TextField(blank=True)
+
+ def __unicode__(self):
+ return u'#%s: %s' % (self.library_id, self.library_name)
+
+ class Meta:
+ verbose_name_plural = "libraries"
+ #ordering = ["-creation_date"]
+ ordering = ["-library_id"]
+
+ def antibody_name(self):
+ str ='<a target=_self href="/admin/samples/antibody/'+self.antibody.id.__str__()+'/" title="'+self.antibody.__str__()+'">'+self.antibody.nickname+'</a>'
+ return str
+ antibody_name.allow_tags = True
+
+ def organism(self):
+ return self.library_species.common_name
+
+ def affiliation(self):
+ affs = self.affiliations.all().order_by('name')
+ tstr = ''
+ ar = []
+ for t in affs:
+ ar.append(t.__unicode__())
+ return '%s' % (", ".join(ar))
+
+ def is_archived(self):
+ """
+ returns True if archived else False
+ """
+ if self.longtermstorage_set.count() > 0:
+ return True
+ else:
+ return False
+
+ def libtags(self):
+ affs = self.tags.all().order_by('tag_name')
+ ar = []
+ for t in affs:
+ ar.append(t.__unicode__())
+ return u'%s' % ( ", ".join(ar))
+
+ def DataRun(self):
+ str ='<a target=_self href="/admin/experiments/datarun/?q='+self.library_id+'" title="Check All Data Runs for This Specific Library ..." ">Data Run</a>'
+ return str
+ DataRun.allow_tags = True
+
+ def aligned_m_reads(self):
+ return getLibReads(self.library_id)
+
+ def aligned_reads(self):
+ res = getLibReads(self.library_id)
+
+ # Check data sanity
+ if res[2] != "OK":
+ return u'<div style="border:solid red 2px">'+res[2]+'</div>'
+
+ rc = "%1.2f" % (res[1]/1000000.0)
+ # Color Scheme: green is more than 10M, blue is more than 5M, orange is more than 3M and red is less. For RNAseq, all those thresholds should be doubled
+ if res[0] > 0:
+ bgcolor = '#ff3300' # Red
+ rc_thr = [10000000,5000000,3000000]
+ if self.experiment_type == 'RNA-seq':
+ rc_thr = [20000000,10000000,6000000]
+
+ if res[1] > rc_thr[0]:
+ bgcolor = '#66ff66' # Green
+ else:
+ if res[1] > rc_thr[1]:
+ bgcolor ='#00ccff' # Blue
+ else:
+ if res[1] > rc_thr[2]:
+ bgcolor ='#ffcc33' # Orange
+ tstr = '<div style="background-color:'+bgcolor+';color:black">'
+ tstr += res[0].__unicode__()+' Lanes, '+rc+' M Reads'
+ tstr += '</div>'
+ else: tstr = 'not processed yet'
+ return tstr
+ aligned_reads.allow_tags = True
+
+ def public(self):
+ SITE_ROOT = '/'
+ summary_url = self.get_absolute_url()
+ return '<a href="%s">S</a>' % (summary_url,)
+ public.allow_tags = True
+
+ @models.permalink
+ def get_absolute_url(self):
+ return ('htsworkflow.frontend.samples.views.library_to_flowcells', [str(self.library_id)])
--- /dev/null
+from htsworkflow.frontend import settings
+
+import glob
+import os
+import re
+
+s_paren = re.compile("^\w+")
+
+def get_flowcell_result_dict(flowcell_id):
+ """
+ returns a dictionary following the following pattern for
+ a given flowcell_id:
+
+
+ d['C1-33']['summary'] # Summary.htm file path
+ d['C1-33']['eland_results'][5] # C1-33 lane 5 file eland results file path
+ d['C1-33']['run_xml'] # run_*.xml file path
+ d['C1-33']['scores'] # scores.tar.gz file path
+ """
+ flowcell_id = flowcell_id.strip()
+
+ d = {}
+
+ ################################
+ # Flowcell Directory
+ fc_dir = glob.glob(os.path.join(settings.RESULT_HOME_DIR, flowcell_id))
+
+ # Not found
+ if len(fc_dir) == 0:
+ return None
+
+ # No duplicates!
+ assert len(fc_dir) <= 1
+
+ # Found fc dir
+ fc_dir = fc_dir[0]
+
+ ################################
+ # C#-## dirs
+ c_dir_list = glob.glob(os.path.join(fc_dir, 'C*'))
+
+ # Not found
+ if len(c_dir_list) == 0:
+ return d
+
+ for c_dir_path in c_dir_list:
+ summary_file = glob.glob(os.path.join(c_dir_path, 'Summary.htm'))
+ pathdir, c_dir = os.path.split(c_dir_path)
+
+ # Create sub-dictionary
+ d[c_dir] = {}
+
+
+ ###############################
+ # Summary.htm file
+
+ # Not found
+ if len(summary_file) == 0:
+ d[c_dir]['summary'] = None
+
+ # Found
+ else:
+ # No duplicates!
+ assert len(summary_file) == 1
+
+ summary_file = summary_file[0]
+ d[c_dir]['summary'] = summary_file
+
+ ###############################
+ # Result files
+
+ d[c_dir]['eland_results'] = {}
+
+ result_filepaths = glob.glob(os.path.join(c_dir_path, 's_*_eland_*'))
+
+ for filepath in result_filepaths:
+
+ junk, result_name = os.path.split(filepath)
+
+ #lanes 1-8, single digit, therefore s_#; # == index 2
+ lane = int(result_name[2])
+ d[c_dir]['eland_results'][lane] = filepath
+
+ ###############################
+ # run*.xml file
+ run_xml_filepath = glob.glob(os.path.join(c_dir_path, 'run_*.xml'))
+
+ if len(run_xml_filepath) == 0:
+ d[c_dir]['run_xml'] = None
+ else:
+ # No duplicates
+ assert len(run_xml_filepath) == 1
+
+ d[c_dir]['run_xml'] = run_xml_filepath[0]
+
+ ###############################
+ # scores.tar.gz
+ scores_filepath = glob.glob(os.path.join(c_dir_path, 'scores*'))
+
+ if len(scores_filepath) == 0:
+ d[c_dir]['scores'] = None
+ else:
+ # No duplicates
+ assert len(scores_filepath) == 1
+
+ d[c_dir]['scores'] = scores_filepath[0]
+
+ return d
+
+
+def cn_mTobp(cn_m):
+ """
+ Converts CN-M (i.e. C1-33, C1-26, C4-28) cycle information into
+ number of base pairs.
+ """
+ pass
+
+
+def parse_flowcell_id(flowcell_id):
+ """
+ Return flowcell id and any status encoded in the id
+
+ We stored the status information in the flowcell id name.
+ this was dumb, but database schemas are hard to update.
+ """
+ fields = flowcell_id.split()
+ fcid = None
+ status = None
+ if len(fields) > 0:
+ fcid = fields[0]
+ if len(fields) > 1:
+ status = fields[1]
+ return fcid, status
+
--- /dev/null
+import datetime
+import unittest
+from htsworkflow.frontend.samples.models import \
+ Affiliation, \
+ ExperimentType, \
+ Species, \
+ Library
+
+# The django test runner flushes the database between test suites not cases,
+# so to be more compatible with running via nose we flush the database tables
+# of interest before creating our sample data.
+def create_db(obj):
+ Species.objects.all().delete()
+ obj.species_human = Species(
+ scientific_name = 'Homo Sapeins',
+ common_name = 'human',
+ )
+ obj.species_human.save()
+ obj.species_worm = Species(
+ scientific_name = 'C. Elegans',
+ common_name = 'worm',
+ )
+ obj.species_worm.save()
+ obj.species_phix = Species(
+ scientific_name = 'PhiX',
+ common_name = 'PhiX'
+ )
+ obj.species_phix.save()
+
+ ExperimentType.objects.all().delete()
+ obj.experiment_de_novo = ExperimentType(
+ name = 'De Novo',
+ )
+ obj.experiment_de_novo.save()
+ obj.experiment_chip_seq = ExperimentType(
+ name = 'ChIP-Seq'
+ )
+ obj.experiment_chip_seq.save()
+ obj.experiment_rna_seq = ExperimentType(
+ name = 'RNA-Seq'
+ )
+ obj.experiment_rna_seq.save()
+
+ Affiliation.objects.all().delete()
+ obj.affiliation_alice = Affiliation(
+ name = 'Alice',
+ contact = 'Lab Boss',
+ email = 'alice@some.where.else.'
+ )
+ obj.affiliation_alice.save()
+ obj.affiliation_bob = Affiliation(
+ name = 'Bob',
+ contact = 'Other Lab Boss',
+ email = 'bob@some.where.else',
+ )
+ obj.affiliation_bob.save()
+
+ Library.objects.all().delete()
+ obj.library_10001 = Library(
+ library_id = 10001,
+ library_name = 'C2C12 named poorly',
+ library_species = obj.species_human,
+ experiment_type = obj.experiment_rna_seq,
+ creation_date = datetime.datetime.now(),
+ made_for = 'scientist unit 2007',
+ made_by = 'microfludics system 7321',
+ stopping_point = '2A',
+ undiluted_concentration = '5.01',
+ )
+ obj.library_10001.save()
+ obj.library_10002 = Library(
+ library_id = 10002,
+ library_name = 'Worm named poorly',
+ library_species = obj.species_human,
+ experiment_type = obj.experiment_rna_seq,
+ creation_date = datetime.datetime.now(),
+ made_for = 'scientist unit 2007',
+ made_by = 'microfludics system 7321',
+ stopping_point = '2A',
+ undiluted_concentration = '5.01',
+ )
+ obj.library_10002.save()
+
+class LibraryTestCase(unittest.TestCase):
+ def setUp(self):
+ create_db(self)
+
+ def testOrganism(self):
+ self.assertEquals(self.library_10001.organism(), 'human')
+
+ def testAffiliations(self):
+ self.library_10001.affiliations.add(self.affiliation_alice)
+ self.library_10002.affiliations.add(
+ self.affiliation_alice,
+ self.affiliation_bob
+ )
+ self.failUnless(len(self.library_10001.affiliations.all()), 1)
+ self.failUnless(self.library_10001.affiliation(), 'Alice')
+
+ self.failUnless(len(self.library_10002.affiliations.all()), 2)
+ self.failUnless(self.library_10001.affiliation(), 'Alice, Bob')
+
--- /dev/null
+# Create your views here.
+from htsworkflow.frontend.experiments.models import FlowCell
+from htsworkflow.frontend.samples.changelist import ChangeList
+from htsworkflow.frontend.samples.models import Library
+from htsworkflow.frontend.samples.results import get_flowcell_result_dict, parse_flowcell_id
+from htsworkflow.pipelines.runfolder import load_pipeline_run_xml
+from htsworkflow.pipelines import runfolder
+from htsworkflow.frontend import settings
+from htsworkflow.util import makebed
+from htsworkflow.util import opener
+
+from django.core.exceptions import ObjectDoesNotExist
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.template.loader import get_template
+
+import StringIO
+import logging
+import os
+
+LANE_LIST = [1,2,3,4,5,6,7,8]
+
+def create_library_context(cl):
+ """
+ Create a list of libraries that includes how many lanes were run
+ """
+ records = []
+ #for lib in library_items.object_list:
+ for lib in cl.result_list:
+ summary = {}
+ summary['library_id'] = lib.library_id
+ summary['library_name'] = lib.library_name
+ summary['species_name' ] = lib.library_species.scientific_name
+ if lib.amplified_from_sample is not None:
+ summary['amplified_from'] = lib.amplified_from_sample.library_id
+ else:
+ summary['amplified_from'] = ''
+ lanes_run = 0
+ for lane_id in LANE_LIST:
+ lane = getattr(lib, 'lane_%d_library' % (lane_id,))
+ lanes_run += len( lane.all() )
+ summary['lanes_run'] = lanes_run
+ summary['is_archived'] = lib.is_archived()
+ records.append(summary)
+ cl.result_count = unicode(cl.paginator._count) + u" libraries"
+ return {'library_list': records }
+
+def library(request):
+ # build changelist
+ fcl = ChangeList(request, Library,
+ list_filter=['affiliations', 'library_species'],
+ search_fields=['library_id', 'library_name', 'amplified_from_sample__library_id'],
+ list_per_page=200,
+ queryset=Library.objects.filter(hidden__exact=0)
+ )
+
+ context = { 'cl': fcl, 'title': 'Library Index'}
+ context.update(create_library_context(fcl))
+ t = get_template('samples/library_index.html')
+ c = RequestContext(request, context)
+ return HttpResponse( t.render(c) )
+
+def library_to_flowcells(request, lib_id):
+ """
+ Display information about all the flowcells a library has been run on.
+ """
+
+ try:
+ lib = Library.objects.get(library_id=lib_id)
+ except:
+ return HttpResponse("Library %s does not exist" % (lib_id))
+
+ flowcell_list = []
+ interesting_flowcells = {} # aka flowcells we're looking at
+ for lane in LANE_LIST:
+ lane_library = getattr(lib, 'lane_%d_library' % (lane,))
+ for fc in lane_library.all():
+ flowcell_id, id = parse_flowcell_id(fc.flowcell_id)
+ if flowcell_id not in interesting_flowcells:
+ interesting_flowcells[flowcell_id] = get_flowcell_result_dict(flowcell_id)
+ flowcell_list.append((fc.flowcell_id, lane))
+
+ flowcell_list.sort()
+
+ lane_summary_list = []
+ eland_results = []
+ for fc, lane in flowcell_list:
+ lane_summary, err_list = _summary_stats(fc, lane)
+
+ eland_results.extend(_make_eland_results(fc, lane, interesting_flowcells))
+ lane_summary_list.extend(lane_summary)
+
+ return render_to_response(
+ 'samples/library_detail.html',
+ {'lib': lib,
+ 'eland_results': eland_results,
+ 'lane_summary_list': lane_summary_list,
+ },
+ context_instance = RequestContext(request))
+
+def summaryhtm_fc_cnm(request, flowcell_id, cnm):
+ """
+ returns a Summary.htm file if it exists.
+ """
+ fc_id, status = parse_flowcell_id(flowcell_id)
+ d = get_flowcell_result_dict(fc_id)
+
+ if d is None:
+ return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
+
+ if cnm not in d:
+ return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
+
+ summary_filepath = d[cnm]['summary']
+
+ if summary_filepath is None:
+ return HttpResponse('<b>Summary.htm for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
+
+ f = open(summary_filepath, 'r')
+
+ return HttpResponse(f)
+
+
+def result_fc_cnm_eland_lane(request, flowcell_id, cnm, lane):
+ """
+ returns an eland_file upon calling.
+ """
+ fc_id, status = parse_flowcell_id(flowcell_id)
+ d = get_flowcell_result_dict(fc_id)
+
+ if d is None:
+ return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
+
+ if cnm not in d:
+ return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
+
+ erd = d[cnm]['eland_results']
+ lane = int(lane)
+
+ if lane not in erd:
+ return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
+
+ filepath = erd[lane]
+
+ #f = opener.autoopen(filepath, 'r')
+ # return HttpResponse(f, mimetype="application/x-elandresult")
+
+ f = open(filepath, 'r')
+ return HttpResponse(f, mimetype='application/x-bzip2')
+
+
+
+def bedfile_fc_cnm_eland_lane_ucsc(request, fc_id, cnm, lane):
+ """
+ returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane (ucsc compatible)
+ """
+ return bedfile_fc_cnm_eland_lane(request, fc_id, cnm, lane, ucsc_compatible=True)
+
+
+def bedfile_fc_cnm_eland_lane(request, flowcell_id, cnm, lane, ucsc_compatible=False):
+ """
+ returns a bed file for a given flowcell, CN-M (i.e. C1-33), and lane
+ """
+ fc_id, status = parse_flowcell_id(flowcell_id)
+ d = get_flowcell_result_dict(fc_id)
+
+ if d is None:
+ return HttpResponse('<b>Results for Flowcell %s not found.</b>' % (fc_id))
+
+ if cnm not in d:
+ return HttpResponse('<b>Results for Flowcell %s; %s not found.</b>' % (fc_id, cnm))
+
+ erd = d[cnm]['eland_results']
+ lane = int(lane)
+
+ if lane not in erd:
+ return HttpResponse('<b>Results for Flowcell %s; %s; lane %s not found.</b>' % (fc_id, cnm, lane))
+
+ filepath = erd[lane]
+
+ # Eland result file
+ fi = opener.autoopen(filepath, 'r')
+ # output memory file
+
+ name, description = makebed.make_description( fc_id, lane )
+
+ bedgen = makebed.make_bed_from_eland_generator(fi, name, description)
+
+ if ucsc_compatible:
+ return HttpResponse(bedgen)
+ else:
+ return HttpResponse(bedgen, mimetype="application/x-bedfile")
+
+
+def _summary_stats(flowcell_id, lane_id):
+ """
+ Return the summary statistics for a given flowcell, lane, and end.
+ """
+ fc_id, status = parse_flowcell_id(flowcell_id)
+ fc_result_dict = get_flowcell_result_dict(fc_id)
+
+ summary_list = []
+ err_list = []
+
+ if fc_result_dict is None:
+ err_list.append('Results for Flowcell %s not found.' % (fc_id))
+ return (summary_list, err_list)
+
+ for cycle_width in fc_result_dict:
+ xmlpath = fc_result_dict[cycle_width]['run_xml']
+
+ if xmlpath is None:
+ err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cycle_width))
+ continue
+
+ run = load_pipeline_run_xml(xmlpath)
+ gerald_summary = run.gerald.summary.lane_results
+ for end in range(len(gerald_summary)):
+ eland_summary = run.gerald.eland_results.results[end][lane_id]
+ # add information to lane_summary
+ eland_summary.flowcell_id = flowcell_id
+ eland_summary.clusters = gerald_summary[end][lane_id].cluster
+ eland_summary.cycle_width = cycle_width
+ if hasattr(eland_summary, 'genome_map'):
+ eland_summary.summarized_reads = runfolder.summarize_mapped_reads(
+ eland_summary.genome_map,
+ eland_summary.mapped_reads)
+
+ # grab some more information out of the flowcell db
+ flowcell = FlowCell.objects.get(flowcell_id=flowcell_id)
+ pm_field = 'lane_%d_pM' % (lane_id)
+ eland_summary.successful_pm = getattr(flowcell, pm_field)
+
+ summary_list.append(eland_summary)
+
+ #except Exception, e:
+ # summary_list.append("Summary report needs to be updated.")
+ # logging.error("Exception: " + str(e))
+
+ return (summary_list, err_list)
+
+def _summary_stats_old(flowcell_id, lane):
+ """
+ return a dictionary of summary stats for a given flowcell_id & lane.
+ """
+ fc_id, status = parse_flowcell_id(flowcell_id)
+ fc_result_dict = get_flowcell_result_dict(fc_id)
+
+ dict_list = []
+ err_list = []
+ summary_list = []
+
+ if fc_result_dict is None:
+ err_list.append('Results for Flowcell %s not found.' % (fc_id))
+ return (dict_list, err_list, summary_list)
+
+ for cnm in fc_result_dict:
+
+ xmlpath = fc_result_dict[cnm]['run_xml']
+
+ if xmlpath is None:
+ err_list.append('Run xml for Flowcell %s(%s) not found.' % (fc_id, cnm))
+ continue
+
+ tree = ElementTree.parse(xmlpath).getroot()
+ results = runfolder.PipelineRun(pathname='', xml=tree)
+ try:
+ lane_report = runfolder.summarize_lane(results.gerald, lane)
+ summary_list.append(os.linesep.join(lane_report))
+ except Exception, e:
+ summary_list.append("Summary report needs to be updated.")
+ logging.error("Exception: " + str(e))
+
+ print "----------------------------------"
+ print "-- DOES NOT SUPPORT PAIRED END ---"
+ print "----------------------------------"
+ lane_results = results.gerald.summary[0][lane]
+ lrs = lane_results
+
+ d = {}
+
+ d['average_alignment_score'] = lrs.average_alignment_score
+ d['average_first_cycle_intensity'] = lrs.average_first_cycle_intensity
+ d['cluster'] = lrs.cluster
+ d['lane'] = lrs.lane
+ d['flowcell'] = flowcell_id
+ d['cnm'] = cnm
+ d['percent_error_rate'] = lrs.percent_error_rate
+ d['percent_intensity_after_20_cycles'] = lrs.percent_intensity_after_20_cycles
+ d['percent_pass_filter_align'] = lrs.percent_pass_filter_align
+ d['percent_pass_filter_clusters'] = lrs.percent_pass_filter_clusters
+
+ #FIXME: function finished, but need to take advantage of
+ # may need to take in a list of lanes so we only have to
+ # load the xml file once per flowcell rather than once
+ # per lane.
+ dict_list.append(d)
+
+ return (dict_list, err_list, summary_list)
+
+
+def get_eland_result_type(pathname):
+ """
+ Guess the eland result file type from the filename
+ """
+ path, filename = os.path.split(pathname)
+ if 'extended' in filename:
+ return 'extended'
+ elif 'multi' in filename:
+ return 'multi'
+ elif 'result' in filename:
+ return 'result'
+ else:
+ return 'unknown'
+
+def _make_eland_results(flowcell_id, lane, interesting_flowcells):
+ fc_id, status = parse_flowcell_id(flowcell_id)
+ cur_fc = interesting_flowcells.get(fc_id, None)
+ if cur_fc is None:
+ return []
+
+ results = []
+ for cycle in cur_fc.keys():
+ result_path = cur_fc[cycle]['eland_results'].get(lane, None)
+ result_link = make_result_link(fc_id, cycle, lane, result_path)
+ results.append({'flowcell_id': fc_id,
+ 'cycle': cycle,
+ 'lane': lane,
+ 'summary_url': make_summary_url(flowcell_id, cycle),
+ 'result_url': result_link[0],
+ 'result_label': result_link[1],
+ 'bed_url': result_link[2],
+ })
+ return results
+
+def make_summary_url(flowcell_id, cycle_name):
+ url = '/results/%s/%s/summary/' % (flowcell_id, cycle_name)
+ return url
+
+def make_result_link(flowcell_id, cycle_name, lane, eland_result_path):
+ if eland_result_path is None:
+ return ("", "", "")
+
+ result_type = get_eland_result_type(eland_result_path)
+ result_url = '/results/%s/%s/eland_result/%s' % (flowcell_id, cycle_name, lane)
+ result_label = 'eland %s' % (result_type,)
+ bed_url = None
+ if result_type == 'result':
+ bed_url_pattern = '/results/%s/%s/bedfile/%s'
+ bed_url = bed_url_pattern % (flowcell_id, cycle_name, lane)
+
+ return (result_url, result_label, bed_url)
+
+def _files(flowcell_id, lane):
+ """
+ Sets up available files for download
+ """
+ lane = int(lane)
+
+ flowcell_id, id = parse_flowcell_id(flowcell_id)
+ d = get_flowcell_result_dict(flowcell_id)
+
+ if d is None:
+ return ''
+
+ output = []
+
+ # c_name == 'CN-M' (i.e. C1-33)
+ for c_name in d:
+
+ if d[c_name]['summary'] is not None:
+ output.append('<a href="/results/%s/%s/summary/">summary(%s)</a>' \
+ % (flowcell_id, c_name, c_name))
+
+ erd = d[c_name]['eland_results']
+ if lane in erd:
+ result_type = get_eland_result_type(erd[lane])
+ result_url_pattern = '<a href="/results/%s/%s/eland_result/%s">eland %s(%s)</a>'
+ output.append(result_url_pattern % (flowcell_id, c_name, lane, result_type, c_name))
+ if result_type == 'result':
+ bed_url_pattern = '<a href="/results/%s/%s/bedfile/%s">bedfile(%s)</a>'
+ output.append(bed_url_pattern % (flowcell_id, c_name, lane, c_name))
+
+ if len(output) == 0:
+ return ''
+
+ return '(' + '|'.join(output) + ')'
+
+def library_id_to_admin_url(request, lib_id):
+ lib = Library.objects.get(library_id=lib_id)
+ return HttpResponseRedirect('/admin/samples/library/%s' % (lib.id,))
+
--- /dev/null
+"""
+Generate settings for the Django Application.
+
+To make it easier to customize the application the settings can be
+defined in a configuration file read by ConfigParser.
+
+The options understood by this module are (with their defaults):
+
+ [frontend]
+ email_host=localhost
+ email_port=25
+ database_engine=sqlite3
+ database_name=/path/to/db
+
+ [admins]
+ #name1=email1
+
+ [allowed_hosts]
+ #name1=ip
+ localhost=127.0.0.1
+
+ [allowed_analysis_hosts]
+ #name1=ip
+ localhost=127.0.0.1
+
+"""
+import ConfigParser
+import os
+
+# make epydoc happy
+__docformat__ = "restructuredtext en"
+
+def options_to_list(dest, section_name):
+ """
+ Load a options from section_name and store in a dictionary
+ """
+ if options.has_section(section_name):
+ for name in options.options(section_name):
+ dest.append( options.get(section_name, name) )
+
+def options_to_dict(dest, section_name):
+ """
+ Load a options from section_name and store in a dictionary
+ """
+ if options.has_section(section_name):
+ for name in options.options(section_name):
+ dest[name] = options.get(section_name, name)
+
+# define your defaults here
+options = ConfigParser.SafeConfigParser(
+ { 'email_host': 'localhost',
+ 'email_port': '25',
+ 'database_engine': 'sqlite3',
+ 'database_name':
+ os.path.abspath('/htsworkflow/htswfrontend/dev_fctracker.db'),
+ 'time_zone': 'America/Los_Angeles',
+ 'default_pm': '5',
+ 'link_flowcell_storage_device_url': "http://localhost:8000/inventory/lts/link/"
+ })
+
+options.read([os.path.expanduser("~/.htsworkflow.ini"),
+ '/etc/htsworkflow.ini',])
+
+# Django settings for elandifier project.
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = []
+options_to_list(ADMINS, 'admins')
+
+MANAGERS = ADMINS
+
+EMAIL_HOST = options.get('frontend', 'email_host')
+EMAIL_PORT = int(options.get('frontend', 'email_port'))
+
+# 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
+DATABASE_ENGINE = options.get('frontend', 'database_engine')
+
+# Or path to database file if using sqlite3.
+DATABASE_NAME = options.get('frontend', 'database_name' )
+DATABASE_USER = '' # Not used with sqlite3.
+DATABASE_PASSWORD = '' # Not used with sqlite3.
+DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
+DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
+
+# Local time zone for this installation. Choices can be found here:
+# http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
+# although not all variations may be possible on all operating systems.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = options.get('frontend', 'time_zone')
+
+# Language code for this installation. All choices can be found here:
+# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
+# http://blogs.law.harvard.edu/tech/stories/storyReader$15
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# Absolute path to the directory that holds media.
+# Example: "/home/media/media.lawrence.com/"
+MEDIA_ROOT = os.path.abspath(os.path.split(__file__)[0]) + '/static/'
+
+# URL that handles the media served from MEDIA_ROOT.
+# Example: "http://media.lawrence.com"
+MEDIA_URL = '/static/'
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/media/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = '(ekv^=gf(j9f(x25@a7r+8)hqlz%&_1!tw^75l%^041#vi=@4n'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.load_template_source',
+ 'django.template.loaders.app_directories.load_template_source',
+# 'django.template.loaders.eggs.load_template_source',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.middleware.doc.XViewMiddleware',
+)
+
+ROOT_URLCONF = 'htsworkflow.frontend.urls'
+
+TEMPLATE_DIRS = (
+ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+ os.path.join(os.path.split(__file__)[0], 'templates'),
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.admin',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.humanize',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'htsworkflow.frontend.eland_config',
+ 'htsworkflow.frontend.samples',
+ # modules from htsworkflow branch
+ 'htsworkflow.frontend.experiments',
+ 'htsworkflow.frontend.analysis',
+ 'htsworkflow.frontend.reports',
+ 'htsworkflow.frontend.inventory',
+ 'django.contrib.databrowse',
+)
+
+# Project specific settings
+
+ALLOWED_IPS={'127.0.0.1': '127.0.0.1'}
+options_to_dict(ALLOWED_IPS, 'allowed_hosts')
+
+ALLOWED_ANALYS_IPS = {'127.0.0.1': '127.0.0.1'}
+options_to_dict(ALLOWED_ANALYS_IPS, 'allowed_analysis_hosts')
+#UPLOADTO_HOME = os.path.abspath('../../uploads')
+#UPLOADTO_CONFIG_FILE = os.path.join(UPLOADTO_HOME, 'eland_config')
+#UPLOADTO_ELAND_RESULT_PACKS = os.path.join(UPLOADTO_HOME, 'eland_results')
+#UPLOADTO_BED_PACKS = os.path.join(UPLOADTO_HOME, 'bed_packs')
+RESULT_HOME_DIR='/Users/diane/proj/solexa/results/flowcells'
+
+LINK_FLOWCELL_STORAGE_DEVICE_URL = options.get('frontend', 'link_flowcell_storage_device_url')
+
--- /dev/null
+/*
+ DJANGO Admin
+ by Wilson Miner wilson@lawrence.com
+*/
+
+/* Block IE 5 */
+@import "null.css?\"\{";
+
+/* Import other styles */
+@import url('global.css');
+@import url('layout.css');
+
+/* Import patch for IE 6 Windows */
+/*\*/ @import "patch-iewin.css"; /**/
--- /dev/null
+@import url('base.css');
+
+/* CHANGELISTS */
+#changelist { position:relative; width:100%; }
+#changelist table { width:100%; }
+.change-list .filtered table { border-right:1px solid #ddd; }
+.change-list .filtered { min-height:400px; }
+.change-list .filtered { background:white url(../img/changelist-bg.gif) top right repeat-y !important; }
+.change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { margin-right:160px !important; width:auto !important; }
+.change-list .filtered table tbody th { padding-right:1em; }
+#changelist .toplinks { border-bottom:1px solid #ccc !important; }
+#changelist .paginator { color:#666; border-top:1px solid #eee; border-bottom:1px solid #eee; background:white url(../img/nav-bg.gif) 0 180% repeat-x; overflow:hidden; }
+.change-list .filtered .paginator { border-right:1px solid #ddd; }
+
+/* CHANGELIST TABLES */
+#changelist table thead th { white-space:nowrap; }
+#changelist table tbody td { border-left: 1px solid #ddd; }
+#changelist table tfoot { color: #666; }
+
+/* TOOLBAR */
+#changelist #toolbar { padding:3px; border-bottom:1px solid #ddd; background:#e1e1e1 url(../img/nav-bg.gif) top left repeat-x; color:#666; }
+#changelist #toolbar form input { font-size:11px; padding:1px 2px; }
+#changelist #toolbar form #searchbar { padding:2px; }
+#changelist #changelist-search img { vertical-align:middle; }
+
+/* FILTER COLUMN */
+#changelist-filter { position:absolute; top:0; right:0; z-index:1000; width:160px; border-left:1px solid #ddd; background:#efefef; margin:0; }
+#changelist-filter h2 { font-size:11px; padding:2px 5px; border-bottom:1px solid #ddd; }
+#changelist-filter h3 { font-size:12px; margin-bottom:0; }
+#changelist-filter ul { padding-left:0;margin-left:10px; }
+#changelist-filter li { list-style-type:none; margin-left:0; padding-left:0; }
+#changelist-filter a { color:#999; }
+#changelist-filter a:hover { color:#036; }
+#changelist-filter li.selected { border-left:5px solid #ccc; padding-left:5px;margin-left:-10px; }
+#changelist-filter li.selected a { color:#5b80b2 !important; }
+
+/* DATE DRILLDOWN */
+.change-list ul.toplinks { display:block; background:white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x; border-top:1px solid white; float:left; padding:0 !important; margin:0 !important; width:100%; }
+.change-list ul.toplinks li { float: left; width: 9em; padding:3px 6px; font-weight: bold; list-style-type:none; }
+.change-list ul.toplinks .date-back a { color:#999; }
+.change-list ul.toplinks .date-back a:hover { color:#036; }
+
+/* PAGINATOR */
+.paginator { font-size:11px; padding-top:10px; padding-bottom:10px; line-height:22px; margin:0; border-top:1px solid #ddd; }
+.paginator a:link, .paginator a:visited { padding:2px 6px; border:solid 1px #ccc; background:white; text-decoration:none; }
+.paginator a.showall { padding:0 !important; border:none !important; }
+.paginator a.showall:hover { color:#036 !important; background:transparent !important; }
+.paginator .end { border-width:2px !important; margin-right:6px; }
+.paginator .this-page { padding:2px 6px; font-weight:bold; font-size:13px; vertical-align:top; }
+.paginator a:hover { color:white; background:#5b80b2; border-color:#036; }
--- /dev/null
+table, td {
+ border-style: solid;
+}
+table {
+ border-width: 0 0 1px 1px;
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+thead {
+ text-align: center;
+}
+td {
+ margin: 0;
+ padding: 4px;
+ border-width: 1px 1px 0 0;
+}
+td a {
+ display: block;
+}
--- /dev/null
+@import url('changelists.css');
+@import url('click-table.css');
--- /dev/null
+@import url('base.css');
+@import url('widgets.css');
+
+/* FORM ROWS */
+.form-row { overflow:hidden; padding:8px 12px; font-size:11px; border-bottom:1px solid #eee; }
+.form-row img, .form-row input { vertical-align:middle; }
+form .form-row p { padding-left:0; font-size:11px; }
+
+/* FORM LABELS */
+form h4 { margin:0 !important; padding:0 !important; border:none !important; }
+label { font-weight:normal !important; color:#666; font-size:12px; }
+.required label, label.required { font-weight:bold !important; color:#333 !important; }
+
+/* RADIO BUTTONS */
+form ul.radiolist li { list-style-type:none; }
+form ul.radiolist label { float:none; display:inline; }
+form ul.inline { margin-left:0; padding:0; }
+form ul.inline li { float:left; padding-right:7px; }
+
+/* ALIGNED FIELDSETS */
+.aligned label { display:block; padding:3px 10px 0 0; float:left; width:8em; }
+.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField { width:350px; }
+form .aligned p, form .aligned ul { margin-left:7em; padding-left:30px; }
+form .aligned table p { margin-left:0; padding-left:0; }
+form .aligned p.help { padding-left:38px; }
+.aligned .vCheckboxLabel { float:none !important; display:inline; padding-left:4px; }
+.colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField { width:610px; }
+.checkbox-row p.help { margin-left:0; padding-left:0 !important; }
+fieldset .field-box { float:left; margin-right: 20px; }
+
+/* WIDE FIELDSETS */
+.wide label { width:15em !important; }
+form .wide p { margin-left:15em; }
+form .wide p.help { padding-left:38px; }
+.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField { width:450px; }
+
+/* COLLAPSED FIELDSETS */
+fieldset.collapsed * { display:none; }
+fieldset.collapsed h2, fieldset.collapsed { display:block !important; }
+fieldset.collapsed h2 { background-image:url(../img/nav-bg.gif); background-position:bottom left; color:#999; }
+fieldset.collapsed .collapse-toggle { padding:3px 5px !important; background:transparent; display:inline !important;}
+
+/* MONOSPACE TEXTAREAS */
+fieldset.monospace textarea { font-family:"Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace; }
+
+/* SUBMIT ROW */
+.submit-row { padding:5px 7px; text-align:right; background:white url(../img/nav-bg.gif) 0 100% repeat-x; border:1px solid #ccc; margin:5px 0; overflow:hidden; }
+.submit-row input { margin:0 0 0 5px; }
+.submit-row p { margin:0.3em; }
+.submit-row p.deletelink-box { float: left; }
+.submit-row .deletelink { background:url(../img/icon_deletelink.gif) 0 50% no-repeat; padding-left:14px; }
+
+/* CUSTOM FORM FIELDS */
+.vSelectMultipleField { vertical-align:top !important; }
+.vCheckboxField { border:none; }
+.vDateField, .vTimeField { margin-right:2px; }
+.vURLField { width:30em; }
+.vLargeTextField, .vXMLLargeTextField { width:48em; }
+.flatpages-flatpage #id_content { height:40.2em; }
+.module table .vPositiveSmallIntegerField { width:2.2em; }
+.vTextField { width:20em; }
+.vIntegerField { width:5em; }
+.vForeignKeyRawIdAdminField { width: 5em; }
+
+/* INLINES */
+.inline-group {padding:0; border:1px solid #ccc; margin:10px 0;}
+.inline-group .aligned label { width: 8em; }
+
+.inline-related {position:relative;}
+.inline-related h3 {margin: 0; color:#666; padding:3px 5px; font-size:11px; background:#e1e1e1 url(../img/nav-bg.gif) top left repeat-x; border-bottom:1px solid #ddd;}
+.inline-related h3 span.delete {padding-left:20px; position:absolute; top:2px; right:10px;}
+.inline-related h3 span.delete label {margin-left:2px; font-size: 11px;}
+.inline-related fieldset {margin: 0; background:#fff; border: none; }
+.inline-related fieldset.module h3 { margin:0; padding:2px 5px 3px 5px; font-size:11px; text-align:left; font-weight:bold; background:#bcd; color:#fff; }
+.inline-related.tabular fieldset.module table {width:100%;}
+.last-related fieldset {border: none;}
+
+.inline-group .tabular tr.has_original td {padding-top:2em;}
+.inline-group .tabular tr td.original { padding:2px 0 0 0; width:0; _position:relative; }
+.inline-group .tabular th.original {width:0px; padding:0;}
+.inline-group .tabular td.original p {position:absolute; left:0; height:1.1em; padding:2px 7px; overflow:hidden; font-size:9px; font-weight:bold; color:#666; _width:700px; }
+.inline-group ul.tools {padding:0; margin: 0; list-style:none;}
+.inline-group ul.tools li {display:inline; padding:0 5px;}
+.inline-group ul.tools a.add {background:url(../img/icon_addlink.gif) 0 50% no-repeat; padding-left:14px;}
--- /dev/null
+body { margin:0; padding:0; font-size:12px; font-family:"Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif; color:#333; background:#fff; }
+
+/* LINKS */
+a:link, a:visited { color: #5b80b2; text-decoration:none; }
+a:hover { color: #036; }
+a img { border:none; }
+a.section:link, a.section:visited { color: white; text-decoration:none; }
+
+/* GLOBAL DEFAULTS */
+p, ol, ul, dl { margin:.2em 0 .8em 0; }
+p { padding:0; line-height:140%; }
+
+h1,h2,h3,h4,h5 { font-weight:bold; }
+h1 { font-size:18px; color:#666; padding:0 6px 0 0; margin:0 0 .2em 0; }
+h2 { font-size:16px; margin:1em 0 .5em 0; }
+h2.subhead { font-weight:normal;margin-top:0; }
+h3 { font-size:14px; margin:.8em 0 .3em 0; color:#666; font-weight:bold; }
+h4 { font-size:12px; margin:1em 0 .8em 0; padding-bottom:3px; }
+h5 { font-size:10px; margin:1.5em 0 .5em 0; color:#666; text-transform:uppercase; letter-spacing:1px; }
+
+ul li { list-style-type:square; padding:1px 0; }
+ul.plainlist { margin-left:0 !important; }
+ul.plainlist li { list-style-type:none; }
+li ul { margin-bottom:0; }
+li, dt, dd { font-size:11px; line-height:14px; }
+dt { font-weight:bold; margin-top:4px; }
+dd { margin-left:0; }
+
+form { margin:0; padding:0; }
+fieldset { margin:0; padding:0; }
+
+blockquote { font-size:11px; color:#777; margin-left:2px; padding-left:10px; border-left:5px solid #ddd; }
+code, pre { font-family:"Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; background:inherit; color:#666; font-size:11px; }
+pre.literal-block { margin:10px; background:#eee; padding:6px 8px; }
+code strong { color:#930; }
+hr { clear:both; color:#eee; background-color:#eee; height:1px; border:none; margin:0; padding:0; font-size:1px; line-height:1px; }
+
+/* TEXT STYLES & MODIFIERS */
+.small { font-size:11px; }
+.tiny { font-size:10px; }
+p.tiny { margin-top:-2px; }
+.mini { font-size:9px; }
+p.mini { margin-top:-3px; }
+.help, p.help { font-size:10px !important; color:#999; }
+p img, h1 img, h2 img, h3 img, h4 img, td img { vertical-align:middle; }
+.quiet, a.quiet:link, a.quiet:visited { color:#999 !important;font-weight:normal !important; }
+.quiet strong { font-weight:bold !important; }
+.float-right { float:right; }
+.float-left { float:left; }
+.clear { clear:both; }
+.align-left { text-align:left; }
+.align-right { text-align:right; }
+.example { margin:10px 0; padding:5px 10px; background:#efefef; }
+.nowrap { white-space:nowrap; }
+
+/* TABLES */
+table { border-collapse:collapse; border-color:#ccc; }
+td, th { font-size:11px; line-height:13px; border-bottom:1px solid #eee; vertical-align:top; padding:5px; font-family:"Lucida Grande", Verdana, Arial, sans-serif; }
+th { text-align:left; font-size:12px; font-weight:bold; }
+thead th,
+tfoot td { color:#666; padding:2px 5px; font-size:11px; background:#e1e1e1 url(../img/nav-bg.gif) top left repeat-x; border-left:1px solid #ddd; border-bottom:1px solid #ddd; }
+tfoot td { border-bottom:none; border-top:1px solid #ddd; }
+thead th:first-child,
+tfoot td:first-child { border-left:none !important; }
+thead th.optional { font-weight:normal !important; }
+fieldset table { border-right:1px solid #eee; }
+tr.row-label td { font-size:9px; padding-top:2px; padding-bottom:0; border-bottom:none; color:#666; margin-top:-1px; }
+tr.alt { background:#f6f6f6; }
+.row1 { background:#EDF3FE; }
+.row2 { background:white; }
+
+/* SORTABLE TABLES */
+thead th a:link, thead th a:visited { color:#666; display:block; }
+table thead th.sorted { background-position:bottom left !important; }
+table thead th.sorted a { padding-right:13px; }
+table thead th.ascending a { background:url(../img/arrow-down.gif) right .4em no-repeat; }
+table thead th.descending a { background:url(../img/arrow-up.gif) right .4em no-repeat; }
+
+/* ORDERABLE TABLES */
+table.orderable tbody tr td:hover { cursor:move; }
+table.orderable tbody tr td:first-child { padding-left:14px; background-image:url(../img/nav-bg-grabber.gif); background-repeat:repeat-y; }
+table.orderable-initalized .order-cell, body>tr>td.order-cell { display:none; }
+
+/* FORM DEFAULTS */
+input, textarea, select { margin:2px 0; padding:2px 3px; vertical-align:middle; font-family:"Lucida Grande", Verdana, Arial, sans-serif; font-weight:normal; font-size:11px; }
+textarea { vertical-align:top !important; }
+input[type=text], input[type=password], textarea, select, .vTextField { border:1px solid #ccc; }
+
+/* FORM BUTTONS */
+.button, input[type=submit], input[type=button], .submit-row input { background:white url(../img/nav-bg.gif) bottom repeat-x; padding:3px; color:black; border:1px solid #bbb; border-color:#ddd #aaa #aaa #ddd; }
+.button:active, input[type=submit]:active, input[type=button]:active { background-image:url(../img/nav-bg-reverse.gif); background-position:top; }
+.button.default, input[type=submit].default, .submit-row input.default { border:2px solid #5b80b2; background:#7CA0C7 url(../img/default-bg.gif) bottom repeat-x; font-weight:bold; color:white; float:right; }
+.button.default:active, input[type=submit].default:active { background-image:url(../img/default-bg-reverse.gif); background-position:top; }
+
+/* MODULES */
+.module { border:1px solid #ccc; margin-bottom:5px; background:white; }
+.module p, .module ul, .module h3, .module h4, .module dl, .module pre { padding-left:10px; padding-right:10px; }
+.module blockquote { margin-left:12px; }
+.module ul, .module ol { margin-left:1.5em; }
+.module h3 { margin-top:.6em; }
+.module h2, .module caption, .inline-group h2 { margin:0; padding:2px 5px 3px 5px; font-size:11px; text-align:left; font-weight:bold; background:#7CA0C7 url(../img/default-bg.gif) top left repeat-x; color:white; }
+.module table { border-collapse: collapse; }
+
+/* MESSAGES & ERRORS */
+ul.messagelist { padding:0 0 5px 0; margin:0; }
+ul.messagelist li { font-size:12px; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border-bottom:1px solid #ddd; color:#666; background:#ffc url(../img/icon_success.gif) 5px .3em no-repeat; }
+.errornote { font-size:12px !important; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border:1px solid red; color:red;background:#ffc url(../img/icon_error.gif) 5px .3em no-repeat; }
+ul.errorlist { margin:0 !important; padding:0 !important; }
+.errorlist li { font-size:12px !important; display:block; padding:4px 5px 4px 25px; margin:0 0 3px 0; border:1px solid red; color:white; background:red url(../img/icon_alert.gif) 5px .3em no-repeat; }
+td ul.errorlist { margin:0 !important; padding:0 !important; }
+td ul.errorlist li { margin:0 !important; }
+.errors { background:#ffc; }
+.errors input, .errors select { border:1px solid red; }
+div.system-message { background: #ffc; margin: 10px; padding: 6px 8px; font-size: .8em; }
+div.system-message p.system-message-title { padding:4px 5px 4px 25px; margin:0; color:red; background:#ffc url(../img/icon_error.gif) 5px .3em no-repeat; }
+.description { font-size:12px; padding:5px 0 0 12px; }
+
+/* BREADCRUMBS */
+div.breadcrumbs { background:white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x; padding:2px 8px 3px 8px; font-size:11px; color:#999; border-top:1px solid white; border-bottom:1px solid #ccc; text-align:left; }
+
+/* ACTION ICONS */
+.addlink { padding-left:12px; background:url(../img/icon_addlink.gif) 0 .2em no-repeat; }
+.changelink { padding-left:12px; background:url(../img/icon_changelink.gif) 0 .2em no-repeat; }
+.deletelink { padding-left:12px; background:url(../img/icon_deletelink.gif) 0 .25em no-repeat; }
+a.deletelink:link, a.deletelink:visited { color:#CC3434; }
+a.deletelink:hover { color:#993333; }
+
+/* OBJECT TOOLS */
+.object-tools { font-size:10px; font-weight:bold; font-family:Arial,Helvetica,sans-serif; padding-left:0; float:right; position:relative; margin-top:-2.4em; margin-bottom:-2em; }
+.form-row .object-tools { margin-top:5px; margin-bottom:5px; float:none; height:2em; padding-left:3.5em; }
+.object-tools li { display:block; float:left; background:url(../img/tool-left.gif) 0 0 no-repeat; padding:0 0 0 8px; margin-left:2px; height:16px; }
+.object-tools li:hover { background:url(../img/tool-left_over.gif) 0 0 no-repeat; }
+.object-tools a:link, .object-tools a:visited { display:block; float:left; color:white; padding:.1em 14px .1em 8px; height:14px; background:#999 url(../img/tool-right.gif) 100% 0 no-repeat; }
+.object-tools a:hover, .object-tools li:hover a { background:#5b80b2 url(../img/tool-right_over.gif) 100% 0 no-repeat; }
+.object-tools a.viewsitelink, .object-tools a.golink { background:#999 url(../img/tooltag-arrowright.gif) top right no-repeat; padding-right:28px; }
+.object-tools a.viewsitelink:hover, .object-tools a.golink:hover { background:#5b80b2 url(../img/tooltag-arrowright_over.gif) top right no-repeat; }
+.object-tools a.addlink { background:#999 url(../img/tooltag-add.gif) top right no-repeat; padding-right:28px; }
+.object-tools a.addlink:hover { background:#5b80b2 url(../img/tooltag-add_over.gif) top right no-repeat; }
+
+/* OBJECT HISTORY */
+table#change-history { width:100%; }
+table#change-history tbody th { width:16em; }
--- /dev/null
+/* PAGE STRUCTURE */
+#container { position:relative; width:100%; min-width:760px; padding:0; }
+#content { margin:10px 15px; }
+#header { width:100%; }
+#content-main { float:left; width:100%; }
+#content-related { float:right; width:18em; position:relative; margin-right:-19em; }
+#footer { clear:both; padding:10px; }
+
+/* COLUMN TYPES */
+.colMS { margin-right:20em !important; }
+.colSM { margin-left:20em !important; }
+.colSM #content-related { float:left; margin-right:0; margin-left:-19em; }
+.colSM #content-main { float:right; }
+.popup .colM { width:95%; }
+.subcol { float:left; width:46%; margin-right:15px; }
+.dashboard #content { width:500px; }
+
+/* HEADER */
+#header { background:#417690; color:#ffc; overflow:hidden; }
+#header a:link, #header a:visited { color:white; }
+#header a:hover { text-decoration:underline; }
+#branding h1 { padding:0 10px; font-size:18px; margin:8px 0; font-weight:normal; color:#f4f379; }
+#branding h2 { padding:0 10px; font-size:14px; margin:-8px 0 8px 0; font-weight:normal; color:#ffc; }
+#user-tools { position:absolute; top:0; right:0; padding:1.2em 10px; font-size:11px; text-align:right; }
+
+/* SIDEBAR */
+#content-related h3 { font-size:12px; color:#666; margin-bottom:3px; }
+#content-related h4 { font-size:11px; }
+#content-related .module h2 { background:#eee url(../img/nav-bg.gif) bottom left repeat-x; color:#666; }
--- /dev/null
+/* Nothing to see here. Dummy file to feed to the high pass filter which hides CSS from IE5/win. Details: http://tantek.com/CSS/Examples/highpass.html */
\ No newline at end of file
--- /dev/null
+* html #container { position:static; } /* keep header from flowing off the page */
+* html .colMS #content-related { margin-right:0; margin-left:10px; position:static; } /* put the right sidebars back on the page */
+* html .colSM #content-related { margin-right:10px; margin-left:-115px; position:static; } /* put the left sidebars back on the page */
+* html .form-row { height:1%; }
+* html .dashboard #content { width:768px; } /* proper fixed width for dashboard in IE6 */
+* html .dashboard #content-main { width:535px; } /* proper fixed width for dashboard in IE6 */
+* html #changelist-filter ul { margin-right:-10px; } /* fix right margin for changelist filters in IE6 */
+* html .change-list .filtered { height:400px; } /* IE ignores min-height, but treats height as if it were min-height */
\ No newline at end of file
--- /dev/null
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+This copyright and license notice covers the following images:
+ * hdd_unmount.png
+************************************************************************
+
+TITLE: Crystal Project Icons
+AUTHOR: Everaldo Coelho
+SITE: http://www.everaldo.com
+CONTACT: everaldo@everaldo.com
+
+Copyright (c) 2006-2007 Everaldo Coelho.
--- /dev/null
+{% extends "admin/base.html" %}
+{% load i18n %}
+
+{% block title %}
+{{ title }}|{%trans "dev site admin" %}
+{% endblock %}
+
+{% block branding %}
+<h1 id="site-name" style="background-color:#cccccc;color:black">
+ {%block sitename %}
+ {% trans 'HTS Workflow Dev Server' %}
+ {%endblock%}
+</h1>
+{% endblock %}
+
+{% block nav-global %}{% endblock %}
--- /dev/null
+{% extends "admin/base_site.html" %}
+{% load i18n %}
+
+{% block stylesheet %}{% load adminmedia %}{% admin_media_prefix %}css/dashboard.css{% endblock %}
+
+{% block coltype %}colMS{% endblock %}
+
+{% block bodyclass %}dashboard{% endblock %}
+
+{% block breadcrumbs %}{% endblock %}
+
+{% block content %}
+<div id="content-main">
+
+{% if app_list %}
+ {% for app in app_list %}
+ <div class="module">
+ <table summary="{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}">
+ <caption><a href="{{ app.app_url }}" class="section">{% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}</a></caption>
+ {% for model in app.models %}
+ <tr>
+ {% if model.perms.change %}
+ <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
+ {% else %}
+ <th scope="row">{{ model.name }}</th>
+ {% endif %}
+
+ {% if model.perms.add %}
+ <td><a href="{{ model.admin_url }}add/" class="addlink">{% trans 'Add' %}</a></td>
+ {% else %}
+ <td> </td>
+ {% endif %}
+
+ {% if model.perms.change %}
+ <td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
+ {% else %}
+ <td> </td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </table>
+ </div>
+ {% endfor %}
+{% else %}
+ <p>{% trans "You don't have permission to edit anything." %}</p>
+{% endif %}
+</div>
+
+ <div class="module">
+ <table>
+ <caption><span style="color:red">New!</span> Reports <span style="color:black;font-size:80%">(Note: Some features currently work only on Firefox)</span></caption>
+ <tr>
+ <th scope="row"><a href="/reports/report" target=_self>ChIP-Seq Reports</a></th>
+ <th scope="row"></th><td></td><td> </td><td></td><td> </td>
+ </tr>
+ <tr>
+ <th scope="row"><a href="/reports/report_RM" target=_self>RNA-Seq Reports</a></th>
+ <th scope="row"></th><td></td><td> </td><td></td><td> </td>
+ </tr>
+ <tr>
+ <th scope="row"><a href="/reports/report_RM?exp=Methyl-seq" target=_self>Methyl-Seq Reports</a></th>
+ <th scope="row"></th><td></td><td> </td><td></td><td> </td>
+ </tr>
+ </table>
+ </div>
+ <div class="module">
+ <table>
+ <caption>Docs & Tools</caption>
+ <tr>
+ <th scope="row"><a href="http://illumina-mac.stanford.edu/SequencingSummaries/SequencingSummary.html" target=_blank>Sequencing Summary Page</a></th>
+ <th scope="row"></th>
+ <td></td>
+ <td> </td>
+ <td></td>
+ <td> </td>
+ </tr>
+ <tr>
+ <th scope="row"><a href="http://m304-apple-server.stanford.edu/PrimerDesign" target=_blank>ChIP QC Primer Design</a>
+ <a href="http://m304-apple-server.stanford.edu/ValidationDesign/" target=_blank>ChIP Validation Design</a>
+ </th>
+ <th scope="row"></th>
+ <td></td>
+ <td> </td>
+ <td></td>
+ <td> </td>
+ </tr>
+ <tr>
+ <th scope="row"><a href="http://myers.hudsonalpha.org/content/protocols.html" target=_blank>Protocols - Myers Lab</a></th>
+ <th scope="row"></th>
+ <td></td>
+ <td> </td>
+ <td></td>
+ <td> </td>
+ </tr>
+ <tr>
+ <th scope="row"><a href="https://woldlab.caltech.edu/html/protocols" target=_blank>Protocols - Wold Lab</a></th>
+ <th scope="row"></th>
+ <td></td>
+ <td> </td>
+ <td></td>
+ <td> </td>
+ </tr>
+ <tr>
+ <th scope="row"><a href="http://www.ncbi.nlm.nih.gov/pubmed/18711362" target=_blank>QuEST</a></th>
+ <th scope="row"></th>
+ <td></td>
+ <td> </td>
+ <td></td>
+ <td> </td>
+ </tr>
+ </table>
+ </div>
+</div>
+{% endblock %}
+
+
+{% block sidebar %}
+<div id="content-related">
+ <div class="module" id="recent-actions-module">
+ <h2>{% trans 'Recent Actions' %}</h2>
+ <h3>{% trans 'My Actions' %}</h3>
+ {% load log %}
+ {% get_admin_log 10 as admin_log for_user user %}
+ {% if not admin_log %}
+ <p>{% trans 'None available' %}</p>
+ {% else %}
+ <ul class="actionlist">
+ {% for entry in admin_log %}
+ <li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">{% if not entry.is_deletion %}<a href="{{ entry.get_admin_url }}">{% endif %}{{ entry.object_repr }}{% if not entry.is_deletion %}</a>{% endif %}<br /><span class="mini quiet">{% filter capfirst %}{% trans entry.content_type.name %}{% endfilter %}</span></li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </div>
+</div>
+{% endblock %}
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE }}" xml:lang="{{ LANGUAGE_CODE }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
+<head>
+<title>{% block title %}{% endblock %}</title>
+<link rel="stylesheet" type="text/css" href="{% block stylesheet %}{% load adminmedia %}{% admin_media_prefix %}css/base.css{% endblock %}" />
+{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% admin_media_prefix %}css/rtl.css{% endblock %}" />{% endif %}
+{% block extrastyle %}{% endblock %}
+{% block extrahead %}{% endblock %}
+{% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
+</head>
+{% load i18n %}
+
+<body class="{% if is_popup %}popup {% endif %}{% block bodyclass %}{% endblock %}">
+
+<!-- Container -->
+<div id="container">
+
+ {% if not is_popup %}
+ <!-- Header -->
+ <div id="header">
+ <div id="branding">
+ {% block branding %}{% endblock %}
+ </div>
+ {% if user.is_authenticated and user.is_staff %}
+ <div id="user-tools">{% trans 'Welcome,' %} <strong>{% firstof user.first_name user.username %}</strong>. {% block userlinks %}{% url django-admindocs-docroot as docsroot %}{% if docsroot %}<a href="{{ docsroot }}">{% trans 'Documentation' %}</a> / {% endif %}<a href="{{ root_path }}password_change/">{% trans 'Change password' %}</a> / <a href="{{ root_path }}logout/">{% trans 'Log out' %}</a>{% endblock %}
+ </div>
+ {% endif %}
+ {% block nav-global %}{% endblock %}
+ </div>
+ <!-- END Header -->
+ {% block breadcrumbs %}<div class="breadcrumbs"><a href="/">{% trans 'Home' %}</a>{% if title %} › {{ title }}{% endif %}</div>{% endblock %}
+ {% endif %}
+
+ {% if messages %}
+ <ul class="messagelist">{% for message in messages %}<li>{{ message }}</li>{% endfor %}</ul>
+ {% endif %}
+
+ <!-- Content -->
+ <div id="content" class="{% block coltype %}colM{% endblock %}">
+ {% block pretitle %}{% endblock %}
+ {% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
+ {% block content %}
+ {% block object-tools %}{% endblock %}
+ {{ content }}
+ {% endblock %}
+ {% block sidebar %}{% endblock %}
+ <br class="clear" />
+ </div>
+ <!-- END Content -->
+
+ {% block footer %}<div id="footer"></div>{% endblock %}
+</div>
+<!-- END Container -->
+
+</body>
+</html>
--- /dev/null
+{% extends "admin/base.html" %}
+{% load i18n %}
+
+{% block title %}{{ sitename }}{% endblock %}
+
+{% block branding %}
+<h1 id="site-name">HTS Workflow</h1>
+{% endblock %}
+
+{% block nav-global %}{% endblock %}
--- /dev/null
+{% if run_f %}
+ <ul>
+ RUN FOLDER: <li>{{ run_f.run_folder }}</li>
+ </ul>
+{% else %}
+ <p>Run folder not found.</p>
+{% endif %}
--- /dev/null
+<html><head><title>{{ fc.flowcell_id }} - GA SEQUENCING (SOLEXA) LOG</title>
+<style type="text/css">
+<!--
+TD
+ {
+ color:black;
+ font-size:9pt;
+ font-face:Arial;
+ }
+-->
+</style>
+</head><body>
+{% if fc %}
+<table border="1" cellspacing="1">
+<tr><td colspan=2 nowrap><b>GA SEQUENCING (SOLEXA) LOG</b></td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>Date Run Started</td><td colspan=2>{{ fc.run_date }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>Cluster station used</td><td colspan=2 nowrap>{{ fc.cluster_mac_id }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>GA used</td><td colspan=2 nowrap>{{ fc.seq_mac_id }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+
+<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>Flowcell number</td><td colspan=2 nowrap>{{ fc.flowcell_id }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>Number of Tiles per Lane</td><td>100</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td>Number of Cycles</td><td>{{ fc.read_length }}</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td><font point-size="9" face="Arial"><b>SAMPLE INFORMATION</b><font></td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr>
+<tr><td> </td><td>FC#</td><td> </td><td> </td><td> </td><td> </td><td> </td><td colspan=2 nowrap>FC bar code</td></tr>
+
+<tr><td valign=middle nowrap>Lane</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td></tr>
+<tr><td valign=middle nowrap>Solexa Library Number</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_1_library.library_id }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_2_library.library_id }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_3_library.library_id }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_4_library.library_id }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_5_library.library_id }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_6_library.library_id }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_7_library.library_id }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_8_library.library_id }}</td></tr>
+
+<tr><td valign=middle nowrap>Sample Name</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_1_library.library_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_2_library.library_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_3_library.library_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_4_library.library_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_5_library.library_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_6_library.library_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_7_library.library_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_8_library.library_name }}</td>
+</tr>
+
+<tr><td valign=middle nowrap>Organism</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_1_library.library_species.common_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_2_library.library_species.common_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_3_library.library_species.common_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_4_library.library_species.common_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_5_library.library_species.common_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_6_library.library_species.common_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_7_library.library_species.common_name }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_8_library.library_species.common_name }}</td>
+</tr>
+
+<tr><td valign=middle nowrap>Submitter</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_1_library.made_by }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_2_library.made_by }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_3_library.made_by }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_4_library.made_by }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_5_library.made_by }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_6_library.made_by }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_7_library.made_by }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_8_library.made_by }}</td>
+</tr>
+
+
+<tr><td valign=middle nowrap>First time run?</td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td><td bgcolor=#CCFFCC></td></tr>
+
+<tr><td valign=middle nowrap>Average Library Size (bp)</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_1_library.avg_lib_size }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_2_library.avg_lib_size }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_3_library.avg_lib_size }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_4_library.avg_lib_size }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_5_library.avg_lib_size }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_6_library.avg_lib_size }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_7_library.avg_lib_size }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_8_library.avg_lib_size }}</td>
+</tr>
+
+<tr><td valign=middle nowrap>Template Concentration (ng/ul)</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_1_library.undiluted_concentration }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_2_library.undiluted_concentration }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_3_library.undiluted_concentration }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_4_library.undiluted_concentration }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_5_library.undiluted_concentration }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_6_library.undiluted_concentration }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_7_library.undiluted_concentration }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_8_library.undiluted_concentration }}</td>
+</tr>
+
+<tr><td valign=middle nowrap>Run Concentration (pM)</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_1_pM }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_2_pM }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_3_pM }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_4_pM }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_5_pM }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_6_pM }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_7_pM }}</td>
+<td bgcolor=#CCFFCC>{{ fc.lane_8_pM }}</td>
+</tr>
+
+</table>
+
+{% else %}
+ <p>Flowcell object missing. Can't create sheet.</p>
+{% endif %}
+
+</body></html
--- /dev/null
+{% if data_run_list %}
+ <ul>
+ {% for run in data_run_list %}
+ <li>{{ run.run_folder }}</li>
+ {% endfor %}
+ </ul>
+{% else %}
+ <p>No data runs are available.</p>
+{% endif %}
--- /dev/null
+{% extends "admin/base_site.html" %}
+
+{% if main %}
+{% block content %}
+
+ {{ main|safe }}
+
+{% endblock %}
+{% else %}
+ <p>No content. Can't create report.</p>
+{% endif %}
--- /dev/null
+{% load humanize %}
+<style type="text/css">
+ /* <![CDATA[ */
+ table, td {
+ border-style: solid;
+ }
+ table {
+ border-width: 0 0 1px 1px;
+ border-spacing: 0;
+ border-collapse: collapse;
+ }
+ td {
+ margin: 0;
+ padding: 4px;
+ border-width: 1px 1px 0 0;
+ }
+ thead {
+ text-align: center;
+ }
+ tbody {
+ text-align: right;
+ }
+ /* ]]> */
+</style>
+
+<h2>About this library</h2>
+<b>Library ID</b>: {{ lib.library_id }}<br/>
+<b>Name</b>: {{ lib.library_name }}<br/>
+<b>Species</b>: {{ lib.library_species.scientific_name }}<br/>
+<b>Affiliations</b>:
+<ul>
+ {% for individual in lib.affiliations.all %}
+ <li>{{ individual.name }} ( {{ individual.contact }} )</li>
+ {% endfor %}
+</ul>
+
+<h2>Raw Result Files</h2>
+<table>
+<thead>
+ <tr>
+ <td>Cycle</td>
+ <td>Flowcell</td>
+ <td>Lane</td>
+ <td>Summary</td>
+ <td>Eland</td>
+ <td>Bed</td>
+ </tr>
+{% for result in eland_results %}
+<tr>
+ <td>{{ result.cycle }}</td>
+ <td>{{ result.flowcell_id }}</td>
+ <td>{{ result.lane }}</td>
+ <td><a href="{{ result.summary_url }}">Summary</a></td>
+ <td><a href="{{ result.result_url }}">{{ result.result_label }}</a></td>
+ <td>
+ {% if result.bed_url %}
+ <a href="{{ result.bed_url }}">Bed</a>
+ {% endif %}
+ </td>
+</tr>
+{% endfor %}
+</table>
+
+<h2>Lane Summary Statistics</h2>
+{% block summary_stats %}
+<table>
+ <thead>
+ <tr>
+ <td colspan="7"></td>
+ <td colspan="2">No Match</td>
+ <td colspan="2">QC Failed</td>
+ <td colspan="4">Unique</td>
+ <td colspan="4">Repeat</td>
+ </tr>
+ <tr>
+ <td>Cycles</td>
+ <td>Flowcell</td>
+ <td>Lane</td>
+ <td>End</td>
+ <td>Cluster / Tile</td>
+ <td>pM</td>
+ <td>Raw Reads</td>
+ <td>total</td>
+ <td>%</td>
+ <td>total</td>
+ <td>%</td>
+ <td>0 mismatch</td>
+ <td>1 mismatch</td>
+ <td>2 mismatch</td>
+ <td>Total</td>
+ <td>0 mismatch</td>
+ <td>1 mismatch</td>
+ <td>2 mismatch</td>
+ <td>Total</td>
+ </tr>
+ </thead>
+ <tbody>
+
+ {% for lane in lane_summary_list %}
+ <tr>
+ <td>{{ lane.cycle_width }}</td>
+ <td>{{ lane.flowcell_id }}</td>
+ <td>{{ lane.lane_id }}</td>
+ <td>{% if lane.end %}{{ lane.end }}{% endif %}</td>
+ <td>{{ lane.clusters.0|intcomma }}</td>
+ <td>{{ lane.successful_pm }}</td>
+ <td>{{ lane.reads|intcomma }}</td>
+ <td>{{ lane.no_match|intcomma }}</td>
+ <td>{{ lane.no_match_percent|stringformat:".2f" }}</td>
+ <td>{{ lane.qc_failed|intcomma }}</td>
+ <td>{{ lane.qc_failed_percent|stringformat:".2f" }}</td>
+ <td>{{ lane.match_codes.U0|intcomma }}</td>
+ <td>{{ lane.match_codes.U1|intcomma }}</td>
+ <td>{{ lane.match_codes.U2|intcomma }}</td>
+ <td>{{ lane.unique_reads|intcomma }}</td>
+ <td>{{ lane.match_codes.R0|intcomma }}</td>
+ <td>{{ lane.match_codes.R1|intcomma }}</td>
+ <td>{{ lane.match_codes.R2|intcomma }}</td>
+ <td>{{ lane.repeat_reads|intcomma }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+<br/>
+<hr/>
+<h2>Count of multi-reads</h2>
+{% for lane in lane_summary_list %}
+ {% if lane.summarized_reads %}
+ <h3>
+ {{lane.cycle_width}} {{ lane.flowcell_id }} lane {{ lane.lane_id }}
+ {% if lane.end %} end {{ lane.end }}{% endif %}
+ </h3>
+ <ul>
+ {% for name, counts in lane.summarized_reads.items %}
+ <li><b>{{ name }}</b>: {{ counts|intcomma }}</li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+{% endfor %}
+{% endblock %}
--- /dev/null
+{% extends "base_site.html" %}
+{% load adminmedia admin_list i18n %}
+
+{% block stylesheet %}{{ MEDIA_URL }}css/data-browse-index.css{% endblock %}
+
+{% block bodyclass %}change-list{% endblock %}
+{% block coltype %}flex{% endblock %}
+
+{% block content %}
+<div id="content-main">
+ <div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
+ {% block search %}{% search_form cl %}{% endblock %}
+
+ {% block filters %}
+ {% if cl.has_filters %}
+ <div id="changelist-filter">
+ <h2>{% trans 'Filter' %}</h2>
+ {% for spec in cl.filter_specs %}
+ {% admin_list_filter cl spec %}
+ {% endfor %}
+ </div>
+ {% endif %}
+ {% endblock %}
+
+
+ {% block pagination %}{% pagination cl %}{% endblock %}
+
+{% block summary_stats %}
+<table>
+ <thead>
+ <tr>
+ <td>Parent</td>
+ <td>Library ID</td>
+ <td>Species</td>
+ <td>Library Name</td>
+ <td>Total Lanes</td>
+ <td>HD</td>
+ </tr>
+ </thead>
+ <tbody>
+ {% for lib in library_list %}
+ <tr>
+ <td><a href="/library/{{ lib.library_id }}">{{ lib.amplified_from }}</a></td>
+ <td><a href="/library/{{ lib.library_id }}">{{ lib.library_id }}</a></td>
+ <td><a href="/library/{{ lib.library_id }}">{{ lib.species_name }}</a></td>
+ <td><a href="/library/{{ lib.library_id }}">{{ lib.library_name }}</a></td>
+ <td>{{ lib.lanes_run }}</td>
+ {% if lib.is_archived %}
+ <td><img src="/static/img/hdd_unmount.png" alt="Archived" /></td>
+ {% else %}
+ <td></td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+</div>
+{% endblock %}
+{% endblock %}
--- /dev/null
+{% load adminmedia %}
+{% load i18n %}
+{% if cl.search_fields %}
+<div id="toolbar"><form id="changelist-search" action="" method="get">
+<div><!-- DIV needed for valid HTML -->
+<label for="searchbar"><img src="{% admin_media_prefix %}img/admin/icon_searchbox.png" alt="Search" /></label>
+<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar" />
+<input type="submit" value="{% trans 'Go' %}" />
+{% if show_result_count %}
+ <span class="small quiet">{% blocktrans count cl.result_count as counter %}1 result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?{% if cl.is_popup %}pop=1{% endif %}">{% blocktrans with cl.full_result_count as full_result_count %}{{ full_result_count }} total{% endblocktrans %}</a>)</span>
+{% endif %}
+{% for pair in cl.params.items %}
+ {% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0 }}" value="{{ pair.1 }}"/>{% endifnotequal %}
+{% endfor %}
+</div>
+</form></div>
+<script type="text/javascript">document.getElementById("searchbar").focus();</script>
+{% endif %}
--- /dev/null
+from django.conf.urls.defaults import *
+from django.contrib import admin
+admin.autodiscover()
+
+# Databrowser:
+#from django.contrib import databrowse
+#from htsworkflow.frontend.samples.models import Library
+#databrowse.site.register(Library)
+#databrowse.site.register(FlowCell)
+
+from htsworkflow.frontend import settings
+
+urlpatterns = patterns('',
+ # Base:
+ (r'^eland_config/', include('htsworkflow.frontend.eland_config.urls')),
+ # Admin:
+ (r'^admin/(.*)', admin.site.root),
+ # Experiments:
+ (r'^experiments/', include('htsworkflow.frontend.experiments.urls')),
+ # AnalysTrack:
+ #(r'^analysis/', include('htsworkflow.frontend.analysis.urls')),
+ # Report Views:
+ (r'^inventory/', include('htsworkflow.frontend.inventory.urls')),
+ (r'^reports/', include('htsworkflow.frontend.reports.urls')),
+ # Library browser
+ (r'^library/$', 'htsworkflow.frontend.samples.views.library'),
+ (r'^library/(?P<lib_id>\w+)/$',
+ 'htsworkflow.frontend.samples.views.library_to_flowcells'),
+ # library id to admin url
+ (r'^library_id_to_admin_url/(?P<lib_id>\w+)/$',
+ 'htsworkflow.frontend.samples.views.library_id_to_admin_url'),
+ # Raw result files
+ (r'^results/(?P<fc_id>\w+)/(?P<cnm>C[1-9]-[0-9]+)/summary/',
+ 'htsworkflow.frontend.samples.views.summaryhtm_fc_cnm'),
+ (r'^results/(?P<fc_id>\w+)/(?P<cnm>C[1-9]-[0-9]+)/eland_result/(?P<lane>[1-8])',
+ 'htsworkflow.frontend.samples.views.result_fc_cnm_eland_lane'),
+ (r'^results/(?P<fc_id>\w+)/(?P<cnm>C[1-9]-[0-9]+)/bedfile/(?P<lane>[1-8])/ucsc',
+ 'htsworkflow.frontend.samples.views.bedfile_fc_cnm_eland_lane_ucsc'),
+ (r'^results/(?P<fc_id>\w+)/(?P<cnm>C[1-9]-[0-9]+)/bedfile/(?P<lane>[1-8])',
+ 'htsworkflow.frontend.samples.views.bedfile_fc_cnm_eland_lane'),
+
+ # databrowser
+ #(r'^databrowse/(.*)', databrowse.site.root)
+)
+
+if settings.DEBUG:
+ urlpatterns += patterns('',
+ (r'^static/(?P<path>.*)$', 'django.views.static.serve',
+ {'document_root': settings.MEDIA_ROOT}),
+ )
--- /dev/null
+"""
+Provide code to interact with the vendor tools to produce useable "raw" data.
+
+the illumina sub-package contains components to interact with the Illumina provided
+GAPipeline
+"""
--- /dev/null
+"""
+Extract configuration from Illumina Bustard Directory.
+
+This includes the version number, run date, bustard executable parameters, and
+phasing estimates.
+"""
+from copy import copy
+from datetime import date
+from glob import glob
+import logging
+import os
+import re
+import sys
+import time
+
+from htsworkflow.pipelines.runfolder import \
+ ElementTree, \
+ VERSION_RE, \
+ EUROPEAN_STRPTIME
+
+# make epydoc happy
+__docformat__ = "restructuredtext en"
+
+LANE_LIST = range(1,9)
+
+class Phasing(object):
+ PHASING = 'Phasing'
+ PREPHASING = 'Prephasing'
+
+ def __init__(self, fromfile=None, xml=None):
+ self.lane = None
+ self.phasing = None
+ self.prephasing = None
+
+ if fromfile is not None:
+ self._initialize_from_file(fromfile)
+ elif xml is not None:
+ self.set_elements(xml)
+
+ def _initialize_from_file(self, pathname):
+ path, name = os.path.split(pathname)
+ basename, ext = os.path.splitext(name)
+ # the last character of the param base filename should be the
+ # lane number
+ tree = ElementTree.parse(pathname).getroot()
+ self.set_elements(tree)
+ self.lane = int(basename[-1])
+
+ def get_elements(self):
+ root = ElementTree.Element(Phasing.PHASING, {'lane': str(self.lane)})
+ root.tail = os.linesep
+ phasing = ElementTree.SubElement(root, Phasing.PHASING)
+ phasing.text = str(self.phasing)
+ phasing.tail = os.linesep
+ prephasing = ElementTree.SubElement(root, Phasing.PREPHASING)
+ prephasing.text = str(self.prephasing)
+ prephasing.tail = os.linesep
+ return root
+
+ def set_elements(self, tree):
+ if tree.tag not in ('Phasing', 'Parameters'):
+ raise ValueError('exptected Phasing or Parameters')
+ lane = tree.attrib.get('lane', None)
+ if lane is not None:
+ self.lane = int(lane)
+ for element in list(tree):
+ if element.tag == Phasing.PHASING:
+ self.phasing = float(element.text)
+ elif element.tag == Phasing.PREPHASING:
+ self.prephasing = float(element.text)
+
+class CrosstalkMatrix(object):
+ CROSSTALK = "MatrixElements"
+ BASE = 'Base'
+ ELEMENT = 'Element'
+
+ def __init__(self, fromfile=None, xml=None):
+ self.base = {}
+
+ if fromfile is not None:
+ self._initialize_from_file(fromfile)
+ elif xml is not None:
+ self.set_elements(xml)
+
+ def _initialize_from_file(self, pathname):
+ data = open(pathname).readlines()
+ auto_header = '# Auto-generated frequency response matrix'
+ if data[0].strip() != auto_header or len(data) != 9:
+ raise RuntimeError("matrix file %s is unusual" % (pathname,))
+ # skip over lines 1,2,3,4 which contain the 4 bases
+ self.base['A'] = [ float(v) for v in data[5].split() ]
+ self.base['C'] = [ float(v) for v in data[6].split() ]
+ self.base['G'] = [ float(v) for v in data[7].split() ]
+ self.base['T'] = [ float(v) for v in data[8].split() ]
+
+ def get_elements(self):
+ root = ElementTree.Element(CrosstalkMatrix.CROSSTALK)
+ root.tail = os.linesep
+ base_order = ['A','C','G','T']
+ for b in base_order:
+ base_element = ElementTree.SubElement(root, CrosstalkMatrix.BASE)
+ base_element.text = b
+ base_element.tail = os.linesep
+ for b in base_order:
+ for value in self.base[b]:
+ crosstalk_value = ElementTree.SubElement(root, CrosstalkMatrix.ELEMENT)
+ crosstalk_value.text = unicode(value)
+ crosstalk_value.tail = os.linesep
+
+ return root
+
+ def set_elements(self, tree):
+ if tree.tag != CrosstalkMatrix.CROSSTALK:
+ raise ValueError('Invalid run-xml exptected '+CrosstalkMatrix.CROSSTALK)
+ base_order = []
+ current_base = None
+ current_index = 0
+ for element in tree.getchildren():
+ # read in the order of the bases
+ if element.tag == 'Base':
+ base_order.append(element.text)
+ elif element.tag == 'Element':
+ # we're done reading bases, now its just the 4x4 matrix
+ # written out as a list of elements
+ # if this is the first element, make a copy of the list
+ # to play with and initialize an empty list for the current base
+ if current_base is None:
+ current_base = copy(base_order)
+ self.base[current_base[0]] = []
+ # we found (probably) 4 bases go to the next base
+ if current_index == len(base_order):
+ current_base.pop(0)
+ current_index = 0
+ self.base[current_base[0]] = []
+ value = float(element.text)
+ self.base[current_base[0]].append(value)
+
+ current_index += 1
+ else:
+ raise RuntimeError("Unrecognized tag in run xml: %s" %(element.tag,))
+
+def crosstalk_matrix_from_bustard_config(bustard_path, bustard_config_tree):
+ """
+ Analyze the bustard config file and try to find the crosstalk matrix.
+ """
+ bustard_run = bustard_config_tree[0]
+ if bustard_run.tag != 'Run':
+ raise RuntimeError('Expected Run tag, got %s' % (bustard_run.tag,))
+
+ call_parameters = bustard_run.find('BaseCallParameters')
+ if call_parameters is None:
+ raise RuntimeError('Missing BaseCallParameters section')
+
+ matrix = call_parameters.find('Matrix')
+ if matrix is None:
+ raise RuntimeError('Expected to find Matrix in Bustard BaseCallParameters')
+
+ matrix_auto_flag = int(matrix.find('AutoFlag').text)
+ matrix_auto_lane = int(matrix.find('AutoLane').text)
+
+ if matrix_auto_flag:
+ # we estimated the matrix from something in this run.
+ # though we don't really care which lane it was
+ matrix_path = os.path.join(bustard_path, 'Matrix', 's_02_matrix.txt')
+ matrix = CrosstalkMatrix(matrix_path)
+ else:
+ # the matrix was provided
+ matrix_elements = call_parameters.find('MatrixElements')
+ if matrix_elements is None:
+ raise RuntimeError('Expected to find MatrixElements in Bustard BaseCallParameters')
+ matrix = CrosstalkMatrix(xml=matrix_elements)
+
+ return matrix
+
+class Bustard(object):
+ XML_VERSION = 2
+
+ # Xml Tags
+ BUSTARD = 'Bustard'
+ SOFTWARE_VERSION = 'version'
+ DATE = 'run_time'
+ USER = 'user'
+ PARAMETERS = 'Parameters'
+ BUSTARD_CONFIG = 'BaseCallAnalysis'
+
+ def __init__(self, xml=None):
+ self.version = None
+ self.date = date.today()
+ self.user = None
+ self.phasing = {}
+ self.crosstalk = None
+ self.pathname = None
+ self.bustard_config = None
+
+ if xml is not None:
+ self.set_elements(xml)
+
+ def _get_time(self):
+ return time.mktime(self.date.timetuple())
+ time = property(_get_time, doc='return run time as seconds since epoch')
+
+ def dump(self):
+ #print ElementTree.tostring(self.get_elements())
+ ElementTree.dump(self.get_elements())
+
+ def get_elements(self):
+ root = ElementTree.Element('Bustard',
+ {'version': str(Bustard.XML_VERSION)})
+ version = ElementTree.SubElement(root, Bustard.SOFTWARE_VERSION)
+ version.text = self.version
+ run_date = ElementTree.SubElement(root, Bustard.DATE)
+ run_date.text = str(self.time)
+ user = ElementTree.SubElement(root, Bustard.USER)
+ user.text = self.user
+ params = ElementTree.SubElement(root, Bustard.PARAMETERS)
+
+ # add phasing parameters
+ for lane in LANE_LIST:
+ params.append(self.phasing[lane].get_elements())
+
+ # add crosstalk matrix if it exists
+ if self.crosstalk is not None:
+ root.append(self.crosstalk.get_elements())
+
+ # add bustard config if it exists
+ if self.bustard_config is not None:
+ root.append(self.bustard_config)
+ return root
+
+ def set_elements(self, tree):
+ if tree.tag != Bustard.BUSTARD:
+ raise ValueError('Expected "Bustard" SubElements')
+ xml_version = int(tree.attrib.get('version', 0))
+ if xml_version > Bustard.XML_VERSION:
+ logging.warn('Bustard XML tree is a higher version than this class')
+ for element in list(tree):
+ if element.tag == Bustard.SOFTWARE_VERSION:
+ self.version = element.text
+ elif element.tag == Bustard.DATE:
+ self.date = date.fromtimestamp(float(element.text))
+ elif element.tag == Bustard.USER:
+ self.user = element.text
+ elif element.tag == Bustard.PARAMETERS:
+ for param in element:
+ p = Phasing(xml=param)
+ self.phasing[p.lane] = p
+ elif element.tag == CrosstalkMatrix.CROSSTALK:
+ self.crosstalk = CrosstalkMatrix(xml=element)
+ elif element.tag == Bustard.BUSTARD_CONFIG:
+ self.bustard_config = element
+ else:
+ raise ValueError("Unrecognized tag: %s" % (element.tag,))
+
+def bustard(pathname):
+ """
+ Construct a Bustard object by analyzing an Illumina Bustard directory.
+
+ :Parameters:
+ - `pathname`: A bustard directory
+
+ :Return:
+ Fully initialized Bustard object.
+ """
+ b = Bustard()
+ pathname = os.path.abspath(pathname)
+ path, name = os.path.split(pathname)
+ groups = name.split("_")
+ version = re.search(VERSION_RE, groups[0])
+ b.version = version.group(1)
+ t = time.strptime(groups[1], EUROPEAN_STRPTIME)
+ b.date = date(*t[0:3])
+ b.user = groups[2]
+ b.pathname = pathname
+ bustard_config_filename = os.path.join(pathname, 'config.xml')
+ paramfiles = glob(os.path.join(pathname, "params?.xml"))
+ for paramfile in paramfiles:
+ phasing = Phasing(paramfile)
+ assert (phasing.lane >= 1 and phasing.lane <= 8)
+ b.phasing[phasing.lane] = phasing
+ # I only found these in Bustard1.9.5/1.9.6 directories
+ if b.version in ('1.9.5', '1.9.6'):
+ # at least for our runfolders for 1.9.5 and 1.9.6 matrix[1-8].txt are always the same
+ crosstalk_file = os.path.join(pathname, "matrix1.txt")
+ b.crosstalk = CrosstalkMatrix(crosstalk_file)
+ # for version 1.3.2 of the pipeline the bustard version number went down
+ # to match the rest of the pipeline. However there's now a nifty
+ # new (useful) bustard config file.
+ elif os.path.exists(bustard_config_filename):
+ bustard_config_root = ElementTree.parse(bustard_config_filename)
+ b.bustard_config = bustard_config_root.getroot()
+ b.crosstalk = crosstalk_matrix_from_bustard_config(b.pathname, b.bustard_config)
+
+ return b
+
+def fromxml(tree):
+ """
+ Reconstruct a htsworkflow.pipelines.Bustard object from an xml block
+ """
+ b = Bustard()
+ b.set_elements(tree)
+ return b
+
+def make_cmdline_parser():
+ from optparse import OptionParser
+ parser = OptionParser('%prog: bustard_directory')
+ return parser
+
+def main(cmdline):
+ parser = make_cmdline_parser()
+ opts, args = parser.parse_args(cmdline)
+
+ for bustard_dir in args:
+ print u'analyzing bustard directory: ' + unicode(bustard_dir)
+ bustard_object = bustard(bustard_dir)
+ bustard_object.dump()
+
+ bustard_object2 = Bustard(xml=bustard_object.get_elements())
+ print ('-------------------------------------')
+ bustard_object2.dump()
+ print ('=====================================')
+ b1_tree = bustard_object.get_elements()
+ b1 = ElementTree.tostring(b1_tree).split(os.linesep)
+ b2_tree = bustard_object2.get_elements()
+ b2 = ElementTree.tostring(b2_tree).split(os.linesep)
+ for line1, line2 in zip(b1, b2):
+ if b1 != b2:
+ print "b1: ", b1
+ print "b2: ", b2
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
--- /dev/null
+#!/usr/bin/python
+__docformat__ = "restructuredtext en"
+
+import subprocess
+import logging
+import time
+import re
+import os
+
+from htsworkflow.pipelines.retrieve_config import \
+ CONFIG_SYSTEM, CONFIG_USER, \
+ FlowCellNotFound, getCombinedOptions, saveConfigFile, WebError404
+from htsworkflow.pipelines.genome_mapper import DuplicateGenome, getAvailableGenomes, constructMapperDict
+from htsworkflow.pipelines.run_status import GARunStatus
+
+from pyinotify import WatchManager, ThreadedNotifier
+from pyinotify import EventsCodes, ProcessEvent
+
+class ConfigInfo:
+
+ def __init__(self):
+ #run_path = firecrest analysis directory to run analysis from
+ self.run_path = None
+ self.bustard_path = None
+ self.config_filepath = None
+ self.status = None
+
+ #top level directory where all analyses are placed
+ self.base_analysis_dir = None
+ #analysis_dir, top level analysis dir...
+ # base_analysis_dir + '/070924_USI-EAS44_0022_FC12150'
+ self.analysis_dir = None
+
+
+ def createStatusObject(self):
+ """
+ Creates a status object which can be queried for
+ status of running the pipeline
+
+ returns True if object created
+ returns False if object cannot be created
+ """
+ if self.config_filepath is None:
+ return False
+
+ self.status = GARunStatus(self.config_filepath)
+ return True
+
+
+
+####################################
+# inotify event processor
+
+s_firecrest_finished = re.compile('Firecrest[0-9\._\-A-Za-z]+/finished.txt')
+s_bustard_finished = re.compile('Bustard[0-9\._\-A-Za-z]+/finished.txt')
+s_gerald_finished = re.compile('GERALD[0-9\._\-A-Za-z]+/finished.txt')
+
+s_gerald_all = re.compile('Firecrest[0-9\._\-A-Za-z]+/Bustard[0-9\._\-A-Za-z]+/GERALD[0-9\._\-A-Za-z]+/')
+s_bustard_all = re.compile('Firecrest[0-9\._\-A-Za-z]+/Bustard[0-9\._\-A-Za-z]+/')
+s_firecrest_all = re.compile('Firecrest[0-9\._\-A-Za-z]+/')
+
+class RunEvent(ProcessEvent):
+
+ def __init__(self, conf_info):
+
+ self.run_status_dict = {'firecrest': False,
+ 'bustard': False,
+ 'gerald': False}
+
+ self._ci = conf_info
+
+ ProcessEvent.__init__(self)
+
+
+ def process_IN_CREATE(self, event):
+ fullpath = os.path.join(event.path, event.name)
+ if s_finished.search(fullpath):
+ logging.info("File Found: %s" % (fullpath))
+
+ if s_firecrest_finished.search(fullpath):
+ self.run_status_dict['firecrest'] = True
+ self._ci.status.updateFirecrest(event.name)
+ elif s_bustard_finished.search(fullpath):
+ self.run_status_dict['bustard'] = True
+ self._ci.status.updateBustard(event.name)
+ elif s_gerald_finished.search(fullpath):
+ self.run_status_dict['gerald'] = True
+ self._ci.status.updateGerald(event.name)
+
+ #WARNING: The following order is important!!
+ # Firecrest regex will catch all gerald, bustard, and firecrest
+ # Bustard regex will catch all gerald and bustard
+ # Gerald regex will catch all gerald
+ # So, order needs to be Gerald, Bustard, Firecrest, or this
+ # won't work properly.
+ elif s_gerald_all.search(fullpath):
+ self._ci.status.updateGerald(event.name)
+ elif s_bustard_all.search(fullpath):
+ self._ci.status.updateBustard(event.name)
+ elif s_firecrest_all.search(fullpath):
+ self._ci.status.updateFirecrest(event.name)
+
+ #print "Create: %s" % (os.path.join(event.path, event.name))
+
+ def process_IN_DELETE(self, event):
+ #print "Remove %s" % (os.path.join(event.path, event.name))
+ pass
+
+
+
+
+#FLAGS
+# Config Step Error
+RUN_ABORT = 'abort'
+# Run Step Error
+RUN_FAILED = 'failed'
+
+
+#####################################
+# Configure Step (goat_pipeline.py)
+#Info
+s_start = re.compile('Starting Genome Analyzer Pipeline')
+s_gerald = re.compile("[\S\s]+--GERALD[\S\s]+--make[\S\s]+")
+s_generating = re.compile('^Generating journals, Makefiles')
+s_seq_folder = re.compile('^Sequence folder: ')
+s_seq_folder_sub = re.compile('want to make ')
+s_stderr_taskcomplete = re.compile('^Task complete, exiting')
+
+#Errors
+s_invalid_cmdline = re.compile('Usage:[\S\s]*goat_pipeline.py')
+s_species_dir_err = re.compile('Error: Lane [1-8]:')
+s_goat_traceb = re.compile("^Traceback \(most recent call last\):")
+s_missing_cycles = re.compile('^Error: Tile s_[1-8]_[0-9]+: Different number of cycles: [0-9]+ instead of [0-9]+')
+
+SUPPRESS_MISSING_CYCLES = False
+
+
+##Ignore - Example of out above each ignore regex.
+#NOTE: Commenting out an ignore will cause it to be
+# logged as DEBUG with the logging module.
+#CF_STDERR_IGNORE_LIST = []
+s_skip = re.compile('s_[0-8]_[0-9]+')
+
+
+##########################################
+# Pipeline Run Step (make -j8 recursive)
+
+##Info
+s_finished = re.compile('finished')
+
+##Errors
+s_make_error = re.compile('^make[\S\s]+Error')
+s_no_gnuplot = re.compile('gnuplot: command not found')
+s_no_convert = re.compile('^Can\'t exec "convert"')
+s_no_ghostscript = re.compile('gs: command not found')
+
+##Ignore - Example of out above each ignore regex.
+#NOTE: Commenting out an ignore will cause it to be
+# logged as DEBUG with the logging module.
+#
+PL_STDERR_IGNORE_LIST = []
+# Info: PF 11802
+PL_STDERR_IGNORE_LIST.append( re.compile('^Info: PF') )
+# About to analyse intensity file s_4_0101_sig2.txt
+PL_STDERR_IGNORE_LIST.append( re.compile('^About to analyse intensity file') )
+# Will send output to standard output
+PL_STDERR_IGNORE_LIST.append( re.compile('^Will send output to standard output') )
+# Found 31877 clusters
+PL_STDERR_IGNORE_LIST.append( re.compile('^Found [0-9]+ clusters') )
+# Will use quality criterion ((CHASTITY>=0.6)
+PL_STDERR_IGNORE_LIST.append( re.compile('^Will use quality criterion') )
+# Quality criterion translated to (($F[5]>=0.6))
+PL_STDERR_IGNORE_LIST.append( re.compile('^Quality criterion translated to') )
+# opened /woldlab/trog/data1/king/070924_USI-EAS44_0022_FC12150/Data/C1-36_Firecrest1.9.1_14-11-2007_king.4/Bustard1.9.1_14-11-2007_king/s_4_0101_qhg.txt
+# AND
+# opened s_4_0103_qhg.txt
+PL_STDERR_IGNORE_LIST.append( re.compile('^opened[\S\s]+qhg.txt') )
+# 81129 sequences out of 157651 passed filter criteria
+PL_STDERR_IGNORE_LIST.append( re.compile('^[0-9]+ sequences out of [0-9]+ passed filter criteria') )
+
+
+def pl_stderr_ignore(line):
+ """
+ Searches lines for lines to ignore (i.e. not to log)
+
+ returns True if line should be ignored
+ returns False if line should NOT be ignored
+ """
+ for s in PL_STDERR_IGNORE_LIST:
+ if s.search(line):
+ return True
+ return False
+
+
+def config_stdout_handler(line, conf_info):
+ """
+ Processes each line of output from GOAT
+ and stores useful information using the logging module
+
+ Loads useful information into conf_info as well, for future
+ use outside the function.
+
+ returns True if found condition that signifies success.
+ """
+
+ # Skip irrelevant line (without logging)
+ if s_skip.search(line):
+ pass
+
+ # Detect invalid command-line arguments
+ elif s_invalid_cmdline.search(line):
+ logging.error("Invalid commandline options!")
+
+ # Detect starting of configuration
+ elif s_start.search(line):
+ logging.info('START: Configuring pipeline')
+
+ # Detect it made it past invalid arguments
+ elif s_gerald.search(line):
+ logging.info('Running make now')
+
+ # Detect that make files have been generated (based on output)
+ elif s_generating.search(line):
+ logging.info('Make files generted')
+ return True
+
+ # Capture run directory
+ elif s_seq_folder.search(line):
+ mo = s_seq_folder_sub.search(line)
+ #Output changed when using --tiles=<tiles>
+ # at least in pipeline v0.3.0b2
+ if mo:
+ firecrest_bustard_gerald_makefile = line[mo.end():]
+ firecrest_bustard_gerald, junk = \
+ os.path.split(firecrest_bustard_gerald_makefile)
+ firecrest_bustard, junk = os.path.split(firecrest_bustard_gerald)
+ firecrest, junk = os.path.split(firecrest_bustard)
+
+ conf_info.bustard_path = firecrest_bustard
+ conf_info.run_path = firecrest
+
+ #Standard output handling
+ else:
+ print 'Sequence line:', line
+ mo = s_seq_folder.search(line)
+ conf_info.bustard_path = line[mo.end():]
+ conf_info.run_path, temp = os.path.split(conf_info.bustard_path)
+
+ # Log all other output for debugging purposes
+ else:
+ logging.warning('CONF:?: %s' % (line))
+
+ return False
+
+
+
+def config_stderr_handler(line, conf_info):
+ """
+ Processes each line of output from GOAT
+ and stores useful information using the logging module
+
+ Loads useful information into conf_info as well, for future
+ use outside the function.
+
+ returns RUN_ABORT upon detecting failure;
+ True on success message;
+ False if neutral message
+ (i.e. doesn't signify failure or success)
+ """
+ global SUPPRESS_MISSING_CYCLES
+
+ # Detect invalid species directory error
+ if s_species_dir_err.search(line):
+ logging.error(line)
+ return RUN_ABORT
+ # Detect goat_pipeline.py traceback
+ elif s_goat_traceb.search(line):
+ logging.error("Goat config script died, traceback in debug output")
+ return RUN_ABORT
+ # Detect indication of successful configuration (from stderr; odd, but ok)
+ elif s_stderr_taskcomplete.search(line):
+ logging.info('Configure step successful (from: stderr)')
+ return True
+ # Detect missing cycles
+ elif s_missing_cycles.search(line):
+
+ # Only display error once
+ if not SUPPRESS_MISSING_CYCLES:
+ logging.error("Missing cycles detected; Not all cycles copied?")
+ logging.debug("CONF:STDERR:MISSING_CYCLES: %s" % (line))
+ SUPPRESS_MISSING_CYCLES = True
+ return RUN_ABORT
+
+ # Log all other output as debug output
+ else:
+ logging.debug('CONF:STDERR:?: %s' % (line))
+
+ # Neutral (not failure; nor success)
+ return False
+
+
+#def pipeline_stdout_handler(line, conf_info):
+# """
+# Processes each line of output from running the pipeline
+# and stores useful information using the logging module
+#
+# Loads useful information into conf_info as well, for future
+# use outside the function.
+#
+# returns True if found condition that signifies success.
+# """
+#
+# #f.write(line + '\n')
+#
+# return True
+
+
+
+def pipeline_stderr_handler(line, conf_info):
+ """
+ Processes each line of stderr from pipelien run
+ and stores useful information using the logging module
+
+ ##FIXME: Future feature (doesn't actually do this yet)
+ #Loads useful information into conf_info as well, for future
+ #use outside the function.
+
+ returns RUN_FAILED upon detecting failure;
+ #True on success message; (no clear success state)
+ False if neutral message
+ (i.e. doesn't signify failure or success)
+ """
+
+ if pl_stderr_ignore(line):
+ pass
+ elif s_make_error.search(line):
+ logging.error("make error detected; run failed")
+ return RUN_FAILED
+ elif s_no_gnuplot.search(line):
+ logging.error("gnuplot not found")
+ return RUN_FAILED
+ elif s_no_convert.search(line):
+ logging.error("imagemagick's convert command not found")
+ return RUN_FAILED
+ elif s_no_ghostscript.search(line):
+ logging.error("ghostscript not found")
+ return RUN_FAILED
+ else:
+ logging.debug('PIPE:STDERR:?: %s' % (line))
+
+ return False
+
+
+def retrieve_config(conf_info, flowcell, cfg_filepath, genome_dir):
+ """
+ Gets the config file from server...
+ requires config file in:
+ /etc/ga_frontend/ga_frontend.conf
+ or
+ ~/.ga_frontend.conf
+
+ with:
+ [config_file_server]
+ base_host_url: http://host:port
+
+ return True if successful, False is failure
+ """
+ options = getCombinedOptions()
+
+ if options.url is None:
+ logging.error("%s or %s missing base_host_url option" % \
+ (CONFIG_USER, CONFIG_SYSTEM))
+ return False
+
+ try:
+ saveConfigFile(flowcell, options.url, cfg_filepath)
+ conf_info.config_filepath = cfg_filepath
+ except FlowCellNotFound, e:
+ logging.error(e)
+ return False
+ except WebError404, e:
+ logging.error(e)
+ return False
+ except IOError, e:
+ logging.error(e)
+ return False
+ except Exception, e:
+ logging.error(e)
+ return False
+
+ f = open(cfg_filepath, 'r')
+ data = f.read()
+ f.close()
+
+ genome_dict = getAvailableGenomes(genome_dir)
+ mapper_dict = constructMapperDict(genome_dict)
+
+ logging.debug(data)
+
+ f = open(cfg_filepath, 'w')
+ f.write(data % (mapper_dict))
+ f.close()
+
+ return True
+
+
+
+def configure(conf_info):
+ """
+ Attempts to configure the GA pipeline using goat.
+
+ Uses logging module to store information about status.
+
+ returns True if configuration successful, otherwise False.
+ """
+ #ERROR Test:
+ #pipe = subprocess.Popen(['goat_pipeline.py',
+ # '--GERALD=config32bk.txt',
+ # '--make .',],
+ # #'.'],
+ # stdout=subprocess.PIPE,
+ # stderr=subprocess.PIPE)
+
+ #ERROR Test (2), causes goat_pipeline.py traceback
+ #pipe = subprocess.Popen(['goat_pipeline.py',
+ # '--GERALD=%s' % (conf_info.config_filepath),
+ # '--tiles=s_4_100,s_4_101,s_4_102,s_4_103,s_4_104',
+ # '--make',
+ # '.'],
+ # stdout=subprocess.PIPE,
+ # stderr=subprocess.PIPE)
+
+ ##########################
+ # Run configuration step
+ # Not a test; actual configure attempt.
+ #pipe = subprocess.Popen(['goat_pipeline.py',
+ # '--GERALD=%s' % (conf_info.config_filepath),
+ # '--make',
+ # '.'],
+ # stdout=subprocess.PIPE,
+ # stderr=subprocess.PIPE)
+
+
+ stdout_filepath = os.path.join(conf_info.analysis_dir,
+ "pipeline_configure_stdout.txt")
+ stderr_filepath = os.path.join(conf_info.analysis_dir,
+ "pipeline_configure_stderr.txt")
+
+ fout = open(stdout_filepath, 'w')
+ ferr = open(stderr_filepath, 'w')
+
+ pipe = subprocess.Popen(['goat_pipeline.py',
+ '--GERALD=%s' % (conf_info.config_filepath),
+ '--make',
+ conf_info.analysis_dir],
+ stdout=fout,
+ stderr=ferr)
+
+ print "Configuring pipeline: %s" % (time.ctime())
+ error_code = pipe.wait()
+
+ # Clean up
+ fout.close()
+ ferr.close()
+
+
+ ##################
+ # Process stdout
+ fout = open(stdout_filepath, 'r')
+
+ stdout_line = fout.readline()
+
+ complete = False
+ while stdout_line != '':
+ # Handle stdout
+ if config_stdout_handler(stdout_line, conf_info):
+ complete = True
+ stdout_line = fout.readline()
+
+ fout.close()
+
+
+ #error_code = pipe.wait()
+ if error_code:
+ logging.error('Recieved error_code: %s' % (error_code))
+ else:
+ logging.info('We are go for launch!')
+
+ #Process stderr
+ ferr = open(stderr_filepath, 'r')
+ stderr_line = ferr.readline()
+
+ abort = 'NO!'
+ stderr_success = False
+ while stderr_line != '':
+ stderr_status = config_stderr_handler(stderr_line, conf_info)
+ if stderr_status == RUN_ABORT:
+ abort = RUN_ABORT
+ elif stderr_status is True:
+ stderr_success = True
+ stderr_line = ferr.readline()
+
+ ferr.close()
+
+
+ #Success requirements:
+ # 1) The stdout completed without error
+ # 2) The program exited with status 0
+ # 3) No errors found in stdout
+ print '#Expect: True, False, True, True'
+ print complete, bool(error_code), abort != RUN_ABORT, stderr_success is True
+ status = complete is True and \
+ bool(error_code) is False and \
+ abort != RUN_ABORT and \
+ stderr_success is True
+
+ # If everything was successful, but for some reason
+ # we didn't retrieve the path info, log it.
+ if status is True:
+ if conf_info.bustard_path is None or conf_info.run_path is None:
+ logging.error("Failed to retrieve run_path")
+ return False
+
+ return status
+
+
+def run_pipeline(conf_info):
+ """
+ Run the pipeline and monitor status.
+ """
+ # Fail if the run_path doesn't actually exist
+ if not os.path.exists(conf_info.run_path):
+ logging.error('Run path does not exist: %s' \
+ % (conf_info.run_path))
+ return False
+
+ # Change cwd to run_path
+ stdout_filepath = os.path.join(conf_info.analysis_dir, 'pipeline_run_stdout.txt')
+ stderr_filepath = os.path.join(conf_info.analysis_dir, 'pipeline_run_stderr.txt')
+
+ # Create status object
+ conf_info.createStatusObject()
+
+ # Monitor file creation
+ wm = WatchManager()
+ mask = EventsCodes.IN_DELETE | EventsCodes.IN_CREATE
+ event = RunEvent(conf_info)
+ notifier = ThreadedNotifier(wm, event)
+ notifier.start()
+ wdd = wm.add_watch(conf_info.run_path, mask, rec=True)
+
+ # Log pipeline starting
+ logging.info('STARTING PIPELINE @ %s' % (time.ctime()))
+
+ # Start the pipeline (and hide!)
+ #pipe = subprocess.Popen(['make',
+ # '-j8',
+ # 'recursive'],
+ # stdout=subprocess.PIPE,
+ # stderr=subprocess.PIPE)
+
+ fout = open(stdout_filepath, 'w')
+ ferr = open(stderr_filepath, 'w')
+
+ pipe = subprocess.Popen(['make',
+ '--directory=%s' % (conf_info.run_path),
+ '-j8',
+ 'recursive'],
+ stdout=fout,
+ stderr=ferr)
+ #shell=True)
+ # Wait for run to finish
+ retcode = pipe.wait()
+
+
+ # Clean up
+ notifier.stop()
+ fout.close()
+ ferr.close()
+
+ # Process stderr
+ ferr = open(stderr_filepath, 'r')
+
+ run_failed_stderr = False
+ for line in ferr:
+ err_status = pipeline_stderr_handler(line, conf_info)
+ if err_status == RUN_FAILED:
+ run_failed_stderr = True
+
+ ferr.close()
+
+ # Finished file check!
+ print 'RUN SUCCESS CHECK:'
+ for key, value in event.run_status_dict.items():
+ print ' %s: %s' % (key, value)
+
+ dstatus = event.run_status_dict
+
+ # Success or failure check
+ status = (retcode == 0) and \
+ run_failed_stderr is False and \
+ dstatus['firecrest'] is True and \
+ dstatus['bustard'] is True and \
+ dstatus['gerald'] is True
+
+ return status
+
+
--- /dev/null
+"""
+Analyze ELAND files
+"""
+
+from glob import glob
+import logging
+import os
+import re
+import stat
+
+from htsworkflow.pipelines.runfolder import ElementTree
+from htsworkflow.util.ethelp import indent, flatten
+from htsworkflow.util.opener import autoopen
+
+SAMPLE_NAME = 'SampleName'
+LANE_ID = 'LaneID'
+END = 'End'
+READS = 'Reads'
+
+GENOME_MAP = 'GenomeMap'
+GENOME_ITEM = 'GenomeItem'
+MAPPED_READS = 'MappedReads'
+MAPPED_ITEM = 'MappedItem'
+MATCH_CODES = 'MatchCodes'
+MATCH_ITEM = 'Code'
+READS = 'Reads'
+
+ELAND_SINGLE = 0
+ELAND_MULTI = 1
+ELAND_EXTENDED = 2
+ELAND_EXPORT = 3
+
+
+class ResultLane(object):
+ """
+ Base class for result lanes
+ """
+ XML_VERSION = 2
+ LANE = 'ResultLane'
+
+ def __init__(self, pathname=None, lane_id=None, end=None, xml=None):
+ self.pathname = pathname
+ self._sample_name = None
+ self.lane_id = lane_id
+ self.end = end
+ self._reads = None
+
+ if xml is not None:
+ self.set_elements(xml)
+
+ def _update(self):
+ """
+ Actually read the file and actually count the reads
+ """
+ raise NotImplementedError("Can't count abstract classes")
+
+ def _update_name(self):
+ # extract the sample name
+ if self.pathname is None:
+ return
+
+ path, name = os.path.split(self.pathname)
+ split_name = name.split('_')
+ self._sample_name = split_name[0]
+
+ def _get_sample_name(self):
+ if self._sample_name is None:
+ self._update_name()
+ return self._sample_name
+ sample_name = property(_get_sample_name)
+
+ def _get_reads(self):
+ if self._reads is None:
+ self._update()
+ return self._reads
+ reads = property(_get_reads)
+
+
+class ElandLane(ResultLane):
+ """
+ Process an eland result file
+ """
+ XML_VERSION = 2
+ LANE = "ElandLane"
+
+ def __init__(self, pathname=None, lane_id=None, end=None, genome_map=None, eland_type=None, xml=None):
+ super(ElandLane, self).__init__(pathname, lane_id, end)
+
+ self._mapped_reads = None
+ self._match_codes = None
+ if genome_map is None:
+ genome_map = {}
+ self.genome_map = genome_map
+ self.eland_type = None
+
+ if xml is not None:
+ self.set_elements(xml)
+
+ def _guess_eland_type(self, pathname):
+ if self.eland_type is None:
+ # attempt autodetect eland file type
+ pathn, name = os.path.split(pathname)
+ if re.search('result', name):
+ self.eland_type = ELAND_SINGLE
+ elif re.search('multi', name):
+ self.eland_type = ELAND_MULTI
+ elif re.search('extended', name):
+ self.eland_type = ELAND_EXTENDED
+ elif re.search('export', name):
+ self.eland_type = ELAND_EXPORT
+ else:
+ self.eland_type = ELAND_SINGLE
+
+ def _update(self):
+ """
+ Actually read the file and actually count the reads
+ """
+ # can't do anything if we don't have a file to process
+ if self.pathname is None:
+ return
+ self._guess_eland_type(self.pathname)
+
+ if os.stat(self.pathname)[stat.ST_SIZE] == 0:
+ raise RuntimeError("Eland isn't done, try again later.")
+
+ logging.info("summarizing results for %s" % (self.pathname))
+
+ if self.eland_type == ELAND_SINGLE:
+ result = self._update_eland_result(self.pathname)
+ elif self.eland_type == ELAND_MULTI or \
+ self.eland_type == ELAND_EXTENDED:
+ result = self._update_eland_multi(self.pathname)
+ else:
+ raise NotImplementedError("Only support single/multi/extended eland files")
+ self._match_codes, self._mapped_reads, self._reads = result
+
+ def _update_eland_result(self, pathname):
+ reads = 0
+ mapped_reads = {}
+
+ match_codes = {'NM':0, 'QC':0, 'RM':0,
+ 'U0':0, 'U1':0, 'U2':0,
+ 'R0':0, 'R1':0, 'R2':0,
+ }
+ for line in autoopen(pathname,'r'):
+ reads += 1
+ fields = line.split()
+ # code = fields[2]
+ # match_codes[code] = match_codes.setdefault(code, 0) + 1
+ # the QC/NM etc codes are in the 3rd field and always present
+ match_codes[fields[2]] += 1
+ # ignore lines that don't have a fasta filename
+ if len(fields) < 7:
+ continue
+ fasta = self.genome_map.get(fields[6], fields[6])
+ mapped_reads[fasta] = mapped_reads.setdefault(fasta, 0) + 1
+ return match_codes, mapped_reads, reads
+
+ def _update_eland_multi(self, pathname):
+ reads = 0
+ mapped_reads = {}
+
+ match_codes = {'NM':0, 'QC':0, 'RM':0,
+ 'U0':0, 'U1':0, 'U2':0,
+ 'R0':0, 'R1':0, 'R2':0,
+ }
+ match_counts_re = re.compile("([\d]+):([\d]+):([\d]+)")
+ for line in autoopen(pathname,'r'):
+ reads += 1
+ fields = line.split()
+ # fields[2] = QC/NM/or number of matches
+ groups = match_counts_re.match(fields[2])
+ if groups is None:
+ match_codes[fields[2]] += 1
+ else:
+ # when there are too many hit, eland writes a - where
+ # it would have put the list of hits.
+ # or in a different version of eland, it just leaves
+ # that column blank, and only outputs 3 fields.
+ if len(fields) < 4 or fields[3] == '-':
+ continue
+ zero_mismatches = int(groups.group(1))
+ if zero_mismatches == 1:
+ match_codes['U0'] += 1
+ elif zero_mismatches < 255:
+ match_codes['R0'] += zero_mismatches
+
+ one_mismatches = int(groups.group(2))
+ if one_mismatches == 1:
+ match_codes['U1'] += 1
+ elif one_mismatches < 255:
+ match_codes['R1'] += one_mismatches
+
+ two_mismatches = int(groups.group(3))
+ if two_mismatches == 1:
+ match_codes['U2'] += 1
+ elif two_mismatches < 255:
+ match_codes['R2'] += two_mismatches
+
+ chromo = None
+ for match in fields[3].split(','):
+ match_fragment = match.split(':')
+ if len(match_fragment) == 2:
+ chromo = match_fragment[0]
+ pos = match_fragment[1]
+
+ fasta = self.genome_map.get(chromo, chromo)
+ assert fasta is not None
+ mapped_reads[fasta] = mapped_reads.setdefault(fasta, 0) + 1
+ return match_codes, mapped_reads, reads
+
+ def _get_mapped_reads(self):
+ if self._mapped_reads is None:
+ self._update()
+ return self._mapped_reads
+ mapped_reads = property(_get_mapped_reads)
+
+ def _get_match_codes(self):
+ if self._match_codes is None:
+ self._update()
+ return self._match_codes
+ match_codes = property(_get_match_codes)
+
+ def _get_no_match(self):
+ if self._mapped_reads is None:
+ self._update()
+ return self._match_codes['NM']
+ no_match = property(_get_no_match,
+ doc="total reads that didn't match the target genome.")
+
+ def _get_no_match_percent(self):
+ return float(self.no_match)/self.reads * 100
+ no_match_percent = property(_get_no_match_percent,
+ doc="no match reads as percent of total")
+
+ def _get_qc_failed(self):
+ if self._mapped_reads is None:
+ self._update()
+ return self._match_codes['QC']
+ qc_failed = property(_get_qc_failed,
+ doc="total reads that didn't match the target genome.")
+
+ def _get_qc_failed_percent(self):
+ return float(self.qc_failed)/self.reads * 100
+ qc_failed_percent = property(_get_qc_failed_percent,
+ doc="QC failed reads as percent of total")
+
+ def _get_unique_reads(self):
+ if self._mapped_reads is None:
+ self._update()
+ sum = 0
+ for code in ['U0','U1','U2']:
+ sum += self._match_codes[code]
+ return sum
+ unique_reads = property(_get_unique_reads,
+ doc="total unique reads")
+
+ def _get_repeat_reads(self):
+ if self._mapped_reads is None:
+ self._update()
+ sum = 0
+ for code in ['R0','R1','R2']:
+ sum += self._match_codes[code]
+ return sum
+ repeat_reads = property(_get_repeat_reads,
+ doc="total repeat reads")
+
+ def get_elements(self):
+ lane = ElementTree.Element(ElandLane.LANE,
+ {'version':
+ unicode(ElandLane.XML_VERSION)})
+ sample_tag = ElementTree.SubElement(lane, SAMPLE_NAME)
+ sample_tag.text = self.sample_name
+ lane_tag = ElementTree.SubElement(lane, LANE_ID)
+ lane_tag.text = str(self.lane_id)
+ if self.end is not None:
+ end_tag = ElementTree.SubElement(lane, END)
+ end_tag.text = str(self.end)
+ genome_map = ElementTree.SubElement(lane, GENOME_MAP)
+ for k, v in self.genome_map.items():
+ item = ElementTree.SubElement(
+ genome_map, GENOME_ITEM,
+ {'name':k, 'value':unicode(v)})
+ mapped_reads = ElementTree.SubElement(lane, MAPPED_READS)
+ for k, v in self.mapped_reads.items():
+ item = ElementTree.SubElement(
+ mapped_reads, MAPPED_ITEM,
+ {'name':k, 'value':unicode(v)})
+ match_codes = ElementTree.SubElement(lane, MATCH_CODES)
+ for k, v in self.match_codes.items():
+ item = ElementTree.SubElement(
+ match_codes, MATCH_ITEM,
+ {'name':k, 'value':unicode(v)})
+ reads = ElementTree.SubElement(lane, READS)
+ reads.text = unicode(self.reads)
+
+ return lane
+
+ def set_elements(self, tree):
+ if tree.tag != ElandLane.LANE:
+ raise ValueError('Exptecting %s' % (ElandLane.LANE,))
+
+ # reset dictionaries
+ self._mapped_reads = {}
+ self._match_codes = {}
+
+ for element in tree:
+ tag = element.tag.lower()
+ if tag == SAMPLE_NAME.lower():
+ self._sample_name = element.text
+ elif tag == LANE_ID.lower():
+ self.lane_id = int(element.text)
+ elif tag == END.lower():
+ self.end = int(element.text)
+ elif tag == GENOME_MAP.lower():
+ for child in element:
+ name = child.attrib['name']
+ value = child.attrib['value']
+ self.genome_map[name] = value
+ elif tag == MAPPED_READS.lower():
+ for child in element:
+ name = child.attrib['name']
+ value = child.attrib['value']
+ self._mapped_reads[name] = int(value)
+ elif tag == MATCH_CODES.lower():
+ for child in element:
+ name = child.attrib['name']
+ value = int(child.attrib['value'])
+ self._match_codes[name] = value
+ elif tag == READS.lower():
+ self._reads = int(element.text)
+ else:
+ logging.warn("ElandLane unrecognized tag %s" % (element.tag,))
+
+class SequenceLane(ResultLane):
+ XML_VERSION=1
+ LANE = 'SequenceLane'
+ SEQUENCE_TYPE = 'SequenceType'
+
+ NONE_TYPE = None
+ SCARF_TYPE = 1
+ FASTQ_TYPE = 2
+ SEQUENCE_DESCRIPTION = { NONE_TYPE: 'None', SCARF_TYPE: 'SCARF', FASTQ_TYPE: 'FASTQ' }
+
+ def __init__(self, pathname=None, lane_id=None, end=None, xml=None):
+ self.sequence_type = None
+ super(SequenceLane, self).__init__(pathname, lane_id, end, xml)
+
+ def _guess_sequence_type(self, pathname):
+ """
+ Determine if we have a scarf or fastq sequence file
+ """
+ f = open(pathname,'r')
+ l = f.readline()
+ f.close()
+
+ if l[0] == '@':
+ # fastq starts with a @
+ self.sequence_type = SequenceLane.FASTQ_TYPE
+ else:
+ self.sequence_type = SequenceLane.SCARF_TYPE
+ return self.sequence_type
+
+ def _update(self):
+ """
+ Actually read the file and actually count the reads
+ """
+ # can't do anything if we don't have a file to process
+ if self.pathname is None:
+ return
+
+ if os.stat(self.pathname)[stat.ST_SIZE] == 0:
+ raise RuntimeError("Sequencing isn't done, try again later.")
+
+ self._guess_sequence_type(self.pathname)
+
+ logging.info("summarizing results for %s" % (self.pathname))
+ lines = 0
+ f = open(self.pathname)
+ for l in f.xreadlines():
+ lines += 1
+ f.close()
+
+ if self.sequence_type == SequenceLane.SCARF_TYPE:
+ self._reads = lines
+ elif self.sequence_type == SequenceLane.FASTQ_TYPE:
+ self._reads = lines / 4
+ else:
+ raise NotImplementedError("This only supports scarf or fastq squence files")
+
+ def get_elements(self):
+ lane = ElementTree.Element(SequenceLane.LANE,
+ {'version':
+ unicode(SequenceLane.XML_VERSION)})
+ sample_tag = ElementTree.SubElement(lane, SAMPLE_NAME)
+ sample_tag.text = self.sample_name
+ lane_tag = ElementTree.SubElement(lane, LANE_ID)
+ lane_tag.text = str(self.lane_id)
+ if self.end is not None:
+ end_tag = ElementTree.SubElement(lane, END)
+ end_tag.text = str(self.end)
+ reads = ElementTree.SubElement(lane, READS)
+ reads.text = unicode(self.reads)
+ sequence_type = ElementTree.SubElement(lane, SequenceLane.SEQUENCE_TYPE)
+ sequence_type.text = unicode(SequenceLane.SEQUENCE_DESCRIPTION[self.sequence_type])
+
+ return lane
+
+ def set_elements(self, tree):
+ if tree.tag != SequenceLane.LANE:
+ raise ValueError('Exptecting %s' % (SequenceLane.LANE,))
+ lookup_sequence_type = dict([ (v,k) for k,v in SequenceLane.SEQUENCE_DESCRIPTION.items()])
+
+ for element in tree:
+ tag = element.tag.lower()
+ if tag == SAMPLE_NAME.lower():
+ self._sample_name = element.text
+ elif tag == LANE_ID.lower():
+ self.lane_id = int(element.text)
+ elif tag == END.lower():
+ self.end = int(element.text)
+ elif tag == READS.lower():
+ self._reads = int(element.text)
+ elif tag == SequenceLane.SEQUENCE_TYPE.lower():
+ self.sequence_type = lookup_sequence_type.get(element.text, None)
+ print self.sequence_type
+ else:
+ logging.warn("SequenceLane unrecognized tag %s" % (element.tag,))
+
+class ELAND(object):
+ """
+ Summarize information from eland files
+ """
+ XML_VERSION = 3
+
+ ELAND = 'ElandCollection'
+ LANE = 'Lane'
+ LANE_ID = 'id'
+ END = 'end'
+
+ def __init__(self, xml=None):
+ # we need information from the gerald config.xml
+ self.results = [{},{}]
+
+ if xml is not None:
+ self.set_elements(xml)
+
+ def get_elements(self):
+ root = ElementTree.Element(ELAND.ELAND,
+ {'version': unicode(ELAND.XML_VERSION)})
+ for end in range(len(self.results)):
+ end_results = self.results[end]
+ for lane_id, lane in end_results.items():
+ eland_lane = lane.get_elements()
+ eland_lane.attrib[ELAND.END] = unicode (end)
+ eland_lane.attrib[ELAND.LANE_ID] = unicode(lane_id)
+ root.append(eland_lane)
+ return root
+
+ def set_elements(self, tree):
+ if tree.tag.lower() != ELAND.ELAND.lower():
+ raise ValueError('Expecting %s', ELAND.ELAND)
+ for element in list(tree):
+ lane_id = int(element.attrib[ELAND.LANE_ID])
+ end = int(element.attrib.get(ELAND.END, 0))
+ if element.tag.lower() == ElandLane.LANE.lower():
+ lane = ElandLane(xml=element)
+ elif element.tag.lower() == SequenceLane.LANE.lower():
+ lane = SequenceLane(xml=element)
+
+ self.results[end][lane_id] = lane
+
+def check_for_eland_file(basedir, pattern, lane_id, end):
+ if end is None:
+ full_lane_id = lane_id
+ else:
+ full_lane_id = "%d_%d" % ( lane_id, end )
+
+ basename = pattern % (full_lane_id,)
+ pathname = os.path.join(basedir, basename)
+ if os.path.exists(pathname):
+ logging.info('found eland file in %s' % (pathname,))
+ return pathname
+ else:
+ return None
+
+def update_result_with_eland(gerald, results, lane_id, end, pathname, genome_maps):
+ # yes the lane_id is also being computed in ElandLane._update
+ # I didn't want to clutter up my constructor
+ # but I needed to persist the sample_name/lane_id for
+ # runfolder summary_report
+ path, name = os.path.split(pathname)
+ logging.info("Adding eland file %s" %(name,))
+ # split_name = name.split('_')
+ # lane_id = int(split_name[1])
+
+ if genome_maps is not None:
+ genome_map = genome_maps[lane_id]
+ elif gerald is not None:
+ genome_dir = gerald.lanes[lane_id].eland_genome
+ genome_map = build_genome_fasta_map(genome_dir)
+ else:
+ genome_map = {}
+
+ lane = ElandLane(pathname, lane_id, end, genome_map)
+
+ if end is None:
+ effective_end = 0
+ else:
+ effective_end = end - 1
+
+ results[effective_end][lane_id] = lane
+
+def update_result_with_sequence(gerald, results, lane_id, end, pathname):
+ result = SequenceLane(pathname, lane_id, end)
+
+ if end is None:
+ effective_end = 0
+ else:
+ effective_end = end - 1
+
+ results[effective_end][lane_id] = result
+
+
+def eland(gerald_dir, gerald=None, genome_maps=None):
+ e = ELAND()
+
+ lane_ids = range(1,9)
+ ends = [None, 1, 2]
+
+ basedirs = [gerald_dir]
+
+ # if there is a basedir/Temp change basedir to point to the temp
+ # directory, as 1.1rc1 moves most of the files we've historically
+ # cared about to that subdirectory.
+ # we should look into what the official 'result' files are.
+ # and 1.3 moves them back
+ basedir_temp = os.path.join(gerald_dir, 'Temp')
+ if os.path.isdir(basedir_temp):
+ basedirs.append(basedir_temp)
+
+
+ # the order in patterns determines the preference for what
+ # will be found.
+ MAPPED_ELAND = 0
+ SEQUENCE = 1
+ patterns = [('s_%s_eland_result.txt', MAPPED_ELAND),
+ ('s_%s_eland_result.txt.bz2', MAPPED_ELAND),
+ ('s_%s_eland_result.txt.gz', MAPPED_ELAND),
+ ('s_%s_eland_extended.txt', MAPPED_ELAND),
+ ('s_%s_eland_extended.txt.bz2', MAPPED_ELAND),
+ ('s_%s_eland_extended.txt.gz', MAPPED_ELAND),
+ ('s_%s_eland_multi.txt', MAPPED_ELAND),
+ ('s_%s_eland_multi.txt.bz2', MAPPED_ELAND),
+ ('s_%s_eland_multi.txt.gz', MAPPED_ELAND),
+ ('s_%s_sequence.txt', SEQUENCE),]
+
+ for basedir in basedirs:
+ for end in ends:
+ for lane_id in lane_ids:
+ for p in patterns:
+ pathname = check_for_eland_file(basedir, p[0], lane_id, end)
+ if pathname is not None:
+ if p[1] == MAPPED_ELAND:
+ update_result_with_eland(gerald, e.results, lane_id, end, pathname, genome_maps)
+ elif p[1] == SEQUENCE:
+ update_result_with_sequence(gerald, e.results, lane_id, end, pathname)
+ break
+ else:
+ logging.debug("No eland file found in %s for lane %s and end %s" %(basedir, lane_id, end))
+ continue
+
+ return e
+
+def build_genome_fasta_map(genome_dir):
+ # build fasta to fasta file map
+ logging.info("Building genome map")
+ genome = genome_dir.split(os.path.sep)[-1]
+ fasta_map = {}
+ for vld_file in glob(os.path.join(genome_dir, '*.vld')):
+ is_link = False
+ if os.path.islink(vld_file):
+ is_link = True
+ vld_file = os.path.realpath(vld_file)
+ path, vld_name = os.path.split(vld_file)
+ name, ext = os.path.splitext(vld_name)
+ if is_link:
+ fasta_map[name] = name
+ else:
+ fasta_map[name] = os.path.join(genome, name)
+ return fasta_map
+
+
+def extract_eland_sequence(instream, outstream, start, end):
+ """
+ Extract a chunk of sequence out of an eland file
+ """
+ for line in instream:
+ record = line.split()
+ if len(record) > 1:
+ result = [record[0], record[1][start:end]]
+ else:
+ result = [record[0][start:end]]
+ outstream.write("\t".join(result))
+ outstream.write(os.linesep)
--- /dev/null
+"""
+Extract information about the Firecrest run
+
+Firecrest
+ class holding the properties we found
+firecrest
+ Firecrest factory function initalized from a directory name
+fromxml
+ Firecrest factory function initalized from an xml dump from
+ the Firecrest object.
+"""
+
+from datetime import date
+from glob import glob
+import os
+import re
+import time
+
+from htsworkflow.pipelines.runfolder import \
+ ElementTree, \
+ VERSION_RE, \
+ EUROPEAN_STRPTIME
+
+__docformat__ = "restructuredtext en"
+
+class Firecrest(object):
+ XML_VERSION=1
+
+ # xml tag names
+ FIRECREST = 'Firecrest'
+ SOFTWARE_VERSION = 'version'
+ START = 'FirstCycle'
+ STOP = 'LastCycle'
+ DATE = 'run_time'
+ USER = 'user'
+ MATRIX = 'matrix'
+
+ def __init__(self, xml=None):
+ self.start = None
+ self.stop = None
+ self.version = None
+ self.date = date.today()
+ self.user = None
+ self.matrix = None
+
+ if xml is not None:
+ self.set_elements(xml)
+
+ def _get_time(self):
+ return time.mktime(self.date.timetuple())
+ time = property(_get_time, doc='return run time as seconds since epoch')
+
+ def dump(self):
+ print "Starting cycle:", self.start
+ print "Ending cycle:", self.stop
+ print "Firecrest version:", self.version
+ print "Run date:", self.date
+ print "user:", self.user
+
+ def get_elements(self):
+ attribs = {'version': str(Firecrest.XML_VERSION) }
+ root = ElementTree.Element(Firecrest.FIRECREST, attrib=attribs)
+ version = ElementTree.SubElement(root, Firecrest.SOFTWARE_VERSION)
+ version.text = self.version
+ start_cycle = ElementTree.SubElement(root, Firecrest.START)
+ start_cycle.text = str(self.start)
+ stop_cycle = ElementTree.SubElement(root, Firecrest.STOP)
+ stop_cycle.text = str(self.stop)
+ run_date = ElementTree.SubElement(root, Firecrest.DATE)
+ run_date.text = str(self.time)
+ user = ElementTree.SubElement(root, Firecrest.USER)
+ user.text = self.user
+ if self.matrix is not None:
+ matrix = ElementTree.SubElement(root, Firecrest.MATRIX)
+ matrix.text = self.matrix
+ return root
+
+ def set_elements(self, tree):
+ if tree.tag != Firecrest.FIRECREST:
+ raise ValueError('Expected "Firecrest" SubElements')
+ xml_version = int(tree.attrib.get('version', 0))
+ if xml_version > Firecrest.XML_VERSION:
+ logging.warn('Firecrest XML tree is a higher version than this class')
+ for element in list(tree):
+ if element.tag == Firecrest.SOFTWARE_VERSION:
+ self.version = element.text
+ elif element.tag == Firecrest.START:
+ self.start = int(element.text)
+ elif element.tag == Firecrest.STOP:
+ self.stop = int(element.text)
+ elif element.tag == Firecrest.DATE:
+ self.date = date.fromtimestamp(float(element.text))
+ elif element.tag == Firecrest.USER:
+ self.user = element.text
+ elif element.tag == Firecrest.MATRIX:
+ self.matrix = element.text
+ else:
+ raise ValueError("Unrecognized tag: %s" % (element.tag,))
+
+def firecrest(pathname):
+ """
+ Examine the directory at pathname and initalize a Firecrest object
+ """
+ f = Firecrest()
+ f.pathname = pathname
+
+ # parse firecrest directory name
+ path, name = os.path.split(pathname)
+ groups = name.split('_')
+ # grab the start/stop cycle information
+ cycle = re.match("C([0-9]+)-([0-9]+)", groups[0])
+ f.start = int(cycle.group(1))
+ f.stop = int(cycle.group(2))
+ # firecrest version
+ version = re.search(VERSION_RE, groups[1])
+ f.version = (version.group(1))
+ # datetime
+ t = time.strptime(groups[2], EUROPEAN_STRPTIME)
+ f.date = date(*t[0:3])
+ # username
+ f.user = groups[3]
+
+ bustard_pattern = os.path.join(pathname, 'Bustard*')
+ # should I parse this deeper than just stashing the
+ # contents of the matrix file?
+ matrix_pathname = os.path.join(pathname, 'Matrix', 's_matrix.txt')
+ if os.path.exists(matrix_pathname):
+ # this is for firecrest < 1.3.2
+ f.matrix = open(matrix_pathname, 'r').read()
+ elif glob(bustard_pattern) > 0:
+ f.matrix = None
+ # there are runs here. Bustard should save the matrix.
+ else:
+ return None
+
+ return f
+
+def fromxml(tree):
+ """
+ Initialize a Firecrest object from an element tree node
+ """
+ f = Firecrest()
+ f.set_elements(tree)
+ return f
--- /dev/null
+#!/usr/bin/python
+import glob
+import sys
+import os
+import re
+
+import logging
+
+from htsworkflow.util.alphanum import alphanum
+
+class DuplicateGenome(Exception): pass
+
+
+def _has_metainfo(genome_dir):
+ metapath = os.path.join(genome_dir, '_metainfo_')
+ if os.path.isfile(metapath):
+ return True
+ else:
+ return False
+
+def getAvailableGenomes(genome_base_dir):
+ """
+ raises IOError (on genome_base_dir not found)
+ raises DuplicateGenome on duplicate genomes found.
+
+ returns a double dictionary (i.e. d[species][build] = path)
+ """
+
+ # Need valid directory
+ if not os.path.exists(genome_base_dir):
+ msg = "Directory does not exist: %s" % (genome_base_dir)
+ raise IOError, msg
+
+ # Find all subdirectories
+ filepath_list = glob.glob(os.path.join(genome_base_dir, '*'))
+ potential_genome_dirs = \
+ [ filepath for filepath in filepath_list if os.path.isdir(filepath)]
+
+ # Get list of metadata files
+ genome_dir_list = \
+ [ dirpath \
+ for dirpath in potential_genome_dirs \
+ if _has_metainfo(dirpath) ]
+
+ # Genome double dictionary
+ d = {}
+
+ for genome_dir in genome_dir_list:
+ line = open(os.path.join(genome_dir, '_metainfo_'), 'r').readline().strip()
+
+ # Get species, build... log and skip on failure
+ try:
+ species, build = line.split('|')
+ except:
+ logging.warning('Skipping: Invalid metafile (%s) line: %s' \
+ % (metafile, line))
+ continue
+
+ build_dict = d.setdefault(species, {})
+ if build in build_dict:
+ msg = "Duplicate genome for %s|%s" % (species, build)
+ raise DuplicateGenome, msg
+
+ build_dict[build] = genome_dir
+
+ return d
+
+
+class constructMapperDict(object):
+ """
+ Emulate a dictionary to map genome|build names to paths.
+
+ It uses the dictionary generated by getAvailableGenomes.
+ """
+ def __init__(self, genome_dict):
+ self.genome_dict = genome_dict
+
+ def __getitem__(self, key):
+ """
+ Return the best match for key
+ """
+ elements = re.split("\|", key)
+
+ try:
+ if len(elements) == 1:
+ # we just the species name
+ # get the set of builds
+ builds = self.genome_dict[elements[0]]
+
+ # sort build names the way humans would
+ keys = builds.keys()
+ keys.sort(cmp=alphanum)
+
+ # return the path from the 'last' build name
+ return builds[keys[-1]]
+
+ elif len(elements) == 2:
+ # we have species, and build name
+ return self.genome_dict[elements[0]][elements[1]]
+ else:
+ raise KeyError("Unrecognized key")
+ except KeyError, e:
+ logging.error('Unrecognized genome identifier: %s' % str((elements),))
+ return "NoGenomeAvailable"
+
+ def keys(self):
+ keys = []
+ for species in self.genome_dict.keys():
+ for build in self.genome_dict[species]:
+ keys.append([species+'|'+build])
+ return keys
+
+ def values(self):
+ values = []
+ for species in self.genome_dict.keys():
+ for build in self.genome_dict[species]:
+ values.append(self.genome_dict[species][build])
+ return values
+
+ def items(self):
+ items = []
+ for species in self.genome_dict.keys():
+ for build in self.genome_dict[species]:
+ key = [species+'|'+build]
+ value = self.genome_dict[species][build]
+ items.append((key, value))
+ return items
+
+if __name__ == '__main__':
+
+ if len(sys.argv) != 2:
+ print 'useage: %s <base_genome_dir>' % (sys.argv[0])
+ sys.exit(1)
+
+ d = getAvailableGenomes(sys.argv[1])
+ d2 = constructMapperDict(d)
+
+ for k,v in d2.items():
+ print '%s: %s' % (k,v)
+
+
--- /dev/null
+"""
+Provide access to information stored in the GERALD directory.
+"""
+from datetime import datetime, date
+import logging
+import os
+import time
+
+from htsworkflow.pipelines.summary import Summary
+from htsworkflow.pipelines.eland import eland, ELAND
+
+from htsworkflow.pipelines.runfolder import \
+ ElementTree, \
+ EUROPEAN_STRPTIME, \
+ LANES_PER_FLOWCELL, \
+ VERSION_RE
+from htsworkflow.util.ethelp import indent, flatten
+
+class Gerald(object):
+ """
+ Capture meaning out of the GERALD directory
+ """
+ XML_VERSION = 1
+ GERALD='Gerald'
+ RUN_PARAMETERS='RunParameters'
+ SUMMARY='Summary'
+
+ class LaneParameters(object):
+ """
+ Make it easy to access elements of LaneSpecificRunParameters from python
+ """
+ def __init__(self, gerald, lane_id):
+ self._gerald = gerald
+ self._lane_id = lane_id
+
+ def __get_attribute(self, xml_tag):
+ subtree = self._gerald.tree.find('LaneSpecificRunParameters')
+ container = subtree.find(xml_tag)
+ if container is None:
+ return None
+ if len(container.getchildren()) > LANES_PER_FLOWCELL:
+ raise RuntimeError('GERALD config.xml file changed')
+ lanes = [x.tag.split('_')[1] for x in container.getchildren()]
+ try:
+ index = lanes.index(self._lane_id)
+ except ValueError, e:
+ return None
+ element = container[index]
+ return element.text
+ def _get_analysis(self):
+ return self.__get_attribute('ANALYSIS')
+ analysis = property(_get_analysis)
+
+ def _get_eland_genome(self):
+ genome = self.__get_attribute('ELAND_GENOME')
+ # default to the chipwide parameters if there isn't an
+ # entry in the lane specific paramaters
+ if genome is None:
+ subtree = self._gerald.tree.find('ChipWideRunParameters')
+ container = subtree.find('ELAND_GENOME')
+ genome = container.text
+ return genome
+ eland_genome = property(_get_eland_genome)
+
+ def _get_read_length(self):
+ return self.__get_attribute('READ_LENGTH')
+ read_length = property(_get_read_length)
+
+ def _get_use_bases(self):
+ return self.__get_attribute('USE_BASES')
+ use_bases = property(_get_use_bases)
+
+ class LaneSpecificRunParameters(object):
+ """
+ Provide access to LaneSpecificRunParameters
+ """
+ def __init__(self, gerald):
+ self._gerald = gerald
+ self._lane = None
+
+ def _initalize_lanes(self):
+ """
+ build dictionary of LaneParameters
+ """
+ self._lanes = {}
+ tree = self._gerald.tree
+ analysis = tree.find('LaneSpecificRunParameters/ANALYSIS')
+ # according to the pipeline specs I think their fields
+ # are sampleName_laneID, with sampleName defaulting to s
+ # since laneIDs are constant lets just try using
+ # those consistently.
+ for element in analysis:
+ sample, lane_id = element.tag.split('_')
+ self._lanes[int(lane_id)] = Gerald.LaneParameters(
+ self._gerald, lane_id)
+
+ def __getitem__(self, key):
+ if self._lane is None:
+ self._initalize_lanes()
+ return self._lanes[key]
+ def keys(self):
+ if self._lane is None:
+ self._initalize_lanes()
+ return self._lanes.keys()
+ def values(self):
+ if self._lane is None:
+ self._initalize_lanes()
+ return self._lanes.values()
+ def items(self):
+ if self._lane is None:
+ self._initalize_lanes()
+ return self._lanes.items()
+ def __len__(self):
+ if self._lane is None:
+ self._initalize_lanes()
+ return len(self._lanes)
+
+ def __init__(self, xml=None):
+ self.pathname = None
+ self.tree = None
+
+ # parse lane parameters out of the config.xml file
+ self.lanes = Gerald.LaneSpecificRunParameters(self)
+
+ self.summary = None
+ self.eland_results = None
+
+ if xml is not None:
+ self.set_elements(xml)
+
+ def _get_date(self):
+ if self.tree is None:
+ return datetime.today()
+ timestamp = self.tree.findtext('ChipWideRunParameters/TIME_STAMP')
+ epochstamp = time.mktime(time.strptime(timestamp, '%c'))
+ return datetime.fromtimestamp(epochstamp)
+ date = property(_get_date)
+
+ def _get_time(self):
+ return time.mktime(self.date.timetuple())
+ time = property(_get_time, doc='return run time as seconds since epoch')
+
+ def _get_version(self):
+ if self.tree is None:
+ return None
+ return self.tree.findtext('ChipWideRunParameters/SOFTWARE_VERSION')
+ version = property(_get_version)
+
+ def dump(self):
+ """
+ Debugging function, report current object
+ """
+ print 'Gerald version:', self.version
+ print 'Gerald run date:', self.date
+ print 'Gerald config.xml:', self.tree
+ self.summary.dump()
+
+ def get_elements(self):
+ if self.tree is None or self.summary is None:
+ return None
+
+ gerald = ElementTree.Element(Gerald.GERALD,
+ {'version': unicode(Gerald.XML_VERSION)})
+ gerald.append(self.tree)
+ gerald.append(self.summary.get_elements())
+ if self.eland_results:
+ gerald.append(self.eland_results.get_elements())
+ return gerald
+
+ def set_elements(self, tree):
+ if tree.tag != Gerald.GERALD:
+ raise ValueError('exptected GERALD')
+ xml_version = int(tree.attrib.get('version', 0))
+ if xml_version > Gerald.XML_VERSION:
+ logging.warn('XML tree is a higher version than this class')
+ for element in list(tree):
+ tag = element.tag.lower()
+ if tag == Gerald.RUN_PARAMETERS.lower():
+ self.tree = element
+ elif tag == Gerald.SUMMARY.lower():
+ self.summary = Summary(xml=element)
+ elif tag == ELAND.ELAND.lower():
+ self.eland_results = ELAND(xml=element)
+ else:
+ logging.warn("Unrecognized tag %s" % (element.tag,))
+
+
+def gerald(pathname):
+ g = Gerald()
+ g.pathname = pathname
+ path, name = os.path.split(pathname)
+ logging.info("Parsing gerald config.xml")
+ config_pathname = os.path.join(pathname, 'config.xml')
+ g.tree = ElementTree.parse(config_pathname).getroot()
+
+ # parse Summary.htm file
+ logging.info("Parsing Summary.htm")
+ summary_pathname = os.path.join(pathname, 'Summary.htm')
+ g.summary = Summary(summary_pathname)
+ # parse eland files
+ g.eland_results = eland(g.pathname, g)
+ return g
+
+if __name__ == "__main__":
+ # quick test code
+ import sys
+ g = gerald(sys.argv[1])
+ #ElementTree.dump(g.get_elements())
--- /dev/null
+"""
+Extract information about the IPAR run
+
+IPAR
+ class holding the properties we found
+ipar
+ IPAR factory function initalized from a directory name
+fromxml
+ IPAR factory function initalized from an xml dump from
+ the IPAR object.
+"""
+__docformat__ = "restructuredtext en"
+
+import datetime
+from glob import glob
+import logging
+import os
+import re
+import stat
+import time
+
+from htsworkflow.pipelines.runfolder import \
+ ElementTree, \
+ VERSION_RE, \
+ EUROPEAN_STRPTIME
+
+class Tiles(object):
+ def __init__(self, tree):
+ self.tree = tree.find("TileSelection")
+
+ def keys(self):
+ key_list = []
+ for c in self.tree.getchildren():
+ k = c.attrib.get('Index', None)
+ if k is not None:
+ key_list.append(k)
+ return key_list
+
+ def values(self):
+ value_list = []
+ for lane in self.tree.getchildren():
+ attributes = {}
+ for child in lane.getchildren():
+ if child.tag == "Sample":
+ attributes['Sample'] = child.text
+ elif child.tag == 'TileRange':
+ attributes['TileRange'] = (int(child.attrib['Min']),int(child.attrib['Max']))
+ value_list.append(attributes)
+ return value_list
+
+ def items(self):
+ return zip(self.keys(), self.values())
+
+ def __getitem__(self, key):
+ # FIXME: this is inefficient. building the dictionary be rescanning the xml.
+ v = dict(self.items())
+ return v[key]
+
+class IPAR(object):
+ XML_VERSION=1
+
+ # xml tag names
+ IPAR = 'IPAR'
+ TIMESTAMP = 'timestamp'
+ MATRIX = 'matrix'
+ RUN = 'Run'
+
+ def __init__(self, xml=None):
+ self.tree = None
+ self.date = datetime.datetime.today()
+ self._tiles = None
+ if xml is not None:
+ self.set_elements(xml)
+
+ def _get_time(self):
+ return time.mktime(self.date.timetuple())
+ def _set_time(self, value):
+ mtime_tuple = time.localtime(value)
+ self.date = datetime.datetime(*(mtime_tuple[0:7]))
+ time = property(_get_time, _set_time,
+ doc='run time as seconds since epoch')
+
+ def _get_cycles(self):
+ if self.tree is None:
+ return None
+ cycles = self.tree.find("Cycles")
+ if cycles is None:
+ return None
+ return cycles.attrib
+
+ def _get_start(self):
+ """
+ return cycle start
+ """
+ cycles = self._get_cycles()
+ if cycles is not None:
+ return int(cycles['First'])
+ else:
+ return None
+ start = property(_get_start, doc="get cycle start")
+
+ def _get_stop(self):
+ """
+ return cycle stop
+ """
+ cycles = self._get_cycles()
+ if cycles is not None:
+ return int(cycles['Last'])
+ else:
+ return None
+ stop = property(_get_stop, doc="get cycle stop")
+
+ def _get_tiles(self):
+ if self._tiles is None:
+ self._tiles = Tiles(self.tree)
+ return self._tiles
+ tiles = property(_get_tiles)
+
+ def _get_version(self):
+ software = self.tree.find('Software')
+ if software is not None:
+ return software.attrib['Version']
+ version = property(_get_version, "IPAR software version")
+
+
+ def file_list(self):
+ """
+ Generate list of all files that should be generated by the IPAR unit
+ """
+ suffix_node = self.tree.find('RunParameters/CompressionSuffix')
+ if suffix_node is None:
+ print "find compression suffix failed"
+ return None
+ suffix = suffix_node.text
+ files = []
+ format = "%s_%s_%04d_%s.txt%s"
+ for lane, attrib in self.tiles.items():
+ for file_type in ["int","nse"]:
+ start, stop = attrib['TileRange']
+ for tile in range(start, stop+1):
+ files.append(format % (attrib['Sample'], lane, tile, file_type, suffix))
+ return files
+
+ def dump(self):
+ print "Matrix:", self.matrix
+ print "Tree:", self.tree
+
+ def get_elements(self):
+ attribs = {'version': str(IPAR.XML_VERSION) }
+ root = ElementTree.Element(IPAR.IPAR, attrib=attribs)
+ timestamp = ElementTree.SubElement(root, IPAR.TIMESTAMP)
+ timestamp.text = str(int(self.time))
+ root.append(self.tree)
+ matrix = ElementTree.SubElement(root, IPAR.MATRIX)
+ matrix.text = self.matrix
+ return root
+
+ def set_elements(self, tree):
+ if tree.tag != IPAR.IPAR:
+ raise ValueError('Expected "IPAR" SubElements')
+ xml_version = int(tree.attrib.get('version', 0))
+ if xml_version > IPAR.XML_VERSION:
+ logging.warn('IPAR XML tree is a higher version than this class')
+ for element in list(tree):
+ if element.tag == IPAR.RUN:
+ self.tree = element
+ elif element.tag == IPAR.TIMESTAMP:
+ self.time = int(element.text)
+ elif element.tag == IPAR.MATRIX:
+ self.matrix = element.text
+ else:
+ raise ValueError("Unrecognized tag: %s" % (element.tag,))
+
+def load_ipar_param_tree(paramfile):
+ """
+ look for a .param file and load it if it is an IPAR tree
+ """
+
+ tree = ElementTree.parse(paramfile).getroot()
+ run = tree.find('Run')
+ if run.attrib.has_key('Name') and run.attrib['Name'].startswith("IPAR"):
+ return run
+
+ return None
+
+def ipar(pathname):
+ """
+ Examine the directory at pathname and initalize a IPAR object
+ """
+ logging.info("Searching IPAR directory")
+ i = IPAR()
+ i.pathname = pathname
+
+ # parse firecrest directory name
+ path, name = os.path.split(pathname)
+ groups = name.split('_')
+ if groups[0] != 'IPAR':
+ raise ValueError('ipar can only process IPAR directories')
+
+ bustard_pattern = os.path.join(pathname, 'Bustard*')
+ # contents of the matrix file?
+ matrix_pathname = os.path.join(pathname, 'Matrix', 's_matrix.txt')
+ if os.path.exists(matrix_pathname):
+ # this is IPAR_1.01
+ i.matrix = open(matrix_pathname, 'r').read()
+ elif glob(bustard_pattern) > 0:
+ i.matrix = None
+ # its still live.
+ else:
+ return None
+
+ # look for parameter xml file
+ paramfile = os.path.join(path, '.params')
+ if os.path.exists(paramfile):
+ i.tree = load_ipar_param_tree(paramfile)
+ mtime_local = os.stat(paramfile)[stat.ST_MTIME]
+ i.time = mtime_local
+ return i
+
+def fromxml(tree):
+ """
+ Initialize a IPAR object from an element tree node
+ """
+ f = IPAR()
+ f.set_elements(tree)
+ return f
+
+if __name__ == "__main__":
+ i = ipar(os.path.expanduser('~/gec/081021_HWI-EAS229_0063_30HKUAAXX/Data/IPAR_1.01'))
+ x = i.get_elements()
+ j = fromxml(x)
+ #ElementTree.dump(x)
+ print j.date
+ print j.start
+ print j.stop
+ print i.tiles.keys()
+ print j.tiles.keys()
+ print j.tiles.items()
+ print j.file_list()
--- /dev/null
+from xml import sax
+
+
+def get_cycles(recipe_xml_filepath):
+ """
+ returns the number of cycles found in Recipe*.xml
+ """
+ handler = CycleXmlHandler()
+ sax.parse(recipe_xml_filepath, handler)
+ return handler.cycle_count
+
+
+
+class CycleXmlHandler(sax.ContentHandler):
+
+ def __init__(self):
+ self.cycle_count = 0
+ self.in_protocol = False
+ sax.ContentHandler.__init__(self)
+
+
+ def startDocument(self):
+ self.cycle_count = 0
+ self.in_protocol = False
+
+
+ def startElement(self, name, attrs):
+
+ #Only count Incorporations as cycles if within
+ # the protocol section of the xml document.
+ if name == "Incorporation" and self.in_protocol:
+ #print 'Found a cycle!'
+ self.cycle_count += 1
+ return
+
+ elif name == 'Protocol':
+ #print 'In protocol'
+ self.in_protocol = True
+ return
+
+ #print 'Skipping: %s' % (name)
+
+
+ def endElement(self, name):
+
+ if name == 'Protocol':
+ #print 'End protocol'
+ self.in_protocol = False
--- /dev/null
+#!/usr/bin/env python
+
+from optparse import OptionParser, IndentedHelpFormatter
+from ConfigParser import SafeConfigParser
+
+import logging
+import os
+import sys
+import urllib2
+
+__docformat__ = "restructredtext en"
+
+CONFIG_SYSTEM = '/etc/hts_frontend/hts_frontend.conf'
+CONFIG_USER = os.path.expanduser('~/.hts_frontend.conf')
+
+#Disable or enable commandline arg parsing; disabled by default.
+DISABLE_CMDLINE = True
+
+class FlowCellNotFound(Exception): pass
+class WebError404(Exception): pass
+
+class DummyOptions:
+ """
+ Used when command line parsing is disabled; default
+ """
+ def __init__(self):
+ self.url = None
+ self.output_filepath = None
+ self.flowcell = None
+ self.genome_dir = None
+
+class PreformattedDescriptionFormatter(IndentedHelpFormatter):
+
+ #def format_description(self, description):
+ #
+ # if description:
+ # return description + "\n"
+ # else:
+ # return ""
+
+ def format_epilog(self, epilog):
+ """
+ It was removing my preformated epilog, so this should override
+ that behavior! Muhahaha!
+ """
+ if epilog:
+ return "\n" + epilog + "\n"
+ else:
+ return ""
+
+
+def constructOptionParser():
+ """
+ returns a pre-setup optparser
+ """
+ global DISABLE_CMDLINE
+
+ if DISABLE_CMDLINE:
+ return None
+
+ parser = OptionParser(formatter=PreformattedDescriptionFormatter())
+
+ parser.set_description('Retrieves eland config file from hts_frontend web frontend.')
+
+ parser.epilog = """
+Config File:
+ * %s (System wide)
+ * %s (User specific; overrides system)
+ * command line overrides all config file options
+
+ Example Config File:
+
+ [config_file_server]
+ base_host_url=http://somewhere.domain:port
+""" % (CONFIG_SYSTEM, CONFIG_USER)
+
+ #Special formatter for allowing preformatted description.
+ ##parser.format_epilog(PreformattedDescriptionFormatter())
+
+ parser.add_option("-u", "--url",
+ action="store", type="string", dest="url")
+
+ parser.add_option("-o", "--output",
+ action="store", type="string", dest="output_filepath")
+
+ parser.add_option("-f", "--flowcell",
+ action="store", type="string", dest="flowcell")
+
+ parser.add_option("-g", "--genome_dir",
+ action="store", type="string", dest="genome_dir")
+
+ #parser.set_default("url", "default")
+
+ return parser
+
+def constructConfigParser():
+ """
+ returns a pre-setup config parser
+ """
+ parser = SafeConfigParser()
+ parser.read([CONFIG_SYSTEM, CONFIG_USER])
+ if not parser.has_section('config_file_server'):
+ parser.add_section('config_file_server')
+ if not parser.has_section('local_setup'):
+ parser.add_section('local_setup')
+
+ return parser
+
+
+def getCombinedOptions():
+ """
+ Returns optparse options after it has be updated with ConfigParser
+ config files and merged with parsed commandline options.
+ """
+ cl_parser = constructOptionParser()
+ conf_parser = constructConfigParser()
+
+ if cl_parser is None:
+ options = DummyOptions()
+ else:
+ options, args = cl_parser.parse_args()
+
+ if options.url is None:
+ if conf_parser.has_option('config_file_server', 'base_host_url'):
+ options.url = conf_parser.get('config_file_server', 'base_host_url')
+
+ if options.genome_dir is None:
+ if conf_parser.has_option('local_setup', 'genome_dir'):
+ options.genome_dir = conf_parser.get('local_setup', 'genome_dir')
+
+ print 'USING OPTIONS:'
+ print ' URL:', options.url
+ print ' OUT:', options.output_filepath
+ print ' FC:', options.flowcell
+ print 'GDIR:', options.genome_dir
+ print ''
+
+ return options
+
+
+def saveConfigFile(flowcell, base_host_url, output_filepath):
+ """
+ retrieves the flowcell eland config file, give the base_host_url
+ (i.e. http://sub.domain.edu:port)
+ """
+ url = base_host_url + '/eland_config/%s/' % (flowcell)
+
+ f = open(output_filepath, 'w')
+ #try:
+ try:
+ web = urllib2.urlopen(url)
+ except urllib2.URLError, e:
+ errmsg = 'URLError: %s' % (e.reason,)
+ logging.error(errmsg)
+ logging.error('opened %s' % (url,))
+ raise IOError(errmsg)
+
+ #except IOError, msg:
+ # if str(msg).find("Connection refused") >= 0:
+ # print 'Error: Connection refused for: %s' % (url)
+ # f.close()
+ # sys.exit(1)
+ # elif str(msg).find("Name or service not known") >= 0:
+ # print 'Error: Invalid domain or ip address for: %s' % (url)
+ # f.close()
+ # sys.exit(2)
+ # else:
+ # raise IOError, msg
+
+ data = web.read()
+
+ if data.find('Hmm, config file for') >= 0:
+ msg = "Flowcell (%s) not found in DB; full url(%s)" % (flowcell, url)
+ raise FlowCellNotFound, msg
+
+ if data.find('404 - Not Found') >= 0:
+ msg = "404 - Not Found: Flowcell (%s); base_host_url (%s);\n full url(%s)\n " \
+ "Did you get right port #?" % (flowcell, base_host_url, url)
+ raise FlowCellNotFound, msg
+
+ f.write(data)
+ web.close()
+ f.close()
+ logging.info('Wrote config file to %s' % (output_filepath,))
+
+
--- /dev/null
+__docformat__ = "restructuredtext en"
+
+import glob
+import re
+import os
+import sys
+import time
+import threading
+
+s_comment = re.compile('^#')
+s_general_read_len = re.compile('^READ_LENGTH ')
+s_read_len = re.compile('^[1-8]+:READ_LENGTH ')
+
+s_firecrest = None
+
+# FIRECREST PATTERNS
+# _p2f(<pattern>, lane, tile, cycle)
+PATTERN_FIRECREST_QCM = 's_%s_%s_%s_qcm.xml'
+
+# _p2f(<pattern>, lane, tile)
+PATTERN_FIRECREST_INT = 's_%s_%s_02_int.txt'
+PATTERN_FIRECREST_NSE = 's_%s_%s_nse.txt.gz'
+PATTERN_FIRECREST_POS = 's_%s_%s_pos.txt'
+PATTERN_FIRECREST_IDX = 's_%s_%s_idx.txt'
+PATTERN_FIRECREST_CLU1 = 's_%s_%s_01_1_clu.txt'
+PATTERN_FIRECREST_CLU2 = 's_%s_%s_01_2_clu.txt'
+PATTERN_FIRECREST_CLU3 = 's_%s_%s_01_3_clu.txt'
+PATTERN_FIRECREST_CLU4 = 's_%s_%s_01_4_clu.txt'
+
+
+# BUSTARD PATTERNS
+# _p2f(<pattern>, lane, tile)
+PATTERN_BUSTARD_SIG2 = 's_%s_%s_sig2.txt'
+PATTERN_BUSTARD_PRB = 's_%s_%s_prb.txt'
+
+
+
+# GERALD PATTERNS
+# _p2f(<pattern>, lane, tile)
+PATTERN_GERALD_ALLTMP = 's_%s_%s_all.txt.tmp'
+PATTERN_GERALD_QRAWTMP = 's_%s_%s_qraw.txt.tmp'
+PATTERN_GERALD_ALLPNGTMP = 's_%s_%s_all.tmp.png'
+PATTERN_GERALD_ALIGNTMP = 's_%s_%s_align.txt.tmp'
+PATTERN_GERALD_QVALTMP = 's_%s_%s_qval.txt.tmp'
+PATTERN_GERALD_SCORETMP = 's_%s_%s_score.txt.tmp'
+PATTERN_GERALD_PREALIGNTMP = 's_%s_%s_prealign.txt.tmp'
+PATTERN_GERALD_REALIGNTMP = 's_%s_%s_realign.txt.tmp'
+PATTERN_GERALD_RESCORETMP = 's_%s_%s_rescore.txt.tmp'
+PATTERN_GERALD_RESCOREPNG = 's_%s_%s_rescore.png'
+PATTERN_GERALD_ERRORSTMPPNG = 's_%s_%s_errors.tmp.png'
+PATTERN_GERALD_QCALTMP = 's_%s_%s_qcal.txt.tmp'
+PATTERN_GERALD_QVAL = 's_%s_%s_qval.txt'
+
+# _p2f(<pattern>, lane)
+PATTERN_GERALD_SEQPRETMP = 's_%s_seqpre.txt.tmp'
+PATTERN_GERALD_RESULTTMP = 's_%s_eland_result.txt.tmp'
+PATTERN_GERALD_SIGMEANSTMP = 's_%s_Signal_Means.txt.tmp'
+PATTERN_GERALD_CALLPNG = 's_%s_call.png'
+PATTERN_GERALD_ALLPNG = 's_%s_all.png'
+PATTERN_GERALD_PERCENTALLPNG = 's_%s_percent_all.png'
+PATTERN_GERALD_PERCENTCALLPNG = 's_%s_percent_call.png'
+PATTERN_GERALD_PERCENTBASEPNG = 's_%s_percent_base.png'
+PATTERN_GERALD_FILTTMP = 's_%s_filt.txt.tmp'
+PATTERN_GERALD_FRAGTMP = 's_%s_frag.txt.tmp'
+PATTERN_GERALD_QREPORTTMP = 's_%s_qreport.txt.tmp'
+PATTERN_GERALD_QTABLETMP = 's_%s_qtable.txt.tmp'
+PATTERN_GERALD_QCALREPORTTMP = 's_%s_qcalreport.txt.tmp'
+PATTERN_GERALD_SEQUENCETMP = 's_%s_sequence.txt.tmp'
+PATTERN_GERALD_LANEFINISHED = 's_%s_finished.txt'
+
+
+
+def _p2f(pattern, lane, tile=None, cycle=None):
+ """
+ Converts a pattern plus info into file names
+ """
+
+ # lane, and cycle provided (INVALID)
+ if tile is None and cycle is not None:
+ msg = "Handling of cycle without tile is not currently implemented."
+ raise ValueError, msg
+
+ # lane, tile, cycle provided
+ elif cycle:
+ return pattern % (lane,
+ "%04d" % (tile,),
+ "%02d" % (cycle,))
+
+ # lane, tile provided
+ elif tile:
+ return pattern % (lane, "%04d" % (tile,))
+
+ # lane provided
+ else:
+ return pattern % (lane)
+
+
+class GARunStatus(object):
+
+ def __init__(self, conf_filepath):
+ """
+ Given an eland config file in the top level directory
+ of a run, predicts the files that will be generated
+ during a run and provides methods for retrieving
+ (completed, total) for each step or entire run.
+ """
+ #print 'self._conf_filepath = %s' % (conf_filepath)
+ self._conf_filepath = conf_filepath
+ self._base_dir, junk = os.path.split(conf_filepath)
+ self._image_dir = os.path.join(self._base_dir, 'Images')
+
+ self.lanes = []
+ self.lane_read_length = {}
+ self.tiles = None
+ self.cycles = None
+
+ self.status = {}
+ self.status['firecrest'] = {}
+ self.status['bustard'] = {}
+ self.status['gerald'] = {}
+
+ self._process_config()
+ self._count_tiles()
+ self._count_cycles()
+ self._generate_expected()
+
+
+ def _process_config(self):
+ """
+ Grabs info from self._conf_filepath
+ """
+ f = open(self._conf_filepath, 'r')
+
+ for line in f:
+
+ #Skip comment lines for now.
+ if s_comment.search(line):
+ continue
+
+ mo = s_general_read_len.search(line)
+ if mo:
+ read_length = int(line[mo.end():])
+ #Handle general READ_LENGTH
+ for i in range(1,9):
+ self.lane_read_length[i] = read_length
+
+ mo = s_read_len.search(line)
+ if mo:
+ read_length = int(line[mo.end():])
+ lanes, junk = line.split(':')
+
+ #Convert lanes from string of lanes to list of lane #s.
+ lanes = [ int(i) for i in lanes ]
+
+
+ for lane in lanes:
+
+ #Keep track of which lanes are being run.
+ if lane not in self.lanes:
+ self.lanes.append(lane)
+
+ #Update with lane specific read lengths
+ self.lane_read_length[lane] = read_length
+
+ self.lanes.sort()
+
+
+ def _count_tiles(self):
+ """
+ Count the number of tiles being used
+ """
+ self.tiles = len(glob.glob(os.path.join(self._image_dir,
+ 'L001',
+ 'C1.1',
+ 's_1_*_a.tif')))
+
+ def _count_cycles(self):
+ """
+ Figures out the number of cycles that are available
+ """
+ #print 'self._image_dir = %s' % (self._image_dir)
+ cycle_dirs = glob.glob(os.path.join(self._image_dir, 'L001', 'C*.1'))
+ #print 'cycle_dirs = %s' % (cycle_dirs)
+ cycle_list = []
+ for cycle_dir in cycle_dirs:
+ junk, c = os.path.split(cycle_dir)
+ cycle_list.append(int(c[1:c.find('.')]))
+
+ self.cycles = max(cycle_list)
+
+
+
+
+ def _generate_expected(self):
+ """
+ generates a list of files we expect to find.
+ """
+
+ firecrest = self.status['firecrest']
+ bustard = self.status['bustard']
+ gerald = self.status['gerald']
+
+
+ for lane in self.lanes:
+ for tile in range(1,self.tiles+1):
+ for cycle in range(1, self.cycles+1):
+
+ ##########################
+ # LANE, TILE, CYCLE LAYER
+
+ # FIRECREST
+ firecrest[_p2f(PATTERN_FIRECREST_QCM, lane, tile, cycle)] = False
+
+
+ ###################
+ # LANE, TILE LAYER
+
+ # FIRECREST
+ firecrest[_p2f(PATTERN_FIRECREST_INT, lane, tile)] = False
+ firecrest[_p2f(PATTERN_FIRECREST_NSE, lane, tile)] = False
+ firecrest[_p2f(PATTERN_FIRECREST_POS, lane, tile)] = False
+ firecrest[_p2f(PATTERN_FIRECREST_IDX, lane, tile)] = False
+ firecrest[_p2f(PATTERN_FIRECREST_CLU1, lane, tile)] = False
+ firecrest[_p2f(PATTERN_FIRECREST_CLU2, lane, tile)] = False
+ firecrest[_p2f(PATTERN_FIRECREST_CLU3, lane, tile)] = False
+ firecrest[_p2f(PATTERN_FIRECREST_CLU4, lane, tile)] = False
+
+
+ # BUSTARD
+ bustard[_p2f(PATTERN_BUSTARD_SIG2, lane, tile)] = False
+ bustard[_p2f(PATTERN_BUSTARD_PRB, lane, tile)] = False
+
+
+ # GERALD
+ #gerald[_p2f(PATTERN_GERALD_ALLTMP, lane, tile)] = False
+ #gerald[_p2f(PATTERN_GERALD_QRAWTMP, lane, tile)] = False
+ #gerald[_p2f(PATTERN_GERALD_ALLPNGTMP, lane, tile)] = False
+ #gerald[_p2f(PATTERN_GERALD_ALIGNTMP, lane, tile)] = False
+ #gerald[_p2f(PATTERN_GERALD_QVALTMP, lane, tile)] = False
+ #gerald[_p2f(PATTERN_GERALD_SCORETMP, lane, tile)] = False
+ #gerald[_p2f(PATTERN_GERALD_PREALIGNTMP, lane, tile)] = False
+ #gerald[_p2f(PATTERN_GERALD_REALIGNTMP, lane, tile)] = False
+ #gerald[_p2f(PATTERN_GERALD_RESCORETMP, lane, tile)] = False
+ gerald[_p2f(PATTERN_GERALD_RESCOREPNG, lane, tile)] = False
+ #gerald[_p2f(PATTERN_GERALD_ERRORSTMPPNG, lane, tile)] = False
+ #gerald[_p2f(PATTERN_GERALD_QCALTMP, lane, tile)] = False
+ #gerald[_p2f(PATTERN_GERALD_QVAL, lane, tile)] = False
+
+ ###################
+ # LANE LAYER
+
+ # GERALD
+ #gerald[_p2f(PATTERN_GERALD_SEQPRETMP, lane)] = False
+ #gerald[_p2f(PATTERN_GERALD_RESULTTMP, lane)] = False
+ #gerald[_p2f(PATTERN_GERALD_SIGMEANSTMP, lane)] = False
+ gerald[_p2f(PATTERN_GERALD_CALLPNG, lane)] = False
+ gerald[_p2f(PATTERN_GERALD_ALLPNG, lane)] = False
+ gerald[_p2f(PATTERN_GERALD_PERCENTALLPNG, lane)] = False
+ gerald[_p2f(PATTERN_GERALD_PERCENTCALLPNG, lane)] = False
+ gerald[_p2f(PATTERN_GERALD_PERCENTBASEPNG, lane)] = False
+ #gerald[_p2f(PATTERN_GERALD_FILTTMP, lane)] = False
+ #gerald[_p2f(PATTERN_GERALD_FRAGTMP, lane)] = False
+ #gerald[_p2f(PATTERN_GERALD_QREPORTTMP, lane)] = False
+ #gerald[_p2f(PATTERN_GERALD_QTABLETMP, lane)] = False
+ #gerald[_p2f(PATTERN_GERALD_QCALREPORTTMP, lane)] = False
+ #gerald[_p2f(PATTERN_GERALD_SEQUENCETMP, lane)] = False
+ gerald[_p2f(PATTERN_GERALD_LANEFINISHED, lane)] = False
+
+
+
+ #################
+ # LOOPS FINISHED
+
+ # FIRECREST
+ firecrest['offsets_finished.txt'] = False
+ firecrest['finished.txt'] = False
+
+ # BUSTARD
+ bustard['finished.txt'] = False
+
+ # GERALD
+ gerald['tiles.txt'] = False
+ gerald['FullAll.htm'] = False
+ #gerald['All.htm.tmp'] = False
+ #gerald['Signal_Means.txt.tmp'] = False
+ #gerald['plotIntensity_for_IVC'] = False
+ #gerald['IVC.htm.tmp'] = False
+ gerald['FullError.htm'] = False
+ gerald['FullPerfect.htm'] = False
+ #gerald['Error.htm.tmp'] = False
+ #gerald['Perfect.htm.tmp'] = False
+ #gerald['Summary.htm.tmp'] = False
+ #gerald['Tile.htm.tmp'] = False
+ gerald['finished.txt'] = False
+
+ def statusFirecrest(self):
+ """
+ returns (<completed>, <total>)
+ """
+ firecrest = self.status['firecrest']
+ total = len(firecrest)
+ completed = firecrest.values().count(True)
+
+ return (completed, total)
+
+
+ def statusBustard(self):
+ """
+ returns (<completed>, <total>)
+ """
+ bustard = self.status['bustard']
+ total = len(bustard)
+ completed = bustard.values().count(True)
+
+ return (completed, total)
+
+
+ def statusGerald(self):
+ """
+ returns (<completed>, <total>)
+ """
+ gerald = self.status['gerald']
+ total = len(gerald)
+ completed = gerald.values().count(True)
+
+ return (completed, total)
+
+
+ def statusTotal(self):
+ """
+ returns (<completed>, <total>)
+ """
+ #f = firecrest c = completed
+ #b = bustard t = total
+ #g = gerald
+ fc, ft = self.statusFirecrest()
+ bc, bt = self.statusBustard()
+ gc, gt = self.statusGerald()
+
+ return (fc+bc+gc, ft+bt+gt)
+
+
+ def statusReport(self):
+ """
+ Generate the basic percent complete report
+ """
+ def _percentCompleted(completed, total):
+ """
+ Returns precent completed as float
+ """
+ return (completed / float(total)) * 100
+
+ fc, ft = self.statusFirecrest()
+ bc, bt = self.statusBustard()
+ gc, gt = self.statusGerald()
+ tc, tt = self.statusTotal()
+
+ fp = _percentCompleted(fc, ft)
+ bp = _percentCompleted(bc, bt)
+ gp = _percentCompleted(gc, gt)
+ tp = _percentCompleted(tc, tt)
+
+ report = ['Firecrest: %s%% (%s/%s)' % (fp, fc, ft),
+ ' Bustard: %s%% (%s/%s)' % (bp, bc, bt),
+ ' Gerald: %s%% (%s/%s)' % (gp, gc, gt),
+ '-----------------------',
+ ' Total: %s%% (%s/%s)' % (tp, tc, tt),
+ ]
+ return report
+
+ def updateFirecrest(self, filename):
+ """
+ Marks firecrest filename as being completed.
+ """
+ self.status['firecrest'][filename] = True
+
+
+ def updateBustard(self, filename):
+ """
+ Marks bustard filename as being completed.
+ """
+ self.status['bustard'][filename] = True
+
+
+ def updateGerald(self, filename):
+ """
+ Marks gerald filename as being completed.
+ """
+ self.status['gerald'][filename] = True
+
+
+
+##################################################
+# Functions to be called by Thread(target=<func>)
+def _cmdLineStatusMonitorFunc(conf_info):
+ """
+ Given a ConfigInfo object, provides status to stdout.
+
+ You should probably use startCmdLineStatusMonitor()
+ instead of ths function.
+
+ .. python:
+ def example_launch():
+ t = threading.Thread(target=_cmdLineStatusMonitorFunc,
+ args=[conf_info])
+ t.setDaemon(True)
+ t.start()
+ """
+ SLEEP_AMOUNT = 30
+
+ while 1:
+ if conf_info.status is None:
+ print "No status object yet."
+ time.sleep(SLEEP_AMOUNT)
+ continue
+
+ report = conf_info.status.statusReport()
+ print os.linesep.join(report)
+ print
+
+ time.sleep(SLEEP_AMOUNT)
+
+
+#############################################
+# Start monitor thread convenience functions
+def startCmdLineStatusMonitor(conf_info):
+ """
+ Starts a command line status monitor given a conf_info object.
+ """
+ t = threading.Thread(target=_cmdLineStatusMonitorFunc, args=[conf_info])
+ t.setDaemon(True)
+ t.start()
+
+from optparse import OptionParser
+def make_parser():
+ usage = "%prog: config file"
+
+ parser = OptionParser()
+ return parser
+
+def main(cmdline=None):
+ parser = make_parser()
+ opt, args = parser.parse_args(cmdline)
+
+ if len(args) != 1:
+ parser.error("need name of configuration file")
+
+ status = GARunStatus(args[0])
+ print os.linesep.join(status.statusReport())
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
+
--- /dev/null
+"""
+Core information needed to inspect a runfolder.
+"""
+from glob import glob
+import logging
+import os
+import re
+import shutil
+import stat
+import subprocess
+import sys
+import time
+
+try:
+ from xml.etree import ElementTree
+except ImportError, e:
+ from elementtree import ElementTree
+
+EUROPEAN_STRPTIME = "%d-%m-%Y"
+EUROPEAN_DATE_RE = "([0-9]{1,2}-[0-9]{1,2}-[0-9]{4,4})"
+VERSION_RE = "([0-9\.]+)"
+USER_RE = "([a-zA-Z0-9]+)"
+LANES_PER_FLOWCELL = 8
+
+from htsworkflow.util.alphanum import alphanum
+from htsworkflow.util.ethelp import indent, flatten
+
+class PipelineRun(object):
+ """
+ Capture "interesting" information about a pipeline run
+ """
+ XML_VERSION = 1
+ PIPELINE_RUN = 'PipelineRun'
+ FLOWCELL_ID = 'FlowcellID'
+
+ def __init__(self, pathname=None, xml=None):
+ if pathname is not None:
+ self.pathname = os.path.normpath(pathname)
+ else:
+ self.pathname = None
+ self._name = None
+ self._flowcell_id = None
+ self.image_analysis = None
+ self.bustard = None
+ self.gerald = None
+
+ if xml is not None:
+ self.set_elements(xml)
+
+ def _get_flowcell_id(self):
+ # extract flowcell ID
+ if self._flowcell_id is None:
+ config_dir = os.path.join(self.pathname, 'Config')
+ flowcell_id_path = os.path.join(config_dir, 'FlowcellId.xml')
+ if os.path.exists(flowcell_id_path):
+ flowcell_id_tree = ElementTree.parse(flowcell_id_path)
+ self._flowcell_id = flowcell_id_tree.findtext('Text')
+ else:
+ path_fields = self.pathname.split('_')
+ if len(path_fields) > 0:
+ # guessing last element of filename
+ flowcell_id = path_fields[-1]
+ else:
+ flowcell_id = 'unknown'
+
+ logging.warning(
+ "Flowcell id was not found, guessing %s" % (
+ flowcell_id))
+ self._flowcell_id = flowcell_id
+ return self._flowcell_id
+ flowcell_id = property(_get_flowcell_id)
+
+ def get_elements(self):
+ """
+ make one master xml file from all of our sub-components.
+ """
+ root = ElementTree.Element(PipelineRun.PIPELINE_RUN)
+ flowcell = ElementTree.SubElement(root, PipelineRun.FLOWCELL_ID)
+ flowcell.text = self.flowcell_id
+ root.append(self.image_analysis.get_elements())
+ root.append(self.bustard.get_elements())
+ root.append(self.gerald.get_elements())
+ return root
+
+ def set_elements(self, tree):
+ # this file gets imported by all the others,
+ # so we need to hide the imports to avoid a cyclic imports
+ from htsworkflow.pipelines import firecrest
+ from htsworkflow.pipelines import ipar
+ from htsworkflow.pipelines import bustard
+ from htsworkflow.pipelines import gerald
+
+ tag = tree.tag.lower()
+ if tag != PipelineRun.PIPELINE_RUN.lower():
+ raise ValueError('Pipeline Run Expecting %s got %s' % (
+ PipelineRun.PIPELINE_RUN, tag))
+ for element in tree:
+ tag = element.tag.lower()
+ if tag == PipelineRun.FLOWCELL_ID.lower():
+ self._flowcell_id = element.text
+ #ok the xword.Xword.XWORD pattern for module.class.constant is lame
+ # you should only have Firecrest or IPAR, never both of them.
+ elif tag == firecrest.Firecrest.FIRECREST.lower():
+ self.image_analysis = firecrest.Firecrest(xml=element)
+ elif tag == ipar.IPAR.IPAR.lower():
+ self.image_analysis = ipar.IPAR(xml=element)
+ elif tag == bustard.Bustard.BUSTARD.lower():
+ self.bustard = bustard.Bustard(xml=element)
+ elif tag == gerald.Gerald.GERALD.lower():
+ self.gerald = gerald.Gerald(xml=element)
+ else:
+ logging.warn('PipelineRun unrecognized tag %s' % (tag,))
+
+ def _get_run_name(self):
+ """
+ Given a run tuple, find the latest date and use that as our name
+ """
+ if self._name is None:
+ tmax = max(self.image_analysis.time, self.bustard.time, self.gerald.time)
+ timestamp = time.strftime('%Y-%m-%d', time.localtime(tmax))
+ self._name = 'run_'+self.flowcell_id+"_"+timestamp+'.xml'
+ return self._name
+ name = property(_get_run_name)
+
+ def save(self, destdir=None):
+ if destdir is None:
+ destdir = ''
+ logging.info("Saving run report "+ self.name)
+ xml = self.get_elements()
+ indent(xml)
+ dest_pathname = os.path.join(destdir, self.name)
+ ElementTree.ElementTree(xml).write(dest_pathname)
+
+ def load(self, filename):
+ logging.info("Loading run report from " + filename)
+ tree = ElementTree.parse(filename).getroot()
+ self.set_elements(tree)
+
+def load_pipeline_run_xml(pathname):
+ """
+ Load and instantiate a Pipeline run from a run xml file
+
+ :Parameters:
+ - `pathname` : location of an run xml file
+
+ :Returns: initialized PipelineRun object
+ """
+ tree = ElementTree.parse(pathname).getroot()
+ run = PipelineRun(xml=tree)
+ return run
+
+def get_runs(runfolder):
+ """
+ Search through a run folder for all the various sub component runs
+ and then return a PipelineRun for each different combination.
+
+ For example if there are two different GERALD runs, this will
+ generate two different PipelineRun objects, that differ
+ in there gerald component.
+ """
+ from htsworkflow.pipelines import firecrest
+ from htsworkflow.pipelines import ipar
+ from htsworkflow.pipelines import bustard
+ from htsworkflow.pipelines import gerald
+
+ def scan_post_image_analysis(runs, runfolder, image_analysis, pathname):
+ logging.info("Looking for bustard directories in %s" % (pathname,))
+ bustard_glob = os.path.join(pathname, "Bustard*")
+ for bustard_pathname in glob(bustard_glob):
+ logging.info("Found bustard directory %s" % (bustard_pathname,))
+ b = bustard.bustard(bustard_pathname)
+ gerald_glob = os.path.join(bustard_pathname, 'GERALD*')
+ logging.info("Looking for gerald directories in %s" % (pathname,))
+ for gerald_pathname in glob(gerald_glob):
+ logging.info("Found gerald directory %s" % (gerald_pathname,))
+ try:
+ g = gerald.gerald(gerald_pathname)
+ p = PipelineRun(runfolder)
+ p.image_analysis = image_analysis
+ p.bustard = b
+ p.gerald = g
+ runs.append(p)
+ except IOError, e:
+ logging.error("Ignoring " + str(e))
+
+ datadir = os.path.join(runfolder, 'Data')
+
+ logging.info('Searching for runs in ' + datadir)
+ runs = []
+ # scan for firecrest directories
+ for firecrest_pathname in glob(os.path.join(datadir,"*Firecrest*")):
+ logging.info('Found firecrest in ' + datadir)
+ image_analysis = firecrest.firecrest(firecrest_pathname)
+ if image_analysis is None:
+ logging.warn(
+ "%s is an empty or invalid firecrest directory" % (firecrest_pathname,)
+ )
+ else:
+ scan_post_image_analysis(
+ runs, runfolder, image_analysis, firecrest_pathname
+ )
+ # scan for IPAR directories
+ for ipar_pathname in glob(os.path.join(datadir,"IPAR_*")):
+ logging.info('Found ipar directories in ' + datadir)
+ image_analysis = ipar.ipar(ipar_pathname)
+ if image_analysis is None:
+ logging.warn(
+ "%s is an empty or invalid IPAR directory" %(ipar_pathname,)
+ )
+ else:
+ scan_post_image_analysis(
+ runs, runfolder, image_analysis, ipar_pathname
+ )
+
+ return runs
+
+def get_specific_run(gerald_dir):
+ """
+ Given a gerald directory, construct a PipelineRun out of its parents
+
+ Basically this allows specifying a particular run instead of the previous
+ get_runs which scans a runfolder for various combinations of
+ firecrest/ipar/bustard/gerald runs.
+ """
+ from htsworkflow.pipelines import firecrest
+ from htsworkflow.pipelines import ipar
+ from htsworkflow.pipelines import bustard
+ from htsworkflow.pipelines import gerald
+
+ bustard_dir = os.path.abspath(os.path.join(gerald_dir, '..'))
+ image_dir = os.path.abspath(os.path.join(gerald_dir, '..', '..'))
+
+ runfolder_dir = os.path.abspath(os.path.join(image_dir, '..','..'))
+
+ logging.info('--- use-run detected options ---')
+ logging.info('runfolder: %s' % (runfolder_dir,))
+ logging.info('image_dir: %s' % (image_dir,))
+ logging.info('bustard_dir: %s' % (bustard_dir,))
+ logging.info('gerald_dir: %s' % (gerald_dir,))
+
+ # find our processed image dir
+ image_run = None
+ # split into parent, and leaf directory
+ # leaf directory should be an IPAR or firecrest directory
+ data_dir, short_image_dir = os.path.split(image_dir)
+ logging.info('data_dir: %s' % (data_dir,))
+ logging.info('short_iamge_dir: %s' %(short_image_dir,))
+
+ # guess which type of image processing directory we have by looking
+ # in the leaf directory name
+ if re.search('Firecrest', short_image_dir, re.IGNORECASE) is not None:
+ image_run = firecrest.firecrest(image_dir)
+ elif re.search('IPAR', short_image_dir, re.IGNORECASE) is not None:
+ image_run = ipar.ipar(image_dir)
+ # if we din't find a run, report the error and return
+ if image_run is None:
+ msg = '%s does not contain an image processing step' % (image_dir,)
+ logging.error(msg)
+ return None
+
+ # find our base calling
+ base_calling_run = bustard.bustard(bustard_dir)
+ if base_calling_run is None:
+ logging.error('%s does not contain a bustard run' % (bustard_dir,))
+ return None
+
+ # find alignments
+ gerald_run = gerald.gerald(gerald_dir)
+ if gerald_run is None:
+ logging.error('%s does not contain a gerald run' % (gerald_dir,))
+ return None
+
+ p = PipelineRun(runfolder_dir)
+ p.image_analysis = image_run
+ p.bustard = base_calling_run
+ p.gerald = gerald_run
+
+ logging.info('Constructed PipelineRun from %s' % (gerald_dir,))
+ return p
+
+def extract_run_parameters(runs):
+ """
+ Search through runfolder_path for various runs and grab their parameters
+ """
+ for run in runs:
+ run.save()
+
+def summarize_mapped_reads(genome_map, mapped_reads):
+ """
+ Summarize per chromosome reads into a genome count
+ But handle spike-in/contamination symlinks seperately.
+ """
+ summarized_reads = {}
+ genome_reads = 0
+ genome = 'unknown'
+ for k, v in mapped_reads.items():
+ path, k = os.path.split(k)
+ if len(path) > 0 and not genome_map.has_key(path):
+ genome = path
+ genome_reads += v
+ else:
+ summarized_reads[k] = summarized_reads.setdefault(k, 0) + v
+ summarized_reads[genome] = genome_reads
+ return summarized_reads
+
+def summarize_lane(gerald, lane_id):
+ report = []
+ summary_results = gerald.summary.lane_results
+ for end in range(len(summary_results)):
+ eland_result = gerald.eland_results.results[end][lane_id]
+ report.append("Sample name %s" % (eland_result.sample_name))
+ report.append("Lane id %s end %s" % (eland_result.lane_id, end))
+ cluster = summary_results[end][eland_result.lane_id].cluster
+ report.append("Clusters %d +/- %d" % (cluster[0], cluster[1]))
+ report.append("Total Reads: %d" % (eland_result.reads))
+
+ if hasattr(eland_result, 'match_codes'):
+ mc = eland_result.match_codes
+ nm = mc['NM']
+ nm_percent = float(nm)/eland_result.reads * 100
+ qc = mc['QC']
+ qc_percent = float(qc)/eland_result.reads * 100
+
+ report.append("No Match: %d (%2.2g %%)" % (nm, nm_percent))
+ report.append("QC Failed: %d (%2.2g %%)" % (qc, qc_percent))
+ report.append('Unique (0,1,2 mismatches) %d %d %d' % \
+ (mc['U0'], mc['U1'], mc['U2']))
+ report.append('Repeat (0,1,2 mismatches) %d %d %d' % \
+ (mc['R0'], mc['R1'], mc['R2']))
+
+ if hasattr(eland_result, 'genome_map'):
+ report.append("Mapped Reads")
+ mapped_reads = summarize_mapped_reads(eland_result.genome_map, eland_result.mapped_reads)
+ for name, counts in mapped_reads.items():
+ report.append(" %s: %d" % (name, counts))
+
+ report.append('')
+ return report
+
+def summary_report(runs):
+ """
+ Summarize cluster numbers and mapped read counts for a runfolder
+ """
+ report = []
+ for run in runs:
+ # print a run name?
+ report.append('Summary for %s' % (run.name,))
+ # sort the report
+ eland_keys = run.gerald.eland_results.results[0].keys()
+ eland_keys.sort(alphanum)
+
+ for lane_id in eland_keys:
+ report.extend(summarize_lane(run.gerald, lane_id))
+ report.append('---')
+ report.append('')
+ return os.linesep.join(report)
+
+def is_compressed(filename):
+ if os.path.splitext(filename)[1] == ".gz":
+ return True
+ elif os.path.splitext(filename)[1] == '.bz2':
+ return True
+ else:
+ return False
+
+def extract_results(runs, output_base_dir=None):
+ if output_base_dir is None:
+ output_base_dir = os.getcwd()
+
+ for r in runs:
+ result_dir = os.path.join(output_base_dir, r.flowcell_id)
+ logging.info("Using %s as result directory" % (result_dir,))
+ if not os.path.exists(result_dir):
+ os.mkdir(result_dir)
+
+ # create cycle_dir
+ cycle = "C%d-%d" % (r.image_analysis.start, r.image_analysis.stop)
+ logging.info("Filling in %s" % (cycle,))
+ cycle_dir = os.path.join(result_dir, cycle)
+ if os.path.exists(cycle_dir):
+ logging.error("%s already exists, not overwriting" % (cycle_dir,))
+ continue
+ else:
+ os.mkdir(cycle_dir)
+
+ # copy stuff out of the main run
+ g = r.gerald
+
+ # save run file
+ r.save(cycle_dir)
+
+ # Copy Summary.htm
+ summary_path = os.path.join(r.gerald.pathname, 'Summary.htm')
+ if os.path.exists(summary_path):
+ logging.info('Copying %s to %s' % (summary_path, cycle_dir))
+ shutil.copy(summary_path, cycle_dir)
+ else:
+ logging.info('Summary file %s was not found' % (summary_path,))
+
+ # tar score files
+ score_files = []
+
+ # check for g.pathname/Temp a new feature of 1.1rc1
+ scores_path = g.pathname
+ scores_path_temp = os.path.join(scores_path, 'Temp')
+ if os.path.isdir(scores_path_temp):
+ scores_path = scores_path_temp
+
+ # hopefully we have a directory that contains s_*_score files
+ for f in os.listdir(scores_path):
+ if re.match('.*_score.txt', f):
+ score_files.append(f)
+
+ tar_cmd = ['/bin/tar', 'c'] + score_files
+ bzip_cmd = [ 'bzip2', '-9', '-c' ]
+ tar_dest_name =os.path.join(cycle_dir, 'scores.tar.bz2')
+ tar_dest = open(tar_dest_name, 'w')
+ logging.info("Compressing score files from %s" % (scores_path,))
+ logging.info("Running tar: " + " ".join(tar_cmd[:10]))
+ logging.info("Running bzip2: " + " ".join(bzip_cmd))
+ logging.info("Writing to %s" %(tar_dest_name))
+
+ env = {'BZIP': '-9'}
+ tar = subprocess.Popen(tar_cmd, stdout=subprocess.PIPE, shell=False, env=env,
+ cwd=scores_path)
+ bzip = subprocess.Popen(bzip_cmd, stdin=tar.stdout, stdout=tar_dest)
+ tar.wait()
+
+ # copy & bzip eland files
+ for lanes_dictionary in g.eland_results.results:
+ for eland_lane in lanes_dictionary.values():
+ source_name = eland_lane.pathname
+ path, name = os.path.split(eland_lane.pathname)
+ dest_name = os.path.join(cycle_dir, name)
+ logging.info("Saving eland file %s to %s" % \
+ (source_name, dest_name))
+
+ if is_compressed(name):
+ logging.info('Already compressed, Saving to %s' % (dest_name, ))
+ shutil.copy(source_name, dest_name)
+ else:
+ # not compressed
+ dest_name += '.bz2'
+ args = ['bzip2', '-9', '-c', source_name]
+ logging.info('Running: %s' % ( " ".join(args) ))
+ bzip_dest = open(dest_name, 'w')
+ bzip = subprocess.Popen(args, stdout=bzip_dest)
+ logging.info('Saving to %s' % (dest_name, ))
+ bzip.wait()
+
+def rm_list(files, dry_run=True):
+ for f in files:
+ if os.path.exists(f):
+ logging.info('deleting %s' % (f,))
+ if not dry_run:
+ if os.path.isdir(f):
+ shutil.rmtree(f)
+ else:
+ os.unlink(f)
+ else:
+ logging.warn("%s doesn't exist."% (f,))
+
+def clean_runs(runs, dry_run=True):
+ """
+ Clean up run folders to optimize for compression.
+ """
+ if dry_run:
+ logging.info('In dry-run mode')
+
+ for run in runs:
+ logging.info('Cleaninging %s' % (run.pathname,))
+ # rm RunLog*.xml
+ runlogs = glob(os.path.join(run.pathname, 'RunLog*xml'))
+ rm_list(runlogs, dry_run)
+ # rm pipeline_*.txt
+ pipeline_logs = glob(os.path.join(run.pathname, 'pipeline*.txt'))
+ rm_list(pipeline_logs, dry_run)
+ # rm gclog.txt?
+ # rm NetCopy.log? Isn't this robocopy?
+ logs = glob(os.path.join(run.pathname, '*.log'))
+ rm_list(logs, dry_run)
+ # rm nfn.log?
+ # Calibration
+ calibration_dir = glob(os.path.join(run.pathname, 'Calibration_*'))
+ rm_list(calibration_dir, dry_run)
+ # rm Images/L*
+ logging.info("Cleaning images")
+ image_dirs = glob(os.path.join(run.pathname, 'Images', 'L*'))
+ rm_list(image_dirs, dry_run)
+ # cd Data/C1-*_Firecrest*
+ logging.info("Cleaning intermediate files")
+ # make clean_intermediate
+ if os.path.exists(os.path.join(run.image_analysis.pathname, 'Makefile')):
+ clean_process = subprocess.Popen(['make', 'clean_intermediate'],
+ cwd=run.image_analysis.pathname,)
+ clean_process.wait()
+
+
+
--- /dev/null
+"""
+Analyze the Summary.htm file produced by GERALD
+"""
+import types
+from pprint import pprint
+
+from htsworkflow.pipelines.runfolder import ElementTree
+from htsworkflow.util.ethelp import indent, flatten
+
+nan = float('nan')
+
+class Summary(object):
+ """
+ Extract some useful information from the Summary.htm file
+ """
+ XML_VERSION = 3
+ SUMMARY = 'Summary'
+
+ class LaneResultSummary(object):
+ """
+ Parse the LaneResultSummary table out of Summary.htm
+ Mostly for the cluster number
+ """
+ LANE_RESULT_SUMMARY = 'LaneResultSummary'
+ TAGS = {
+ 'LaneYield': 'lane_yield',
+ 'Cluster': 'cluster', # Raw
+ 'ClusterPF': 'cluster_pass_filter',
+ 'AverageFirstCycleIntensity': 'average_first_cycle_intensity',
+ 'PercentIntensityAfter20Cycles': 'percent_intensity_after_20_cycles',
+ 'PercentPassFilterClusters': 'percent_pass_filter_clusters',
+ 'PercentPassFilterAlign': 'percent_pass_filter_align',
+ 'AverageAlignmentScore': 'average_alignment_score',
+ 'PercentErrorRate': 'percent_error_rate'
+ }
+
+ def __init__(self, html=None, xml=None):
+ self.lane = None
+ self.end = 0
+ self.lane_yield = None
+ self.cluster = None
+ self.cluster_pass_filter = None
+ self.average_first_cycle_intensity = None
+ self.percent_intensity_after_20_cycles = None
+ self.percent_pass_filter_clusters = None
+ self.percent_pass_filter_align = None
+ self.average_alignment_score = None
+ self.percent_error_rate = None
+
+ if html is not None:
+ self.set_elements_from_html(html)
+ if xml is not None:
+ self.set_elements(xml)
+
+ def set_elements_from_html(self, data):
+ if not len(data) in (8,10):
+ raise RuntimeError("Summary.htm file format changed, len(data)=%d" % (len(data),))
+
+ # same in pre-0.3.0 Summary file and 0.3 summary file
+ self.lane = int(data[0])
+
+ if len(data) == 8:
+ parsed_data = [ parse_mean_range(x) for x in data[1:] ]
+ # this is the < 0.3 Pipeline version
+ self.cluster = parsed_data[0]
+ self.average_first_cycle_intensity = parsed_data[1]
+ self.percent_intensity_after_20_cycles = parsed_data[2]
+ self.percent_pass_filter_clusters = parsed_data[3]
+ self.percent_pass_filter_align = parsed_data[4]
+ self.average_alignment_score = parsed_data[5]
+ self.percent_error_rate = parsed_data[6]
+ elif len(data) == 10:
+ parsed_data = [ parse_mean_range(x) for x in data[2:] ]
+ # this is the >= 0.3 summary file
+ self.lane_yield = data[1]
+ self.cluster = parsed_data[0]
+ self.cluster_pass_filter = parsed_data[1]
+ self.average_first_cycle_intensity = parsed_data[2]
+ self.percent_intensity_after_20_cycles = parsed_data[3]
+ self.percent_pass_filter_clusters = parsed_data[4]
+ self.percent_pass_filter_align = parsed_data[5]
+ self.average_alignment_score = parsed_data[6]
+ self.percent_error_rate = parsed_data[7]
+
+ def get_elements(self):
+ lane_result = ElementTree.Element(
+ Summary.LaneResultSummary.LANE_RESULT_SUMMARY,
+ {'lane': str(self.lane), 'end': str(self.end)})
+ for tag, variable_name in Summary.LaneResultSummary.TAGS.items():
+ value = getattr(self, variable_name)
+ if value is None:
+ continue
+ # it looks like a sequence
+ elif type(value) in (types.TupleType, types.ListType):
+ element = make_mean_range_element(
+ lane_result,
+ tag,
+ *value
+ )
+ else:
+ element = ElementTree.SubElement(lane_result, tag)
+ element.text = value
+ return lane_result
+
+ def set_elements(self, tree):
+ if tree.tag != Summary.LaneResultSummary.LANE_RESULT_SUMMARY:
+ raise ValueError('Expected %s' % (
+ Summary.LaneResultSummary.LANE_RESULT_SUMMARY))
+ self.lane = int(tree.attrib['lane'])
+ # default to the first end, for the older summary files
+ # that are single ended
+ self.end = int(tree.attrib.get('end', 0))
+ tags = Summary.LaneResultSummary.TAGS
+ for element in list(tree):
+ try:
+ variable_name = tags[element.tag]
+ setattr(self, variable_name,
+ parse_summary_element(element))
+ except KeyError, e:
+ logging.warn('Unrecognized tag %s' % (element.tag,))
+
+ def __init__(self, filename=None, xml=None):
+ # lane results is a list of 1 or 2 ends containing
+ # a dictionary of all the lanes reported in this
+ # summary file
+ self.lane_results = [{}]
+
+ if filename is not None:
+ self._extract_lane_results(filename)
+ if xml is not None:
+ self.set_elements(xml)
+
+ def __getitem__(self, key):
+ return self.lane_results[key]
+
+ def __len__(self):
+ return len(self.lane_results)
+
+ def _flattened_row(self, row):
+ """
+ flatten the children of a <tr>...</tr>
+ """
+ return [flatten(x) for x in row.getchildren() ]
+
+ def _parse_table(self, table):
+ """
+ assumes the first line is the header of a table,
+ and that the remaining rows are data
+ """
+ rows = table.getchildren()
+ data = []
+ for r in rows:
+ data.append(self._flattened_row(r))
+ return data
+
+ def _extract_named_tables(self, pathname):
+ """
+ extract all the 'named' tables from a Summary.htm file
+ and return as a dictionary
+
+ Named tables are <h2>...</h2><table>...</table> pairs
+ The contents of the h2 tag is considered to the name
+ of the table.
+ """
+ # tree = ElementTree.parse(pathname).getroot()
+ # hack for 1.1rc1, this should be removed when possible.
+ file_body = open(pathname).read()
+ file_body = file_body.replace('CHASTITY<=', 'CHASTITY<=')
+ tree = ElementTree.fromstring(file_body)
+ body = tree.find('body')
+ tables = {}
+ for i in range(len(body)):
+ if body[i].tag == 'h2' and body[i+1].tag == 'table':
+ # we have an interesting table
+ name = flatten(body[i])
+ table = body[i+1]
+ data = self._parse_table(table)
+ tables[name] = data
+ return tables
+
+ def _extract_lane_results(self, pathname):
+ tables = self._extract_named_tables(pathname)
+ table_names = [ ('Lane Results Summary', 0),
+ ('Lane Results Summary : Read 1', 0),
+ ('Lane Results Summary : Read 2', 1),]
+ for name, end in table_names:
+ if tables.has_key(name):
+ self._extract_lane_results_for_end(tables, name, end)
+
+ def _extract_lane_results_for_end(self, tables, table_name, end):
+ """
+ extract the Lane Results Summary table
+ """
+ # parse lane result summary
+ lane_summary = tables[table_name]
+ # this is version 1 of the summary file
+ if len(lane_summary[-1]) == 8:
+ # strip header
+ headers = lane_summary[0]
+ # grab the lane by lane data
+ lane_summary = lane_summary[1:]
+
+ # len(lane_summary[-1] = 10 is version 2 of the summary file
+ # = 9 is version 3 of the Summary.htm file
+ elif len(lane_summary[-1]) in (9, 10):
+ # lane_summary[0] is a different less specific header row
+ headers = lane_summary[1]
+ lane_summary = lane_summary[2:10]
+ # after the last lane, there's a set of chip wide averages
+
+ # append an extra dictionary if needed
+ if len(self.lane_results) < (end + 1):
+ self.lane_results.append({})
+
+ for r in lane_summary:
+ lrs = Summary.LaneResultSummary(html=r)
+ lrs.end = end
+ self.lane_results[lrs.end][lrs.lane] = lrs
+
+ def get_elements(self):
+ summary = ElementTree.Element(Summary.SUMMARY,
+ {'version': unicode(Summary.XML_VERSION)})
+ for end in self.lane_results:
+ for lane in end.values():
+ summary.append(lane.get_elements())
+ return summary
+
+ def set_elements(self, tree):
+ if tree.tag != Summary.SUMMARY:
+ return ValueError("Expected %s" % (Summary.SUMMARY,))
+ xml_version = int(tree.attrib.get('version', 0))
+ if xml_version > Summary.XML_VERSION:
+ logging.warn('Summary XML tree is a higher version than this class')
+ for element in list(tree):
+ lrs = Summary.LaneResultSummary()
+ lrs.set_elements(element)
+ if len(self.lane_results) < (lrs.end + 1):
+ self.lane_results.append({})
+ self.lane_results[lrs.end][lrs.lane] = lrs
+
+ def is_paired_end(self):
+ return len(self.lane_results) == 2
+
+ def dump(self):
+ """
+ Debugging function, report current object
+ """
+ pass
+
+def tonumber(v):
+ """
+ Convert a value to int if its an int otherwise a float.
+ """
+ try:
+ v = int(v)
+ except ValueError, e:
+ v = float(v)
+ return v
+
+def parse_mean_range(value):
+ """
+ Parse values like 123 +/- 4.5
+ """
+ if value.strip() == 'unknown':
+ return nan, nan
+
+ values = value.split()
+ if len(values) == 1:
+ if values[0] == '+/-':
+ return nan,nan
+ else:
+ return tonumber(values[0])
+
+ average, pm, deviation = values
+ if pm != '+/-':
+ raise RuntimeError("Summary.htm file format changed")
+ return tonumber(average), tonumber(deviation)
+
+def make_mean_range_element(parent, name, mean, deviation):
+ """
+ Make an ElementTree subelement <Name mean='mean', deviation='deviation'/>
+ """
+ element = ElementTree.SubElement(parent, name,
+ { 'mean': unicode(mean),
+ 'deviation': unicode(deviation)})
+ return element
+
+def parse_mean_range_element(element):
+ """
+ Grab mean/deviation out of element
+ """
+ return (tonumber(element.attrib['mean']),
+ tonumber(element.attrib['deviation']))
+
+def parse_summary_element(element):
+ """
+ Determine if we have a simple element or a mean/deviation element
+ """
+ if len(element.attrib) > 0:
+ return parse_mean_range_element(element)
+ else:
+ return element.text
--- /dev/null
+"""
+Create simulated solexa/illumina runfolders for testing
+"""
+
+import os
+import shutil
+
+TEST_CODE_DIR = os.path.split(__file__)[0]
+TESTDATA_DIR = os.path.join(TEST_CODE_DIR, 'testdata')
+LANE_LIST = range(1,9)
+
+def make_firecrest_dir(data_dir, version="1.9.2", start=1, stop=37):
+ firecrest_dir = os.path.join(data_dir,
+ 'C%d-%d_Firecrest%s_12-04-2008_diane' % (start, stop, version)
+ )
+ os.mkdir(firecrest_dir)
+ return firecrest_dir
+
+def make_ipar_dir(data_dir, version='1.01'):
+ """
+ Construct an artificial ipar parameter file and directory
+ """
+ ipar1_01_file = os.path.join(TESTDATA_DIR, 'IPAR1.01.params')
+ shutil.copy(ipar1_01_file, os.path.join(data_dir, '.params'))
+
+ ipar_dir = os.path.join(data_dir, 'IPAR_%s' % (version,))
+ if not os.path.exists(ipar_dir):
+ os.mkdir(ipar_dir)
+ return ipar_dir
+
+def make_flowcell_id(runfolder_dir, flowcell_id=None):
+ if flowcell_id is None:
+ flowcell_id = '207BTAAXY'
+
+ config = """<?xml version="1.0"?>
+<FlowcellId>
+ <Text>%s</Text>
+</FlowcellId>""" % (flowcell_id,)
+ config_dir = os.path.join(runfolder_dir, 'Config')
+
+ if not os.path.exists(config_dir):
+ os.mkdir(config_dir)
+ pathname = os.path.join(config_dir, 'FlowcellId.xml')
+ f = open(pathname,'w')
+ f.write(config)
+ f.close()
+
+def make_bustard_config132(gerald_dir):
+ source = os.path.join(TESTDATA_DIR, 'bustard-config132.xml')
+ destination = os.path.join(gerald_dir, 'config.xml')
+ shutil.copy(source, destination)
+
+def make_matrix(matrix_filename):
+ contents = """# Auto-generated frequency response matrix
+> A
+> C
+> G
+> T
+0.77 0.15 -0.04 -0.04
+0.76 1.02 -0.05 -0.06
+-0.10 -0.10 1.17 -0.03
+-0.13 -0.12 0.80 1.27
+"""
+ f = open(matrix_filename, 'w')
+ f.write(contents)
+ f.close()
+
+def make_phasing_params(bustard_dir):
+ for lane in range(1,9):
+ pathname = os.path.join(bustard_dir, 'params%d.xml' % (lane))
+ f = open(pathname, 'w')
+ f.write("""<Parameters>
+ <Phasing>0.009900</Phasing>
+ <Prephasing>0.003500</Prephasing>
+</Parameters>
+""")
+ f.close()
+
+def make_gerald_config_026(gerald_dir):
+ source = os.path.join(TESTDATA_DIR, 'gerald_config_0.2.6.xml')
+ destination = os.path.join(gerald_dir, 'config.xml')
+ shutil.copy(source, destination)
+
+def make_gerald_config_100(gerald_dir):
+ source = os.path.join(TESTDATA_DIR, 'gerald_config_1.0.xml')
+ destination = os.path.join(gerald_dir, 'config.xml')
+ shutil.copy(source, destination)
+
+def make_summary_htm_100(gerald_dir):
+ source = os.path.join(TESTDATA_DIR, 'Summary-pipeline100.htm')
+ destination = os.path.join(gerald_dir, 'Summary.htm')
+ shutil.copy(source, destination)
+
+def make_summary_htm_110(gerald_dir):
+ source = os.path.join(TESTDATA_DIR, 'Summary-pipeline110.htm')
+ destination = os.path.join(gerald_dir, 'Summary.htm')
+ shutil.copy(source, destination)
+
+def make_summary_paired_htm(gerald_dir):
+ source = os.path.join(TESTDATA_DIR, 'Summary-paired-pipeline110.htm')
+ destination = os.path.join(gerald_dir, 'Summary.htm')
+ shutil.copy(source, destination)
+
+def make_summary_ipar130_htm(gerald_dir):
+ source = os.path.join(TESTDATA_DIR, 'Summary-ipar130.htm')
+ destination = os.path.join(gerald_dir, 'Summary.htm')
+ shutil.copy(source, destination)
+
+def make_eland_results(gerald_dir):
+ eland_result = """>HWI-EAS229_24_207BTAAXX:1:7:599:759 ACATAGNCACAGACATAAACATAGACATAGAC U0 1 1 3 chrUextra.fa 28189829 R D.
+>HWI-EAS229_24_207BTAAXX:1:7:205:842 AAACAANNCTCCCAAACACGTAAACTGGAAAA U1 0 1 0 chr2L.fa 8796855 R DD 24T
+>HWI-EAS229_24_207BTAAXX:1:7:776:582 AGCTCANCCGATCGAAAACCTCNCCAAGCAAT NM 0 0 0
+>HWI-EAS229_24_207BTAAXX:1:7:205:842 AAACAANNCTCCCAAACACGTAAACTGGAAAA U1 0 1 0 Lambda.fa 8796855 R DD 24T
+"""
+ for i in range(1,9):
+ pathname = os.path.join(gerald_dir,
+ 's_%d_eland_result.txt' % (i,))
+ f = open(pathname, 'w')
+ f.write(eland_result)
+ f.close()
+
+def make_eland_multi(gerald_dir, paired=False, lane_list=LANE_LIST):
+ eland_multi = [""">HWI-EAS229_60_30DP9AAXX:1:1:1221:788 AAGATATCTACGACGTGGTATGGCGGTGTCTGGTCGT NM
+>HWI-EAS229_60_30DP9AAXX:1:1:931:747 AAAAAAGCAAATTTCATTCACATGTTCTGTGTTCATA 1:0:2 chr5.fa:55269838R0
+>HWI-EAS229_60_30DP9AAXX:1:1:1121:379 AGAAGAGACATTAAGAGTTCCTGAAATTTATATCTGG 2:1:0 chr16.fa:46189180R1,chr7.fa:122968519R0,chr8.fa:48197174F0
+>HWI-EAS229_60_30DP9AAXX:1:1:892:1155 ACATTCTCCTTTCCTTCTGAAGTTTTTACGATTCTTT 0:9:10 chr10.fa:114298201F1,chr12.fa:8125072F1,19500297F2,42341293R2,chr13.fa:27688155R2,95069772R1,chr15.fa:51016475F2,chr16.fa:27052155F2,chr1.fa:192426217R2,chr21.fa:23685310R2,chr2.fa:106680068F1,chr3.fa:185226695F2,chr4.fa:106626808R2,chr5.fa:14704894F1,43530779F1,126543189F2,chr6.fa:74284101F1,chr7.fa:22516603F1,chr9.fa:134886204R
+>HWI-EAS229_60_30DP9AAXX:1:1:931:747 AAAAAAGCAAATTTCATTCACATGTTCTGTGTTCATA 1:0:0 spike.fa/sample1:55269838R0
+>HWI-EAS229_60_30DP9AAXX:1:1:931:747 AAAAAAGCAAATTTCATTCACATGTTCTGTGTTCATA 1:0:0 spike.fa/sample2:55269838R0
+""", """>HWI-EAS229_60_30DP9AAXX:1:1:1221:788 AAGATATCTACGACGTGGTATGGCGGTGTCTGGTCGT NM
+>HWI-EAS229_60_30DP9AAXX:1:1:1221:788 NNNNNNNNNNNNNNGTGGTATGGCGGTGTCTGGTCGT QC
+>HWI-EAS229_60_30DP9AAXX:1:1:931:747 AAAAAAGCAAATTTCATTCACATGTTCTGTGTTCATA 1:0:2 chr5.fa:55269838R0
+>HWI-EAS229_60_30DP9AAXX:1:1:1121:379 AGAAGAGACATTAAGAGTTCCTGAAATTTATATCTGG 2:1:0 chr16.fa:46189180R1,chr7.fa:122968519R0,chr8.fa:48197174F0,chr7.fa:22516603F1,chr9.fa:134886204R
+>HWI-EAS229_60_30DP9AAXX:1:1:892:1155 ACATTCTCCTTTCCTTCTGAAGTTTTTACGATTCTTT 0:9:10 chr10.fa:114298201F1,chr12.fa:8125072F1,19500297F2,42341293R2,chr13.fa:27688155R2,95069772R1,chr15.fa:51016475F2,chr16.fa:27052155F2,chr1.fa:192426217R2,chr21.fa:23685310R2,chr2.fa:106680068F1,chr3.fa:185226695F2,chr4.fa:106626808R2,chr5.fa:14704894F1,43530779F1,126543189F2,chr6.fa:74284101F1
+>HWI-EAS229_60_30DP9AAXX:1:1:931:747 AAAAAAGCAAATTTCATTCACATGTTCTGTGTTCATA 1:0:0 spike.fa/sample1:55269838R0
+>HWI-EAS229_60_30DP9AAXX:1:1:931:747 AAAAAAGCAAATTTCATTCACATGTTCTGTGTTCATA 1:0:0 spike.fa/sample2:55269838R0
+"""]
+ if paired:
+ for e in [1,2]:
+ for i in lane_list:
+ pathname = os.path.join(gerald_dir,
+ 's_%d_%d_eland_multi.txt' % (i,e))
+ f = open(pathname, 'w')
+ f.write(eland_multi[e-1])
+ f.close()
+ else:
+ for i in lane_list:
+ pathname = os.path.join(gerald_dir,
+ 's_%d_eland_multi.txt' % (i,))
+ f = open(pathname, 'w')
+ f.write(eland_multi[0])
+ f.close()
+
+def make_scarf(gerald_dir, lane_list=LANE_LIST):
+ seq = """HWI-EAS229_92_30VNBAAXX:1:1:0:161:NCAATTACACGACGCTAGCCCTAAAGCTATTTCGAGG:E[aaaabb^a\a_^^a[S`ba_WZUXaaaaaaUKPER
+HWI-EAS229_92_30VNBAAXX:1:1:0:447:NAGATGCGCATTTGAAGTAGGAGCAAAAGATCAAGGT:EUabaab^baabaaaaaaaa^^Uaaaaa\aaaa__`a
+HWI-EAS229_92_30VNBAAXX:1:1:0:1210:NATAGCCTCTATAGAAGCCACTATTATTTTTTTCTTA:EUa`]`baaaaa^XQU^a`S``S_`J_aaaaaabb^V
+HWI-EAS229_92_30VNBAAXX:1:1:0:1867:NTGGAGCAGATATAAAAACAGATGGTGACGTTGAAGT:E[^UaaaUaba^aaa^aa^XV\baaLaLaaaaQVXV^
+HWI-EAS229_92_30VNBAAXX:1:1:0:1898:NAGCTCGTGTCGTGAGATGTTAGGTTAAGTCCTGCAA:EK_aaaaaaaaaaaUZaaZaXM[aaaXSM\aaZ]URE
+"""
+ for l in lane_list:
+ pathname = os.path.join(gerald_dir, 's_%d_sequence.txt' %(l,))
+ f = open(pathname,'w')
+ f.write(seq)
+ f.close()
+
+def make_fastq(gerald_dir, lane_list=LANE_LIST):
+ seq = """@HWI-EAS229:1:2:182:712#0/1
+AAAAAAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAA
++HWI-EAS229:1:2:182:712#0/1
+\bab_bbaabbababbaaa]]D]bb_baabbab\baa
+@HWI-EAS229:1:2:198:621#0/1
+CCCCCCCCCCCCCCCCCCCCCNCCCCCCCCCCCCCCC
++HWI-EAS229:1:2:198:621#0/1
+[aaaaaaa`_`aaaaaaa[`ZDZaaaaaaaaaaaaaa
+@HWI-EAS229:1:2:209:1321#0/1
+AAAAAAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAA
++HWI-EAS229:1:2:209:1321#0/1
+_bbbbbaaababaabbbbab]D]aaaaaaaaaaaaaa
+"""
+ for l in lane_list:
+ pathname = os.path.join(gerald_dir, 's_%d_sequence.txt' %(l,))
+ f = open(pathname,'w')
+ f.write(seq)
+ f.close()
+
+
--- /dev/null
+import unittest
+
+from StringIO import StringIO
+from htsworkflow.pipelines import genome_mapper
+
+class testGenomeMapper(unittest.TestCase):
+ def test_construct_mapper(self):
+ genomes = {
+ 'Arabidopsis thaliana': {'v01212004': '/arabidopsis'},
+ 'Homo sapiens': {'hg18': '/hg18'},
+ 'Mus musculus': {'mm8': '/mm8',
+ 'mm9': '/mm9',
+ 'mm10': '/mm10'},
+ 'Phage': {'174': '/phi'},
+ }
+ genome_map = genome_mapper.constructMapperDict(genomes)
+
+ self.failUnlessEqual("%(Mus musculus|mm8)s" % (genome_map), "/mm8")
+ self.failUnlessEqual("%(Phage|174)s" % (genome_map), "/phi")
+ self.failUnlessEqual("%(Mus musculus)s" % (genome_map), "/mm10")
+ self.failUnlessEqual("%(Mus musculus|mm8)s" % (genome_map), "/mm8")
+ self.failUnlessEqual("%(Mus musculus|mm10)s" % (genome_map), "/mm10")
+
+ self.failUnlessEqual(len(genome_map.keys()), 6)
+ self.failUnlessEqual(len(genome_map.values()), 6)
+ self.failUnlessEqual(len(genome_map.items()), 6)
+
+
+def suite():
+ return unittest.makeSuite(testGenomeMapper,'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="suite")
--- /dev/null
+#!/usr/bin/env python
+
+from datetime import datetime, date
+import os
+import tempfile
+import shutil
+import unittest
+
+from htsworkflow.pipelines import firecrest
+from htsworkflow.pipelines import bustard
+from htsworkflow.pipelines import gerald
+from htsworkflow.pipelines import runfolder
+from htsworkflow.pipelines.runfolder import ElementTree
+
+from htsworkflow.pipelines.test.simulate_runfolder import *
+
+
+def make_summary_htm(gerald_dir):
+ summary_htm = """<!--RUN_TIME Mon Apr 21 11:52:25 2008 -->
+<!--SOFTWARE_VERSION @(#) $Id: jerboa.pl,v 1.31 2007/03/05 17:52:15 km Exp $-->
+<html>
+<body>
+
+<a name="Top"><h2><title>080416_HWI-EAS229_0024_207BTAAXX Summary</title></h2></a>
+<h1>Summary Information For Experiment 080416_HWI-EAS229_0024_207BTAAXX on Machine HWI-EAS229</h1>
+<h2><br></br>Chip Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr><td>Machine</td><td>HWI-EAS229</td></tr>
+<tr><td>Run Folder</td><td>080416_HWI-EAS229_0024_207BTAAXX</td></tr>
+<tr><td>Chip ID</td><td>unknown</td></tr>
+</table>
+<h2><br></br>Lane Parameter Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane</td>
+<td>Sample ID</td>
+<td>Sample Target</td>
+<td>Sample Type</td>
+<td>Length</td>
+<td>Filter</td>
+<td>Tiles</td>
+</tr>
+<tr>
+<td>1</td>
+<td>unknown</td>
+<td>dm3</td>
+<td>ELAND</td>
+<td>32</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td><a href="#Lane1">Lane 1</a></td>
+</tr>
+<tr>
+<td>2</td>
+<td>unknown</td>
+<td>equcab1</td>
+<td>ELAND</td>
+<td>32</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td><a href="#Lane2">Lane 2</a></td>
+</tr>
+<tr>
+<td>3</td>
+<td>unknown</td>
+<td>equcab1</td>
+<td>ELAND</td>
+<td>32</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td><a href="#Lane3">Lane 3</a></td>
+</tr>
+<tr>
+<td>4</td>
+<td>unknown</td>
+<td>canfam2</td>
+<td>ELAND</td>
+<td>32</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td><a href="#Lane4">Lane 4</a></td>
+</tr>
+<tr>
+<td>5</td>
+<td>unknown</td>
+<td>hg18</td>
+<td>ELAND</td>
+<td>32</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td><a href="#Lane5">Lane 5</a></td>
+</tr>
+<tr>
+<td>6</td>
+<td>unknown</td>
+<td>hg18</td>
+<td>ELAND</td>
+<td>32</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td><a href="#Lane6">Lane 6</a></td>
+</tr>
+<tr>
+<td>7</td>
+<td>unknown</td>
+<td>hg18</td>
+<td>ELAND</td>
+<td>32</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td><a href="#Lane7">Lane 7</a></td>
+</tr>
+<tr>
+<td>8</td>
+<td>unknown</td>
+<td>hg18</td>
+<td>ELAND</td>
+<td>32</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td><a href="#Lane8">Lane 8</a></td>
+</tr>
+</table>
+<h2><br></br>Lane Results Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+
+<td>Lane </td>
+<td>Clusters </td>
+<td>Av 1st Cycle Int </td>
+<td>% intensity after 20 cycles </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td> % Error Rate (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>17421 +/- 2139</td>
+<td>7230 +/- 801</td>
+<td>23.73 +/- 10.79</td>
+<td>13.00 +/- 22.91</td>
+<td>32.03 +/- 18.45</td>
+<td>6703.57 +/- 3753.85</td>
+<td>4.55 +/- 4.81</td>
+</tr>
+<tr>
+<td>2</td>
+<td>20311 +/- 2402</td>
+<td>7660 +/- 678</td>
+<td>17.03 +/- 4.40</td>
+<td>40.74 +/- 30.33</td>
+<td>29.54 +/- 9.03</td>
+<td>5184.02 +/- 1631.54</td>
+<td>3.27 +/- 3.94</td>
+</tr>
+<tr>
+<td>3</td>
+<td>20193 +/- 2399</td>
+<td>7700 +/- 797</td>
+<td>15.75 +/- 3.30</td>
+<td>56.56 +/- 17.16</td>
+<td>27.33 +/- 7.48</td>
+<td>4803.49 +/- 1313.31</td>
+<td>3.07 +/- 2.86</td>
+</tr>
+<tr>
+<td>4</td>
+<td>15537 +/- 2531</td>
+<td>7620 +/- 1392</td>
+<td>15.37 +/- 3.79</td>
+<td>63.05 +/- 18.30</td>
+<td>15.88 +/- 4.99</td>
+<td>3162.13 +/- 962.59</td>
+<td>3.11 +/- 2.22</td>
+</tr>
+<tr>
+<td>5</td>
+<td>32047 +/- 3356</td>
+<td>8093 +/- 831</td>
+<td>23.79 +/- 6.18</td>
+<td>53.36 +/- 18.06</td>
+<td>48.04 +/- 13.77</td>
+<td>9866.23 +/- 2877.30</td>
+<td>2.26 +/- 1.16</td>
+</tr>
+<tr>
+<td>6</td>
+<td>32946 +/- 4753</td>
+<td>8227 +/- 736</td>
+<td>24.07 +/- 4.69</td>
+<td>54.65 +/- 12.57</td>
+<td>50.98 +/- 10.54</td>
+<td>10468.86 +/- 2228.53</td>
+<td>2.21 +/- 2.33</td>
+</tr>
+<tr>
+<td>7</td>
+<td>39504 +/- 4171</td>
+<td>8401 +/- 785</td>
+<td>22.55 +/- 4.56</td>
+<td>45.22 +/- 10.34</td>
+<td>48.41 +/- 9.67</td>
+<td>9829.40 +/- 1993.20</td>
+<td>2.26 +/- 1.11</td>
+</tr>
+<tr>
+<td>8</td>
+<td>37998 +/- 3792</td>
+<td>8443 +/- 1211</td>
+<td>39.03 +/- 7.52</td>
+<td>42.16 +/- 12.35</td>
+<td>40.98 +/- 14.89</td>
+<td>8128.87 +/- 3055.34</td>
+<td>3.57 +/- 2.77</td>
+</tr>
+</table>
+</body>
+</html>
+"""
+ pathname = os.path.join(gerald_dir, 'Summary.htm')
+ f = open(pathname, 'w')
+ f.write(summary_htm)
+ f.close()
+
+def make_eland_results(gerald_dir):
+ eland_result = """>HWI-EAS229_24_207BTAAXX:1:7:599:759 ACATAGNCACAGACATAAACATAGACATAGAC U0 1 1 3 chrUextra.fa 28189829 R D.
+>HWI-EAS229_24_207BTAAXX:1:7:205:842 AAACAANNCTCCCAAACACGTAAACTGGAAAA U1 0 1 0 chr2L.fa 8796855 R DD 24T
+>HWI-EAS229_24_207BTAAXX:1:7:776:582 AGCTCANCCGATCGAAAACCTCNCCAAGCAAT NM 0 0 0
+>HWI-EAS229_24_207BTAAXX:1:7:205:842 AAACAANNCTCCCAAACACGTAAACTGGAAAA U1 0 1 0 Lambda.fa 8796855 R DD 24T
+"""
+ for i in range(1,9):
+ pathname = os.path.join(gerald_dir,
+ 's_%d_eland_result.txt' % (i,))
+ f = open(pathname, 'w')
+ f.write(eland_result)
+ f.close()
+
+class RunfolderTests(unittest.TestCase):
+ """
+ Test components of the runfolder processing code
+ which includes firecrest, bustard, and gerald
+ """
+ def setUp(self):
+ # make a fake runfolder directory
+ self.temp_dir = tempfile.mkdtemp(prefix='tmp_runfolder_')
+
+ self.runfolder_dir = os.path.join(self.temp_dir,
+ '080102_HWI-EAS229_0010_207BTAAXX')
+ os.mkdir(self.runfolder_dir)
+
+ self.data_dir = os.path.join(self.runfolder_dir, 'Data')
+ os.mkdir(self.data_dir)
+
+ self.firecrest_dir = os.path.join(self.data_dir,
+ 'C1-33_Firecrest1.8.28_12-04-2008_diane'
+ )
+ os.mkdir(self.firecrest_dir)
+ self.matrix_dir = os.path.join(self.firecrest_dir, 'Matrix')
+ os.mkdir(self.matrix_dir)
+ matrix_filename = os.path.join(self.matrix_dir, 's_matrix')
+ make_matrix(matrix_filename)
+
+ self.bustard_dir = os.path.join(self.firecrest_dir,
+ 'Bustard1.8.28_12-04-2008_diane')
+ os.mkdir(self.bustard_dir)
+ make_phasing_params(self.bustard_dir)
+
+ self.gerald_dir = os.path.join(self.bustard_dir,
+ 'GERALD_12-04-2008_diane')
+ os.mkdir(self.gerald_dir)
+ make_gerald_config_026(self.gerald_dir)
+ make_summary_htm(self.gerald_dir)
+ make_eland_results(self.gerald_dir)
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+
+ def test_firecrest(self):
+ """
+ Construct a firecrest object
+ """
+ f = firecrest.firecrest(self.firecrest_dir)
+ self.failUnlessEqual(f.version, '1.8.28')
+ self.failUnlessEqual(f.start, 1)
+ self.failUnlessEqual(f.stop, 33)
+ self.failUnlessEqual(f.user, 'diane')
+ self.failUnlessEqual(f.date, date(2008,4,12))
+
+ xml = f.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+
+ f2 = firecrest.Firecrest(xml=xml)
+ self.failUnlessEqual(f.version, f2.version)
+ self.failUnlessEqual(f.start, f2.start)
+ self.failUnlessEqual(f.stop, f2.stop)
+ self.failUnlessEqual(f.user, f2.user)
+ self.failUnlessEqual(f.date, f2.date)
+
+ def test_bustard(self):
+ """
+ construct a bustard object
+ """
+ b = bustard.bustard(self.bustard_dir)
+ self.failUnlessEqual(b.version, '1.8.28')
+ self.failUnlessEqual(b.date, date(2008,4,12))
+ self.failUnlessEqual(b.user, 'diane')
+ self.failUnlessEqual(len(b.phasing), 8)
+ self.failUnlessAlmostEqual(b.phasing[8].phasing, 0.0099)
+
+ xml = b.get_elements()
+ b2 = bustard.Bustard(xml=xml)
+ self.failUnlessEqual(b.version, b2.version)
+ self.failUnlessEqual(b.date, b2.date )
+ self.failUnlessEqual(b.user, b2.user)
+ self.failUnlessEqual(len(b.phasing), len(b2.phasing))
+ for key in b.phasing.keys():
+ self.failUnlessEqual(b.phasing[key].lane,
+ b2.phasing[key].lane)
+ self.failUnlessEqual(b.phasing[key].phasing,
+ b2.phasing[key].phasing)
+ self.failUnlessEqual(b.phasing[key].prephasing,
+ b2.phasing[key].prephasing)
+
+ def test_gerald(self):
+ # need to update gerald and make tests for it
+ g = gerald.gerald(self.gerald_dir)
+
+ self.failUnlessEqual(g.version,
+ '@(#) Id: GERALD.pl,v 1.68.2.2 2007/06/13 11:08:49 km Exp')
+ self.failUnlessEqual(g.date, datetime(2008,4,19,19,8,30))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.items()))
+
+
+ # list of genomes, matches what was defined up in
+ # make_gerald_config.
+ # the first None is to offset the genomes list to be 1..9
+ # instead of pythons default 0..8
+ genomes = [None, '/g/dm3', '/g/equcab1', '/g/equcab1', '/g/canfam2',
+ '/g/hg18', '/g/hg18', '/g/hg18', '/g/hg18', ]
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ cur_lane = g.lanes[i]
+ self.failUnlessEqual(cur_lane.analysis, 'eland')
+ self.failUnlessEqual(cur_lane.eland_genome, genomes[i])
+ self.failUnlessEqual(cur_lane.read_length, '32')
+ self.failUnlessEqual(cur_lane.use_bases, 'Y'*32)
+
+ # test data extracted from summary file
+ clusters = [None,
+ (17421, 2139), (20311, 2402), (20193, 2399), (15537, 2531),
+ (32047, 3356), (32946, 4753), (39504, 4171), (37998, 3792)]
+
+ self.failUnlessEqual(len(g.summary), 1)
+ for i in range(1,9):
+ summary_lane = g.summary[0][i]
+ self.failUnlessEqual(summary_lane.cluster, clusters[i])
+ self.failUnlessEqual(summary_lane.lane, i)
+
+ xml = g.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ g2 = gerald.Gerald(xml=xml)
+
+ # do it all again after extracting from the xml file
+ self.failUnlessEqual(g.version, g2.version)
+ self.failUnlessEqual(g.date, g2.date)
+ self.failUnlessEqual(len(g.lanes.keys()), len(g2.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes.items()), len(g2.lanes.items()))
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ g_lane = g.lanes[i]
+ g2_lane = g2.lanes[i]
+ self.failUnlessEqual(g_lane.analysis, g2_lane.analysis)
+ self.failUnlessEqual(g_lane.eland_genome, g2_lane.eland_genome)
+ self.failUnlessEqual(g_lane.read_length, g2_lane.read_length)
+ self.failUnlessEqual(g_lane.use_bases, g2_lane.use_bases)
+
+ self.failUnlessEqual(len(g.summary), 1)
+ # test (some) summary elements
+ for i in range(1,9):
+ g_summary = g.summary[0][i]
+ g2_summary = g2.summary[0][i]
+ self.failUnlessEqual(g_summary.cluster, g2_summary.cluster)
+ self.failUnlessEqual(g_summary.lane, g2_summary.lane)
+
+ g_eland = g.eland_results
+ g2_eland = g2.eland_results
+ for lane in g_eland.results[0].keys():
+ g_results = g_eland.results[0][lane]
+ g2_results = g2_eland.results[0][lane]
+ self.failUnlessEqual(g_results.reads,
+ g2_results.reads)
+ self.failUnlessEqual(len(g_results.mapped_reads),
+ len(g2_results.mapped_reads))
+ for k in g_results.mapped_reads.keys():
+ self.failUnlessEqual(g_results.mapped_reads[k],
+ g2_results.mapped_reads[k])
+
+ self.failUnlessEqual(len(g_results.match_codes),
+ len(g2_results.match_codes))
+ for k in g_results.match_codes.keys():
+ self.failUnlessEqual(g_results.match_codes[k],
+ g2_results.match_codes[k])
+
+
+ def test_eland(self):
+ dm3_map = { 'chrUextra.fa' : 'dm3/chrUextra.fa',
+ 'chr2L.fa': 'dm3/chr2L.fa',
+ 'Lambda.fa': 'Lambda.fa'}
+ genome_maps = { 1:dm3_map, 2:dm3_map, 3:dm3_map, 4:dm3_map,
+ 5:dm3_map, 6:dm3_map, 7:dm3_map, 8:dm3_map }
+ eland = gerald.eland(self.gerald_dir, genome_maps=genome_maps)
+
+ for i in range(1,9):
+ lane = eland.results[0][i]
+ self.failUnlessEqual(lane.reads, 4)
+ self.failUnlessEqual(lane.sample_name, "s")
+ self.failUnlessEqual(lane.lane_id, i)
+ self.failUnlessEqual(len(lane.mapped_reads), 3)
+ self.failUnlessEqual(lane.mapped_reads['Lambda.fa'], 1)
+ self.failUnlessEqual(lane.mapped_reads['dm3/chr2L.fa'], 1)
+ self.failUnlessEqual(lane.match_codes['U1'], 2)
+ self.failUnlessEqual(lane.match_codes['NM'], 1)
+
+ xml = eland.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ e2 = gerald.ELAND(xml=xml)
+
+ for i in range(1,9):
+ l1 = eland.results[0][i]
+ l2 = e2.results[0][i]
+ self.failUnlessEqual(l1.reads, l2.reads)
+ self.failUnlessEqual(l1.sample_name, l2.sample_name)
+ self.failUnlessEqual(l1.lane_id, l2.lane_id)
+ self.failUnlessEqual(len(l1.mapped_reads), len(l2.mapped_reads))
+ self.failUnlessEqual(len(l1.mapped_reads), 3)
+ for k in l1.mapped_reads.keys():
+ self.failUnlessEqual(l1.mapped_reads[k],
+ l2.mapped_reads[k])
+
+ self.failUnlessEqual(len(l1.match_codes), 9)
+ self.failUnlessEqual(len(l1.match_codes), len(l2.match_codes))
+ for k in l1.match_codes.keys():
+ self.failUnlessEqual(l1.match_codes[k],
+ l2.match_codes[k])
+
+ def test_runfolder(self):
+ runs = runfolder.get_runs(self.runfolder_dir)
+
+ # do we get the flowcell id from the filename?
+ self.failUnlessEqual(len(runs), 1)
+ self.failUnlessEqual(runs[0].name, 'run_207BTAAXX_2008-04-19.xml')
+
+ # do we get the flowcell id from the FlowcellId.xml file
+ make_flowcell_id(self.runfolder_dir, '207BTAAXY')
+ runs = runfolder.get_runs(self.runfolder_dir)
+ self.failUnlessEqual(len(runs), 1)
+ self.failUnlessEqual(runs[0].name, 'run_207BTAAXY_2008-04-19.xml')
+
+ r1 = runs[0]
+ xml = r1.get_elements()
+ xml_str = ElementTree.tostring(xml)
+
+ r2 = runfolder.PipelineRun(xml=xml)
+ self.failUnlessEqual(r1.name, r2.name)
+ self.failIfEqual(r2.image_analysis, None)
+ self.failIfEqual(r2.bustard, None)
+ self.failIfEqual(r2.gerald, None)
+
+
+def suite():
+ return unittest.makeSuite(RunfolderTests,'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="suite")
+
--- /dev/null
+#!/usr/bin/env python
+
+from datetime import datetime, date
+import os
+import tempfile
+import shutil
+import unittest
+
+from htsworkflow.pipelines import firecrest
+from htsworkflow.pipelines import bustard
+from htsworkflow.pipelines import gerald
+from htsworkflow.pipelines import runfolder
+from htsworkflow.pipelines.runfolder import ElementTree
+
+from htsworkflow.pipelines.test.simulate_runfolder import *
+
+
+def make_summary_htm(gerald_dir):
+ summary_htm="""<!--RUN_TIME Wed Jul 2 06:47:44 2008 -->
+<!--SOFTWARE_VERSION @(#) $Id: jerboa.pl,v 1.94 2007/12/04 09:59:07 rshaw Exp $-->
+<html>
+<body>
+
+<a name="Top"><h2><title>080627_HWI-EAS229_0036_3055HAXX Summary</title></h2></a>
+<h1>Summary Information For Experiment 080627_HWI-EAS229_0036_3055HAXX on Machine HWI-EAS229</h1>
+<h2><br></br>Chip Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr><td>Machine</td><td>HWI-EAS229</td></tr>
+<tr><td>Run Folder</td><td>080627_HWI-EAS229_0036_3055HAXX</td></tr>
+<tr><td>Chip ID</td><td>unknown</td></tr>
+</table>
+<h2><br></br>Chip Results Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Clusters</td>
+<td>Clusters (PF)</td>
+<td>Yield (kbases)</td>
+</tr>
+<tr><td>80933224</td>
+<td>43577803</td>
+<td>1133022</td>
+</tr>
+</table>
+<h2><br></br>Lane Parameter Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane</td>
+<td>Sample ID</td>
+<td>Sample Target</td>
+<td>Sample Type</td>
+<td>Length</td>
+<td>Filter</td>
+<td>Num Tiles</td>
+<td>Tiles</td>
+</tr>
+<tr>
+<td>1</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane1">Lane 1</a></td>
+</tr>
+<tr>
+<td>2</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane2">Lane 2</a></td>
+</tr>
+<tr>
+<td>3</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane3">Lane 3</a></td>
+</tr>
+<tr>
+<td>4</td>
+<td>unknown</td>
+<td>elegans170</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane4">Lane 4</a></td>
+</tr>
+<tr>
+<td>5</td>
+<td>unknown</td>
+<td>elegans170</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane5">Lane 5</a></td>
+</tr>
+<tr>
+<td>6</td>
+<td>unknown</td>
+<td>elegans170</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane6">Lane 6</a></td>
+</tr>
+<tr>
+<td>7</td>
+<td>unknown</td>
+<td>elegans170</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane7">Lane 7</a></td>
+</tr>
+<tr>
+<td>8</td>
+<td>unknown</td>
+<td>elegans170</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane8">Lane 8</a></td>
+</tr>
+</table>
+<h2><br></br>Lane Results Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td colspan="2">Lane Info</td>
+<td colspan="8">Tile Mean +/- SD for Lane</td>
+</tr>
+<tr>
+<td>Lane </td>
+<td>Lane Yield (kbases) </td>
+<td>Clusters (raw)</td>
+<td>Clusters (PF) </td>
+<td>1st Cycle Int (PF) </td>
+<td>% intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Alignment Score (PF) </td>
+<td> % Error Rate (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>158046</td>
+<td>96483 +/- 9074</td>
+<td>60787 +/- 4240</td>
+<td>329 +/- 35</td>
+<td>101.88 +/- 6.03</td>
+<td>63.21 +/- 3.29</td>
+<td>70.33 +/- 0.24</td>
+<td>9054.08 +/- 59.16</td>
+<td>0.46 +/- 0.18</td>
+</tr>
+<tr>
+<td>2</td>
+<td>156564</td>
+<td>133738 +/- 7938</td>
+<td>60217 +/- 1926</td>
+<td>444 +/- 39</td>
+<td>92.62 +/- 7.58</td>
+<td>45.20 +/- 3.31</td>
+<td>51.98 +/- 0.74</td>
+<td>6692.04 +/- 92.49</td>
+<td>0.46 +/- 0.09</td>
+</tr>
+<tr>
+<td>3</td>
+<td>185818</td>
+<td>152142 +/- 10002</td>
+<td>71468 +/- 2827</td>
+<td>366 +/- 36</td>
+<td>91.53 +/- 8.66</td>
+<td>47.19 +/- 3.80</td>
+<td>82.24 +/- 0.44</td>
+<td>10598.68 +/- 64.13</td>
+<td>0.41 +/- 0.04</td>
+</tr>
+<tr>
+<td>4</td>
+<td>34953</td>
+<td>15784 +/- 2162</td>
+<td>13443 +/- 1728</td>
+<td>328 +/- 40</td>
+<td>97.53 +/- 9.87</td>
+<td>85.29 +/- 1.91</td>
+<td>80.02 +/- 0.53</td>
+<td>10368.82 +/- 71.08</td>
+<td>0.15 +/- 0.05</td>
+</tr>
+<tr>
+<td>5</td>
+<td>167936</td>
+<td>119735 +/- 8465</td>
+<td>64590 +/- 2529</td>
+<td>417 +/- 37</td>
+<td>88.69 +/- 14.79</td>
+<td>54.10 +/- 2.59</td>
+<td>76.95 +/- 0.32</td>
+<td>9936.47 +/- 65.75</td>
+<td>0.28 +/- 0.02</td>
+</tr>
+<tr>
+<td>6</td>
+<td>173463</td>
+<td>152177 +/- 8146</td>
+<td>66716 +/- 2493</td>
+<td>372 +/- 39</td>
+<td>87.06 +/- 9.86</td>
+<td>43.98 +/- 3.12</td>
+<td>78.80 +/- 0.43</td>
+<td>10162.28 +/- 49.65</td>
+<td>0.38 +/- 0.03</td>
+</tr>
+<tr>
+<td>7</td>
+<td>149287</td>
+<td>84649 +/- 7325</td>
+<td>57418 +/- 3617</td>
+<td>295 +/- 28</td>
+<td>89.40 +/- 8.23</td>
+<td>67.97 +/- 1.82</td>
+<td>33.38 +/- 0.25</td>
+<td>4247.92 +/- 32.37</td>
+<td>1.00 +/- 0.03</td>
+</tr>
+<tr>
+<td>8</td>
+<td>106953</td>
+<td>54622 +/- 4812</td>
+<td>41136 +/- 3309</td>
+<td>284 +/- 37</td>
+<td>90.21 +/- 9.10</td>
+<td>75.39 +/- 2.27</td>
+<td>48.33 +/- 0.29</td>
+<td>6169.21 +/- 169.50</td>
+<td>0.86 +/- 1.22</td>
+</tr>
+<tr><td colspan="13">Tile mean across chip</td></tr>
+<tr>
+<td>Av.</td>
+<td></td>
+<td>101166</td>
+<td>54472</td>
+<td>354</td>
+<td>92.36</td>
+<td>60.29</td>
+<td>65.25</td>
+<td>8403.69</td>
+<td>0.50</td>
+</tr>
+</table>
+<h2><br></br>Expanded Lane Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+
+<tr><td colspan="2">Lane Info</td>
+<td colspan="2">Phasing Info</td>
+<td colspan="2">Raw Data (tile mean)</td>
+<td colspan="7">Filtered Data (tile mean)</td></tr>
+<td>Lane </td>
+<td>Clusters (tile mean) (raw)</td>
+<td>% Phasing </td>
+<td>% Prephasing </td>
+<td>% Error Rate (raw) </td>
+<td> Equiv Perfect Clusters (raw) </td>
+<td>% retained </td>
+<td>Cycle 2-4 Av Int (PF) </td>
+<td>Cycle 2-10 Av % Loss (PF) </td>
+<td>Cycle 10-20 Av % Loss (PF) </td>
+<td>% Align (PF) </td>
+<td>% Error Rate (PF) </td>
+<td> Equiv Perfect Clusters (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>96483</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.00</td>
+<td>49676</td>
+<td>63.21</td>
+<td>317 +/- 32</td>
+<td>0.13 +/- 0.44</td>
+<td>-1.14 +/- 0.34</td>
+<td>70.33</td>
+<td>0.46</td>
+<td>41758</td>
+</tr>
+<tr>
+<td>2</td>
+<td>133738</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.22</td>
+<td>40467</td>
+<td>45.20</td>
+<td>415 +/- 33</td>
+<td>0.29 +/- 0.40</td>
+<td>-0.79 +/- 0.35</td>
+<td>51.98</td>
+<td>0.46</td>
+<td>30615</td>
+</tr>
+<tr>
+<td>3</td>
+<td>152142</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.30</td>
+<td>78588</td>
+<td>47.19</td>
+<td>344 +/- 26</td>
+<td>0.68 +/- 0.51</td>
+<td>-0.77 +/- 0.42</td>
+<td>82.24</td>
+<td>0.41</td>
+<td>57552</td>
+</tr>
+<tr>
+<td>4</td>
+<td>15784</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>0.29</td>
+<td>11095</td>
+<td>85.29</td>
+<td>306 +/- 34</td>
+<td>0.20 +/- 0.69</td>
+<td>-1.28 +/- 0.66</td>
+<td>80.02</td>
+<td>0.15</td>
+<td>10671</td>
+</tr>
+<tr>
+<td>5</td>
+<td>119735</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>0.85</td>
+<td>60335</td>
+<td>54.10</td>
+<td>380 +/- 32</td>
+<td>0.34 +/- 0.49</td>
+<td>-1.55 +/- 4.69</td>
+<td>76.95</td>
+<td>0.28</td>
+<td>49015</td>
+</tr>
+<tr>
+<td>6</td>
+<td>152177</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.21</td>
+<td>70905</td>
+<td>43.98</td>
+<td>333 +/- 27</td>
+<td>0.57 +/- 0.50</td>
+<td>-0.91 +/- 0.39</td>
+<td>78.80</td>
+<td>0.38</td>
+<td>51663</td>
+</tr>
+<tr>
+<td>7</td>
+<td>84649</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.38</td>
+<td>21069</td>
+<td>67.97</td>
+<td>272 +/- 20</td>
+<td>1.15 +/- 0.52</td>
+<td>-0.84 +/- 0.58</td>
+<td>33.38</td>
+<td>1.00</td>
+<td>18265</td>
+</tr>
+<tr>
+<td>8</td>
+<td>54622</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.17</td>
+<td>21335</td>
+<td>75.39</td>
+<td>262 +/- 31</td>
+<td>1.10 +/- 0.59</td>
+<td>-1.01 +/- 0.47</td>
+<td>48.33</td>
+<td>0.86</td>
+<td>19104</td>
+</tr>
+</table>
+<b><br></br>IVC Plots</b>
+<p> <a href='IVC.htm' target="_blank"> IVC.htm
+ </a></p>
+<b><br></br>All Intensity Plots</b>
+<p> <a href='All.htm' target="_blank"> All.htm
+ </a></p>
+<b><br></br>Error graphs: </b>
+<p> <a href='Error.htm' target="_blank"> Error.htm
+ </a></p>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane1"><h2><br></br>Lane 1<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>0001</td>
+<td>114972</td>
+<td>326.48</td>
+<td>94.39</td>
+<td>57.44</td>
+<td>70.2</td>
+<td>9038.6</td>
+<td>0.44</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane2"><h2><br></br>Lane 2<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>2</td>
+<td>0001</td>
+<td>147793</td>
+<td>448.12</td>
+<td>83.68</td>
+<td>38.57</td>
+<td>53.7</td>
+<td>6905.4</td>
+<td>0.54</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane3"><h2><br></br>Lane 3<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>3</td>
+<td>0001</td>
+<td>167904</td>
+<td>374.05</td>
+<td>86.91</td>
+<td>40.36</td>
+<td>81.3</td>
+<td>10465.0</td>
+<td>0.47</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane4"><h2><br></br>Lane 4<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>4</td>
+<td>0001</td>
+<td>20308</td>
+<td>276.85</td>
+<td>92.87</td>
+<td>84.26</td>
+<td>80.4</td>
+<td>10413.8</td>
+<td>0.16</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane5"><h2><br></br>Lane 5<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane6"><h2><br></br>Lane 6<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>6</td>
+<td>0001</td>
+<td>166844</td>
+<td>348.12</td>
+<td>77.59</td>
+<td>38.13</td>
+<td>79.7</td>
+<td>10264.4</td>
+<td>0.44</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane7"><h2><br></br>Lane 7<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>7</td>
+<td>0001</td>
+<td>98913</td>
+<td>269.90</td>
+<td>86.66</td>
+<td>64.55</td>
+<td>33.2</td>
+<td>4217.5</td>
+<td>1.02</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane8"><h2><br></br>Lane 8<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>8</td>
+<td>0001</td>
+<td>64972</td>
+<td>243.60</td>
+<td>89.40</td>
+<td>73.17</td>
+<td>48.3</td>
+<td>6182.8</td>
+<td>0.71</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+</body>
+</html>
+"""
+ pathname = os.path.join(gerald_dir, 'Summary.htm')
+ f = open(pathname, 'w')
+ f.write(summary_htm)
+ f.close()
+
+def make_eland_results(gerald_dir):
+ eland_result = """>HWI-EAS229_24_207BTAAXX:1:7:599:759 ACATAGNCACAGACATAAACATAGACATAGAC U0 1 1 3 chrUextra.fa 28189829 R D.
+>HWI-EAS229_24_207BTAAXX:1:7:205:842 AAACAANNCTCCCAAACACGTAAACTGGAAAA U1 0 1 0 chr2L.fa 8796855 R DD 24T
+>HWI-EAS229_24_207BTAAXX:1:7:776:582 AGCTCANCCGATCGAAAACCTCNCCAAGCAAT NM 0 0 0
+>HWI-EAS229_24_207BTAAXX:1:7:205:842 AAACAANNCTCCCAAACACGTAAACTGGAAAA U1 0 1 0 Lambda.fa 8796855 R DD 24T
+"""
+ for i in range(1,9):
+ pathname = os.path.join(gerald_dir,
+ 's_%d_eland_result.txt' % (i,))
+ f = open(pathname, 'w')
+ f.write(eland_result)
+ f.close()
+
+def make_runfolder(obj=None):
+ """
+ Make a fake runfolder, attach all the directories to obj if defined
+ """
+ # make a fake runfolder directory
+ temp_dir = tempfile.mkdtemp(prefix='tmp_runfolder_')
+
+ runfolder_dir = os.path.join(temp_dir,
+ '080102_HWI-EAS229_0010_207BTAAXX')
+ os.mkdir(runfolder_dir)
+
+ data_dir = os.path.join(runfolder_dir, 'Data')
+ os.mkdir(data_dir)
+
+ firecrest_dir = os.path.join(data_dir,
+ 'C1-33_Firecrest1.8.28_12-04-2008_diane'
+ )
+ os.mkdir(firecrest_dir)
+ matrix_dir = os.path.join(firecrest_dir, 'Matrix')
+ os.mkdir(matrix_dir)
+ matrix_filename = os.path.join(matrix_dir, 's_matrix.txt')
+ make_matrix(matrix_filename)
+
+ bustard_dir = os.path.join(firecrest_dir,
+ 'Bustard1.8.28_12-04-2008_diane')
+ os.mkdir(bustard_dir)
+ make_phasing_params(bustard_dir)
+
+ gerald_dir = os.path.join(bustard_dir,
+ 'GERALD_12-04-2008_diane')
+ os.mkdir(gerald_dir)
+ make_gerald_config_026(gerald_dir)
+ make_summary_htm(gerald_dir)
+ make_eland_results(gerald_dir)
+
+ if obj is not None:
+ obj.temp_dir = temp_dir
+ obj.runfolder_dir = runfolder_dir
+ obj.data_dir = data_dir
+ obj.firecrest_dir = firecrest_dir
+ obj.matrix_dir = matrix_dir
+ obj.bustard_dir = bustard_dir
+ obj.gerald_dir = gerald_dir
+
+
+class RunfolderTests(unittest.TestCase):
+ """
+ Test components of the runfolder processing code
+ which includes firecrest, bustard, and gerald
+ """
+ def setUp(self):
+ # attaches all the directories to the object passed in
+ make_runfolder(self)
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+
+ def test_firecrest(self):
+ """
+ Construct a firecrest object
+ """
+ f = firecrest.firecrest(self.firecrest_dir)
+ self.failUnlessEqual(f.version, '1.8.28')
+ self.failUnlessEqual(f.start, 1)
+ self.failUnlessEqual(f.stop, 33)
+ self.failUnlessEqual(f.user, 'diane')
+ self.failUnlessEqual(f.date, date(2008,4,12))
+
+ xml = f.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+
+ f2 = firecrest.Firecrest(xml=xml)
+ self.failUnlessEqual(f.version, f2.version)
+ self.failUnlessEqual(f.start, f2.start)
+ self.failUnlessEqual(f.stop, f2.stop)
+ self.failUnlessEqual(f.user, f2.user)
+ self.failUnlessEqual(f.date, f2.date)
+
+ def test_bustard(self):
+ """
+ construct a bustard object
+ """
+ b = bustard.bustard(self.bustard_dir)
+ self.failUnlessEqual(b.version, '1.8.28')
+ self.failUnlessEqual(b.date, date(2008,4,12))
+ self.failUnlessEqual(b.user, 'diane')
+ self.failUnlessEqual(len(b.phasing), 8)
+ self.failUnlessAlmostEqual(b.phasing[8].phasing, 0.0099)
+
+ xml = b.get_elements()
+ b2 = bustard.Bustard(xml=xml)
+ self.failUnlessEqual(b.version, b2.version)
+ self.failUnlessEqual(b.date, b2.date )
+ self.failUnlessEqual(b.user, b2.user)
+ self.failUnlessEqual(len(b.phasing), len(b2.phasing))
+ for key in b.phasing.keys():
+ self.failUnlessEqual(b.phasing[key].lane,
+ b2.phasing[key].lane)
+ self.failUnlessEqual(b.phasing[key].phasing,
+ b2.phasing[key].phasing)
+ self.failUnlessEqual(b.phasing[key].prephasing,
+ b2.phasing[key].prephasing)
+
+ def test_gerald(self):
+ # need to update gerald and make tests for it
+ g = gerald.gerald(self.gerald_dir)
+
+ self.failUnlessEqual(g.version,
+ '@(#) Id: GERALD.pl,v 1.68.2.2 2007/06/13 11:08:49 km Exp')
+ self.failUnlessEqual(g.date, datetime(2008,4,19,19,8,30))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.items()))
+
+
+ # list of genomes, matches what was defined up in
+ # make_gerald_config.
+ # the first None is to offset the genomes list to be 1..9
+ # instead of pythons default 0..8
+ genomes = [None, '/g/dm3', '/g/equcab1', '/g/equcab1', '/g/canfam2',
+ '/g/hg18', '/g/hg18', '/g/hg18', '/g/hg18', ]
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ cur_lane = g.lanes[i]
+ self.failUnlessEqual(cur_lane.analysis, 'eland')
+ self.failUnlessEqual(cur_lane.eland_genome, genomes[i])
+ self.failUnlessEqual(cur_lane.read_length, '32')
+ self.failUnlessEqual(cur_lane.use_bases, 'Y'*32)
+
+ # test data extracted from summary file
+ clusters = [None,
+ (96483, 9074), (133738, 7938),
+ (152142, 10002), (15784, 2162),
+ (119735, 8465), (152177, 8146),
+ (84649, 7325), (54622, 4812),]
+
+ self.failUnlessEqual(len(g.summary), 1)
+ for i in range(1,9):
+ summary_lane = g.summary[0][i]
+ self.failUnlessEqual(summary_lane.cluster, clusters[i])
+ self.failUnlessEqual(summary_lane.lane, i)
+
+ xml = g.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ g2 = gerald.Gerald(xml=xml)
+
+ # do it all again after extracting from the xml file
+ self.failUnlessEqual(g.version, g2.version)
+ self.failUnlessEqual(g.date, g2.date)
+ self.failUnlessEqual(len(g.lanes.keys()), len(g2.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes.items()), len(g2.lanes.items()))
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ g_lane = g.lanes[i]
+ g2_lane = g2.lanes[i]
+ self.failUnlessEqual(g_lane.analysis, g2_lane.analysis)
+ self.failUnlessEqual(g_lane.eland_genome, g2_lane.eland_genome)
+ self.failUnlessEqual(g_lane.read_length, g2_lane.read_length)
+ self.failUnlessEqual(g_lane.use_bases, g2_lane.use_bases)
+
+ # test (some) summary elements
+ self.failUnlessEqual(len(g.summary), 1)
+ for i in range(1,9):
+ g_summary = g.summary[0][i]
+ g2_summary = g2.summary[0][i]
+ self.failUnlessEqual(g_summary.cluster, g2_summary.cluster)
+ self.failUnlessEqual(g_summary.lane, g2_summary.lane)
+
+ g_eland = g.eland_results
+ g2_eland = g2.eland_results
+ for lane in g_eland.results[0].keys():
+ g_results = g_eland.results[0][lane]
+ g2_results = g2_eland.results[0][lane]
+ self.failUnlessEqual(g_results.reads,
+ g2_results.reads)
+ self.failUnlessEqual(len(g_results.mapped_reads),
+ len(g2_results.mapped_reads))
+ for k in g_results.mapped_reads.keys():
+ self.failUnlessEqual(g_results.mapped_reads[k],
+ g2_results.mapped_reads[k])
+
+ self.failUnlessEqual(len(g_results.match_codes),
+ len(g2_results.match_codes))
+ for k in g_results.match_codes.keys():
+ self.failUnlessEqual(g_results.match_codes[k],
+ g2_results.match_codes[k])
+
+
+ def test_eland(self):
+ dm3_map = { 'chrUextra.fa' : 'dm3/chrUextra.fa',
+ 'chr2L.fa': 'dm3/chr2L.fa',
+ 'Lambda.fa': 'Lambda.fa'}
+ genome_maps = { 1:dm3_map, 2:dm3_map, 3:dm3_map, 4:dm3_map,
+ 5:dm3_map, 6:dm3_map, 7:dm3_map, 8:dm3_map }
+ eland = gerald.eland(self.gerald_dir, genome_maps=genome_maps)
+
+ for i in range(1,9):
+ lane = eland.results[0][i]
+ self.failUnlessEqual(lane.reads, 4)
+ self.failUnlessEqual(lane.sample_name, "s")
+ self.failUnlessEqual(lane.lane_id, i)
+ self.failUnlessEqual(len(lane.mapped_reads), 3)
+ self.failUnlessEqual(lane.mapped_reads['Lambda.fa'], 1)
+ self.failUnlessEqual(lane.mapped_reads['dm3/chr2L.fa'], 1)
+ self.failUnlessEqual(lane.match_codes['U1'], 2)
+ self.failUnlessEqual(lane.match_codes['NM'], 1)
+
+ xml = eland.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ e2 = gerald.ELAND(xml=xml)
+
+ for i in range(1,9):
+ l1 = eland.results[0][i]
+ l2 = e2.results[0][i]
+ self.failUnlessEqual(l1.reads, l2.reads)
+ self.failUnlessEqual(l1.sample_name, l2.sample_name)
+ self.failUnlessEqual(l1.lane_id, l2.lane_id)
+ self.failUnlessEqual(len(l1.mapped_reads), len(l2.mapped_reads))
+ self.failUnlessEqual(len(l1.mapped_reads), 3)
+ for k in l1.mapped_reads.keys():
+ self.failUnlessEqual(l1.mapped_reads[k],
+ l2.mapped_reads[k])
+
+ self.failUnlessEqual(len(l1.match_codes), 9)
+ self.failUnlessEqual(len(l1.match_codes), len(l2.match_codes))
+ for k in l1.match_codes.keys():
+ self.failUnlessEqual(l1.match_codes[k],
+ l2.match_codes[k])
+
+ def test_runfolder(self):
+ runs = runfolder.get_runs(self.runfolder_dir)
+
+ # do we get the flowcell id from the filename?
+ self.failUnlessEqual(len(runs), 1)
+ self.failUnlessEqual(runs[0].name, 'run_207BTAAXX_2008-04-19.xml')
+
+ # do we get the flowcell id from the FlowcellId.xml file
+ make_flowcell_id(self.runfolder_dir, '207BTAAXY')
+ runs = runfolder.get_runs(self.runfolder_dir)
+ self.failUnlessEqual(len(runs), 1)
+ self.failUnlessEqual(runs[0].name, 'run_207BTAAXY_2008-04-19.xml')
+
+ r1 = runs[0]
+ xml = r1.get_elements()
+ xml_str = ElementTree.tostring(xml)
+
+ r2 = runfolder.PipelineRun(xml=xml)
+ self.failUnlessEqual(r1.name, r2.name)
+ self.failIfEqual(r2.image_analysis, None)
+ self.failIfEqual(r2.bustard, None)
+ self.failIfEqual(r2.gerald, None)
+
+
+def suite():
+ return unittest.makeSuite(RunfolderTests,'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="suite")
+
--- /dev/null
+#!/usr/bin/env python
+
+from datetime import datetime, date
+import os
+import tempfile
+import shutil
+import unittest
+
+from htsworkflow.pipelines import firecrest
+from htsworkflow.pipelines import bustard
+from htsworkflow.pipelines import gerald
+from htsworkflow.pipelines import runfolder
+from htsworkflow.pipelines.runfolder import ElementTree
+
+from htsworkflow.pipelines.test.simulate_runfolder import *
+
+
+def make_runfolder(obj=None):
+ """
+ Make a fake runfolder, attach all the directories to obj if defined
+ """
+ # make a fake runfolder directory
+ temp_dir = tempfile.mkdtemp(prefix='tmp_runfolder_')
+
+ runfolder_dir = os.path.join(temp_dir,
+ '081017_HWI-EAS229_0062_30J55AAXX')
+ os.mkdir(runfolder_dir)
+
+ data_dir = os.path.join(runfolder_dir, 'Data')
+ os.mkdir(data_dir)
+
+ firecrest_dir = os.path.join(data_dir,
+ 'C1-37_Firecrest1.9.6_20-10-2008_diane')
+ os.mkdir(firecrest_dir)
+
+ bustard_dir = os.path.join(firecrest_dir,
+ 'Bustard1.9.6_20-10-2008_diane')
+ os.mkdir(bustard_dir)
+ make_phasing_params(bustard_dir)
+
+ matrix_name = os.path.join(bustard_dir, 'matrix1.txt')
+ make_matrix(matrix_name)
+
+
+ gerald_dir = os.path.join(bustard_dir,
+ 'GERALD_20-10-2008_diane')
+ os.mkdir(gerald_dir)
+ make_gerald_config_100(gerald_dir)
+ make_summary_htm_110(gerald_dir)
+ make_eland_multi(gerald_dir)
+
+ if obj is not None:
+ obj.temp_dir = temp_dir
+ obj.runfolder_dir = runfolder_dir
+ obj.data_dir = data_dir
+ obj.image_analysis_dir = firecrest_dir
+ obj.bustard_dir = bustard_dir
+ obj.gerald_dir = gerald_dir
+
+
+class RunfolderTests(unittest.TestCase):
+ """
+ Test components of the runfolder processing code
+ which includes firecrest, bustard, and gerald
+ """
+ def setUp(self):
+ # attaches all the directories to the object passed in
+ make_runfolder(self)
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+
+ def test_firecrest(self):
+ """
+ Construct a firecrest object
+ """
+ f = firecrest.firecrest(self.image_analysis_dir)
+ self.failUnlessEqual(f.version, '1.9.6')
+ self.failUnlessEqual(f.start, 1)
+ self.failUnlessEqual(f.stop, 37)
+ self.failUnlessEqual(f.user, 'diane')
+ self.failUnlessEqual(f.date, date(2008,10,20))
+
+ xml = f.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+
+ f2 = firecrest.Firecrest(xml=xml)
+ self.failUnlessEqual(f.version, f2.version)
+ self.failUnlessEqual(f.start, f2.start)
+ self.failUnlessEqual(f.stop, f2.stop)
+ self.failUnlessEqual(f.user, f2.user)
+
+ def test_bustard(self):
+ """
+ construct a bustard object
+ """
+ b = bustard.bustard(self.bustard_dir)
+ self.failUnlessEqual(b.version, '1.9.6')
+ self.failUnlessEqual(b.date, date(2008,10,20))
+ self.failUnlessEqual(b.user, 'diane')
+ self.failUnlessEqual(len(b.phasing), 8)
+ self.failUnlessAlmostEqual(b.phasing[8].phasing, 0.0099)
+
+ xml = b.get_elements()
+ b2 = bustard.Bustard(xml=xml)
+ self.failUnlessEqual(b.version, b2.version)
+ self.failUnlessEqual(b.date, b2.date )
+ self.failUnlessEqual(b.user, b2.user)
+ self.failUnlessEqual(len(b.phasing), len(b2.phasing))
+ for key in b.phasing.keys():
+ self.failUnlessEqual(b.phasing[key].lane,
+ b2.phasing[key].lane)
+ self.failUnlessEqual(b.phasing[key].phasing,
+ b2.phasing[key].phasing)
+ self.failUnlessEqual(b.phasing[key].prephasing,
+ b2.phasing[key].prephasing)
+
+ def test_gerald(self):
+ # need to update gerald and make tests for it
+ g = gerald.gerald(self.gerald_dir)
+
+ self.failUnlessEqual(g.version,
+ '@(#) Id: GERALD.pl,v 1.171 2008/05/19 17:36:14 mzerara Exp')
+ self.failUnlessEqual(g.date, datetime(2009,2,22,21,15,59))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.items()))
+
+
+ # list of genomes, matches what was defined up in
+ # make_gerald_config.
+ # the first None is to offset the genomes list to be 1..9
+ # instead of pythons default 0..8
+ genomes = [None,
+ '/g/mm9',
+ '/g/mm9',
+ '/g/elegans190',
+ '/g/arabidopsis01222004',
+ '/g/mm9',
+ '/g/mm9',
+ '/g/mm9',
+ '/g/mm9', ]
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ cur_lane = g.lanes[i]
+ self.failUnlessEqual(cur_lane.analysis, 'eland_extended')
+ self.failUnlessEqual(cur_lane.eland_genome, genomes[i])
+ self.failUnlessEqual(cur_lane.read_length, '37')
+ self.failUnlessEqual(cur_lane.use_bases, 'Y'*37)
+
+ # I want to be able to use a simple iterator
+ for l in g.lanes.values():
+ self.failUnlessEqual(l.analysis, 'eland_extended')
+ self.failUnlessEqual(l.read_length, '37')
+ self.failUnlessEqual(l.use_bases, 'Y'*37)
+
+ # raw cluster numbers extracted from summary file
+ # its the first +/- value in the lane results summary
+ # section
+ clusters = [None,
+ (190220, 15118), (190560, 14399),
+ (187597, 12369), (204142, 16877),
+ (247308, 11600), (204298, 15640),
+ (202707, 15404), (198075, 14702),]
+
+ self.failUnlessEqual(len(g.summary), 1)
+ for i in range(1,9):
+ summary_lane = g.summary[0][i]
+ self.failUnlessEqual(summary_lane.cluster, clusters[i])
+ self.failUnlessEqual(summary_lane.lane, i)
+
+ xml = g.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ g2 = gerald.Gerald(xml=xml)
+
+ # do it all again after extracting from the xml file
+ self.failUnlessEqual(g.version, g2.version)
+ self.failUnlessEqual(g.date, g2.date)
+ self.failUnlessEqual(len(g.lanes.keys()), len(g2.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes.items()), len(g2.lanes.items()))
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ g_lane = g.lanes[i]
+ g2_lane = g2.lanes[i]
+ self.failUnlessEqual(g_lane.analysis, g2_lane.analysis)
+ self.failUnlessEqual(g_lane.eland_genome, g2_lane.eland_genome)
+ self.failUnlessEqual(g_lane.read_length, g2_lane.read_length)
+ self.failUnlessEqual(g_lane.use_bases, g2_lane.use_bases)
+
+ self.failUnlessEqual(len(g.summary), 1)
+ # test (some) summary elements
+ for i in range(1,9):
+ g_summary = g.summary[0][i]
+ g2_summary = g2.summary[0][i]
+ self.failUnlessEqual(g_summary.cluster, g2_summary.cluster)
+ self.failUnlessEqual(g_summary.lane, g2_summary.lane)
+
+ g_eland = g.eland_results
+ g2_eland = g2.eland_results
+ for lane in g_eland.results[0].keys():
+ g_results = g_eland.results[0][lane]
+ g2_results = g2_eland.results[0][lane]
+ self.failUnlessEqual(g_results.reads,
+ g2_results.reads)
+ self.failUnlessEqual(len(g_results.mapped_reads),
+ len(g2_results.mapped_reads))
+ for k in g_results.mapped_reads.keys():
+ self.failUnlessEqual(g_results.mapped_reads[k],
+ g2_results.mapped_reads[k])
+
+ self.failUnlessEqual(len(g_results.match_codes),
+ len(g2_results.match_codes))
+ for k in g_results.match_codes.keys():
+ self.failUnlessEqual(g_results.match_codes[k],
+ g2_results.match_codes[k])
+
+
+ def test_eland(self):
+ hg_map = {'Lambda.fa': 'Lambda.fa'}
+ for i in range(1,22):
+ short_name = 'chr%d.fa' % (i,)
+ long_name = 'hg18/chr%d.fa' % (i,)
+ hg_map[short_name] = long_name
+
+ genome_maps = { 1:hg_map, 2:hg_map, 3:hg_map, 4:hg_map,
+ 5:hg_map, 6:hg_map, 7:hg_map, 8:hg_map }
+ eland = gerald.eland(self.gerald_dir, genome_maps=genome_maps)
+
+ for i in range(1,9):
+ lane = eland.results[0][i]
+ self.failUnlessEqual(lane.reads, 6)
+ self.failUnlessEqual(lane.sample_name, "s")
+ self.failUnlessEqual(lane.lane_id, i)
+ self.failUnlessEqual(len(lane.mapped_reads), 17)
+ self.failUnlessEqual(lane.mapped_reads['hg18/chr5.fa'], 4)
+ self.failUnlessEqual(lane.match_codes['U0'], 3)
+ self.failUnlessEqual(lane.match_codes['R0'], 2)
+ self.failUnlessEqual(lane.match_codes['U1'], 1)
+ self.failUnlessEqual(lane.match_codes['R1'], 9)
+ self.failUnlessEqual(lane.match_codes['U2'], 0)
+ self.failUnlessEqual(lane.match_codes['R2'], 12)
+ self.failUnlessEqual(lane.match_codes['NM'], 1)
+ self.failUnlessEqual(lane.match_codes['QC'], 0)
+
+ xml = eland.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ e2 = gerald.ELAND(xml=xml)
+
+ for i in range(1,9):
+ l1 = eland.results[0][i]
+ l2 = e2.results[0][i]
+ self.failUnlessEqual(l1.reads, l2.reads)
+ self.failUnlessEqual(l1.sample_name, l2.sample_name)
+ self.failUnlessEqual(l1.lane_id, l2.lane_id)
+ self.failUnlessEqual(len(l1.mapped_reads), len(l2.mapped_reads))
+ self.failUnlessEqual(len(l1.mapped_reads), 17)
+ for k in l1.mapped_reads.keys():
+ self.failUnlessEqual(l1.mapped_reads[k],
+ l2.mapped_reads[k])
+
+ self.failUnlessEqual(len(l1.match_codes), 9)
+ self.failUnlessEqual(len(l1.match_codes), len(l2.match_codes))
+ for k in l1.match_codes.keys():
+ self.failUnlessEqual(l1.match_codes[k],
+ l2.match_codes[k])
+
+ def test_runfolder(self):
+ runs = runfolder.get_runs(self.runfolder_dir)
+
+ # do we get the flowcell id from the filename?
+ self.failUnlessEqual(len(runs), 1)
+ name = 'run_30J55AAXX_2009-02-22.xml'
+ self.failUnlessEqual(runs[0].name, name)
+
+ # do we get the flowcell id from the FlowcellId.xml file
+ make_flowcell_id(self.runfolder_dir, '30J55AAXX')
+ runs = runfolder.get_runs(self.runfolder_dir)
+ self.failUnlessEqual(len(runs), 1)
+ name = 'run_30J55AAXX_2009-02-22.xml'
+ self.failUnlessEqual(runs[0].name, name)
+
+ r1 = runs[0]
+ xml = r1.get_elements()
+ xml_str = ElementTree.tostring(xml)
+
+ r2 = runfolder.PipelineRun(xml=xml)
+ self.failUnlessEqual(r1.name, r2.name)
+ self.failIfEqual(r2.image_analysis, None)
+ self.failIfEqual(r2.bustard, None)
+ self.failIfEqual(r2.gerald, None)
+
+
+def suite():
+ return unittest.makeSuite(RunfolderTests,'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="suite")
+
--- /dev/null
+#!/usr/bin/env python
+
+from datetime import datetime, date
+import os
+import tempfile
+import shutil
+import unittest
+
+from htsworkflow.pipelines import ipar
+from htsworkflow.pipelines import bustard
+from htsworkflow.pipelines import gerald
+from htsworkflow.pipelines import runfolder
+from htsworkflow.pipelines.runfolder import ElementTree
+
+from htsworkflow.pipelines.test.simulate_runfolder import *
+
+
+def make_runfolder(obj=None):
+ """
+ Make a fake runfolder, attach all the directories to obj if defined
+ """
+ # make a fake runfolder directory
+ temp_dir = tempfile.mkdtemp(prefix='tmp_runfolder_')
+
+ runfolder_dir = os.path.join(temp_dir,
+ '080102_HWI-EAS229_0010_207BTAAXX')
+ os.mkdir(runfolder_dir)
+
+ data_dir = os.path.join(runfolder_dir, 'Data')
+ os.mkdir(data_dir)
+
+ ipar_dir = make_ipar_dir(data_dir)
+
+ matrix_dir = os.path.join(ipar_dir, 'Matrix')
+ os.mkdir(matrix_dir)
+ matrix_name = os.path.join(matrix_dir, 's_matrix.txt')
+ make_matrix(matrix_name)
+
+ bustard_dir = os.path.join(ipar_dir,
+ 'Bustard1.8.28_12-04-2008_diane')
+ os.mkdir(bustard_dir)
+ make_phasing_params(bustard_dir)
+
+ gerald_dir = os.path.join(bustard_dir,
+ 'GERALD_12-04-2008_diane')
+ os.mkdir(gerald_dir)
+ make_gerald_config_100(gerald_dir)
+ make_summary_htm_100(gerald_dir)
+ make_eland_multi(gerald_dir)
+
+ if obj is not None:
+ obj.temp_dir = temp_dir
+ obj.runfolder_dir = runfolder_dir
+ obj.data_dir = data_dir
+ obj.image_analysis_dir = ipar_dir
+ obj.matrix_dir = matrix_dir
+ obj.bustard_dir = bustard_dir
+ obj.gerald_dir = gerald_dir
+
+
+class RunfolderTests(unittest.TestCase):
+ """
+ Test components of the runfolder processing code
+ which includes firecrest, bustard, and gerald
+ """
+ def setUp(self):
+ # attaches all the directories to the object passed in
+ make_runfolder(self)
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+
+ def test_ipar(self):
+ """
+ Construct a firecrest object
+ """
+ i = ipar.ipar(self.image_analysis_dir)
+ self.failUnlessEqual(i.version, '2.01.192.0')
+ self.failUnlessEqual(i.start, 1)
+ self.failUnlessEqual(i.stop, 37)
+
+ xml = i.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+
+ i2 = ipar.IPAR(xml=xml)
+ self.failUnlessEqual(i.version, i2.version)
+ self.failUnlessEqual(i.start, i2.start)
+ self.failUnlessEqual(i.stop, i2.stop)
+ self.failUnlessEqual(i.date, i2.date)
+ self.failUnlessEqual(i.file_list(), i2.file_list())
+
+ def test_bustard(self):
+ """
+ construct a bustard object
+ """
+ b = bustard.bustard(self.bustard_dir)
+ self.failUnlessEqual(b.version, '1.8.28')
+ self.failUnlessEqual(b.date, date(2008,4,12))
+ self.failUnlessEqual(b.user, 'diane')
+ self.failUnlessEqual(len(b.phasing), 8)
+ self.failUnlessAlmostEqual(b.phasing[8].phasing, 0.0099)
+
+ xml = b.get_elements()
+ b2 = bustard.Bustard(xml=xml)
+ self.failUnlessEqual(b.version, b2.version)
+ self.failUnlessEqual(b.date, b2.date )
+ self.failUnlessEqual(b.user, b2.user)
+ self.failUnlessEqual(len(b.phasing), len(b2.phasing))
+ for key in b.phasing.keys():
+ self.failUnlessEqual(b.phasing[key].lane,
+ b2.phasing[key].lane)
+ self.failUnlessEqual(b.phasing[key].phasing,
+ b2.phasing[key].phasing)
+ self.failUnlessEqual(b.phasing[key].prephasing,
+ b2.phasing[key].prephasing)
+
+ def test_gerald(self):
+ # need to update gerald and make tests for it
+ g = gerald.gerald(self.gerald_dir)
+
+ self.failUnlessEqual(g.version,
+ '@(#) Id: GERALD.pl,v 1.171 2008/05/19 17:36:14 mzerara Exp')
+ self.failUnlessEqual(g.date, datetime(2009,2,22,21,15,59))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.items()))
+
+
+ # list of genomes, matches what was defined up in
+ # make_gerald_config.
+ # the first None is to offset the genomes list to be 1..9
+ # instead of pythons default 0..8
+ genomes = [None,
+ '/g/mm9',
+ '/g/mm9',
+ '/g/elegans190',
+ '/g/arabidopsis01222004',
+ '/g/mm9',
+ '/g/mm9',
+ '/g/mm9',
+ '/g/mm9', ]
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ cur_lane = g.lanes[i]
+ self.failUnlessEqual(cur_lane.analysis, 'eland_extended')
+ self.failUnlessEqual(cur_lane.eland_genome, genomes[i])
+ self.failUnlessEqual(cur_lane.read_length, '37')
+ self.failUnlessEqual(cur_lane.use_bases, 'Y'*37)
+
+ # I want to be able to use a simple iterator
+ for l in g.lanes.values():
+ self.failUnlessEqual(l.analysis, 'eland_extended')
+ self.failUnlessEqual(l.read_length, '37')
+ self.failUnlessEqual(l.use_bases, 'Y'*37)
+
+ # test data extracted from summary file
+ clusters = [None,
+ (96483, 9074), (133738, 7938),
+ (152142, 10002), (15784, 2162),
+ (119735, 8465), (152177, 8146),
+ (84649, 7325), (54622, 4812),]
+
+ self.failUnlessEqual(len(g.summary), 1)
+ for i in range(1,9):
+ summary_lane = g.summary[0][i]
+ self.failUnlessEqual(summary_lane.cluster, clusters[i])
+ self.failUnlessEqual(summary_lane.lane, i)
+
+ xml = g.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ g2 = gerald.Gerald(xml=xml)
+
+ # do it all again after extracting from the xml file
+ self.failUnlessEqual(g.version, g2.version)
+ self.failUnlessEqual(g.date, g2.date)
+ self.failUnlessEqual(len(g.lanes.keys()), len(g2.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes.items()), len(g2.lanes.items()))
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ g_lane = g.lanes[i]
+ g2_lane = g2.lanes[i]
+ self.failUnlessEqual(g_lane.analysis, g2_lane.analysis)
+ self.failUnlessEqual(g_lane.eland_genome, g2_lane.eland_genome)
+ self.failUnlessEqual(g_lane.read_length, g2_lane.read_length)
+ self.failUnlessEqual(g_lane.use_bases, g2_lane.use_bases)
+
+ # test (some) summary elements
+ self.failUnlessEqual(len(g.summary), 1)
+ for i in range(1,9):
+ g_summary = g.summary[0][i]
+ g2_summary = g2.summary[0][i]
+ self.failUnlessEqual(g_summary.cluster, g2_summary.cluster)
+ self.failUnlessEqual(g_summary.lane, g2_summary.lane)
+
+ g_eland = g.eland_results
+ g2_eland = g2.eland_results
+ for lane in g_eland.results[0].keys():
+ g_results = g_eland.results[0][lane]
+ g2_results = g2_eland.results[0][lane]
+ self.failUnlessEqual(g_results.reads,
+ g2_results.reads)
+ self.failUnlessEqual(len(g_results.mapped_reads),
+ len(g2_results.mapped_reads))
+ for k in g_results.mapped_reads.keys():
+ self.failUnlessEqual(g_results.mapped_reads[k],
+ g2_results.mapped_reads[k])
+
+ self.failUnlessEqual(len(g_results.match_codes),
+ len(g2_results.match_codes))
+ for k in g_results.match_codes.keys():
+ self.failUnlessEqual(g_results.match_codes[k],
+ g2_results.match_codes[k])
+
+
+ def test_eland(self):
+ hg_map = {'Lambda.fa': 'Lambda.fa'}
+ for i in range(1,22):
+ short_name = 'chr%d.fa' % (i,)
+ long_name = 'hg18/chr%d.fa' % (i,)
+ hg_map[short_name] = long_name
+
+ genome_maps = { 1:hg_map, 2:hg_map, 3:hg_map, 4:hg_map,
+ 5:hg_map, 6:hg_map, 7:hg_map, 8:hg_map }
+ eland = gerald.eland(self.gerald_dir, genome_maps=genome_maps)
+
+ for i in range(1,9):
+ lane = eland.results[0][i]
+ self.failUnlessEqual(lane.reads, 6)
+ self.failUnlessEqual(lane.sample_name, "s")
+ self.failUnlessEqual(lane.lane_id, i)
+ self.failUnlessEqual(len(lane.mapped_reads), 17)
+ self.failUnlessEqual(lane.mapped_reads['hg18/chr5.fa'], 4)
+ self.failUnlessEqual(lane.mapped_reads['spike.fa/sample1'], 1)
+ self.failUnlessEqual(lane.mapped_reads['spike.fa/sample2'], 1)
+ self.failUnlessEqual(lane.match_codes['U0'], 3)
+ self.failUnlessEqual(lane.match_codes['R0'], 2)
+ self.failUnlessEqual(lane.match_codes['U1'], 1)
+ self.failUnlessEqual(lane.match_codes['R1'], 9)
+ self.failUnlessEqual(lane.match_codes['U2'], 0)
+ self.failUnlessEqual(lane.match_codes['R2'], 12)
+ self.failUnlessEqual(lane.match_codes['NM'], 1)
+ self.failUnlessEqual(lane.match_codes['QC'], 0)
+
+ xml = eland.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ e2 = gerald.ELAND(xml=xml)
+
+ for i in range(1,9):
+ l1 = eland.results[0][i]
+ l2 = e2.results[0][i]
+ self.failUnlessEqual(l1.reads, l2.reads)
+ self.failUnlessEqual(l1.sample_name, l2.sample_name)
+ self.failUnlessEqual(l1.lane_id, l2.lane_id)
+ self.failUnlessEqual(len(l1.mapped_reads), len(l2.mapped_reads))
+ self.failUnlessEqual(len(l1.mapped_reads), 17)
+ for k in l1.mapped_reads.keys():
+ self.failUnlessEqual(l1.mapped_reads[k],
+ l2.mapped_reads[k])
+
+ self.failUnlessEqual(len(l1.match_codes), 9)
+ self.failUnlessEqual(len(l1.match_codes), len(l2.match_codes))
+ for k in l1.match_codes.keys():
+ self.failUnlessEqual(l1.match_codes[k],
+ l2.match_codes[k])
+
+ def test_runfolder(self):
+ runs = runfolder.get_runs(self.runfolder_dir)
+
+ # do we get the flowcell id from the filename?
+ self.failUnlessEqual(len(runs), 1)
+ name = 'run_207BTAAXX_%s.xml' % ( date.today().strftime('%Y-%m-%d'),)
+ self.failUnlessEqual(runs[0].name, name)
+
+ # do we get the flowcell id from the FlowcellId.xml file
+ make_flowcell_id(self.runfolder_dir, '207BTAAXY')
+ runs = runfolder.get_runs(self.runfolder_dir)
+ self.failUnlessEqual(len(runs), 1)
+ name = 'run_207BTAAXY_%s.xml' % ( date.today().strftime('%Y-%m-%d'),)
+ self.failUnlessEqual(runs[0].name, name)
+
+ r1 = runs[0]
+ xml = r1.get_elements()
+ xml_str = ElementTree.tostring(xml)
+
+ r2 = runfolder.PipelineRun(xml=xml)
+ self.failUnlessEqual(r1.name, r2.name)
+ self.failIfEqual(r2.image_analysis, None)
+ self.failIfEqual(r2.bustard, None)
+ self.failIfEqual(r2.gerald, None)
+
+
+def suite():
+ return unittest.makeSuite(RunfolderTests,'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="suite")
+
--- /dev/null
+#!/usr/bin/env python
+
+from datetime import datetime, date
+import os
+import tempfile
+import shutil
+import unittest
+
+from htsworkflow.pipelines import eland
+from htsworkflow.pipelines import ipar
+from htsworkflow.pipelines import bustard
+from htsworkflow.pipelines import gerald
+from htsworkflow.pipelines import runfolder
+from htsworkflow.pipelines.runfolder import ElementTree
+
+from htsworkflow.pipelines.test.simulate_runfolder import *
+
+
+def make_runfolder(obj=None):
+ """
+ Make a fake runfolder, attach all the directories to obj if defined
+ """
+ # make a fake runfolder directory
+ temp_dir = tempfile.mkdtemp(prefix='tmp_runfolder_')
+
+ runfolder_dir = os.path.join(temp_dir,
+ '090313_HWI-EAS229_0101_3021JAAXX')
+ os.mkdir(runfolder_dir)
+
+ data_dir = os.path.join(runfolder_dir, 'Data')
+ os.mkdir(data_dir)
+
+ ipar_dir = make_ipar_dir(data_dir, '1.30')
+
+ bustard_dir = os.path.join(ipar_dir,
+ 'Bustard1.3.2_15-03-2008_diane')
+ os.mkdir(bustard_dir)
+ make_phasing_params(bustard_dir)
+ make_bustard_config132(bustard_dir)
+
+ gerald_dir = os.path.join(bustard_dir,
+ 'GERALD_15-03-2008_diane')
+ os.mkdir(gerald_dir)
+ make_gerald_config_100(gerald_dir)
+ make_summary_ipar130_htm(gerald_dir)
+ make_eland_multi(gerald_dir, lane_list=[1,2,3,4,5,6,])
+ make_scarf(gerald_dir, lane_list=[7,])
+ make_fastq(gerald_dir, lane_list=[8,])
+
+ if obj is not None:
+ obj.temp_dir = temp_dir
+ obj.runfolder_dir = runfolder_dir
+ obj.data_dir = data_dir
+ obj.image_analysis_dir = ipar_dir
+ obj.bustard_dir = bustard_dir
+ obj.gerald_dir = gerald_dir
+
+
+class RunfolderTests(unittest.TestCase):
+ """
+ Test components of the runfolder processing code
+ which includes firecrest, bustard, and gerald
+ """
+ def setUp(self):
+ # attaches all the directories to the object passed in
+ make_runfolder(self)
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+
+ def test_ipar(self):
+ """
+ Construct a firecrest object
+ """
+ i = ipar.ipar(self.image_analysis_dir)
+ self.failUnlessEqual(i.version, '2.01.192.0')
+ self.failUnlessEqual(i.start, 1)
+ self.failUnlessEqual(i.stop, 37)
+
+ xml = i.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+
+ i2 = ipar.IPAR(xml=xml)
+ self.failUnlessEqual(i.version, i2.version)
+ self.failUnlessEqual(i.start, i2.start)
+ self.failUnlessEqual(i.stop, i2.stop)
+ self.failUnlessEqual(i.date, i2.date)
+ self.failUnlessEqual(i.file_list(), i2.file_list())
+
+ def test_bustard(self):
+ """
+ construct a bustard object
+ """
+ def check_crosstalk(crosstalk):
+ self.failUnlessAlmostEqual(crosstalk.base['A'][0], 1.27)
+ self.failUnlessAlmostEqual(crosstalk.base['A'][1], 0.20999999999999)
+ self.failUnlessAlmostEqual(crosstalk.base['A'][2], -0.02)
+ self.failUnlessAlmostEqual(crosstalk.base['A'][3], -0.03)
+
+ self.failUnlessAlmostEqual(crosstalk.base['C'][0], 0.57)
+ self.failUnlessAlmostEqual(crosstalk.base['C'][1], 0.58)
+ self.failUnlessAlmostEqual(crosstalk.base['C'][2], -0.01)
+ self.failUnlessAlmostEqual(crosstalk.base['C'][3], -0.01)
+
+ self.failUnlessAlmostEqual(crosstalk.base['T'][0], -0.02)
+ self.failUnlessAlmostEqual(crosstalk.base['T'][1], -0.02)
+ self.failUnlessAlmostEqual(crosstalk.base['T'][2], 0.80)
+ self.failUnlessAlmostEqual(crosstalk.base['T'][3], 1.07)
+
+ self.failUnlessAlmostEqual(crosstalk.base['G'][0], -0.03)
+ self.failUnlessAlmostEqual(crosstalk.base['G'][1], -0.04)
+ self.failUnlessAlmostEqual(crosstalk.base['G'][2], 1.51)
+ self.failUnlessAlmostEqual(crosstalk.base['G'][3], -0.02)
+
+ b = bustard.bustard(self.bustard_dir)
+ self.failUnlessEqual(b.version, '1.3.2')
+ self.failUnlessEqual(b.date, date(2008,3,15))
+ self.failUnlessEqual(b.user, 'diane')
+ self.failUnlessEqual(len(b.phasing), 8)
+ self.failUnlessAlmostEqual(b.phasing[8].phasing, 0.0099)
+ self.failUnlessEqual(b.crosstalk.base.keys(), ['A','C','T','G'])
+ check_crosstalk(b.crosstalk)
+
+ xml = b.get_elements()
+ print ElementTree.dump(xml)
+ b2 = bustard.Bustard(xml=xml)
+ self.failUnlessEqual(b.version, b2.version)
+ self.failUnlessEqual(b.date, b2.date )
+ self.failUnlessEqual(b.user, b2.user)
+ self.failUnlessEqual(len(b.phasing), len(b2.phasing))
+ for key in b.phasing.keys():
+ self.failUnlessEqual(b.phasing[key].lane,
+ b2.phasing[key].lane)
+ self.failUnlessEqual(b.phasing[key].phasing,
+ b2.phasing[key].phasing)
+ self.failUnlessEqual(b.phasing[key].prephasing,
+ b2.phasing[key].prephasing)
+ check_crosstalk(b2.crosstalk)
+
+ def test_gerald(self):
+ # need to update gerald and make tests for it
+ g = gerald.gerald(self.gerald_dir)
+
+ self.failUnlessEqual(g.version,
+ '@(#) Id: GERALD.pl,v 1.171 2008/05/19 17:36:14 mzerara Exp')
+ self.failUnlessEqual(g.date, datetime(2009,2,22,21,15,59))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.items()))
+
+
+ # list of genomes, matches what was defined up in
+ # make_gerald_config.
+ # the first None is to offset the genomes list to be 1..9
+ # instead of pythons default 0..8
+ genomes = [None,
+ '/g/mm9',
+ '/g/mm9',
+ '/g/elegans190',
+ '/g/arabidopsis01222004',
+ '/g/mm9',
+ '/g/mm9',
+ '/g/mm9',
+ '/g/mm9', ]
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ cur_lane = g.lanes[i]
+ self.failUnlessEqual(cur_lane.analysis, 'eland_extended')
+ self.failUnlessEqual(cur_lane.eland_genome, genomes[i])
+ self.failUnlessEqual(cur_lane.read_length, '37')
+ self.failUnlessEqual(cur_lane.use_bases, 'Y'*37)
+
+ # I want to be able to use a simple iterator
+ for l in g.lanes.values():
+ self.failUnlessEqual(l.analysis, 'eland_extended')
+ self.failUnlessEqual(l.read_length, '37')
+ self.failUnlessEqual(l.use_bases, 'Y'*37)
+
+ # test data extracted from summary file
+ clusters = [None,
+ (126910, 4300), (165739, 6792),
+ (196565, 8216), (153897, 8501),
+ (135536, 3908), (154083, 9315),
+ (159991, 9292), (198479, 17671),]
+
+ self.failUnlessEqual(len(g.summary), 1)
+ for i in range(1,9):
+ summary_lane = g.summary[0][i]
+ self.failUnlessEqual(summary_lane.cluster, clusters[i])
+ self.failUnlessEqual(summary_lane.lane, i)
+
+ xml = g.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ g2 = gerald.Gerald(xml=xml)
+
+ # do it all again after extracting from the xml file
+ self.failUnlessEqual(g.version, g2.version)
+ self.failUnlessEqual(g.date, g2.date)
+ self.failUnlessEqual(len(g.lanes.keys()), len(g2.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes.items()), len(g2.lanes.items()))
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ g_lane = g.lanes[i]
+ g2_lane = g2.lanes[i]
+ self.failUnlessEqual(g_lane.analysis, g2_lane.analysis)
+ self.failUnlessEqual(g_lane.eland_genome, g2_lane.eland_genome)
+ self.failUnlessEqual(g_lane.read_length, g2_lane.read_length)
+ self.failUnlessEqual(g_lane.use_bases, g2_lane.use_bases)
+
+ # test (some) summary elements
+ self.failUnlessEqual(len(g.summary), 1)
+ for i in range(1,9):
+ g_summary = g.summary[0][i]
+ g2_summary = g2.summary[0][i]
+ self.failUnlessEqual(g_summary.cluster, g2_summary.cluster)
+ self.failUnlessEqual(g_summary.lane, g2_summary.lane)
+
+ g_eland = g.eland_results
+ g2_eland = g2.eland_results
+ for lane in g_eland.results[0].keys():
+ g_results = g_eland.results[0][lane]
+ g2_results = g2_eland.results[0][lane]
+ self.failUnlessEqual(g_results.reads,
+ g2_results.reads)
+ if isinstance(g_results, eland.ElandLane):
+ self.failUnlessEqual(len(g_results.mapped_reads),
+ len(g2_results.mapped_reads))
+ for k in g_results.mapped_reads.keys():
+ self.failUnlessEqual(g_results.mapped_reads[k],
+ g2_results.mapped_reads[k])
+
+ self.failUnlessEqual(len(g_results.match_codes),
+ len(g2_results.match_codes))
+ for k in g_results.match_codes.keys():
+ self.failUnlessEqual(g_results.match_codes[k],
+ g2_results.match_codes[k])
+
+
+ def test_eland(self):
+ hg_map = {'Lambda.fa': 'Lambda.fa'}
+ for i in range(1,22):
+ short_name = 'chr%d.fa' % (i,)
+ long_name = 'hg18/chr%d.fa' % (i,)
+ hg_map[short_name] = long_name
+
+ genome_maps = { 1:hg_map, 2:hg_map, 3:hg_map, 4:hg_map,
+ 5:hg_map, 6:hg_map, 7:hg_map, 8:hg_map }
+ eland_container = gerald.eland(self.gerald_dir, genome_maps=genome_maps)
+
+ # I added sequence lanes to the last 2 lanes of this test case
+ for i in range(1,7):
+ lane = eland_container.results[0][i]
+ self.failUnlessEqual(lane.reads, 6)
+ self.failUnlessEqual(lane.sample_name, "s")
+ self.failUnlessEqual(lane.lane_id, i)
+ self.failUnlessEqual(len(lane.mapped_reads), 17)
+ self.failUnlessEqual(lane.mapped_reads['hg18/chr5.fa'], 4)
+ self.failUnlessEqual(lane.match_codes['U0'], 3)
+ self.failUnlessEqual(lane.match_codes['R0'], 2)
+ self.failUnlessEqual(lane.match_codes['U1'], 1)
+ self.failUnlessEqual(lane.match_codes['R1'], 9)
+ self.failUnlessEqual(lane.match_codes['U2'], 0)
+ self.failUnlessEqual(lane.match_codes['R2'], 12)
+ self.failUnlessEqual(lane.match_codes['NM'], 1)
+ self.failUnlessEqual(lane.match_codes['QC'], 0)
+
+ # test scarf
+ lane = eland_container.results[0][7]
+ self.failUnlessEqual(lane.reads, 5)
+ self.failUnlessEqual(lane.sample_name, 's')
+ self.failUnlessEqual(lane.lane_id, 7)
+ self.failUnlessEqual(lane.sequence_type, eland.SequenceLane.SCARF_TYPE)
+
+ # test fastq
+ lane = eland_container.results[0][8]
+ self.failUnlessEqual(lane.reads, 3)
+ self.failUnlessEqual(lane.sample_name, 's')
+ self.failUnlessEqual(lane.lane_id, 8)
+ self.failUnlessEqual(lane.sequence_type, eland.SequenceLane.FASTQ_TYPE)
+
+ xml = eland_container.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ e2 = gerald.ELAND(xml=xml)
+
+ for i in range(1,9):
+ l1 = eland_container.results[0][i]
+ l2 = e2.results[0][i]
+ self.failUnlessEqual(l1.reads, l2.reads)
+ self.failUnlessEqual(l1.sample_name, l2.sample_name)
+ self.failUnlessEqual(l1.lane_id, l2.lane_id)
+ if isinstance(l1, eland.ElandLane):
+ self.failUnlessEqual(len(l1.mapped_reads), len(l2.mapped_reads))
+ self.failUnlessEqual(len(l1.mapped_reads), 17)
+ for k in l1.mapped_reads.keys():
+ self.failUnlessEqual(l1.mapped_reads[k],
+ l2.mapped_reads[k])
+
+ self.failUnlessEqual(len(l1.match_codes), 9)
+ self.failUnlessEqual(len(l1.match_codes), len(l2.match_codes))
+ for k in l1.match_codes.keys():
+ self.failUnlessEqual(l1.match_codes[k],
+ l2.match_codes[k])
+ elif isinstance(l1, eland.SequenceLane):
+ print 'l1', l1.__dict__
+ print 'l2', l2.__dict__
+ self.failUnlessEqual(l1.sequence_type, l2.sequence_type)
+
+ def test_runfolder(self):
+ runs = runfolder.get_runs(self.runfolder_dir)
+
+ # do we get the flowcell id from the filename?
+ self.failUnlessEqual(len(runs), 1)
+ name = 'run_3021JAAXX_%s.xml' % ( date.today().strftime('%Y-%m-%d'),)
+ self.failUnlessEqual(runs[0].name, name)
+
+ # do we get the flowcell id from the FlowcellId.xml file
+ make_flowcell_id(self.runfolder_dir, '207BTAAXY')
+ runs = runfolder.get_runs(self.runfolder_dir)
+ self.failUnlessEqual(len(runs), 1)
+ name = 'run_207BTAAXY_%s.xml' % ( date.today().strftime('%Y-%m-%d'),)
+ self.failUnlessEqual(runs[0].name, name)
+
+ r1 = runs[0]
+ xml = r1.get_elements()
+ xml_str = ElementTree.tostring(xml)
+
+ r2 = runfolder.PipelineRun(xml=xml)
+ self.failUnlessEqual(r1.name, r2.name)
+ self.failIfEqual(r2.image_analysis, None)
+ self.failIfEqual(r2.bustard, None)
+ self.failIfEqual(r2.gerald, None)
+
+
+def suite():
+ return unittest.makeSuite(RunfolderTests,'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="suite")
+
--- /dev/null
+#!/usr/bin/env python
+
+from datetime import datetime, date
+import os
+import tempfile
+import shutil
+import unittest
+
+from htsworkflow.pipelines import firecrest
+from htsworkflow.pipelines import bustard
+from htsworkflow.pipelines import gerald
+from htsworkflow.pipelines import runfolder
+from htsworkflow.pipelines.runfolder import ElementTree
+
+from htsworkflow.pipelines.test.simulate_runfolder import *
+
+
+def make_runfolder(obj=None):
+ """
+ Make a fake runfolder, attach all the directories to obj if defined
+ """
+ # make a fake runfolder directory
+ temp_dir = tempfile.mkdtemp(prefix='tmp_runfolder_')
+
+ runfolder_dir = os.path.join(temp_dir,
+ '080102_HWI-EAS229_0010_207BTAAXX')
+ os.mkdir(runfolder_dir)
+
+ data_dir = os.path.join(runfolder_dir, 'Data')
+ os.mkdir(data_dir)
+
+ ipar_dir = make_firecrest_dir(data_dir, "1.9.6", 1, 152)
+
+ matrix_dir = os.path.join(ipar_dir, 'Matrix')
+ os.mkdir(matrix_dir)
+ matrix_name = os.path.join(matrix_dir, 's_matrix.txt')
+ make_matrix(matrix_name)
+
+ bustard_dir = os.path.join(ipar_dir,
+ 'Bustard1.8.28_12-04-2008_diane')
+ os.mkdir(bustard_dir)
+ make_phasing_params(bustard_dir)
+
+ gerald_dir = os.path.join(bustard_dir,
+ 'GERALD_12-04-2008_diane')
+ os.mkdir(gerald_dir)
+ make_gerald_config_100(gerald_dir)
+ make_summary_paired_htm(gerald_dir)
+ make_eland_multi(gerald_dir, paired=True)
+
+ if obj is not None:
+ obj.temp_dir = temp_dir
+ obj.runfolder_dir = runfolder_dir
+ obj.data_dir = data_dir
+ obj.image_analysis_dir = ipar_dir
+ obj.matrix_dir = matrix_dir
+ obj.bustard_dir = bustard_dir
+ obj.gerald_dir = gerald_dir
+
+
+class RunfolderTests(unittest.TestCase):
+ """
+ Test components of the runfolder processing code
+ which includes firecrest, bustard, and gerald
+ """
+ def setUp(self):
+ # attaches all the directories to the object passed in
+ make_runfolder(self)
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+
+ def test_firecrest(self):
+ """
+ Construct a firecrest object
+ """
+ f = firecrest.firecrest(self.image_analysis_dir)
+ self.failUnlessEqual(f.version, '1.9.6')
+ self.failUnlessEqual(f.start, 1)
+ self.failUnlessEqual(f.stop, 152)
+ self.failUnlessEqual(f.user, 'diane')
+ # As of 2008-12-8, the date was being set in
+ # simulate_runfolder.make_firecrest_dir
+ self.failUnlessEqual(f.date, date(2008,4,12))
+
+ xml = f.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+
+ f2 = firecrest.Firecrest(xml=xml)
+ self.failUnlessEqual(f.version, f2.version)
+ self.failUnlessEqual(f.start, f2.start)
+ self.failUnlessEqual(f.stop, f2.stop)
+ self.failUnlessEqual(f.user, f2.user)
+
+ def test_bustard(self):
+ """
+ construct a bustard object
+ """
+ b = bustard.bustard(self.bustard_dir)
+ self.failUnlessEqual(b.version, '1.8.28')
+ self.failUnlessEqual(b.date, date(2008,4,12))
+ self.failUnlessEqual(b.user, 'diane')
+ self.failUnlessEqual(len(b.phasing), 8)
+ self.failUnlessAlmostEqual(b.phasing[8].phasing, 0.0099)
+
+ xml = b.get_elements()
+ b2 = bustard.Bustard(xml=xml)
+ self.failUnlessEqual(b.version, b2.version)
+ self.failUnlessEqual(b.date, b2.date )
+ self.failUnlessEqual(b.user, b2.user)
+ self.failUnlessEqual(len(b.phasing), len(b2.phasing))
+ for key in b.phasing.keys():
+ self.failUnlessEqual(b.phasing[key].lane,
+ b2.phasing[key].lane)
+ self.failUnlessEqual(b.phasing[key].phasing,
+ b2.phasing[key].phasing)
+ self.failUnlessEqual(b.phasing[key].prephasing,
+ b2.phasing[key].prephasing)
+
+ def test_gerald(self):
+ # need to update gerald and make tests for it
+ g = gerald.gerald(self.gerald_dir)
+
+ self.failUnlessEqual(g.version,
+ '@(#) Id: GERALD.pl,v 1.171 2008/05/19 17:36:14 mzerara Exp')
+ self.failUnlessEqual(g.date, datetime(2009,2,22,21,15,59))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes), len(g.lanes.items()))
+
+
+ # list of genomes, matches what was defined up in
+ # make_gerald_config.
+ # the first None is to offset the genomes list to be 1..9
+ # instead of pythons default 0..8
+ genomes = [None,
+ '/g/mm9',
+ '/g/mm9',
+ '/g/elegans190',
+ '/g/arabidopsis01222004',
+ '/g/mm9',
+ '/g/mm9',
+ '/g/mm9',
+ '/g/mm9', ]
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ cur_lane = g.lanes[i]
+ self.failUnlessEqual(cur_lane.analysis, 'eland_extended')
+ self.failUnlessEqual(cur_lane.eland_genome, genomes[i])
+ self.failUnlessEqual(cur_lane.read_length, '37')
+ self.failUnlessEqual(cur_lane.use_bases, 'Y'*37)
+
+ # I want to be able to use a simple iterator
+ for l in g.lanes.values():
+ self.failUnlessEqual(l.analysis, 'eland_extended')
+ self.failUnlessEqual(l.read_length, '37')
+ self.failUnlessEqual(l.use_bases, 'Y'*37)
+
+ # test data extracted from summary file
+ clusters = [[None,
+ (103646, 4515), (106678, 4652),
+ (84583, 5963), (68813, 4782),
+ (104854, 4664), (43555, 1632),
+ (54265, 1588), (64363, 2697),],
+ [None,
+ (103647, 4516), (106679, 4653),
+ (84584, 5964), (68814, 4783),
+ (104855, 4665), (43556, 1633),
+ (54266, 1589), (64364, 2698),],]
+
+ for end in [0,1]:
+ for lane in range(1,9):
+ summary_lane = g.summary[end][lane]
+ self.failUnlessEqual(summary_lane.cluster, clusters[end][lane])
+ self.failUnlessEqual(summary_lane.lane, lane)
+
+ xml = g.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ g2 = gerald.Gerald(xml=xml)
+
+ # do it all again after extracting from the xml file
+ self.failUnlessEqual(g.version, g2.version)
+ self.failUnlessEqual(g.date, g2.date)
+ self.failUnlessEqual(len(g.lanes.keys()), len(g2.lanes.keys()))
+ self.failUnlessEqual(len(g.lanes.items()), len(g2.lanes.items()))
+
+ # test lane specific parameters from gerald config file
+ for i in range(1,9):
+ g_lane = g.lanes[i]
+ g2_lane = g2.lanes[i]
+ self.failUnlessEqual(g_lane.analysis, g2_lane.analysis)
+ self.failUnlessEqual(g_lane.eland_genome, g2_lane.eland_genome)
+ self.failUnlessEqual(g_lane.read_length, g2_lane.read_length)
+ self.failUnlessEqual(g_lane.use_bases, g2_lane.use_bases)
+
+ # test (some) summary elements
+ for end in [0,1]:
+ for i in range(1,9):
+ g_summary = g.summary[end][i]
+ g2_summary = g2.summary[end][i]
+ self.failUnlessEqual(g_summary.cluster, g2_summary.cluster)
+ self.failUnlessEqual(g_summary.lane, g2_summary.lane)
+
+ g_eland = g.eland_results
+ g2_eland = g2.eland_results
+ for lane in g_eland.results[end].keys():
+ g_results = g_eland.results[end][lane]
+ g2_results = g_eland.results[end][lane]
+ self.failUnlessEqual(g_results.reads,
+ g2_results.reads)
+ self.failUnlessEqual(len(g_results.mapped_reads),
+ len(g2_results.mapped_reads))
+ for k in g_results.mapped_reads.keys():
+ self.failUnlessEqual(g_results.mapped_reads[k],
+ g2_results.mapped_reads[k])
+
+ self.failUnlessEqual(len(g_results.match_codes),
+ len(g2_results.match_codes))
+ for k in g_results.match_codes.keys():
+ self.failUnlessEqual(g_results.match_codes[k],
+ g2_results.match_codes[k])
+
+
+ def test_eland(self):
+ hg_map = {'Lambda.fa': 'Lambda.fa'}
+ for i in range(1,22):
+ short_name = 'chr%d.fa' % (i,)
+ long_name = 'hg18/chr%d.fa' % (i,)
+ hg_map[short_name] = long_name
+
+ genome_maps = { 1:hg_map, 2:hg_map, 3:hg_map, 4:hg_map,
+ 5:hg_map, 6:hg_map, 7:hg_map, 8:hg_map }
+ eland = gerald.eland(self.gerald_dir, genome_maps=genome_maps)
+
+ # check first end
+ for i in range(1,9):
+ lane = eland.results[0][i]
+ self.failUnlessEqual(lane.reads, 6)
+ self.failUnlessEqual(lane.sample_name, "s")
+ self.failUnlessEqual(lane.lane_id, i)
+ self.failUnlessEqual(len(lane.mapped_reads), 17)
+ self.failUnlessEqual(lane.mapped_reads['hg18/chr5.fa'], 4)
+ self.failUnlessEqual(lane.match_codes['U0'], 3)
+ self.failUnlessEqual(lane.match_codes['R0'], 2)
+ self.failUnlessEqual(lane.match_codes['U1'], 1)
+ self.failUnlessEqual(lane.match_codes['R1'], 9)
+ self.failUnlessEqual(lane.match_codes['U2'], 0)
+ self.failUnlessEqual(lane.match_codes['R2'], 12)
+ self.failUnlessEqual(lane.match_codes['NM'], 1)
+ self.failUnlessEqual(lane.match_codes['QC'], 0)
+
+ # check second end
+ for i in range(1,9):
+ lane = eland.results[1][i]
+ self.failUnlessEqual(lane.reads, 7)
+ self.failUnlessEqual(lane.sample_name, "s")
+ self.failUnlessEqual(lane.lane_id, i)
+ self.failUnlessEqual(len(lane.mapped_reads), 17)
+ self.failUnlessEqual(lane.mapped_reads['hg18/chr5.fa'], 4)
+ self.failUnlessEqual(lane.match_codes['U0'], 3)
+ self.failUnlessEqual(lane.match_codes['R0'], 2)
+ self.failUnlessEqual(lane.match_codes['U1'], 1)
+ self.failUnlessEqual(lane.match_codes['R1'], 9)
+ self.failUnlessEqual(lane.match_codes['U2'], 0)
+ self.failUnlessEqual(lane.match_codes['R2'], 12)
+ self.failUnlessEqual(lane.match_codes['NM'], 1)
+ self.failUnlessEqual(lane.match_codes['QC'], 1)
+
+ xml = eland.get_elements()
+ # just make sure that element tree can serialize the tree
+ xml_str = ElementTree.tostring(xml)
+ e2 = gerald.ELAND(xml=xml)
+
+ for end in [0, 1]:
+ for i in range(1,9):
+ l1 = eland.results[end][i]
+ l2 = e2.results[end][i]
+ self.failUnlessEqual(l1.reads, l2.reads)
+ self.failUnlessEqual(l1.sample_name, l2.sample_name)
+ self.failUnlessEqual(l1.lane_id, l2.lane_id)
+ self.failUnlessEqual(len(l1.mapped_reads), len(l2.mapped_reads))
+ self.failUnlessEqual(len(l1.mapped_reads), 17)
+ for k in l1.mapped_reads.keys():
+ self.failUnlessEqual(l1.mapped_reads[k],
+ l2.mapped_reads[k])
+
+ self.failUnlessEqual(len(l1.match_codes), 9)
+ self.failUnlessEqual(len(l1.match_codes), len(l2.match_codes))
+ for k in l1.match_codes.keys():
+ self.failUnlessEqual(l1.match_codes[k],
+ l2.match_codes[k])
+
+ def test_runfolder(self):
+ runs = runfolder.get_runs(self.runfolder_dir)
+
+ # do we get the flowcell id from the filename?
+ self.failUnlessEqual(len(runs), 1)
+ # firecrest's date depends on filename not the create time.
+ name = 'run_207BTAAXX_2009-02-22.xml'
+ self.failUnlessEqual(runs[0].name, name)
+
+ # do we get the flowcell id from the FlowcellId.xml file
+ make_flowcell_id(self.runfolder_dir, '207BTAAXY')
+ runs = runfolder.get_runs(self.runfolder_dir)
+ self.failUnlessEqual(len(runs), 1)
+ name = 'run_207BTAAXY_2009-02-22.xml'
+ self.failUnlessEqual(runs[0].name, name)
+
+ r1 = runs[0]
+ xml = r1.get_elements()
+ xml_str = ElementTree.tostring(xml)
+
+ r2 = runfolder.PipelineRun(xml=xml)
+ self.failUnlessEqual(r1.name, r2.name)
+ self.failIfEqual(r2.image_analysis, None)
+ self.failIfEqual(r2.bustard, None)
+ self.failIfEqual(r2.gerald, None)
+
+
+def suite():
+ return unittest.makeSuite(RunfolderTests,'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="suite")
+
--- /dev/null
+<?xml version="1.0"?>\r
+<ImageAnalysis>\r
+ <Run Name="IPAR_1.01">\r
+ <Software Name="IPAR" Version="2.01.192.0" />\r
+ <Cycles First="1" Last="37" Number="37" />\r
+ <RunParameters>\r
+ <ImagingReads Index="1">\r
+ <FirstCycle>1</FirstCycle>\r
+ <LastCycle>37</LastCycle>\r
+ <RunFolder>090220_HWI-EAS229_0093_30VR0AAXX</RunFolder>\r
+ </ImagingReads>\r
+ <Reads Index="1">\r
+ <FirstCycle>1</FirstCycle>\r
+ <LastCycle>37</LastCycle>\r
+ <RunFolder>090220_HWI-EAS229_0093_30VR0AAXX</RunFolder>\r
+ </Reads>\r
+ <Compression>gzip</Compression>\r
+ <CompressionSuffix>.p.gz</CompressionSuffix>\r
+ <Instrument>HWI-EAS229</Instrument>\r
+ <RunFolder>090220_HWI-EAS229_0093_30VR0AAXX</RunFolder>\r
+ </RunParameters>\r
+ <ImageParameters>\r
+ <AutoOffsetFlag>1</AutoOffsetFlag>\r
+ <Fwhm>2.7</Fwhm>\r
+ <RemappingDistance>1.5</RemappingDistance>\r
+ <Threshold>4</Threshold>\r
+ </ImageParameters>\r
+ <TileSelection>\r
+ <Lane Index="1">\r
+ <Sample>s</Sample>\r
+ <TileRange Max="100" Min="1" />\r
+ </Lane>\r
+ <Lane Index="2">\r
+ <Sample>s</Sample>\r
+ <TileRange Max="100" Min="1" />\r
+ </Lane>\r
+ <Lane Index="3">\r
+ <Sample>s</Sample>\r
+ <TileRange Max="100" Min="1" />\r
+ </Lane>\r
+ <Lane Index="4">\r
+ <Sample>s</Sample>\r
+ <TileRange Max="100" Min="1" />\r
+ </Lane>\r
+ <Lane Index="5">\r
+ <Sample>s</Sample>\r
+ <TileRange Max="100" Min="1" />\r
+ </Lane>\r
+ <Lane Index="6">\r
+ <Sample>s</Sample>\r
+ <TileRange Max="100" Min="1" />\r
+ </Lane>\r
+ <Lane Index="7">\r
+ <Sample>s</Sample>\r
+ <TileRange Max="100" Min="1" />\r
+ </Lane>\r
+ <Lane Index="8">\r
+ <Sample>s</Sample>\r
+ <TileRange Max="100" Min="1" />\r
+ </Lane>\r
+ </TileSelection>\r
+ </Run>\r
+</ImageAnalysis>
\ No newline at end of file
--- /dev/null
+<html><body>
+<h1>Summary Information For Experiment 090313_HWI-EAS229_0101_3021JAAXX</h1>
+<h2>Chip Summary</h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Machine</td>
+<td>HWI-EAS229</td>
+</tr>
+<tr>
+<td>Run Folder</td>
+<td>090313_HWI-EAS229_0101_3021JAAXX</td>
+</tr>
+<tr>
+<td>Chip ID</td>
+<td>unknown</td>
+</tr>
+</table>
+<h2>Chip Results Summary</h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Clusters</td>
+<td>Clusters (PF)</td>
+<td>Yield (kbases)</td>
+</tr>
+<tr>
+<td>128921986</td>
+<td>21940781</td>
+<td>811809</td>
+</tr>
+</table>
+<h2>Lane Parameter Summary</h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Sample ID</td>
+<td>Sample Target</td>
+<td>Sample Type</td>
+<td>Length</td>
+<td>Filter</td>
+<td>Chast. Thresh.</td>
+<td>Num Tiles</td>
+<td>Tiles</td>
+</tr>
+<tr>
+<td>1</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND_EXTENDED</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1.000000))'</td>
+<td>0.600000</td>
+<td>100</td>
+<td><a href="#Lane1">
+ Lane 1</a></td>
+</tr>
+<tr>
+<td>2</td>
+<td>unknown</td>
+<td>elegans190</td>
+<td>ELAND_EXTENDED</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1.000000))'</td>
+<td>0.600000</td>
+<td>100</td>
+<td><a href="#Lane2">
+ Lane 2</a></td>
+</tr>
+<tr>
+<td>3</td>
+<td>unknown</td>
+<td>elegans190</td>
+<td>ELAND_EXTENDED</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1.000000))'</td>
+<td>0.600000</td>
+<td>100</td>
+<td><a href="#Lane3">
+ Lane 3</a></td>
+</tr>
+<tr>
+<td>4</td>
+<td>unknown</td>
+<td>elegans190</td>
+<td>ELAND_EXTENDED</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1.000000))'</td>
+<td>0.600000</td>
+<td>100</td>
+<td><a href="#Lane4">
+ Lane 4</a></td>
+</tr>
+<tr>
+<td>5</td>
+<td>unknown</td>
+<td>elegans190</td>
+<td>ELAND_EXTENDED</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1.000000))'</td>
+<td>0.600000</td>
+<td>100</td>
+<td><a href="#Lane5">
+ Lane 5</a></td>
+</tr>
+<tr>
+<td>6</td>
+<td>unknown</td>
+<td>elegans190</td>
+<td>ELAND_EXTENDED</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1.000000))'</td>
+<td>0.600000</td>
+<td>100</td>
+<td><a href="#Lane6">
+ Lane 6</a></td>
+</tr>
+<tr>
+<td>7</td>
+<td>unknown</td>
+<td>elegans190</td>
+<td>ELAND_EXTENDED</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1.000000))'</td>
+<td>0.600000</td>
+<td>100</td>
+<td><a href="#Lane7">
+ Lane 7</a></td>
+</tr>
+<tr>
+<td>8</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND_EXTENDED</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1.000000))'</td>
+<td>0.600000</td>
+<td>100</td>
+<td><a href="#Lane8">
+ Lane 8</a></td>
+</tr>
+</table>
+<h2>Lane Results Summary</h2>
+<table border="1" cellpadding="5">
+<tr>
+<td colspan="2">Lane Info</td>
+<td colspan="8">Tile Mean +/- SD for Lane</td>
+</tr>
+<tr>
+<td>Lane </td>
+<td>Lane Yield (kbases) </td>
+<td>Clusters (raw)</td>
+<td>Clusters (PF) </td>
+<td>1st Cycle Int (PF) </td>
+<td>% intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>57684</td>
+<td>126910 +/- 4300</td>
+<td>15590 +/- 4874</td>
+<td>54 +/- 14</td>
+<td>124.36 +/- 27.05</td>
+<td>12.29 +/- 3.82</td>
+<td>7.36 +/- 1.84</td>
+<td>5.92 +/- 1.64</td>
+<td>4.52 +/- 0.58</td>
+</tr>
+<tr>
+<td>2</td>
+<td>78644</td>
+<td>165739 +/- 6792</td>
+<td>21255 +/- 5034</td>
+<td>76 +/- 16</td>
+<td>88.44 +/- 20.59</td>
+<td>12.94 +/- 3.52</td>
+<td>13.55 +/- 0.83</td>
+<td>12.33 +/- 0.84</td>
+<td>5.05 +/- 0.24</td>
+</tr>
+<tr>
+<td>3</td>
+<td>68671</td>
+<td>196565 +/- 8216</td>
+<td>18559 +/- 5413</td>
+<td>106 +/- 19</td>
+<td>78.51 +/- 19.65</td>
+<td>9.41 +/- 2.64</td>
+<td>1.07 +/- 0.10</td>
+<td>0.81 +/- 0.08</td>
+<td>6.27 +/- 0.46</td>
+</tr>
+<tr>
+<td>4</td>
+<td>126273</td>
+<td>153897 +/- 8501</td>
+<td>34128 +/- 7984</td>
+<td>75 +/- 12</td>
+<td>110.44 +/- 26.03</td>
+<td>22.13 +/- 4.82</td>
+<td>4.53 +/- 0.36</td>
+<td>4.51 +/- 0.38</td>
+<td>3.58 +/- 0.22</td>
+</tr>
+<tr>
+<td>5</td>
+<td>116257</td>
+<td>135536 +/- 3908</td>
+<td>31420 +/- 5039</td>
+<td>70 +/- 10</td>
+<td>116.68 +/- 24.46</td>
+<td>23.21 +/- 3.84</td>
+<td>4.25 +/- 0.39</td>
+<td>4.19 +/- 0.41</td>
+<td>3.62 +/- 0.26</td>
+</tr>
+<tr>
+<td>6</td>
+<td>159230</td>
+<td>154083 +/- 9315</td>
+<td>43035 +/- 10193</td>
+<td>79 +/- 14</td>
+<td>123.00 +/- 28.80</td>
+<td>27.76 +/- 5.59</td>
+<td>3.64 +/- 0.30</td>
+<td>3.53 +/- 0.31</td>
+<td>3.48 +/- 0.30</td>
+</tr>
+<tr>
+<td>7</td>
+<td>180779</td>
+<td>159991 +/- 9292</td>
+<td>48859 +/- 8420</td>
+<td>82 +/- 14</td>
+<td>121.76 +/- 24.75</td>
+<td>30.47 +/- 4.53</td>
+<td>0.86 +/- 0.10</td>
+<td>0.58 +/- 0.07</td>
+<td>3.11 +/- 0.36</td>
+</tr>
+<tr>
+<td>8</td>
+<td>24267</td>
+<td>198479 +/- 17671</td>
+<td>6625 +/- 1773</td>
+<td>122 +/- 14</td>
+<td>73.80 +/- 14.41</td>
+<td>3.30 +/- 0.68</td>
+<td>48.65 +/- 5.61</td>
+<td>43.07 +/- 6.50</td>
+<td>3.28 +/- 0.29</td>
+</tr>
+<tr><td colspan="13">Tile mean across chip</td></tr>
+<tr>
+<td colspan="2">Average</td>
+<td>161400</td>
+<td>27434</td>
+<td>83</td>
+<td>104.62</td>
+<td>17.69</td>
+<td>10.49</td>
+<td>9.37</td>
+<td>4.11</td>
+</tr>
+</table>
+<h2>Expanded Lane Summary</h2>
+<table border="1" cellpadding="5">
+<tr>
+<td colspan="2">Lane Info</td>
+<td colspan="2">Phasing Info</td>
+<td colspan="2">Raw Data (tile mean)</td>
+<td colspan="7">Filtered Data (tile mean)</td>
+</tr>
+<tr>
+<td>Lane </td>
+<td> Clusters (tile mean) (raw) </td>
+<td>% Phasing </td>
+<td>% Prephasing </td>
+<td>% Error Rate (raw) </td>
+<td> Equiv Perfect Clusters (raw) </td>
+<td>% retained </td>
+<td>Cycle 2-4 Av Int (PF) </td>
+<td>Cycle 2-10 Av % Loss (PF) </td>
+<td>Cycle 10-20 Av % Loss (PF) </td>
+<td>% Align (PF) </td>
+<td> % Error Rate (PF) </td>
+<td> Equiv Perfect Clusters (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>126911</td>
+<td>0.4800</td>
+<td>0.3000</td>
+<td>5.57</td>
+<td>3076</td>
+<td>12.29</td>
+<td>65.81 +/- 15.68</td>
+<td>-0.47 +/- 1.84</td>
+<td>2.12 +/- 1.13</td>
+<td>7.36</td>
+<td>4.52</td>
+<td>1075</td>
+</tr>
+<tr>
+<td>2</td>
+<td>165740</td>
+<td>0.4800</td>
+<td>0.3000</td>
+<td>5.96</td>
+<td>6076</td>
+<td>12.94</td>
+<td>76.73 +/- 12.15</td>
+<td>1.47 +/- 1.92</td>
+<td>1.21 +/- 1.90</td>
+<td>13.55</td>
+<td>5.05</td>
+<td>2541</td>
+</tr>
+<tr>
+<td>3</td>
+<td>196566</td>
+<td>0.4800</td>
+<td>0.3000</td>
+<td>7.47</td>
+<td>488</td>
+<td>9.41</td>
+<td>103.17 +/- 13.33</td>
+<td>2.71 +/- 1.99</td>
+<td>1.26 +/- 1.88</td>
+<td>1.07</td>
+<td>6.27</td>
+<td>173</td>
+</tr>
+<tr>
+<td>4</td>
+<td>153898</td>
+<td>0.4800</td>
+<td>0.3000</td>
+<td>4.79</td>
+<td>3322</td>
+<td>22.13</td>
+<td>95.07 +/- 11.42</td>
+<td>1.28 +/- 2.12</td>
+<td>2.69 +/- 1.55</td>
+<td>4.53</td>
+<td>3.58</td>
+<td>1402</td>
+</tr>
+<tr>
+<td>5</td>
+<td>135536</td>
+<td>0.4800</td>
+<td>0.3000</td>
+<td>4.75</td>
+<td>2582</td>
+<td>23.21</td>
+<td>87.51 +/- 10.87</td>
+<td>1.01 +/- 2.07</td>
+<td>2.00 +/- 1.53</td>
+<td>4.25</td>
+<td>3.62</td>
+<td>1221</td>
+</tr>
+<tr>
+<td>6</td>
+<td>154084</td>
+<td>0.4800</td>
+<td>0.3000</td>
+<td>4.76</td>
+<td>3270</td>
+<td>27.76</td>
+<td>109.23 +/- 14.97</td>
+<td>1.17 +/- 2.12</td>
+<td>3.01 +/- 1.73</td>
+<td>3.64</td>
+<td>3.48</td>
+<td>1422</td>
+</tr>
+<tr>
+<td>7</td>
+<td>159991</td>
+<td>0.4800</td>
+<td>0.3000</td>
+<td>4.36</td>
+<td>1001</td>
+<td>30.47</td>
+<td>109.94 +/- 12.23</td>
+<td>1.48 +/- 2.32</td>
+<td>2.30 +/- 2.47</td>
+<td>0.86</td>
+<td>3.11</td>
+<td>394</td>
+</tr>
+<tr>
+<td>8</td>
+<td>198479</td>
+<td>0.4800</td>
+<td>0.3000</td>
+<td>5.16</td>
+<td>10876</td>
+<td>3.30</td>
+<td>115.81 +/- 11.51</td>
+<td>2.09 +/- 1.67</td>
+<td>1.19 +/- 2.91</td>
+<td>48.65</td>
+<td>3.28</td>
+<td>2958</td>
+</tr>
+</table>
+<a name="Lane"><h2>Lane 1</h2></a><table border="1" cellpadding="5">
+<tr>
+<td colspan="1">Lane </td>
+<td colspan="1">Tile</td>
+<td colspan="1">Clusters (raw)</td>
+<td colspan="1">Av 1st Cycle Int (PF)</td>
+<td colspan="1">Av % intensity after 20 cycles (PF)</td>
+<td colspan="1">% PF Clusters </td>
+<td colspan="1">% Align (PF) </td>
+<td colspan="1">Av Alignment Score (PF)</td>
+<td colspan="1">% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>0001</td>
+<td>137187</td>
+<td>30.60</td>
+<td>217.24</td>
+<td>5.91</td>
+<td>4.17</td>
+<td>2.48</td>
+<td>5.11</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0002</td>
+<td>128576</td>
+<td>29.07</td>
+<td>106.36</td>
+<td>5.06</td>
+<td>3.23</td>
+<td>2.29</td>
+<td>6.25</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0003</td>
+<td>131374</td>
+<td>26.72</td>
+<td>120.11</td>
+<td>5.04</td>
+<td>3.34</td>
+<td>2.44</td>
+<td>5.43</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0004</td>
+<td>129258</td>
+<td>28.42</td>
+<td>121.90</td>
+<td>4.57</td>
+<td>3.10</td>
+<td>2.05</td>
+<td>6.42</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0005</td>
+<td>127183</td>
+<td>31.92</td>
+<td>128.19</td>
+<td>5.23</td>
+<td>3.66</td>
+<td>2.62</td>
+<td>5.68</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0006</td>
+<td>126810</td>
+<td>35.93</td>
+<td>107.59</td>
+<td>5.37</td>
+<td>3.54</td>
+<td>2.44</td>
+<td>5.83</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0007</td>
+<td>127600</td>
+<td>34.18</td>
+<td>128.16</td>
+<td>5.69</td>
+<td>3.68</td>
+<td>2.62</td>
+<td>5.90</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0008</td>
+<td>127404</td>
+<td>45.38</td>
+<td>81.27</td>
+<td>6.10</td>
+<td>3.47</td>
+<td>2.47</td>
+<td>5.65</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0009</td>
+<td>126616</td>
+<td>36.17</td>
+<td>126.68</td>
+<td>7.14</td>
+<td>4.21</td>
+<td>3.05</td>
+<td>5.36</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0010</td>
+<td>126528</td>
+<td>33.95</td>
+<td>143.96</td>
+<td>7.82</td>
+<td>4.62</td>
+<td>3.49</td>
+<td>5.31</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0011</td>
+<td>127241</td>
+<td>42.65</td>
+<td>104.63</td>
+<td>8.20</td>
+<td>4.81</td>
+<td>3.39</td>
+<td>5.50</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0012</td>
+<td>130637</td>
+<td>33.40</td>
+<td>151.65</td>
+<td>8.72</td>
+<td>4.43</td>
+<td>3.43</td>
+<td>4.97</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0013</td>
+<td>134557</td>
+<td>29.95</td>
+<td>152.84</td>
+<td>8.36</td>
+<td>4.69</td>
+<td>3.52</td>
+<td>5.34</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0014</td>
+<td>126519</td>
+<td>33.45</td>
+<td>124.07</td>
+<td>8.65</td>
+<td>5.17</td>
+<td>3.93</td>
+<td>5.14</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0015</td>
+<td>132462</td>
+<td>31.15</td>
+<td>167.26</td>
+<td>8.33</td>
+<td>5.70</td>
+<td>4.42</td>
+<td>4.71</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0016</td>
+<td>130705</td>
+<td>57.93</td>
+<td>75.96</td>
+<td>7.87</td>
+<td>6.65</td>
+<td>4.97</td>
+<td>5.12</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0017</td>
+<td>134599</td>
+<td>40.48</td>
+<td>139.53</td>
+<td>9.01</td>
+<td>6.53</td>
+<td>5.17</td>
+<td>4.46</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0018</td>
+<td>127550</td>
+<td>41.45</td>
+<td>130.16</td>
+<td>8.48</td>
+<td>6.34</td>
+<td>4.95</td>
+<td>4.89</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0019</td>
+<td>126880</td>
+<td>54.35</td>
+<td>108.00</td>
+<td>9.76</td>
+<td>6.03</td>
+<td>4.59</td>
+<td>4.71</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0020</td>
+<td>126811</td>
+<td>38.05</td>
+<td>122.40</td>
+<td>8.72</td>
+<td>6.23</td>
+<td>4.88</td>
+<td>4.88</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0021</td>
+<td>130562</td>
+<td>34.10</td>
+<td>140.98</td>
+<td>8.79</td>
+<td>5.43</td>
+<td>4.18</td>
+<td>5.19</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0022</td>
+<td>126586</td>
+<td>42.05</td>
+<td>99.64</td>
+<td>8.31</td>
+<td>5.63</td>
+<td>4.16</td>
+<td>5.41</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0023</td>
+<td>124746</td>
+<td>38.08</td>
+<td>108.08</td>
+<td>8.96</td>
+<td>5.85</td>
+<td>4.35</td>
+<td>5.07</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0024</td>
+<td>125450</td>
+<td>45.17</td>
+<td>109.24</td>
+<td>8.75</td>
+<td>5.39</td>
+<td>3.84</td>
+<td>5.37</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0025</td>
+<td>124739</td>
+<td>45.58</td>
+<td>109.05</td>
+<td>9.17</td>
+<td>6.51</td>
+<td>5.04</td>
+<td>4.72</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0026</td>
+<td>120845</td>
+<td>47.38</td>
+<td>104.96</td>
+<td>9.93</td>
+<td>5.87</td>
+<td>4.63</td>
+<td>4.63</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0027</td>
+<td>122292</td>
+<td>47.65</td>
+<td>104.56</td>
+<td>8.95</td>
+<td>6.27</td>
+<td>4.75</td>
+<td>4.91</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0028</td>
+<td>125133</td>
+<td>48.95</td>
+<td>128.50</td>
+<td>9.63</td>
+<td>7.69</td>
+<td>5.96</td>
+<td>4.74</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0029</td>
+<td>121876</td>
+<td>47.25</td>
+<td>123.44</td>
+<td>9.56</td>
+<td>7.61</td>
+<td>6.02</td>
+<td>4.53</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0030</td>
+<td>129067</td>
+<td>36.33</td>
+<td>140.61</td>
+<td>8.70</td>
+<td>7.21</td>
+<td>5.50</td>
+<td>4.83</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0031</td>
+<td>126997</td>
+<td>39.03</td>
+<td>148.37</td>
+<td>9.88</td>
+<td>7.62</td>
+<td>6.08</td>
+<td>4.44</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0032</td>
+<td>123097</td>
+<td>47.68</td>
+<td>129.52</td>
+<td>10.24</td>
+<td>8.10</td>
+<td>6.33</td>
+<td>4.61</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0033</td>
+<td>127916</td>
+<td>46.25</td>
+<td>171.78</td>
+<td>14.14</td>
+<td>8.11</td>
+<td>6.72</td>
+<td>4.29</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0034</td>
+<td>124936</td>
+<td>52.72</td>
+<td>129.07</td>
+<td>9.45</td>
+<td>9.24</td>
+<td>7.40</td>
+<td>4.65</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0035</td>
+<td>123332</td>
+<td>49.62</td>
+<td>135.67</td>
+<td>10.67</td>
+<td>8.91</td>
+<td>7.13</td>
+<td>4.50</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0036</td>
+<td>122410</td>
+<td>51.82</td>
+<td>98.94</td>
+<td>11.66</td>
+<td>8.95</td>
+<td>6.99</td>
+<td>4.93</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0037</td>
+<td>125820</td>
+<td>40.17</td>
+<td>143.31</td>
+<td>8.65</td>
+<td>8.68</td>
+<td>6.93</td>
+<td>4.59</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0038</td>
+<td>121654</td>
+<td>47.78</td>
+<td>111.88</td>
+<td>9.95</td>
+<td>9.17</td>
+<td>7.10</td>
+<td>4.67</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0039</td>
+<td>124171</td>
+<td>52.88</td>
+<td>102.84</td>
+<td>9.04</td>
+<td>10.15</td>
+<td>8.01</td>
+<td>4.70</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0040</td>
+<td>124584</td>
+<td>73.90</td>
+<td>98.38</td>
+<td>12.81</td>
+<td>10.30</td>
+<td>8.34</td>
+<td>4.29</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0041</td>
+<td>123949</td>
+<td>52.55</td>
+<td>172.79</td>
+<td>10.25</td>
+<td>10.60</td>
+<td>8.76</td>
+<td>4.27</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0042</td>
+<td>125220</td>
+<td>55.25</td>
+<td>129.95</td>
+<td>9.98</td>
+<td>10.18</td>
+<td>8.31</td>
+<td>4.41</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0043</td>
+<td>124591</td>
+<td>58.95</td>
+<td>126.25</td>
+<td>11.79</td>
+<td>10.23</td>
+<td>8.25</td>
+<td>4.60</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0044</td>
+<td>124204</td>
+<td>53.42</td>
+<td>104.35</td>
+<td>10.31</td>
+<td>9.75</td>
+<td>7.89</td>
+<td>4.62</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0045</td>
+<td>123608</td>
+<td>53.05</td>
+<td>116.35</td>
+<td>10.21</td>
+<td>9.73</td>
+<td>7.94</td>
+<td>4.52</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0046</td>
+<td>123860</td>
+<td>60.00</td>
+<td>135.88</td>
+<td>13.93</td>
+<td>8.24</td>
+<td>6.77</td>
+<td>4.71</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0047</td>
+<td>124395</td>
+<td>49.30</td>
+<td>156.09</td>
+<td>12.72</td>
+<td>8.75</td>
+<td>7.15</td>
+<td>4.58</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0048</td>
+<td>122450</td>
+<td>62.30</td>
+<td>115.21</td>
+<td>15.96</td>
+<td>8.22</td>
+<td>6.80</td>
+<td>4.36</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0049</td>
+<td>122445</td>
+<td>75.00</td>
+<td>96.43</td>
+<td>13.19</td>
+<td>10.02</td>
+<td>8.05</td>
+<td>4.36</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0050</td>
+<td>123765</td>
+<td>49.55</td>
+<td>141.68</td>
+<td>13.12</td>
+<td>9.01</td>
+<td>7.54</td>
+<td>4.32</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0051</td>
+<td>125692</td>
+<td>75.67</td>
+<td>124.12</td>
+<td>18.07</td>
+<td>8.34</td>
+<td>7.03</td>
+<td>3.94</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0052</td>
+<td>125104</td>
+<td>82.65</td>
+<td>120.02</td>
+<td>16.92</td>
+<td>8.82</td>
+<td>7.42</td>
+<td>4.02</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0053</td>
+<td>124636</td>
+<td>80.20</td>
+<td>112.31</td>
+<td>16.61</td>
+<td>9.96</td>
+<td>8.40</td>
+<td>3.94</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0054</td>
+<td>125641</td>
+<td>69.65</td>
+<td>143.90</td>
+<td>18.54</td>
+<td>8.60</td>
+<td>7.25</td>
+<td>4.05</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0055</td>
+<td>125905</td>
+<td>74.35</td>
+<td>116.48</td>
+<td>16.50</td>
+<td>8.73</td>
+<td>7.39</td>
+<td>4.04</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0056</td>
+<td>126935</td>
+<td>59.57</td>
+<td>125.05</td>
+<td>15.19</td>
+<td>9.10</td>
+<td>7.36</td>
+<td>4.51</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0057</td>
+<td>123510</td>
+<td>70.22</td>
+<td>101.57</td>
+<td>13.72</td>
+<td>9.66</td>
+<td>7.79</td>
+<td>4.39</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0058</td>
+<td>125968</td>
+<td>60.57</td>
+<td>144.66</td>
+<td>15.89</td>
+<td>7.99</td>
+<td>6.60</td>
+<td>4.28</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0059</td>
+<td>127385</td>
+<td>75.50</td>
+<td>100.33</td>
+<td>15.17</td>
+<td>9.69</td>
+<td>7.90</td>
+<td>4.33</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0060</td>
+<td>125188</td>
+<td>57.75</td>
+<td>122.21</td>
+<td>12.81</td>
+<td>8.87</td>
+<td>7.31</td>
+<td>4.40</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0061</td>
+<td>127952</td>
+<td>45.27</td>
+<td>124.96</td>
+<td>11.72</td>
+<td>7.77</td>
+<td>6.08</td>
+<td>4.73</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0062</td>
+<td>123964</td>
+<td>75.38</td>
+<td>72.80</td>
+<td>12.58</td>
+<td>8.48</td>
+<td>6.67</td>
+<td>4.47</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0063</td>
+<td>124803</td>
+<td>78.60</td>
+<td>114.57</td>
+<td>14.62</td>
+<td>7.92</td>
+<td>6.33</td>
+<td>4.48</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0064</td>
+<td>130185</td>
+<td>67.62</td>
+<td>142.48</td>
+<td>16.19</td>
+<td>9.94</td>
+<td>8.32</td>
+<td>4.26</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0065</td>
+<td>125654</td>
+<td>73.00</td>
+<td>159.25</td>
+<td>24.92</td>
+<td>8.20</td>
+<td>7.00</td>
+<td>3.89</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0066</td>
+<td>119533</td>
+<td>53.10</td>
+<td>168.69</td>
+<td>15.04</td>
+<td>8.66</td>
+<td>7.16</td>
+<td>4.25</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0067</td>
+<td>121760</td>
+<td>60.47</td>
+<td>97.52</td>
+<td>15.14</td>
+<td>8.68</td>
+<td>7.16</td>
+<td>4.46</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0068</td>
+<td>123664</td>
+<td>66.00</td>
+<td>77.58</td>
+<td>12.92</td>
+<td>7.80</td>
+<td>5.92</td>
+<td>4.65</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0069</td>
+<td>123890</td>
+<td>52.57</td>
+<td>163.58</td>
+<td>14.72</td>
+<td>8.46</td>
+<td>7.00</td>
+<td>4.26</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0070</td>
+<td>126241</td>
+<td>62.42</td>
+<td>137.08</td>
+<td>13.47</td>
+<td>7.70</td>
+<td>6.12</td>
+<td>4.31</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0071</td>
+<td>122834</td>
+<td>54.62</td>
+<td>102.01</td>
+<td>12.68</td>
+<td>8.17</td>
+<td>6.48</td>
+<td>4.45</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0072</td>
+<td>125630</td>
+<td>70.70</td>
+<td>86.95</td>
+<td>14.67</td>
+<td>7.98</td>
+<td>6.37</td>
+<td>4.20</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0073</td>
+<td>125053</td>
+<td>59.30</td>
+<td>162.56</td>
+<td>15.30</td>
+<td>8.57</td>
+<td>7.31</td>
+<td>4.00</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0074</td>
+<td>127668</td>
+<td>61.90</td>
+<td>155.82</td>
+<td>15.91</td>
+<td>8.43</td>
+<td>7.01</td>
+<td>4.14</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0075</td>
+<td>124426</td>
+<td>64.95</td>
+<td>148.38</td>
+<td>17.08</td>
+<td>7.73</td>
+<td>6.37</td>
+<td>4.16</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0076</td>
+<td>132248</td>
+<td>57.95</td>
+<td>97.41</td>
+<td>16.17</td>
+<td>8.18</td>
+<td>7.01</td>
+<td>3.86</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0077</td>
+<td>129486</td>
+<td>80.68</td>
+<td>72.33</td>
+<td>16.41</td>
+<td>8.28</td>
+<td>6.61</td>
+<td>4.30</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0078</td>
+<td>130453</td>
+<td>84.72</td>
+<td>70.64</td>
+<td>13.06</td>
+<td>8.38</td>
+<td>6.54</td>
+<td>4.14</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0079</td>
+<td>134488</td>
+<td>54.73</td>
+<td>107.58</td>
+<td>15.64</td>
+<td>7.24</td>
+<td>6.16</td>
+<td>3.92</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0080</td>
+<td>126663</td>
+<td>72.08</td>
+<td>79.78</td>
+<td>16.09</td>
+<td>8.84</td>
+<td>7.19</td>
+<td>4.15</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0081</td>
+<td>120700</td>
+<td>55.45</td>
+<td>174.62</td>
+<td>17.29</td>
+<td>8.24</td>
+<td>7.11</td>
+<td>3.76</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0082</td>
+<td>124856</td>
+<td>71.95</td>
+<td>78.08</td>
+<td>13.71</td>
+<td>8.54</td>
+<td>6.86</td>
+<td>4.12</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0083</td>
+<td>126594</td>
+<td>67.38</td>
+<td>90.35</td>
+<td>13.11</td>
+<td>8.39</td>
+<td>6.76</td>
+<td>4.19</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0084</td>
+<td>121831</td>
+<td>60.75</td>
+<td>120.33</td>
+<td>16.70</td>
+<td>6.66</td>
+<td>5.57</td>
+<td>3.87</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0085</td>
+<td>120698</td>
+<td>53.15</td>
+<td>138.99</td>
+<td>13.80</td>
+<td>7.06</td>
+<td>5.75</td>
+<td>4.24</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0086</td>
+<td>120737</td>
+<td>54.78</td>
+<td>160.47</td>
+<td>16.59</td>
+<td>6.47</td>
+<td>5.19</td>
+<td>4.33</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0087</td>
+<td>132398</td>
+<td>53.55</td>
+<td>99.58</td>
+<td>15.42</td>
+<td>6.99</td>
+<td>5.91</td>
+<td>3.97</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0088</td>
+<td>127970</td>
+<td>58.12</td>
+<td>140.04</td>
+<td>14.30</td>
+<td>7.38</td>
+<td>6.05</td>
+<td>4.45</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0089</td>
+<td>123522</td>
+<td>65.20</td>
+<td>136.20</td>
+<td>16.81</td>
+<td>7.08</td>
+<td>5.98</td>
+<td>3.90</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0090</td>
+<td>143307</td>
+<td>46.35</td>
+<td>150.70</td>
+<td>13.34</td>
+<td>6.26</td>
+<td>5.35</td>
+<td>3.78</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0091</td>
+<td>130597</td>
+<td>54.43</td>
+<td>113.05</td>
+<td>14.64</td>
+<td>7.42</td>
+<td>6.27</td>
+<td>3.87</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0092</td>
+<td>141366</td>
+<td>46.40</td>
+<td>161.10</td>
+<td>17.07</td>
+<td>6.36</td>
+<td>5.51</td>
+<td>3.69</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0093</td>
+<td>128028</td>
+<td>68.60</td>
+<td>104.26</td>
+<td>16.71</td>
+<td>6.68</td>
+<td>5.45</td>
+<td>3.89</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0094</td>
+<td>128450</td>
+<td>60.07</td>
+<td>127.42</td>
+<td>14.88</td>
+<td>6.89</td>
+<td>5.73</td>
+<td>3.81</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0095</td>
+<td>128962</td>
+<td>72.45</td>
+<td>106.14</td>
+<td>16.63</td>
+<td>6.91</td>
+<td>5.80</td>
+<td>3.43</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0096</td>
+<td>134736</td>
+<td>60.43</td>
+<td>111.87</td>
+<td>15.30</td>
+<td>6.79</td>
+<td>5.85</td>
+<td>3.58</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0097</td>
+<td>131109</td>
+<td>54.83</td>
+<td>174.01</td>
+<td>14.31</td>
+<td>6.62</td>
+<td>5.56</td>
+<td>3.81</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0098</td>
+<td>133717</td>
+<td>56.33</td>
+<td>120.46</td>
+<td>15.52</td>
+<td>6.86</td>
+<td>5.77</td>
+<td>3.70</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0099</td>
+<td>131704</td>
+<td>50.42</td>
+<td>135.45</td>
+<td>11.81</td>
+<td>6.40</td>
+<td>5.28</td>
+<td>4.12</td>
+</tr>
+<tr>
+<td>1</td>
+<td>0100</td>
+<td>136023</td>
+<td>49.25</td>
+<td>148.73</td>
+<td>14.92</td>
+<td>5.67</td>
+<td>4.80</td>
+<td>4.03</td>
+</tr>
+</table>
+<a name="Lane"><h2>Lane 2</h2></a><table border="1" cellpadding="5">
+<tr>
+<td colspan="1">Lane </td>
+<td colspan="1">Tile</td>
+<td colspan="1">Clusters (raw)</td>
+<td colspan="1">Av 1st Cycle Int (PF)</td>
+<td colspan="1">Av % intensity after 20 cycles (PF)</td>
+<td colspan="1">% PF Clusters </td>
+<td colspan="1">% Align (PF) </td>
+<td colspan="1">Av Alignment Score (PF)</td>
+<td colspan="1">% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>2</td>
+<td>0001</td>
+<td>170860</td>
+<td>62.62</td>
+<td>102.59</td>
+<td>8.71</td>
+<td>11.68</td>
+<td>10.42</td>
+<td>5.37</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0002</td>
+<td>168047</td>
+<td>58.73</td>
+<td>101.28</td>
+<td>8.09</td>
+<td>12.01</td>
+<td>11.15</td>
+<td>4.68</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0003</td>
+<td>165611</td>
+<td>55.85</td>
+<td>114.91</td>
+<td>8.35</td>
+<td>12.79</td>
+<td>11.92</td>
+<td>4.72</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0004</td>
+<td>171147</td>
+<td>54.33</td>
+<td>89.00</td>
+<td>7.76</td>
+<td>12.51</td>
+<td>11.06</td>
+<td>5.30</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0005</td>
+<td>166702</td>
+<td>51.80</td>
+<td>98.41</td>
+<td>7.98</td>
+<td>12.93</td>
+<td>11.85</td>
+<td>4.94</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0006</td>
+<td>171530</td>
+<td>56.83</td>
+<td>93.14</td>
+<td>9.66</td>
+<td>13.46</td>
+<td>12.56</td>
+<td>4.80</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0007</td>
+<td>175956</td>
+<td>63.45</td>
+<td>86.25</td>
+<td>9.49</td>
+<td>13.15</td>
+<td>12.13</td>
+<td>4.82</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0008</td>
+<td>178220</td>
+<td>70.48</td>
+<td>77.55</td>
+<td>10.04</td>
+<td>12.91</td>
+<td>11.64</td>
+<td>5.18</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0009</td>
+<td>172420</td>
+<td>54.58</td>
+<td>107.88</td>
+<td>9.77</td>
+<td>12.79</td>
+<td>11.62</td>
+<td>5.02</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0010</td>
+<td>174119</td>
+<td>48.60</td>
+<td>103.65</td>
+<td>8.70</td>
+<td>12.46</td>
+<td>11.47</td>
+<td>4.93</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0011</td>
+<td>173224</td>
+<td>64.15</td>
+<td>83.09</td>
+<td>9.38</td>
+<td>12.71</td>
+<td>11.42</td>
+<td>5.11</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0012</td>
+<td>168945</td>
+<td>56.97</td>
+<td>76.92</td>
+<td>8.67</td>
+<td>13.60</td>
+<td>12.00</td>
+<td>5.37</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0013</td>
+<td>169698</td>
+<td>54.75</td>
+<td>110.09</td>
+<td>8.75</td>
+<td>12.89</td>
+<td>11.82</td>
+<td>4.99</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0014</td>
+<td>176430</td>
+<td>56.88</td>
+<td>76.44</td>
+<td>9.00</td>
+<td>12.51</td>
+<td>11.30</td>
+<td>5.14</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0015</td>
+<td>173392</td>
+<td>54.30</td>
+<td>109.39</td>
+<td>10.27</td>
+<td>13.47</td>
+<td>12.19</td>
+<td>5.16</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0016</td>
+<td>173752</td>
+<td>86.25</td>
+<td>51.80</td>
+<td>11.49</td>
+<td>13.88</td>
+<td>12.43</td>
+<td>5.24</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0017</td>
+<td>172890</td>
+<td>50.90</td>
+<td>95.19</td>
+<td>10.72</td>
+<td>12.90</td>
+<td>11.72</td>
+<td>5.07</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0018</td>
+<td>173359</td>
+<td>60.30</td>
+<td>87.69</td>
+<td>10.50</td>
+<td>13.45</td>
+<td>11.98</td>
+<td>5.21</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0019</td>
+<td>172871</td>
+<td>80.22</td>
+<td>49.80</td>
+<td>11.16</td>
+<td>12.86</td>
+<td>11.12</td>
+<td>5.26</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0020</td>
+<td>167500</td>
+<td>61.65</td>
+<td>109.57</td>
+<td>10.62</td>
+<td>13.95</td>
+<td>12.73</td>
+<td>4.99</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0021</td>
+<td>173061</td>
+<td>64.42</td>
+<td>86.03</td>
+<td>11.19</td>
+<td>13.38</td>
+<td>11.79</td>
+<td>5.27</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0022</td>
+<td>171387</td>
+<td>64.05</td>
+<td>96.57</td>
+<td>10.12</td>
+<td>13.48</td>
+<td>12.34</td>
+<td>5.01</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0023</td>
+<td>178113</td>
+<td>52.73</td>
+<td>81.41</td>
+<td>10.64</td>
+<td>12.86</td>
+<td>11.90</td>
+<td>4.82</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0024</td>
+<td>172379</td>
+<td>65.38</td>
+<td>74.99</td>
+<td>9.79</td>
+<td>13.20</td>
+<td>12.05</td>
+<td>5.08</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0025</td>
+<td>170661</td>
+<td>59.25</td>
+<td>90.97</td>
+<td>10.09</td>
+<td>13.21</td>
+<td>12.08</td>
+<td>5.06</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0026</td>
+<td>169053</td>
+<td>73.67</td>
+<td>66.98</td>
+<td>10.58</td>
+<td>13.00</td>
+<td>11.86</td>
+<td>4.82</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0027</td>
+<td>166006</td>
+<td>69.58</td>
+<td>99.82</td>
+<td>9.55</td>
+<td>13.00</td>
+<td>12.04</td>
+<td>4.98</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0028</td>
+<td>165399</td>
+<td>79.20</td>
+<td>83.78</td>
+<td>11.65</td>
+<td>13.70</td>
+<td>12.73</td>
+<td>4.79</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0029</td>
+<td>164659</td>
+<td>79.80</td>
+<td>59.65</td>
+<td>9.48</td>
+<td>14.10</td>
+<td>12.84</td>
+<td>5.11</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0030</td>
+<td>163419</td>
+<td>74.82</td>
+<td>84.20</td>
+<td>11.40</td>
+<td>13.31</td>
+<td>11.73</td>
+<td>5.30</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0031</td>
+<td>161881</td>
+<td>70.33</td>
+<td>74.65</td>
+<td>12.62</td>
+<td>14.05</td>
+<td>12.82</td>
+<td>5.10</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0032</td>
+<td>162247</td>
+<td>63.85</td>
+<td>78.19</td>
+<td>13.17</td>
+<td>14.19</td>
+<td>13.00</td>
+<td>5.15</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0033</td>
+<td>163268</td>
+<td>93.03</td>
+<td>93.15</td>
+<td>13.97</td>
+<td>14.16</td>
+<td>12.69</td>
+<td>5.25</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0034</td>
+<td>161905</td>
+<td>61.95</td>
+<td>74.01</td>
+<td>13.85</td>
+<td>14.15</td>
+<td>13.25</td>
+<td>4.92</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0035</td>
+<td>162020</td>
+<td>105.35</td>
+<td>45.16</td>
+<td>14.71</td>
+<td>14.62</td>
+<td>13.13</td>
+<td>5.07</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0036</td>
+<td>160276</td>
+<td>67.33</td>
+<td>125.58</td>
+<td>13.97</td>
+<td>13.30</td>
+<td>12.10</td>
+<td>5.19</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0037</td>
+<td>159586</td>
+<td>72.95</td>
+<td>65.08</td>
+<td>12.84</td>
+<td>13.92</td>
+<td>12.45</td>
+<td>5.41</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0038</td>
+<td>158070</td>
+<td>73.65</td>
+<td>138.42</td>
+<td>11.38</td>
+<td>14.15</td>
+<td>12.75</td>
+<td>5.15</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0039</td>
+<td>158382</td>
+<td>78.83</td>
+<td>110.37</td>
+<td>15.20</td>
+<td>14.59</td>
+<td>13.18</td>
+<td>5.21</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0040</td>
+<td>159069</td>
+<td>69.10</td>
+<td>130.35</td>
+<td>20.27</td>
+<td>14.25</td>
+<td>13.31</td>
+<td>4.96</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0041</td>
+<td>157785</td>
+<td>77.08</td>
+<td>88.58</td>
+<td>14.23</td>
+<td>13.85</td>
+<td>12.24</td>
+<td>5.43</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0042</td>
+<td>163264</td>
+<td>157.78</td>
+<td>47.50</td>
+<td>16.67</td>
+<td>13.62</td>
+<td>10.91</td>
+<td>5.45</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0043</td>
+<td>158246</td>
+<td>87.07</td>
+<td>78.95</td>
+<td>16.58</td>
+<td>13.63</td>
+<td>11.93</td>
+<td>5.45</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0044</td>
+<td>157316</td>
+<td>74.78</td>
+<td>113.57</td>
+<td>16.87</td>
+<td>14.24</td>
+<td>12.99</td>
+<td>5.16</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0045</td>
+<td>157310</td>
+<td>82.50</td>
+<td>76.33</td>
+<td>15.73</td>
+<td>14.08</td>
+<td>12.63</td>
+<td>5.31</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0046</td>
+<td>157533</td>
+<td>99.42</td>
+<td>74.53</td>
+<td>16.97</td>
+<td>13.97</td>
+<td>12.29</td>
+<td>5.51</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0047</td>
+<td>157552</td>
+<td>76.73</td>
+<td>102.38</td>
+<td>20.72</td>
+<td>14.55</td>
+<td>13.33</td>
+<td>5.06</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0048</td>
+<td>156112</td>
+<td>85.25</td>
+<td>90.56</td>
+<td>20.76</td>
+<td>14.36</td>
+<td>13.23</td>
+<td>4.99</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0049</td>
+<td>157664</td>
+<td>84.10</td>
+<td>88.70</td>
+<td>18.36</td>
+<td>14.14</td>
+<td>12.89</td>
+<td>5.18</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0050</td>
+<td>156643</td>
+<td>82.57</td>
+<td>85.35</td>
+<td>17.06</td>
+<td>14.13</td>
+<td>12.73</td>
+<td>5.23</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0051</td>
+<td>155494</td>
+<td>118.53</td>
+<td>66.78</td>
+<td>20.25</td>
+<td>14.35</td>
+<td>13.02</td>
+<td>5.06</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0052</td>
+<td>155567</td>
+<td>82.30</td>
+<td>103.52</td>
+<td>21.14</td>
+<td>13.60</td>
+<td>12.45</td>
+<td>5.08</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0053</td>
+<td>155000</td>
+<td>95.65</td>
+<td>82.02</td>
+<td>20.36</td>
+<td>14.14</td>
+<td>12.67</td>
+<td>5.20</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0054</td>
+<td>155088</td>
+<td>74.28</td>
+<td>120.13</td>
+<td>20.83</td>
+<td>13.90</td>
+<td>12.89</td>
+<td>4.98</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0055</td>
+<td>155123</td>
+<td>93.98</td>
+<td>85.98</td>
+<td>19.28</td>
+<td>14.74</td>
+<td>13.64</td>
+<td>4.80</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0056</td>
+<td>154192</td>
+<td>83.12</td>
+<td>93.77</td>
+<td>18.86</td>
+<td>14.62</td>
+<td>13.09</td>
+<td>5.31</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0057</td>
+<td>155718</td>
+<td>96.32</td>
+<td>62.70</td>
+<td>16.99</td>
+<td>14.48</td>
+<td>12.86</td>
+<td>5.32</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0058</td>
+<td>156380</td>
+<td>74.72</td>
+<td>129.91</td>
+<td>16.59</td>
+<td>15.16</td>
+<td>14.02</td>
+<td>5.07</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0059</td>
+<td>157556</td>
+<td>86.45</td>
+<td>104.86</td>
+<td>15.49</td>
+<td>13.58</td>
+<td>12.06</td>
+<td>5.39</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0060</td>
+<td>158323</td>
+<td>87.90</td>
+<td>76.79</td>
+<td>17.49</td>
+<td>14.02</td>
+<td>12.34</td>
+<td>5.52</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0061</td>
+<td>158102</td>
+<td>74.28</td>
+<td>110.06</td>
+<td>17.22</td>
+<td>14.35</td>
+<td>13.16</td>
+<td>5.21</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0062</td>
+<td>157689</td>
+<td>84.80</td>
+<td>94.58</td>
+<td>14.21</td>
+<td>15.18</td>
+<td>13.76</td>
+<td>5.28</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0063</td>
+<td>157540</td>
+<td>92.15</td>
+<td>101.44</td>
+<td>15.93</td>
+<td>15.29</td>
+<td>13.76</td>
+<td>5.24</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0064</td>
+<td>157219</td>
+<td>66.28</td>
+<td>76.80</td>
+<td>17.73</td>
+<td>15.35</td>
+<td>14.87</td>
+<td>4.50</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0065</td>
+<td>160003</td>
+<td>65.15</td>
+<td>82.08</td>
+<td>17.30</td>
+<td>15.00</td>
+<td>14.21</td>
+<td>4.71</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0066</td>
+<td>160320</td>
+<td>73.30</td>
+<td>93.93</td>
+<td>14.96</td>
+<td>14.98</td>
+<td>13.99</td>
+<td>4.88</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0067</td>
+<td>160868</td>
+<td>80.20</td>
+<td>115.27</td>
+<td>14.21</td>
+<td>14.93</td>
+<td>13.76</td>
+<td>5.02</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0068</td>
+<td>161772</td>
+<td>76.65</td>
+<td>66.89</td>
+<td>13.31</td>
+<td>13.73</td>
+<td>12.73</td>
+<td>4.89</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0069</td>
+<td>163754</td>
+<td>87.00</td>
+<td>77.39</td>
+<td>12.65</td>
+<td>13.72</td>
+<td>12.24</td>
+<td>5.22</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0070</td>
+<td>163426</td>
+<td>82.33</td>
+<td>99.85</td>
+<td>12.72</td>
+<td>13.60</td>
+<td>12.44</td>
+<td>4.93</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0071</td>
+<td>161780</td>
+<td>74.80</td>
+<td>90.91</td>
+<td>13.03</td>
+<td>14.13</td>
+<td>12.81</td>
+<td>5.38</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0072</td>
+<td>165226</td>
+<td>100.00</td>
+<td>96.10</td>
+<td>12.45</td>
+<td>14.19</td>
+<td>13.05</td>
+<td>5.12</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0073</td>
+<td>167863</td>
+<td>79.80</td>
+<td>83.36</td>
+<td>15.37</td>
+<td>14.03</td>
+<td>13.12</td>
+<td>4.85</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0074</td>
+<td>165913</td>
+<td>101.12</td>
+<td>54.68</td>
+<td>13.22</td>
+<td>14.19</td>
+<td>12.85</td>
+<td>5.15</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0075</td>
+<td>164802</td>
+<td>87.07</td>
+<td>93.11</td>
+<td>11.53</td>
+<td>13.77</td>
+<td>12.31</td>
+<td>5.10</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0076</td>
+<td>166823</td>
+<td>77.25</td>
+<td>66.38</td>
+<td>10.96</td>
+<td>13.49</td>
+<td>12.54</td>
+<td>4.87</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0077</td>
+<td>163962</td>
+<td>76.15</td>
+<td>69.63</td>
+<td>14.11</td>
+<td>14.17</td>
+<td>13.26</td>
+<td>4.85</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0078</td>
+<td>168087</td>
+<td>100.95</td>
+<td>81.40</td>
+<td>12.41</td>
+<td>13.36</td>
+<td>12.18</td>
+<td>4.90</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0079</td>
+<td>165569</td>
+<td>89.40</td>
+<td>58.89</td>
+<td>11.73</td>
+<td>13.73</td>
+<td>12.41</td>
+<td>5.03</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0080</td>
+<td>171955</td>
+<td>74.95</td>
+<td>102.03</td>
+<td>13.60</td>
+<td>12.95</td>
+<td>12.11</td>
+<td>4.78</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0081</td>
+<td>166480</td>
+<td>83.35</td>
+<td>96.94</td>
+<td>12.50</td>
+<td>12.76</td>
+<td>11.20</td>
+<td>5.42</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0082</td>
+<td>171089</td>
+<td>80.08</td>
+<td>64.10</td>
+<td>12.31</td>
+<td>12.98</td>
+<td>11.77</td>
+<td>5.16</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0083</td>
+<td>168658</td>
+<td>69.50</td>
+<td>122.05</td>
+<td>10.71</td>
+<td>13.22</td>
+<td>12.13</td>
+<td>4.99</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0084</td>
+<td>166958</td>
+<td>87.22</td>
+<td>68.13</td>
+<td>10.29</td>
+<td>12.87</td>
+<td>11.46</td>
+<td>5.13</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0085</td>
+<td>168593</td>
+<td>58.42</td>
+<td>82.97</td>
+<td>8.82</td>
+<td>12.17</td>
+<td>11.34</td>
+<td>4.81</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0086</td>
+<td>170048</td>
+<td>94.28</td>
+<td>60.33</td>
+<td>8.64</td>
+<td>12.48</td>
+<td>10.67</td>
+<td>5.22</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0087</td>
+<td>173518</td>
+<td>107.08</td>
+<td>51.27</td>
+<td>9.22</td>
+<td>12.73</td>
+<td>11.01</td>
+<td>5.26</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0088</td>
+<td>168833</td>
+<td>63.73</td>
+<td>131.42</td>
+<td>12.05</td>
+<td>12.97</td>
+<td>12.16</td>
+<td>4.62</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0089</td>
+<td>176200</td>
+<td>82.85</td>
+<td>63.79</td>
+<td>9.28</td>
+<td>12.75</td>
+<td>11.23</td>
+<td>5.20</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0090</td>
+<td>172411</td>
+<td>72.20</td>
+<td>121.95</td>
+<td>14.19</td>
+<td>13.10</td>
+<td>12.33</td>
+<td>4.75</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0091</td>
+<td>171660</td>
+<td>78.12</td>
+<td>82.91</td>
+<td>11.41</td>
+<td>13.20</td>
+<td>12.45</td>
+<td>4.73</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0092</td>
+<td>168257</td>
+<td>79.22</td>
+<td>66.93</td>
+<td>10.41</td>
+<td>13.04</td>
+<td>11.88</td>
+<td>4.96</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0093</td>
+<td>171960</td>
+<td>81.53</td>
+<td>75.80</td>
+<td>10.00</td>
+<td>12.92</td>
+<td>12.23</td>
+<td>4.62</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0094</td>
+<td>171243</td>
+<td>88.10</td>
+<td>68.13</td>
+<td>9.17</td>
+<td>12.34</td>
+<td>11.26</td>
+<td>5.08</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0095</td>
+<td>173740</td>
+<td>70.65</td>
+<td>90.59</td>
+<td>10.44</td>
+<td>12.90</td>
+<td>12.14</td>
+<td>4.76</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0096</td>
+<td>174659</td>
+<td>90.72</td>
+<td>90.88</td>
+<td>12.69</td>
+<td>12.94</td>
+<td>12.15</td>
+<td>4.56</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0097</td>
+<td>177182</td>
+<td>71.08</td>
+<td>114.70</td>
+<td>12.39</td>
+<td>12.77</td>
+<td>12.36</td>
+<td>4.43</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0098</td>
+<td>173849</td>
+<td>63.10</td>
+<td>131.34</td>
+<td>11.79</td>
+<td>12.33</td>
+<td>11.69</td>
+<td>4.50</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0099</td>
+<td>176016</td>
+<td>93.23</td>
+<td>92.01</td>
+<td>11.95</td>
+<td>12.38</td>
+<td>11.23</td>
+<td>4.99</td>
+</tr>
+<tr>
+<td>2</td>
+<td>0100</td>
+<td>174587</td>
+<td>87.28</td>
+<td>95.79</td>
+<td>10.07</td>
+<td>11.09</td>
+<td>10.10</td>
+<td>4.89</td>
+</tr>
+</table>
+<a name="Lane"><h2>Lane 3</h2></a><table border="1" cellpadding="5">
+<tr>
+<td colspan="1">Lane </td>
+<td colspan="1">Tile</td>
+<td colspan="1">Clusters (raw)</td>
+<td colspan="1">Av 1st Cycle Int (PF)</td>
+<td colspan="1">Av % intensity after 20 cycles (PF)</td>
+<td colspan="1">% PF Clusters </td>
+<td colspan="1">% Align (PF) </td>
+<td colspan="1">Av Alignment Score (PF)</td>
+<td colspan="1">% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>3</td>
+<td>0001</td>
+<td>203758</td>
+<td>88.12</td>
+<td>74.13</td>
+<td>6.39</td>
+<td>1.00</td>
+<td>0.70</td>
+<td>6.55</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0002</td>
+<td>186222</td>
+<td>94.22</td>
+<td>65.83</td>
+<td>6.73</td>
+<td>1.07</td>
+<td>0.95</td>
+<td>4.76</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0003</td>
+<td>182117</td>
+<td>83.00</td>
+<td>100.81</td>
+<td>7.14</td>
+<td>1.32</td>
+<td>0.95</td>
+<td>6.20</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0004</td>
+<td>185998</td>
+<td>71.10</td>
+<td>107.91</td>
+<td>7.06</td>
+<td>1.19</td>
+<td>0.95</td>
+<td>5.98</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0005</td>
+<td>190532</td>
+<td>74.88</td>
+<td>104.04</td>
+<td>6.79</td>
+<td>1.00</td>
+<td>0.73</td>
+<td>6.18</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0006</td>
+<td>180425</td>
+<td>73.30</td>
+<td>104.33</td>
+<td>6.62</td>
+<td>0.90</td>
+<td>0.75</td>
+<td>5.91</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0007</td>
+<td>186680</td>
+<td>93.67</td>
+<td>81.10</td>
+<td>6.50</td>
+<td>1.04</td>
+<td>0.84</td>
+<td>5.98</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0008</td>
+<td>194001</td>
+<td>89.23</td>
+<td>61.39</td>
+<td>5.86</td>
+<td>1.04</td>
+<td>0.81</td>
+<td>6.44</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0009</td>
+<td>193360</td>
+<td>94.65</td>
+<td>85.16</td>
+<td>6.54</td>
+<td>0.99</td>
+<td>0.71</td>
+<td>6.31</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0010</td>
+<td>181288</td>
+<td>83.68</td>
+<td>78.67</td>
+<td>6.56</td>
+<td>1.07</td>
+<td>0.84</td>
+<td>6.66</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0011</td>
+<td>187873</td>
+<td>94.00</td>
+<td>82.45</td>
+<td>6.23</td>
+<td>1.01</td>
+<td>0.75</td>
+<td>5.91</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0012</td>
+<td>185405</td>
+<td>70.35</td>
+<td>80.56</td>
+<td>6.46</td>
+<td>1.09</td>
+<td>0.78</td>
+<td>6.35</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0013</td>
+<td>162638</td>
+<td>64.42</td>
+<td>80.87</td>
+<td>4.88</td>
+<td>1.06</td>
+<td>0.83</td>
+<td>6.76</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0014</td>
+<td>197166</td>
+<td>95.83</td>
+<td>60.68</td>
+<td>6.70</td>
+<td>1.05</td>
+<td>0.83</td>
+<td>6.14</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0015</td>
+<td>193488</td>
+<td>83.35</td>
+<td>69.86</td>
+<td>7.03</td>
+<td>1.07</td>
+<td>0.84</td>
+<td>6.26</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0016</td>
+<td>205537</td>
+<td>79.45</td>
+<td>116.65</td>
+<td>8.99</td>
+<td>1.08</td>
+<td>0.85</td>
+<td>6.17</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0017</td>
+<td>192552</td>
+<td>108.75</td>
+<td>55.95</td>
+<td>7.38</td>
+<td>0.89</td>
+<td>0.63</td>
+<td>7.00</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0018</td>
+<td>200383</td>
+<td>103.70</td>
+<td>59.23</td>
+<td>7.50</td>
+<td>1.00</td>
+<td>0.75</td>
+<td>5.93</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0019</td>
+<td>201926</td>
+<td>81.47</td>
+<td>66.40</td>
+<td>7.42</td>
+<td>0.85</td>
+<td>0.69</td>
+<td>5.70</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0020</td>
+<td>182571</td>
+<td>81.12</td>
+<td>70.39</td>
+<td>7.16</td>
+<td>1.13</td>
+<td>0.83</td>
+<td>6.48</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0021</td>
+<td>186698</td>
+<td>82.67</td>
+<td>80.04</td>
+<td>7.10</td>
+<td>1.00</td>
+<td>0.77</td>
+<td>5.77</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0022</td>
+<td>189532</td>
+<td>84.53</td>
+<td>80.95</td>
+<td>7.75</td>
+<td>1.00</td>
+<td>0.77</td>
+<td>6.23</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0023</td>
+<td>188323</td>
+<td>88.72</td>
+<td>73.12</td>
+<td>7.83</td>
+<td>1.15</td>
+<td>0.85</td>
+<td>6.81</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0024</td>
+<td>178383</td>
+<td>83.00</td>
+<td>119.94</td>
+<td>6.88</td>
+<td>0.97</td>
+<td>0.74</td>
+<td>5.47</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0025</td>
+<td>192049</td>
+<td>97.12</td>
+<td>73.72</td>
+<td>8.40</td>
+<td>0.97</td>
+<td>0.77</td>
+<td>5.42</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0026</td>
+<td>197028</td>
+<td>98.62</td>
+<td>92.19</td>
+<td>7.99</td>
+<td>0.85</td>
+<td>0.60</td>
+<td>6.68</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0027</td>
+<td>190899</td>
+<td>92.38</td>
+<td>69.01</td>
+<td>8.77</td>
+<td>1.18</td>
+<td>0.96</td>
+<td>5.56</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0028</td>
+<td>189399</td>
+<td>89.20</td>
+<td>96.30</td>
+<td>8.04</td>
+<td>1.05</td>
+<td>0.73</td>
+<td>6.62</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0029</td>
+<td>184662</td>
+<td>78.98</td>
+<td>108.67</td>
+<td>8.07</td>
+<td>1.08</td>
+<td>0.82</td>
+<td>5.86</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0030</td>
+<td>190688</td>
+<td>92.43</td>
+<td>66.08</td>
+<td>7.91</td>
+<td>0.95</td>
+<td>0.71</td>
+<td>6.76</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0031</td>
+<td>196290</td>
+<td>97.80</td>
+<td>110.61</td>
+<td>9.39</td>
+<td>1.04</td>
+<td>0.82</td>
+<td>5.42</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0032</td>
+<td>196748</td>
+<td>103.58</td>
+<td>108.28</td>
+<td>9.20</td>
+<td>0.99</td>
+<td>0.79</td>
+<td>5.86</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0033</td>
+<td>201464</td>
+<td>133.70</td>
+<td>54.15</td>
+<td>10.83</td>
+<td>1.09</td>
+<td>0.76</td>
+<td>7.01</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0034</td>
+<td>201778</td>
+<td>98.12</td>
+<td>115.41</td>
+<td>12.76</td>
+<td>1.09</td>
+<td>0.81</td>
+<td>6.42</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0035</td>
+<td>195338</td>
+<td>101.52</td>
+<td>65.77</td>
+<td>11.60</td>
+<td>1.16</td>
+<td>0.85</td>
+<td>6.61</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0036</td>
+<td>205839</td>
+<td>137.80</td>
+<td>74.55</td>
+<td>11.89</td>
+<td>1.14</td>
+<td>0.82</td>
+<td>6.16</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0037</td>
+<td>195386</td>
+<td>94.28</td>
+<td>112.54</td>
+<td>11.24</td>
+<td>1.03</td>
+<td>0.80</td>
+<td>6.15</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0038</td>
+<td>192726</td>
+<td>89.83</td>
+<td>67.16</td>
+<td>11.22</td>
+<td>1.02</td>
+<td>0.75</td>
+<td>6.73</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0039</td>
+<td>192642</td>
+<td>88.30</td>
+<td>126.64</td>
+<td>11.39</td>
+<td>1.13</td>
+<td>0.90</td>
+<td>6.10</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0040</td>
+<td>203095</td>
+<td>123.53</td>
+<td>85.10</td>
+<td>13.23</td>
+<td>1.00</td>
+<td>0.78</td>
+<td>6.57</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0041</td>
+<td>201324</td>
+<td>126.23</td>
+<td>77.20</td>
+<td>13.61</td>
+<td>1.23</td>
+<td>0.96</td>
+<td>6.23</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0042</td>
+<td>194426</td>
+<td>102.30</td>
+<td>75.07</td>
+<td>11.98</td>
+<td>0.91</td>
+<td>0.67</td>
+<td>6.30</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0043</td>
+<td>197512</td>
+<td>104.62</td>
+<td>72.88</td>
+<td>12.63</td>
+<td>1.15</td>
+<td>0.82</td>
+<td>6.74</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0044</td>
+<td>196006</td>
+<td>126.12</td>
+<td>61.63</td>
+<td>12.48</td>
+<td>1.15</td>
+<td>0.89</td>
+<td>6.33</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0045</td>
+<td>197592</td>
+<td>129.05</td>
+<td>71.48</td>
+<td>14.25</td>
+<td>1.30</td>
+<td>1.00</td>
+<td>6.77</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0046</td>
+<td>195797</td>
+<td>118.45</td>
+<td>88.64</td>
+<td>14.49</td>
+<td>1.14</td>
+<td>0.84</td>
+<td>6.48</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0047</td>
+<td>194741</td>
+<td>128.00</td>
+<td>78.38</td>
+<td>12.62</td>
+<td>1.19</td>
+<td>0.87</td>
+<td>6.64</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0048</td>
+<td>197436</td>
+<td>124.15</td>
+<td>79.68</td>
+<td>14.71</td>
+<td>1.20</td>
+<td>0.84</td>
+<td>6.80</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0049</td>
+<td>196566</td>
+<td>120.55</td>
+<td>84.55</td>
+<td>15.84</td>
+<td>1.24</td>
+<td>0.91</td>
+<td>6.51</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0050</td>
+<td>196255</td>
+<td>107.57</td>
+<td>89.36</td>
+<td>15.93</td>
+<td>1.15</td>
+<td>0.93</td>
+<td>5.66</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0051</td>
+<td>198773</td>
+<td>129.72</td>
+<td>95.86</td>
+<td>15.54</td>
+<td>1.19</td>
+<td>0.86</td>
+<td>6.44</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0052</td>
+<td>197968</td>
+<td>134.00</td>
+<td>79.46</td>
+<td>13.94</td>
+<td>1.07</td>
+<td>0.78</td>
+<td>6.47</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0053</td>
+<td>198600</td>
+<td>134.55</td>
+<td>57.32</td>
+<td>13.10</td>
+<td>1.16</td>
+<td>0.89</td>
+<td>6.35</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0054</td>
+<td>197173</td>
+<td>113.25</td>
+<td>83.20</td>
+<td>14.05</td>
+<td>1.14</td>
+<td>0.82</td>
+<td>6.53</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0055</td>
+<td>195506</td>
+<td>104.75</td>
+<td>79.33</td>
+<td>11.14</td>
+<td>1.06</td>
+<td>0.76</td>
+<td>6.73</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0056</td>
+<td>193200</td>
+<td>105.30</td>
+<td>88.82</td>
+<td>11.17</td>
+<td>1.08</td>
+<td>0.78</td>
+<td>6.80</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0057</td>
+<td>194216</td>
+<td>121.02</td>
+<td>73.06</td>
+<td>10.95</td>
+<td>1.09</td>
+<td>0.77</td>
+<td>6.45</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0058</td>
+<td>199530</td>
+<td>139.80</td>
+<td>67.01</td>
+<td>12.72</td>
+<td>1.19</td>
+<td>0.90</td>
+<td>6.09</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0059</td>
+<td>202163</td>
+<td>127.15</td>
+<td>68.93</td>
+<td>12.50</td>
+<td>1.08</td>
+<td>0.83</td>
+<td>5.87</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0060</td>
+<td>200721</td>
+<td>130.50</td>
+<td>53.98</td>
+<td>11.62</td>
+<td>1.11</td>
+<td>0.88</td>
+<td>6.27</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0061</td>
+<td>198041</td>
+<td>106.85</td>
+<td>65.79</td>
+<td>12.35</td>
+<td>1.07</td>
+<td>0.79</td>
+<td>6.75</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0062</td>
+<td>197475</td>
+<td>105.67</td>
+<td>74.92</td>
+<td>10.84</td>
+<td>1.13</td>
+<td>0.80</td>
+<td>7.21</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0063</td>
+<td>196647</td>
+<td>102.38</td>
+<td>88.62</td>
+<td>11.75</td>
+<td>1.03</td>
+<td>0.72</td>
+<td>6.89</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0064</td>
+<td>198472</td>
+<td>128.30</td>
+<td>83.94</td>
+<td>13.02</td>
+<td>1.13</td>
+<td>0.80</td>
+<td>7.11</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0065</td>
+<td>207784</td>
+<td>112.43</td>
+<td>91.97</td>
+<td>11.58</td>
+<td>0.96</td>
+<td>0.74</td>
+<td>6.31</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0066</td>
+<td>192575</td>
+<td>92.03</td>
+<td>105.92</td>
+<td>9.69</td>
+<td>1.13</td>
+<td>0.86</td>
+<td>6.44</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0067</td>
+<td>195245</td>
+<td>103.50</td>
+<td>91.38</td>
+<td>10.02</td>
+<td>1.08</td>
+<td>0.86</td>
+<td>6.17</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0068</td>
+<td>198723</td>
+<td>106.42</td>
+<td>81.54</td>
+<td>8.83</td>
+<td>1.25</td>
+<td>0.90</td>
+<td>7.09</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0069</td>
+<td>198214</td>
+<td>118.15</td>
+<td>58.99</td>
+<td>8.65</td>
+<td>0.97</td>
+<td>0.74</td>
+<td>5.99</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0070</td>
+<td>190770</td>
+<td>86.25</td>
+<td>73.45</td>
+<td>7.75</td>
+<td>0.91</td>
+<td>0.75</td>
+<td>5.41</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0071</td>
+<td>196479</td>
+<td>105.03</td>
+<td>52.37</td>
+<td>8.18</td>
+<td>1.13</td>
+<td>0.86</td>
+<td>5.94</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0072</td>
+<td>200551</td>
+<td>113.72</td>
+<td>54.80</td>
+<td>8.51</td>
+<td>1.01</td>
+<td>0.73</td>
+<td>6.82</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0073</td>
+<td>211144</td>
+<td>140.78</td>
+<td>46.47</td>
+<td>10.17</td>
+<td>0.98</td>
+<td>0.75</td>
+<td>6.30</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0074</td>
+<td>213445</td>
+<td>141.62</td>
+<td>47.27</td>
+<td>9.63</td>
+<td>1.10</td>
+<td>0.85</td>
+<td>6.29</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0075</td>
+<td>212336</td>
+<td>138.68</td>
+<td>43.63</td>
+<td>8.82</td>
+<td>0.98</td>
+<td>0.77</td>
+<td>6.20</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0076</td>
+<td>201544</td>
+<td>114.78</td>
+<td>55.11</td>
+<td>8.91</td>
+<td>0.92</td>
+<td>0.70</td>
+<td>5.75</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0077</td>
+<td>193099</td>
+<td>93.45</td>
+<td>130.82</td>
+<td>9.94</td>
+<td>1.03</td>
+<td>0.82</td>
+<td>5.86</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0078</td>
+<td>192730</td>
+<td>113.38</td>
+<td>57.53</td>
+<td>7.04</td>
+<td>0.83</td>
+<td>0.72</td>
+<td>5.07</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0079</td>
+<td>208296</td>
+<td>146.50</td>
+<td>83.21</td>
+<td>9.01</td>
+<td>1.06</td>
+<td>0.75</td>
+<td>7.18</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0080</td>
+<td>198441</td>
+<td>126.60</td>
+<td>46.54</td>
+<td>7.66</td>
+<td>1.07</td>
+<td>0.78</td>
+<td>6.69</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0081</td>
+<td>198612</td>
+<td>125.23</td>
+<td>101.20</td>
+<td>8.25</td>
+<td>1.07</td>
+<td>0.73</td>
+<td>6.21</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0082</td>
+<td>211383</td>
+<td>135.93</td>
+<td>69.38</td>
+<td>9.92</td>
+<td>1.09</td>
+<td>0.82</td>
+<td>5.97</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0083</td>
+<td>205392</td>
+<td>120.15</td>
+<td>49.52</td>
+<td>8.89</td>
+<td>1.06</td>
+<td>0.78</td>
+<td>7.11</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0084</td>
+<td>209166</td>
+<td>132.12</td>
+<td>48.00</td>
+<td>7.41</td>
+<td>1.02</td>
+<td>0.79</td>
+<td>5.75</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0085</td>
+<td>199610</td>
+<td>106.67</td>
+<td>107.97</td>
+<td>7.22</td>
+<td>1.03</td>
+<td>0.84</td>
+<td>5.81</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0086</td>
+<td>200884</td>
+<td>88.35</td>
+<td>63.95</td>
+<td>6.51</td>
+<td>1.22</td>
+<td>1.00</td>
+<td>5.74</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0087</td>
+<td>202820</td>
+<td>122.62</td>
+<td>88.34</td>
+<td>7.90</td>
+<td>1.07</td>
+<td>0.84</td>
+<td>6.27</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0088</td>
+<td>212070</td>
+<td>106.88</td>
+<td>72.70</td>
+<td>7.90</td>
+<td>1.09</td>
+<td>0.81</td>
+<td>5.97</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0089</td>
+<td>198992</td>
+<td>113.72</td>
+<td>78.19</td>
+<td>7.01</td>
+<td>1.03</td>
+<td>0.78</td>
+<td>5.93</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0090</td>
+<td>210462</td>
+<td>100.10</td>
+<td>123.98</td>
+<td>9.42</td>
+<td>1.05</td>
+<td>0.80</td>
+<td>5.99</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0091</td>
+<td>198131</td>
+<td>85.18</td>
+<td>78.02</td>
+<td>7.49</td>
+<td>1.02</td>
+<td>0.75</td>
+<td>6.21</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0092</td>
+<td>195888</td>
+<td>99.88</td>
+<td>76.57</td>
+<td>7.10</td>
+<td>1.08</td>
+<td>0.82</td>
+<td>6.54</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0093</td>
+<td>204882</td>
+<td>113.30</td>
+<td>58.27</td>
+<td>8.77</td>
+<td>1.13</td>
+<td>0.83</td>
+<td>6.31</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0094</td>
+<td>194269</td>
+<td>103.75</td>
+<td>66.31</td>
+<td>7.25</td>
+<td>1.00</td>
+<td>0.79</td>
+<td>6.23</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0095</td>
+<td>210191</td>
+<td>120.05</td>
+<td>55.10</td>
+<td>8.58</td>
+<td>1.10</td>
+<td>0.83</td>
+<td>6.06</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0096</td>
+<td>199862</td>
+<td>111.05</td>
+<td>59.70</td>
+<td>5.99</td>
+<td>1.08</td>
+<td>0.76</td>
+<td>6.31</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0097</td>
+<td>190392</td>
+<td>95.53</td>
+<td>69.33</td>
+<td>8.08</td>
+<td>1.37</td>
+<td>1.04</td>
+<td>6.40</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0098</td>
+<td>201697</td>
+<td>138.38</td>
+<td>74.92</td>
+<td>6.12</td>
+<td>1.02</td>
+<td>0.78</td>
+<td>6.28</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0099</td>
+<td>190314</td>
+<td>90.58</td>
+<td>92.58</td>
+<td>7.91</td>
+<td>1.21</td>
+<td>0.84</td>
+<td>6.13</td>
+</tr>
+<tr>
+<td>3</td>
+<td>0100</td>
+<td>211178</td>
+<td>123.43</td>
+<td>69.78</td>
+<td>8.24</td>
+<td>0.98</td>
+<td>0.78</td>
+<td>5.90</td>
+</tr>
+</table>
+<a name="Lane"><h2>Lane 4</h2></a><table border="1" cellpadding="5">
+<tr>
+<td colspan="1">Lane </td>
+<td colspan="1">Tile</td>
+<td colspan="1">Clusters (raw)</td>
+<td colspan="1">Av 1st Cycle Int (PF)</td>
+<td colspan="1">Av % intensity after 20 cycles (PF)</td>
+<td colspan="1">% PF Clusters </td>
+<td colspan="1">% Align (PF) </td>
+<td colspan="1">Av Alignment Score (PF)</td>
+<td colspan="1">% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>4</td>
+<td>0001</td>
+<td>159972</td>
+<td>82.67</td>
+<td>89.45</td>
+<td>18.60</td>
+<td>4.24</td>
+<td>4.08</td>
+<td>3.55</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0002</td>
+<td>154345</td>
+<td>74.00</td>
+<td>102.60</td>
+<td>17.12</td>
+<td>4.43</td>
+<td>4.40</td>
+<td>3.29</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0003</td>
+<td>149038</td>
+<td>68.75</td>
+<td>107.49</td>
+<td>16.52</td>
+<td>4.70</td>
+<td>4.77</td>
+<td>3.29</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0004</td>
+<td>154208</td>
+<td>67.67</td>
+<td>96.27</td>
+<td>17.36</td>
+<td>4.16</td>
+<td>4.05</td>
+<td>3.58</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0005</td>
+<td>159793</td>
+<td>61.13</td>
+<td>119.88</td>
+<td>14.93</td>
+<td>4.15</td>
+<td>4.16</td>
+<td>3.49</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0006</td>
+<td>160185</td>
+<td>51.15</td>
+<td>122.09</td>
+<td>13.63</td>
+<td>4.29</td>
+<td>4.37</td>
+<td>3.45</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0007</td>
+<td>149174</td>
+<td>56.97</td>
+<td>168.06</td>
+<td>15.41</td>
+<td>4.60</td>
+<td>4.77</td>
+<td>3.43</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0008</td>
+<td>137721</td>
+<td>70.80</td>
+<td>142.13</td>
+<td>16.91</td>
+<td>5.38</td>
+<td>5.39</td>
+<td>3.64</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0009</td>
+<td>141360</td>
+<td>64.75</td>
+<td>144.09</td>
+<td>19.12</td>
+<td>4.63</td>
+<td>4.76</td>
+<td>3.44</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0010</td>
+<td>138912</td>
+<td>58.08</td>
+<td>103.87</td>
+<td>13.67</td>
+<td>5.66</td>
+<td>5.60</td>
+<td>3.77</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0011</td>
+<td>156192</td>
+<td>71.65</td>
+<td>94.73</td>
+<td>15.98</td>
+<td>4.57</td>
+<td>4.48</td>
+<td>3.66</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0012</td>
+<td>151485</td>
+<td>58.58</td>
+<td>98.89</td>
+<td>15.45</td>
+<td>5.08</td>
+<td>4.92</td>
+<td>3.94</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0013</td>
+<td>148542</td>
+<td>78.00</td>
+<td>73.14</td>
+<td>16.06</td>
+<td>4.65</td>
+<td>4.70</td>
+<td>3.34</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0014</td>
+<td>147284</td>
+<td>65.98</td>
+<td>109.06</td>
+<td>18.57</td>
+<td>4.86</td>
+<td>4.80</td>
+<td>3.68</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0015</td>
+<td>152295</td>
+<td>73.32</td>
+<td>88.71</td>
+<td>19.26</td>
+<td>4.26</td>
+<td>4.31</td>
+<td>3.42</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0016</td>
+<td>150073</td>
+<td>60.65</td>
+<td>137.26</td>
+<td>17.33</td>
+<td>5.14</td>
+<td>5.14</td>
+<td>3.69</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0017</td>
+<td>145657</td>
+<td>76.27</td>
+<td>134.74</td>
+<td>18.67</td>
+<td>4.72</td>
+<td>4.60</td>
+<td>3.82</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0018</td>
+<td>152274</td>
+<td>67.92</td>
+<td>146.23</td>
+<td>20.68</td>
+<td>4.64</td>
+<td>4.71</td>
+<td>3.51</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0019</td>
+<td>161998</td>
+<td>86.28</td>
+<td>61.95</td>
+<td>21.88</td>
+<td>4.27</td>
+<td>4.09</td>
+<td>3.95</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0020</td>
+<td>139178</td>
+<td>68.33</td>
+<td>94.80</td>
+<td>17.10</td>
+<td>5.07</td>
+<td>5.08</td>
+<td>3.43</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0021</td>
+<td>144251</td>
+<td>69.20</td>
+<td>119.80</td>
+<td>19.67</td>
+<td>5.20</td>
+<td>5.15</td>
+<td>3.57</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0022</td>
+<td>154202</td>
+<td>64.55</td>
+<td>150.50</td>
+<td>18.84</td>
+<td>4.82</td>
+<td>4.97</td>
+<td>3.12</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0023</td>
+<td>154802</td>
+<td>70.13</td>
+<td>120.71</td>
+<td>21.31</td>
+<td>4.39</td>
+<td>4.49</td>
+<td>3.33</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0024</td>
+<td>155617</td>
+<td>78.33</td>
+<td>108.97</td>
+<td>16.72</td>
+<td>4.88</td>
+<td>4.83</td>
+<td>3.42</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0025</td>
+<td>146497</td>
+<td>57.23</td>
+<td>141.68</td>
+<td>19.74</td>
+<td>4.81</td>
+<td>4.88</td>
+<td>3.47</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0026</td>
+<td>143544</td>
+<td>72.08</td>
+<td>87.51</td>
+<td>18.88</td>
+<td>5.03</td>
+<td>5.01</td>
+<td>3.55</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0027</td>
+<td>164614</td>
+<td>67.30</td>
+<td>85.10</td>
+<td>19.32</td>
+<td>4.44</td>
+<td>4.49</td>
+<td>3.56</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0028</td>
+<td>152714</td>
+<td>73.12</td>
+<td>81.91</td>
+<td>18.15</td>
+<td>4.84</td>
+<td>4.91</td>
+<td>3.49</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0029</td>
+<td>151961</td>
+<td>70.85</td>
+<td>83.42</td>
+<td>20.60</td>
+<td>4.43</td>
+<td>4.46</td>
+<td>3.48</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0030</td>
+<td>149751</td>
+<td>76.05</td>
+<td>93.29</td>
+<td>20.81</td>
+<td>5.11</td>
+<td>5.01</td>
+<td>3.74</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0031</td>
+<td>162295</td>
+<td>96.45</td>
+<td>96.73</td>
+<td>25.74</td>
+<td>4.26</td>
+<td>3.96</td>
+<td>4.04</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0032</td>
+<td>162442</td>
+<td>64.57</td>
+<td>171.35</td>
+<td>25.31</td>
+<td>4.25</td>
+<td>4.14</td>
+<td>3.93</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0033</td>
+<td>156596</td>
+<td>88.92</td>
+<td>72.25</td>
+<td>22.77</td>
+<td>4.43</td>
+<td>4.30</td>
+<td>3.92</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0034</td>
+<td>148376</td>
+<td>59.43</td>
+<td>174.63</td>
+<td>19.78</td>
+<td>5.25</td>
+<td>5.32</td>
+<td>3.63</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0035</td>
+<td>144206</td>
+<td>75.67</td>
+<td>79.35</td>
+<td>27.19</td>
+<td>4.80</td>
+<td>4.76</td>
+<td>3.76</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0036</td>
+<td>138987</td>
+<td>55.15</td>
+<td>153.94</td>
+<td>18.63</td>
+<td>4.79</td>
+<td>4.69</td>
+<td>3.85</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0037</td>
+<td>135083</td>
+<td>66.10</td>
+<td>85.29</td>
+<td>21.96</td>
+<td>4.85</td>
+<td>4.63</td>
+<td>4.11</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0038</td>
+<td>153934</td>
+<td>60.40</td>
+<td>106.91</td>
+<td>22.09</td>
+<td>4.95</td>
+<td>5.01</td>
+<td>3.59</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0039</td>
+<td>148137</td>
+<td>66.30</td>
+<td>138.76</td>
+<td>24.02</td>
+<td>4.56</td>
+<td>4.52</td>
+<td>3.76</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0040</td>
+<td>158443</td>
+<td>84.60</td>
+<td>141.02</td>
+<td>28.12</td>
+<td>4.55</td>
+<td>4.53</td>
+<td>3.62</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0041</td>
+<td>153719</td>
+<td>87.78</td>
+<td>70.38</td>
+<td>26.95</td>
+<td>4.69</td>
+<td>4.54</td>
+<td>3.91</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0042</td>
+<td>150869</td>
+<td>73.07</td>
+<td>87.65</td>
+<td>21.31</td>
+<td>4.70</td>
+<td>4.67</td>
+<td>3.77</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0043</td>
+<td>156425</td>
+<td>70.20</td>
+<td>107.34</td>
+<td>23.59</td>
+<td>4.24</td>
+<td>4.31</td>
+<td>3.60</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0044</td>
+<td>156878</td>
+<td>77.22</td>
+<td>99.48</td>
+<td>24.99</td>
+<td>4.66</td>
+<td>4.64</td>
+<td>3.74</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0045</td>
+<td>155133</td>
+<td>76.70</td>
+<td>106.91</td>
+<td>29.12</td>
+<td>4.56</td>
+<td>4.46</td>
+<td>3.80</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0046</td>
+<td>152250</td>
+<td>80.03</td>
+<td>101.72</td>
+<td>26.17</td>
+<td>4.61</td>
+<td>4.47</td>
+<td>3.94</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0047</td>
+<td>149874</td>
+<td>71.47</td>
+<td>99.97</td>
+<td>19.18</td>
+<td>4.98</td>
+<td>5.06</td>
+<td>3.68</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0048</td>
+<td>154015</td>
+<td>63.02</td>
+<td>121.98</td>
+<td>26.89</td>
+<td>4.36</td>
+<td>4.34</td>
+<td>3.75</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0049</td>
+<td>158335</td>
+<td>80.30</td>
+<td>119.77</td>
+<td>33.14</td>
+<td>4.10</td>
+<td>4.11</td>
+<td>3.47</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0050</td>
+<td>159798</td>
+<td>88.50</td>
+<td>116.13</td>
+<td>31.67</td>
+<td>4.27</td>
+<td>4.36</td>
+<td>3.16</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0051</td>
+<td>160079</td>
+<td>90.17</td>
+<td>119.46</td>
+<td>36.32</td>
+<td>4.20</td>
+<td>4.07</td>
+<td>3.25</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0052</td>
+<td>155290</td>
+<td>81.90</td>
+<td>131.84</td>
+<td>29.52</td>
+<td>4.51</td>
+<td>4.53</td>
+<td>3.55</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0053</td>
+<td>158980</td>
+<td>80.47</td>
+<td>101.27</td>
+<td>30.61</td>
+<td>4.14</td>
+<td>4.07</td>
+<td>3.67</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0054</td>
+<td>158421</td>
+<td>78.83</td>
+<td>121.47</td>
+<td>29.54</td>
+<td>4.57</td>
+<td>4.52</td>
+<td>3.52</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0055</td>
+<td>157750</td>
+<td>67.22</td>
+<td>112.01</td>
+<td>26.51</td>
+<td>4.15</td>
+<td>4.25</td>
+<td>3.66</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0056</td>
+<td>157016</td>
+<td>86.95</td>
+<td>96.12</td>
+<td>26.14</td>
+<td>4.38</td>
+<td>4.27</td>
+<td>3.80</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0057</td>
+<td>151799</td>
+<td>84.08</td>
+<td>119.98</td>
+<td>27.60</td>
+<td>4.26</td>
+<td>4.15</td>
+<td>3.83</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0058</td>
+<td>154316</td>
+<td>72.90</td>
+<td>153.43</td>
+<td>25.86</td>
+<td>4.28</td>
+<td>4.20</td>
+<td>3.87</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0059</td>
+<td>157082</td>
+<td>89.60</td>
+<td>73.19</td>
+<td>27.08</td>
+<td>4.40</td>
+<td>4.37</td>
+<td>3.60</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0060</td>
+<td>153022</td>
+<td>59.10</td>
+<td>137.94</td>
+<td>26.12</td>
+<td>4.53</td>
+<td>4.69</td>
+<td>3.38</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0061</td>
+<td>151043</td>
+<td>71.25</td>
+<td>90.21</td>
+<td>23.26</td>
+<td>4.39</td>
+<td>4.53</td>
+<td>3.42</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0062</td>
+<td>159487</td>
+<td>88.62</td>
+<td>113.68</td>
+<td>22.09</td>
+<td>4.56</td>
+<td>4.32</td>
+<td>4.05</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0063</td>
+<td>163188</td>
+<td>100.53</td>
+<td>115.72</td>
+<td>26.63</td>
+<td>4.32</td>
+<td>4.36</td>
+<td>3.45</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0064</td>
+<td>136701</td>
+<td>63.62</td>
+<td>120.43</td>
+<td>33.63</td>
+<td>3.67</td>
+<td>3.69</td>
+<td>3.82</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0065</td>
+<td>136062</td>
+<td>70.90</td>
+<td>79.58</td>
+<td>23.05</td>
+<td>4.78</td>
+<td>4.63</td>
+<td>3.88</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0066</td>
+<td>148835</td>
+<td>57.35</td>
+<td>146.38</td>
+<td>27.34</td>
+<td>4.19</td>
+<td>4.41</td>
+<td>3.17</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0067</td>
+<td>152325</td>
+<td>78.15</td>
+<td>131.80</td>
+<td>23.84</td>
+<td>4.34</td>
+<td>4.30</td>
+<td>3.67</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0068</td>
+<td>155420</td>
+<td>98.58</td>
+<td>58.69</td>
+<td>24.76</td>
+<td>4.44</td>
+<td>4.38</td>
+<td>3.54</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0069</td>
+<td>148803</td>
+<td>83.63</td>
+<td>102.96</td>
+<td>25.18</td>
+<td>4.71</td>
+<td>4.80</td>
+<td>3.46</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0070</td>
+<td>146666</td>
+<td>75.55</td>
+<td>138.45</td>
+<td>27.43</td>
+<td>4.72</td>
+<td>4.72</td>
+<td>3.76</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0071</td>
+<td>161358</td>
+<td>69.85</td>
+<td>118.58</td>
+<td>19.73</td>
+<td>4.10</td>
+<td>4.14</td>
+<td>3.60</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0072</td>
+<td>163756</td>
+<td>80.70</td>
+<td>93.80</td>
+<td>22.76</td>
+<td>4.30</td>
+<td>4.43</td>
+<td>3.27</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0073</td>
+<td>169752</td>
+<td>100.75</td>
+<td>97.79</td>
+<td>27.23</td>
+<td>4.44</td>
+<td>4.31</td>
+<td>3.45</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0074</td>
+<td>153606</td>
+<td>105.57</td>
+<td>90.48</td>
+<td>27.16</td>
+<td>4.76</td>
+<td>4.67</td>
+<td>3.36</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0075</td>
+<td>155840</td>
+<td>99.67</td>
+<td>65.34</td>
+<td>22.83</td>
+<td>4.75</td>
+<td>4.59</td>
+<td>3.70</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0076</td>
+<td>160580</td>
+<td>77.55</td>
+<td>129.98</td>
+<td>26.62</td>
+<td>4.53</td>
+<td>4.57</td>
+<td>3.35</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0077</td>
+<td>133543</td>
+<td>72.98</td>
+<td>149.54</td>
+<td>19.36</td>
+<td>5.16</td>
+<td>5.43</td>
+<td>2.96</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0078</td>
+<td>163879</td>
+<td>66.47</td>
+<td>87.06</td>
+<td>28.07</td>
+<td>4.03</td>
+<td>4.05</td>
+<td>3.61</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0079</td>
+<td>160311</td>
+<td>100.62</td>
+<td>76.52</td>
+<td>24.02</td>
+<td>4.63</td>
+<td>4.45</td>
+<td>3.70</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0080</td>
+<td>147552</td>
+<td>99.77</td>
+<td>122.15</td>
+<td>26.94</td>
+<td>4.32</td>
+<td>4.40</td>
+<td>3.18</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0081</td>
+<td>175728</td>
+<td>67.38</td>
+<td>147.01</td>
+<td>20.25</td>
+<td>3.89</td>
+<td>4.07</td>
+<td>3.24</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0082</td>
+<td>159621</td>
+<td>100.60</td>
+<td>73.86</td>
+<td>24.94</td>
+<td>4.54</td>
+<td>4.54</td>
+<td>3.50</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0083</td>
+<td>151723</td>
+<td>83.72</td>
+<td>97.13</td>
+<td>20.83</td>
+<td>4.60</td>
+<td>4.67</td>
+<td>3.38</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0084</td>
+<td>149291</td>
+<td>75.22</td>
+<td>114.46</td>
+<td>22.02</td>
+<td>4.83</td>
+<td>4.87</td>
+<td>3.48</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0085</td>
+<td>158640</td>
+<td>86.82</td>
+<td>86.55</td>
+<td>19.36</td>
+<td>4.26</td>
+<td>4.10</td>
+<td>3.60</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0086</td>
+<td>149953</td>
+<td>73.95</td>
+<td>111.43</td>
+<td>19.77</td>
+<td>5.06</td>
+<td>5.07</td>
+<td>3.66</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0087</td>
+<td>159982</td>
+<td>99.40</td>
+<td>103.14</td>
+<td>16.81</td>
+<td>4.60</td>
+<td>4.52</td>
+<td>3.48</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0088</td>
+<td>184055</td>
+<td>58.55</td>
+<td>114.90</td>
+<td>24.89</td>
+<td>3.46</td>
+<td>3.52</td>
+<td>3.55</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0089</td>
+<td>159972</td>
+<td>73.67</td>
+<td>104.24</td>
+<td>17.24</td>
+<td>4.25</td>
+<td>4.08</td>
+<td>3.85</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0090</td>
+<td>164917</td>
+<td>101.95</td>
+<td>109.44</td>
+<td>18.70</td>
+<td>4.84</td>
+<td>4.69</td>
+<td>3.52</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0091</td>
+<td>152453</td>
+<td>71.45</td>
+<td>112.07</td>
+<td>18.89</td>
+<td>4.41</td>
+<td>4.37</td>
+<td>3.50</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0092</td>
+<td>155219</td>
+<td>80.20</td>
+<td>93.52</td>
+<td>17.64</td>
+<td>4.49</td>
+<td>4.48</td>
+<td>3.60</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0093</td>
+<td>163900</td>
+<td>87.65</td>
+<td>70.68</td>
+<td>16.48</td>
+<td>4.30</td>
+<td>4.13</td>
+<td>3.60</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0094</td>
+<td>145355</td>
+<td>82.10</td>
+<td>82.86</td>
+<td>15.25</td>
+<td>4.45</td>
+<td>4.34</td>
+<td>3.59</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0095</td>
+<td>138112</td>
+<td>83.02</td>
+<td>123.49</td>
+<td>17.94</td>
+<td>4.70</td>
+<td>4.65</td>
+<td>3.55</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0096</td>
+<td>154654</td>
+<td>57.23</td>
+<td>169.77</td>
+<td>13.99</td>
+<td>4.48</td>
+<td>4.59</td>
+<td>3.47</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0097</td>
+<td>167709</td>
+<td>80.40</td>
+<td>87.13</td>
+<td>18.50</td>
+<td>4.09</td>
+<td>3.98</td>
+<td>3.77</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0098</td>
+<td>160175</td>
+<td>69.58</td>
+<td>131.30</td>
+<td>20.00</td>
+<td>3.95</td>
+<td>3.89</td>
+<td>3.57</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0099</td>
+<td>165398</td>
+<td>73.87</td>
+<td>121.93</td>
+<td>22.00</td>
+<td>3.91</td>
+<td>3.97</td>
+<td>3.17</td>
+</tr>
+<tr>
+<td>4</td>
+<td>0100</td>
+<td>156998</td>
+<td>78.80</td>
+<td>133.66</td>
+<td>23.09</td>
+<td>4.11</td>
+<td>4.14</td>
+<td>3.33</td>
+</tr>
+</table>
+<a name="Lane"><h2>Lane 5</h2></a><table border="1" cellpadding="5">
+<tr>
+<td colspan="1">Lane </td>
+<td colspan="1">Tile</td>
+<td colspan="1">Clusters (raw)</td>
+<td colspan="1">Av 1st Cycle Int (PF)</td>
+<td colspan="1">Av % intensity after 20 cycles (PF)</td>
+<td colspan="1">% PF Clusters </td>
+<td colspan="1">% Align (PF) </td>
+<td colspan="1">Av Alignment Score (PF)</td>
+<td colspan="1">% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>5</td>
+<td>0001</td>
+<td>139658</td>
+<td>72.90</td>
+<td>128.74</td>
+<td>21.85</td>
+<td>3.75</td>
+<td>3.67</td>
+<td>3.28</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0002</td>
+<td>140964</td>
+<td>66.42</td>
+<td>101.92</td>
+<td>21.29</td>
+<td>3.73</td>
+<td>3.58</td>
+<td>3.77</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0003</td>
+<td>139085</td>
+<td>68.25</td>
+<td>102.42</td>
+<td>17.78</td>
+<td>4.29</td>
+<td>4.22</td>
+<td>3.33</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0004</td>
+<td>138352</td>
+<td>69.20</td>
+<td>110.30</td>
+<td>21.41</td>
+<td>3.83</td>
+<td>3.71</td>
+<td>3.75</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0005</td>
+<td>139444</td>
+<td>74.35</td>
+<td>106.86</td>
+<td>19.88</td>
+<td>4.11</td>
+<td>3.98</td>
+<td>3.56</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0006</td>
+<td>139621</td>
+<td>59.90</td>
+<td>104.13</td>
+<td>18.86</td>
+<td>3.67</td>
+<td>3.51</td>
+<td>3.93</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0007</td>
+<td>139048</td>
+<td>64.80</td>
+<td>103.74</td>
+<td>19.50</td>
+<td>3.72</td>
+<td>3.48</td>
+<td>3.69</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0008</td>
+<td>141160</td>
+<td>64.67</td>
+<td>98.76</td>
+<td>18.08</td>
+<td>3.59</td>
+<td>3.41</td>
+<td>3.78</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0009</td>
+<td>139245</td>
+<td>62.23</td>
+<td>94.09</td>
+<td>18.47</td>
+<td>3.89</td>
+<td>3.54</td>
+<td>3.97</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0010</td>
+<td>138211</td>
+<td>57.35</td>
+<td>94.42</td>
+<td>18.35</td>
+<td>3.83</td>
+<td>3.71</td>
+<td>3.57</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0011</td>
+<td>136975</td>
+<td>58.27</td>
+<td>93.22</td>
+<td>18.29</td>
+<td>4.04</td>
+<td>4.04</td>
+<td>3.34</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0012</td>
+<td>135992</td>
+<td>57.35</td>
+<td>86.09</td>
+<td>17.51</td>
+<td>4.11</td>
+<td>4.00</td>
+<td>3.85</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0013</td>
+<td>140930</td>
+<td>53.18</td>
+<td>140.48</td>
+<td>18.62</td>
+<td>3.97</td>
+<td>3.85</td>
+<td>3.73</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0014</td>
+<td>140313</td>
+<td>63.65</td>
+<td>93.05</td>
+<td>17.48</td>
+<td>3.75</td>
+<td>3.45</td>
+<td>3.85</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0015</td>
+<td>141815</td>
+<td>74.38</td>
+<td>81.45</td>
+<td>17.77</td>
+<td>3.92</td>
+<td>3.73</td>
+<td>3.70</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0016</td>
+<td>138206</td>
+<td>77.85</td>
+<td>109.34</td>
+<td>19.30</td>
+<td>3.82</td>
+<td>3.59</td>
+<td>3.65</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0017</td>
+<td>140661</td>
+<td>87.75</td>
+<td>105.41</td>
+<td>18.56</td>
+<td>4.57</td>
+<td>4.38</td>
+<td>3.42</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0018</td>
+<td>139133</td>
+<td>64.83</td>
+<td>77.82</td>
+<td>21.37</td>
+<td>4.05</td>
+<td>4.04</td>
+<td>3.54</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0019</td>
+<td>138919</td>
+<td>77.03</td>
+<td>122.36</td>
+<td>22.40</td>
+<td>4.04</td>
+<td>3.92</td>
+<td>3.62</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0020</td>
+<td>136707</td>
+<td>67.12</td>
+<td>98.32</td>
+<td>19.01</td>
+<td>4.60</td>
+<td>4.51</td>
+<td>3.41</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0021</td>
+<td>140284</td>
+<td>59.67</td>
+<td>110.98</td>
+<td>18.31</td>
+<td>4.13</td>
+<td>4.04</td>
+<td>3.82</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0022</td>
+<td>135887</td>
+<td>54.60</td>
+<td>97.71</td>
+<td>16.94</td>
+<td>3.72</td>
+<td>3.65</td>
+<td>3.73</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0023</td>
+<td>136065</td>
+<td>56.40</td>
+<td>125.98</td>
+<td>19.93</td>
+<td>4.12</td>
+<td>4.22</td>
+<td>3.49</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0024</td>
+<td>137793</td>
+<td>62.90</td>
+<td>131.28</td>
+<td>20.66</td>
+<td>4.12</td>
+<td>4.02</td>
+<td>3.70</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0025</td>
+<td>134349</td>
+<td>62.10</td>
+<td>115.34</td>
+<td>23.38</td>
+<td>4.07</td>
+<td>3.96</td>
+<td>3.62</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0026</td>
+<td>138802</td>
+<td>54.20</td>
+<td>131.55</td>
+<td>20.52</td>
+<td>4.05</td>
+<td>4.11</td>
+<td>3.44</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0027</td>
+<td>134191</td>
+<td>56.70</td>
+<td>167.20</td>
+<td>21.61</td>
+<td>4.64</td>
+<td>4.70</td>
+<td>3.55</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0028</td>
+<td>135596</td>
+<td>57.73</td>
+<td>151.93</td>
+<td>25.57</td>
+<td>4.54</td>
+<td>4.54</td>
+<td>3.61</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0029</td>
+<td>132493</td>
+<td>78.58</td>
+<td>126.44</td>
+<td>22.19</td>
+<td>5.03</td>
+<td>4.83</td>
+<td>3.77</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0030</td>
+<td>132570</td>
+<td>64.17</td>
+<td>157.65</td>
+<td>24.17</td>
+<td>4.67</td>
+<td>4.52</td>
+<td>4.17</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0031</td>
+<td>137864</td>
+<td>84.25</td>
+<td>111.90</td>
+<td>31.20</td>
+<td>4.31</td>
+<td>4.15</td>
+<td>3.87</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0032</td>
+<td>136471</td>
+<td>54.62</td>
+<td>150.30</td>
+<td>28.33</td>
+<td>4.67</td>
+<td>4.67</td>
+<td>3.68</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0033</td>
+<td>133065</td>
+<td>82.12</td>
+<td>107.40</td>
+<td>22.89</td>
+<td>4.72</td>
+<td>4.36</td>
+<td>4.29</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0034</td>
+<td>137713</td>
+<td>66.05</td>
+<td>126.57</td>
+<td>26.09</td>
+<td>4.33</td>
+<td>4.21</td>
+<td>3.91</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0035</td>
+<td>130155</td>
+<td>59.40</td>
+<td>83.16</td>
+<td>21.50</td>
+<td>4.69</td>
+<td>4.87</td>
+<td>3.50</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0036</td>
+<td>135783</td>
+<td>86.45</td>
+<td>90.66</td>
+<td>21.28</td>
+<td>4.70</td>
+<td>4.50</td>
+<td>3.77</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0037</td>
+<td>131641</td>
+<td>67.30</td>
+<td>80.79</td>
+<td>22.36</td>
+<td>4.29</td>
+<td>4.22</td>
+<td>3.68</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0038</td>
+<td>130728</td>
+<td>64.15</td>
+<td>98.99</td>
+<td>20.05</td>
+<td>5.02</td>
+<td>4.93</td>
+<td>3.91</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0039</td>
+<td>132090</td>
+<td>60.83</td>
+<td>99.75</td>
+<td>19.36</td>
+<td>4.95</td>
+<td>4.81</td>
+<td>4.01</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0040</td>
+<td>134211</td>
+<td>51.10</td>
+<td>136.94</td>
+<td>14.11</td>
+<td>4.84</td>
+<td>4.71</td>
+<td>4.03</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0041</td>
+<td>133102</td>
+<td>93.62</td>
+<td>66.57</td>
+<td>21.27</td>
+<td>4.60</td>
+<td>4.43</td>
+<td>3.70</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0042</td>
+<td>132925</td>
+<td>72.62</td>
+<td>104.23</td>
+<td>24.15</td>
+<td>4.12</td>
+<td>4.03</td>
+<td>3.89</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0043</td>
+<td>132602</td>
+<td>76.58</td>
+<td>129.02</td>
+<td>22.13</td>
+<td>4.71</td>
+<td>4.49</td>
+<td>3.87</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0044</td>
+<td>131413</td>
+<td>66.65</td>
+<td>108.93</td>
+<td>25.85</td>
+<td>4.47</td>
+<td>4.34</td>
+<td>3.85</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0045</td>
+<td>129925</td>
+<td>82.50</td>
+<td>115.24</td>
+<td>21.63</td>
+<td>4.65</td>
+<td>4.38</td>
+<td>4.19</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0046</td>
+<td>131687</td>
+<td>61.55</td>
+<td>108.57</td>
+<td>23.72</td>
+<td>4.24</td>
+<td>4.35</td>
+<td>3.43</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0047</td>
+<td>128928</td>
+<td>76.20</td>
+<td>134.02</td>
+<td>26.02</td>
+<td>4.51</td>
+<td>4.28</td>
+<td>3.99</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0048</td>
+<td>129338</td>
+<td>82.23</td>
+<td>98.24</td>
+<td>28.08</td>
+<td>4.53</td>
+<td>4.43</td>
+<td>3.53</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0049</td>
+<td>129280</td>
+<td>59.00</td>
+<td>149.62</td>
+<td>28.80</td>
+<td>4.32</td>
+<td>4.18</td>
+<td>3.96</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0050</td>
+<td>127491</td>
+<td>71.47</td>
+<td>121.55</td>
+<td>30.58</td>
+<td>4.26</td>
+<td>4.13</td>
+<td>3.81</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0051</td>
+<td>130493</td>
+<td>77.25</td>
+<td>106.02</td>
+<td>30.24</td>
+<td>4.35</td>
+<td>4.36</td>
+<td>3.34</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0052</td>
+<td>130852</td>
+<td>62.63</td>
+<td>157.52</td>
+<td>28.30</td>
+<td>4.45</td>
+<td>4.46</td>
+<td>3.44</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0053</td>
+<td>129993</td>
+<td>73.77</td>
+<td>114.50</td>
+<td>24.84</td>
+<td>4.84</td>
+<td>4.80</td>
+<td>3.68</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0054</td>
+<td>132071</td>
+<td>72.70</td>
+<td>113.55</td>
+<td>30.55</td>
+<td>4.38</td>
+<td>4.31</td>
+<td>3.65</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0055</td>
+<td>131652</td>
+<td>73.97</td>
+<td>109.70</td>
+<td>27.14</td>
+<td>4.72</td>
+<td>4.64</td>
+<td>3.69</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0056</td>
+<td>131590</td>
+<td>73.28</td>
+<td>113.99</td>
+<td>26.47</td>
+<td>4.24</td>
+<td>4.17</td>
+<td>3.62</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0057</td>
+<td>132278</td>
+<td>79.77</td>
+<td>91.10</td>
+<td>26.24</td>
+<td>4.49</td>
+<td>4.44</td>
+<td>3.56</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0058</td>
+<td>132006</td>
+<td>68.95</td>
+<td>114.68</td>
+<td>21.47</td>
+<td>4.62</td>
+<td>4.59</td>
+<td>3.93</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0059</td>
+<td>131096</td>
+<td>60.10</td>
+<td>146.55</td>
+<td>24.15</td>
+<td>4.32</td>
+<td>4.30</td>
+<td>3.87</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0060</td>
+<td>138359</td>
+<td>59.00</td>
+<td>169.92</td>
+<td>24.17</td>
+<td>4.29</td>
+<td>4.34</td>
+<td>3.45</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0061</td>
+<td>130472</td>
+<td>64.83</td>
+<td>124.84</td>
+<td>18.73</td>
+<td>4.32</td>
+<td>4.17</td>
+<td>3.86</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0062</td>
+<td>132110</td>
+<td>64.70</td>
+<td>105.41</td>
+<td>21.42</td>
+<td>4.45</td>
+<td>4.30</td>
+<td>4.10</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0063</td>
+<td>136926</td>
+<td>66.60</td>
+<td>115.24</td>
+<td>23.77</td>
+<td>4.11</td>
+<td>3.96</td>
+<td>3.84</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0064</td>
+<td>132948</td>
+<td>80.10</td>
+<td>102.68</td>
+<td>26.12</td>
+<td>3.64</td>
+<td>3.52</td>
+<td>3.83</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0065</td>
+<td>132630</td>
+<td>80.02</td>
+<td>90.82</td>
+<td>24.46</td>
+<td>4.50</td>
+<td>4.54</td>
+<td>3.53</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0066</td>
+<td>134827</td>
+<td>64.57</td>
+<td>103.60</td>
+<td>19.55</td>
+<td>5.25</td>
+<td>5.16</td>
+<td>3.94</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0067</td>
+<td>131930</td>
+<td>65.08</td>
+<td>105.92</td>
+<td>19.20</td>
+<td>4.87</td>
+<td>5.01</td>
+<td>3.46</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0068</td>
+<td>133975</td>
+<td>88.00</td>
+<td>88.32</td>
+<td>20.49</td>
+<td>4.40</td>
+<td>4.40</td>
+<td>3.39</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0069</td>
+<td>132322</td>
+<td>56.48</td>
+<td>119.65</td>
+<td>24.40</td>
+<td>4.37</td>
+<td>4.44</td>
+<td>3.43</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0070</td>
+<td>131826</td>
+<td>64.92</td>
+<td>142.36</td>
+<td>25.01</td>
+<td>4.18</td>
+<td>4.11</td>
+<td>3.85</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0071</td>
+<td>131859</td>
+<td>56.25</td>
+<td>163.07</td>
+<td>23.43</td>
+<td>4.71</td>
+<td>4.68</td>
+<td>3.57</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0072</td>
+<td>132713</td>
+<td>78.30</td>
+<td>124.27</td>
+<td>22.72</td>
+<td>5.16</td>
+<td>5.21</td>
+<td>3.22</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0073</td>
+<td>135125</td>
+<td>97.53</td>
+<td>98.77</td>
+<td>27.41</td>
+<td>4.58</td>
+<td>4.47</td>
+<td>3.51</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0074</td>
+<td>133319</td>
+<td>78.48</td>
+<td>169.32</td>
+<td>32.46</td>
+<td>4.22</td>
+<td>4.29</td>
+<td>3.25</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0075</td>
+<td>135778</td>
+<td>83.65</td>
+<td>98.83</td>
+<td>28.14</td>
+<td>4.50</td>
+<td>4.66</td>
+<td>2.93</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0076</td>
+<td>133109</td>
+<td>55.02</td>
+<td>125.85</td>
+<td>30.99</td>
+<td>3.68</td>
+<td>3.61</td>
+<td>3.76</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0077</td>
+<td>131627</td>
+<td>65.42</td>
+<td>140.73</td>
+<td>23.91</td>
+<td>4.56</td>
+<td>4.73</td>
+<td>2.95</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0078</td>
+<td>140665</td>
+<td>94.43</td>
+<td>81.73</td>
+<td>24.25</td>
+<td>3.91</td>
+<td>3.93</td>
+<td>3.36</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0079</td>
+<td>132710</td>
+<td>84.33</td>
+<td>83.90</td>
+<td>23.84</td>
+<td>4.03</td>
+<td>3.90</td>
+<td>3.52</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0080</td>
+<td>134728</td>
+<td>80.50</td>
+<td>145.93</td>
+<td>30.49</td>
+<td>4.08</td>
+<td>4.04</td>
+<td>3.45</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0081</td>
+<td>143692</td>
+<td>74.45</td>
+<td>113.36</td>
+<td>27.33</td>
+<td>4.02</td>
+<td>4.06</td>
+<td>3.57</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0082</td>
+<td>136092</td>
+<td>82.20</td>
+<td>149.82</td>
+<td>28.86</td>
+<td>4.35</td>
+<td>4.30</td>
+<td>3.50</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0083</td>
+<td>135430</td>
+<td>78.88</td>
+<td>141.58</td>
+<td>26.77</td>
+<td>4.83</td>
+<td>4.79</td>
+<td>3.37</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0084</td>
+<td>138000</td>
+<td>70.45</td>
+<td>145.56</td>
+<td>24.05</td>
+<td>4.52</td>
+<td>4.46</td>
+<td>3.36</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0085</td>
+<td>137474</td>
+<td>61.35</td>
+<td>168.99</td>
+<td>26.20</td>
+<td>3.80</td>
+<td>3.83</td>
+<td>3.54</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0086</td>
+<td>133607</td>
+<td>65.47</td>
+<td>99.58</td>
+<td>22.23</td>
+<td>3.73</td>
+<td>3.65</td>
+<td>3.71</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0087</td>
+<td>135370</td>
+<td>70.42</td>
+<td>147.64</td>
+<td>20.61</td>
+<td>4.04</td>
+<td>3.99</td>
+<td>3.39</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0088</td>
+<td>136082</td>
+<td>77.02</td>
+<td>91.07</td>
+<td>21.90</td>
+<td>3.62</td>
+<td>3.63</td>
+<td>3.55</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0089</td>
+<td>136187</td>
+<td>71.58</td>
+<td>110.20</td>
+<td>25.59</td>
+<td>4.01</td>
+<td>3.90</td>
+<td>3.72</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0090</td>
+<td>134994</td>
+<td>59.78</td>
+<td>195.98</td>
+<td>25.62</td>
+<td>4.13</td>
+<td>4.24</td>
+<td>3.15</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0091</td>
+<td>134835</td>
+<td>78.85</td>
+<td>101.33</td>
+<td>18.80</td>
+<td>4.17</td>
+<td>4.14</td>
+<td>3.48</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0092</td>
+<td>140599</td>
+<td>68.48</td>
+<td>98.80</td>
+<td>20.40</td>
+<td>3.53</td>
+<td>3.58</td>
+<td>3.39</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0093</td>
+<td>142219</td>
+<td>71.75</td>
+<td>133.38</td>
+<td>21.96</td>
+<td>4.09</td>
+<td>4.12</td>
+<td>3.30</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0094</td>
+<td>142205</td>
+<td>75.38</td>
+<td>135.06</td>
+<td>23.88</td>
+<td>3.61</td>
+<td>3.60</td>
+<td>3.47</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0095</td>
+<td>137110</td>
+<td>73.45</td>
+<td>102.11</td>
+<td>23.22</td>
+<td>4.14</td>
+<td>4.11</td>
+<td>3.57</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0096</td>
+<td>140431</td>
+<td>83.15</td>
+<td>105.95</td>
+<td>25.34</td>
+<td>4.28</td>
+<td>4.33</td>
+<td>3.12</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0097</td>
+<td>140497</td>
+<td>80.83</td>
+<td>123.35</td>
+<td>26.31</td>
+<td>3.75</td>
+<td>3.65</td>
+<td>3.45</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0098</td>
+<td>142486</td>
+<td>77.92</td>
+<td>96.82</td>
+<td>26.41</td>
+<td>3.70</td>
+<td>3.68</td>
+<td>3.50</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0099</td>
+<td>145817</td>
+<td>85.30</td>
+<td>110.93</td>
+<td>27.92</td>
+<td>3.85</td>
+<td>3.93</td>
+<td>3.16</td>
+</tr>
+<tr>
+<td>5</td>
+<td>0100</td>
+<td>139604</td>
+<td>74.98</td>
+<td>135.98</td>
+<td>24.92</td>
+<td>3.71</td>
+<td>3.72</td>
+<td>3.21</td>
+</tr>
+</table>
+<a name="Lane"><h2>Lane 6</h2></a><table border="1" cellpadding="5">
+<tr>
+<td colspan="1">Lane </td>
+<td colspan="1">Tile</td>
+<td colspan="1">Clusters (raw)</td>
+<td colspan="1">Av 1st Cycle Int (PF)</td>
+<td colspan="1">Av % intensity after 20 cycles (PF)</td>
+<td colspan="1">% PF Clusters </td>
+<td colspan="1">% Align (PF) </td>
+<td colspan="1">Av Alignment Score (PF)</td>
+<td colspan="1">% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>6</td>
+<td>0001</td>
+<td>153653</td>
+<td>79.58</td>
+<td>136.00</td>
+<td>23.86</td>
+<td>3.57</td>
+<td>3.46</td>
+<td>3.57</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0002</td>
+<td>160739</td>
+<td>56.15</td>
+<td>162.78</td>
+<td>17.73</td>
+<td>3.21</td>
+<td>3.13</td>
+<td>3.67</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0003</td>
+<td>147132</td>
+<td>63.32</td>
+<td>127.79</td>
+<td>17.49</td>
+<td>3.75</td>
+<td>3.65</td>
+<td>3.56</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0004</td>
+<td>151602</td>
+<td>65.30</td>
+<td>109.95</td>
+<td>18.04</td>
+<td>3.53</td>
+<td>3.42</td>
+<td>3.54</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0005</td>
+<td>156959</td>
+<td>61.57</td>
+<td>109.87</td>
+<td>20.25</td>
+<td>3.16</td>
+<td>3.08</td>
+<td>3.64</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0006</td>
+<td>146995</td>
+<td>75.43</td>
+<td>108.25</td>
+<td>19.92</td>
+<td>3.68</td>
+<td>3.57</td>
+<td>3.55</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0007</td>
+<td>147619</td>
+<td>84.72</td>
+<td>103.16</td>
+<td>20.12</td>
+<td>3.92</td>
+<td>3.64</td>
+<td>3.62</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0008</td>
+<td>157868</td>
+<td>73.75</td>
+<td>139.22</td>
+<td>26.32</td>
+<td>3.44</td>
+<td>3.30</td>
+<td>3.66</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0009</td>
+<td>155003</td>
+<td>72.53</td>
+<td>126.27</td>
+<td>23.62</td>
+<td>3.37</td>
+<td>3.25</td>
+<td>3.32</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0010</td>
+<td>148015</td>
+<td>68.85</td>
+<td>141.54</td>
+<td>20.08</td>
+<td>3.68</td>
+<td>3.51</td>
+<td>3.62</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0011</td>
+<td>153943</td>
+<td>71.40</td>
+<td>106.06</td>
+<td>19.50</td>
+<td>3.47</td>
+<td>3.38</td>
+<td>3.37</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0012</td>
+<td>148858</td>
+<td>81.22</td>
+<td>86.43</td>
+<td>19.51</td>
+<td>3.36</td>
+<td>3.25</td>
+<td>3.65</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0013</td>
+<td>144234</td>
+<td>74.60</td>
+<td>90.42</td>
+<td>17.02</td>
+<td>3.59</td>
+<td>3.46</td>
+<td>3.55</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0014</td>
+<td>143006</td>
+<td>69.70</td>
+<td>91.32</td>
+<td>17.26</td>
+<td>3.78</td>
+<td>3.62</td>
+<td>3.63</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0015</td>
+<td>166330</td>
+<td>52.00</td>
+<td>154.47</td>
+<td>20.50</td>
+<td>2.77</td>
+<td>2.70</td>
+<td>3.69</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0016</td>
+<td>144632</td>
+<td>58.68</td>
+<td>215.25</td>
+<td>24.25</td>
+<td>3.59</td>
+<td>3.46</td>
+<td>4.03</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0017</td>
+<td>136245</td>
+<td>75.12</td>
+<td>98.80</td>
+<td>22.86</td>
+<td>4.31</td>
+<td>4.15</td>
+<td>3.81</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0018</td>
+<td>145428</td>
+<td>69.75</td>
+<td>143.51</td>
+<td>21.98</td>
+<td>3.68</td>
+<td>3.61</td>
+<td>3.65</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0019</td>
+<td>136914</td>
+<td>67.10</td>
+<td>160.80</td>
+<td>23.12</td>
+<td>4.20</td>
+<td>4.15</td>
+<td>3.46</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0020</td>
+<td>148171</td>
+<td>66.60</td>
+<td>162.05</td>
+<td>21.47</td>
+<td>3.73</td>
+<td>3.50</td>
+<td>4.06</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0021</td>
+<td>134914</td>
+<td>73.75</td>
+<td>128.85</td>
+<td>16.65</td>
+<td>3.90</td>
+<td>3.61</td>
+<td>4.09</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0022</td>
+<td>138651</td>
+<td>82.20</td>
+<td>76.09</td>
+<td>17.87</td>
+<td>4.14</td>
+<td>3.83</td>
+<td>3.75</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0023</td>
+<td>149423</td>
+<td>62.85</td>
+<td>105.49</td>
+<td>20.75</td>
+<td>3.75</td>
+<td>3.59</td>
+<td>3.61</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0024</td>
+<td>143451</td>
+<td>83.30</td>
+<td>104.17</td>
+<td>20.22</td>
+<td>4.24</td>
+<td>4.10</td>
+<td>3.46</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0025</td>
+<td>147540</td>
+<td>72.50</td>
+<td>91.83</td>
+<td>19.86</td>
+<td>3.74</td>
+<td>3.69</td>
+<td>3.28</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0026</td>
+<td>141154</td>
+<td>72.90</td>
+<td>100.79</td>
+<td>20.73</td>
+<td>4.06</td>
+<td>4.06</td>
+<td>3.25</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0027</td>
+<td>160782</td>
+<td>68.42</td>
+<td>127.91</td>
+<td>22.54</td>
+<td>3.52</td>
+<td>3.50</td>
+<td>3.22</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0028</td>
+<td>148134</td>
+<td>70.67</td>
+<td>121.01</td>
+<td>23.53</td>
+<td>3.48</td>
+<td>3.37</td>
+<td>3.61</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0029</td>
+<td>154465</td>
+<td>69.50</td>
+<td>109.93</td>
+<td>26.04</td>
+<td>3.61</td>
+<td>3.69</td>
+<td>3.26</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0030</td>
+<td>151767</td>
+<td>69.12</td>
+<td>187.70</td>
+<td>22.59</td>
+<td>3.96</td>
+<td>4.02</td>
+<td>3.28</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0031</td>
+<td>164147</td>
+<td>91.00</td>
+<td>96.92</td>
+<td>30.61</td>
+<td>3.14</td>
+<td>2.90</td>
+<td>3.97</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0032</td>
+<td>153275</td>
+<td>65.38</td>
+<td>174.23</td>
+<td>28.83</td>
+<td>3.63</td>
+<td>3.60</td>
+<td>3.56</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0033</td>
+<td>153722</td>
+<td>98.08</td>
+<td>89.12</td>
+<td>27.30</td>
+<td>3.92</td>
+<td>3.56</td>
+<td>3.76</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0034</td>
+<td>152193</td>
+<td>76.95</td>
+<td>102.40</td>
+<td>27.20</td>
+<td>3.90</td>
+<td>3.79</td>
+<td>3.54</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0035</td>
+<td>153463</td>
+<td>74.17</td>
+<td>107.99</td>
+<td>30.03</td>
+<td>3.52</td>
+<td>3.35</td>
+<td>3.75</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0036</td>
+<td>150895</td>
+<td>65.65</td>
+<td>166.83</td>
+<td>32.03</td>
+<td>3.85</td>
+<td>3.71</td>
+<td>3.55</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0037</td>
+<td>145745</td>
+<td>62.45</td>
+<td>116.49</td>
+<td>26.60</td>
+<td>3.77</td>
+<td>3.63</td>
+<td>3.81</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0038</td>
+<td>151284</td>
+<td>64.00</td>
+<td>181.25</td>
+<td>26.09</td>
+<td>3.81</td>
+<td>3.74</td>
+<td>3.52</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0039</td>
+<td>151424</td>
+<td>58.40</td>
+<td>199.40</td>
+<td>26.27</td>
+<td>3.49</td>
+<td>3.39</td>
+<td>3.83</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0040</td>
+<td>157649</td>
+<td>75.05</td>
+<td>119.05</td>
+<td>32.59</td>
+<td>3.05</td>
+<td>2.89</td>
+<td>3.62</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0041</td>
+<td>151062</td>
+<td>60.13</td>
+<td>208.94</td>
+<td>26.71</td>
+<td>3.52</td>
+<td>3.44</td>
+<td>3.68</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0042</td>
+<td>147213</td>
+<td>62.43</td>
+<td>124.99</td>
+<td>25.03</td>
+<td>3.79</td>
+<td>3.65</td>
+<td>3.87</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0043</td>
+<td>153123</td>
+<td>68.88</td>
+<td>123.41</td>
+<td>25.47</td>
+<td>3.55</td>
+<td>3.37</td>
+<td>3.77</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0044</td>
+<td>150099</td>
+<td>77.20</td>
+<td>115.03</td>
+<td>29.38</td>
+<td>3.73</td>
+<td>3.57</td>
+<td>3.46</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0045</td>
+<td>152952</td>
+<td>88.53</td>
+<td>108.39</td>
+<td>32.19</td>
+<td>3.43</td>
+<td>3.21</td>
+<td>3.53</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0046</td>
+<td>150981</td>
+<td>82.27</td>
+<td>104.98</td>
+<td>30.68</td>
+<td>3.82</td>
+<td>3.67</td>
+<td>3.54</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0047</td>
+<td>153505</td>
+<td>82.67</td>
+<td>139.40</td>
+<td>32.67</td>
+<td>3.89</td>
+<td>3.71</td>
+<td>3.62</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0048</td>
+<td>153834</td>
+<td>90.45</td>
+<td>119.02</td>
+<td>33.13</td>
+<td>3.87</td>
+<td>3.62</td>
+<td>3.64</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0049</td>
+<td>152222</td>
+<td>83.83</td>
+<td>121.38</td>
+<td>32.21</td>
+<td>4.08</td>
+<td>3.87</td>
+<td>3.47</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0050</td>
+<td>151798</td>
+<td>70.42</td>
+<td>130.88</td>
+<td>32.01</td>
+<td>3.89</td>
+<td>3.77</td>
+<td>3.43</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0051</td>
+<td>154430</td>
+<td>95.33</td>
+<td>91.40</td>
+<td>32.17</td>
+<td>3.61</td>
+<td>3.44</td>
+<td>3.52</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0052</td>
+<td>157873</td>
+<td>86.33</td>
+<td>102.00</td>
+<td>30.04</td>
+<td>3.52</td>
+<td>3.32</td>
+<td>3.76</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0053</td>
+<td>152489</td>
+<td>74.80</td>
+<td>127.61</td>
+<td>32.86</td>
+<td>3.80</td>
+<td>3.74</td>
+<td>3.43</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0054</td>
+<td>154402</td>
+<td>74.40</td>
+<td>132.02</td>
+<td>31.73</td>
+<td>3.96</td>
+<td>3.84</td>
+<td>3.72</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0055</td>
+<td>151912</td>
+<td>75.03</td>
+<td>96.43</td>
+<td>33.81</td>
+<td>3.97</td>
+<td>3.86</td>
+<td>3.42</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0056</td>
+<td>155460</td>
+<td>76.15</td>
+<td>111.46</td>
+<td>35.00</td>
+<td>3.87</td>
+<td>3.81</td>
+<td>3.45</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0057</td>
+<td>154114</td>
+<td>77.83</td>
+<td>138.19</td>
+<td>36.39</td>
+<td>3.70</td>
+<td>3.57</td>
+<td>3.66</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0058</td>
+<td>156369</td>
+<td>79.62</td>
+<td>125.87</td>
+<td>27.39</td>
+<td>4.04</td>
+<td>3.87</td>
+<td>3.57</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0059</td>
+<td>156151</td>
+<td>79.38</td>
+<td>106.24</td>
+<td>32.37</td>
+<td>3.29</td>
+<td>3.12</td>
+<td>3.89</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0060</td>
+<td>155109</td>
+<td>84.15</td>
+<td>108.53</td>
+<td>32.09</td>
+<td>3.38</td>
+<td>3.15</td>
+<td>4.09</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0061</td>
+<td>142351</td>
+<td>71.72</td>
+<td>140.54</td>
+<td>29.12</td>
+<td>3.92</td>
+<td>3.81</td>
+<td>3.84</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0062</td>
+<td>149140</td>
+<td>84.90</td>
+<td>95.47</td>
+<td>27.32</td>
+<td>3.50</td>
+<td>3.39</td>
+<td>3.86</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0063</td>
+<td>159848</td>
+<td>66.10</td>
+<td>158.89</td>
+<td>25.37</td>
+<td>3.46</td>
+<td>3.30</td>
+<td>4.01</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0064</td>
+<td>159352</td>
+<td>63.03</td>
+<td>119.28</td>
+<td>26.66</td>
+<td>4.04</td>
+<td>3.99</td>
+<td>3.69</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0065</td>
+<td>162441</td>
+<td>94.40</td>
+<td>128.87</td>
+<td>30.65</td>
+<td>3.66</td>
+<td>3.56</td>
+<td>3.35</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0066</td>
+<td>141798</td>
+<td>61.55</td>
+<td>109.63</td>
+<td>22.38</td>
+<td>3.94</td>
+<td>3.99</td>
+<td>3.42</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0067</td>
+<td>160686</td>
+<td>86.90</td>
+<td>121.63</td>
+<td>27.80</td>
+<td>3.62</td>
+<td>3.40</td>
+<td>3.98</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0068</td>
+<td>152539</td>
+<td>67.95</td>
+<td>125.46</td>
+<td>33.74</td>
+<td>3.60</td>
+<td>3.44</td>
+<td>3.78</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0069</td>
+<td>155253</td>
+<td>87.25</td>
+<td>78.65</td>
+<td>27.31</td>
+<td>3.28</td>
+<td>3.12</td>
+<td>3.79</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0070</td>
+<td>158082</td>
+<td>78.60</td>
+<td>92.14</td>
+<td>28.45</td>
+<td>3.35</td>
+<td>3.26</td>
+<td>3.74</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0071</td>
+<td>148641</td>
+<td>72.60</td>
+<td>160.74</td>
+<td>28.05</td>
+<td>3.78</td>
+<td>3.80</td>
+<td>3.25</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0072</td>
+<td>151821</td>
+<td>74.60</td>
+<td>146.15</td>
+<td>27.26</td>
+<td>4.19</td>
+<td>4.26</td>
+<td>3.19</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0073</td>
+<td>159347</td>
+<td>103.45</td>
+<td>121.82</td>
+<td>33.03</td>
+<td>3.82</td>
+<td>3.79</td>
+<td>3.19</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0074</td>
+<td>152598</td>
+<td>68.88</td>
+<td>190.09</td>
+<td>32.13</td>
+<td>4.18</td>
+<td>4.14</td>
+<td>3.25</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0075</td>
+<td>158017</td>
+<td>88.73</td>
+<td>137.81</td>
+<td>36.73</td>
+<td>3.73</td>
+<td>3.63</td>
+<td>3.36</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0076</td>
+<td>168580</td>
+<td>109.37</td>
+<td>119.43</td>
+<td>34.66</td>
+<td>3.25</td>
+<td>3.01</td>
+<td>3.49</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0077</td>
+<td>161724</td>
+<td>110.40</td>
+<td>78.60</td>
+<td>36.10</td>
+<td>3.53</td>
+<td>3.44</td>
+<td>3.10</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0078</td>
+<td>168315</td>
+<td>99.88</td>
+<td>82.25</td>
+<td>34.85</td>
+<td>3.29</td>
+<td>3.16</td>
+<td>3.28</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0079</td>
+<td>160481</td>
+<td>95.53</td>
+<td>124.55</td>
+<td>31.56</td>
+<td>3.73</td>
+<td>3.64</td>
+<td>3.13</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0080</td>
+<td>163992</td>
+<td>78.00</td>
+<td>120.32</td>
+<td>33.98</td>
+<td>3.24</td>
+<td>3.20</td>
+<td>3.01</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0081</td>
+<td>153658</td>
+<td>100.70</td>
+<td>101.49</td>
+<td>35.12</td>
+<td>3.70</td>
+<td>3.59</td>
+<td>3.04</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0082</td>
+<td>171593</td>
+<td>126.27</td>
+<td>113.32</td>
+<td>38.70</td>
+<td>3.15</td>
+<td>3.03</td>
+<td>3.29</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0083</td>
+<td>162775</td>
+<td>119.70</td>
+<td>65.29</td>
+<td>36.56</td>
+<td>3.44</td>
+<td>3.31</td>
+<td>3.08</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0084</td>
+<td>133248</td>
+<td>67.38</td>
+<td>133.40</td>
+<td>31.50</td>
+<td>3.89</td>
+<td>3.78</td>
+<td>3.26</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0085</td>
+<td>152741</td>
+<td>108.30</td>
+<td>119.39</td>
+<td>32.76</td>
+<td>3.35</td>
+<td>3.15</td>
+<td>3.27</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0086</td>
+<td>138270</td>
+<td>68.20</td>
+<td>127.97</td>
+<td>27.14</td>
+<td>3.83</td>
+<td>3.85</td>
+<td>3.13</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0087</td>
+<td>164771</td>
+<td>71.25</td>
+<td>147.44</td>
+<td>29.57</td>
+<td>3.16</td>
+<td>3.19</td>
+<td>2.98</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0088</td>
+<td>131121</td>
+<td>77.50</td>
+<td>134.52</td>
+<td>27.09</td>
+<td>3.87</td>
+<td>3.91</td>
+<td>3.14</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0089</td>
+<td>150558</td>
+<td>89.00</td>
+<td>81.35</td>
+<td>25.53</td>
+<td>3.63</td>
+<td>3.57</td>
+<td>3.25</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0090</td>
+<td>162180</td>
+<td>89.12</td>
+<td>102.92</td>
+<td>25.09</td>
+<td>4.06</td>
+<td>3.88</td>
+<td>3.31</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0091</td>
+<td>161673</td>
+<td>101.30</td>
+<td>108.96</td>
+<td>30.88</td>
+<td>3.20</td>
+<td>3.03</td>
+<td>3.33</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0092</td>
+<td>158822</td>
+<td>93.17</td>
+<td>117.12</td>
+<td>32.93</td>
+<td>3.69</td>
+<td>3.65</td>
+<td>2.97</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0093</td>
+<td>167698</td>
+<td>100.77</td>
+<td>111.51</td>
+<td>35.19</td>
+<td>3.48</td>
+<td>3.40</td>
+<td>2.87</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0094</td>
+<td>169111</td>
+<td>88.40</td>
+<td>117.02</td>
+<td>30.23</td>
+<td>3.32</td>
+<td>3.24</td>
+<td>3.01</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0095</td>
+<td>177848</td>
+<td>103.12</td>
+<td>117.89</td>
+<td>36.78</td>
+<td>3.33</td>
+<td>3.26</td>
+<td>3.07</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0096</td>
+<td>166133</td>
+<td>95.85</td>
+<td>110.67</td>
+<td>32.00</td>
+<td>3.53</td>
+<td>3.46</td>
+<td>3.08</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0097</td>
+<td>178023</td>
+<td>83.72</td>
+<td>145.63</td>
+<td>31.05</td>
+<td>3.19</td>
+<td>3.15</td>
+<td>2.88</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0098</td>
+<td>180358</td>
+<td>84.95</td>
+<td>151.68</td>
+<td>29.70</td>
+<td>3.08</td>
+<td>3.07</td>
+<td>2.89</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0099</td>
+<td>170568</td>
+<td>93.78</td>
+<td>102.45</td>
+<td>34.36</td>
+<td>3.46</td>
+<td>3.41</td>
+<td>2.97</td>
+</tr>
+<tr>
+<td>6</td>
+<td>0100</td>
+<td>159704</td>
+<td>94.20</td>
+<td>119.96</td>
+<td>29.87</td>
+<td>3.44</td>
+<td>3.36</td>
+<td>3.07</td>
+</tr>
+</table>
+<a name="Lane"><h2>Lane 7</h2></a><table border="1" cellpadding="5">
+<tr>
+<td colspan="1">Lane </td>
+<td colspan="1">Tile</td>
+<td colspan="1">Clusters (raw)</td>
+<td colspan="1">Av 1st Cycle Int (PF)</td>
+<td colspan="1">Av % intensity after 20 cycles (PF)</td>
+<td colspan="1">% PF Clusters </td>
+<td colspan="1">% Align (PF) </td>
+<td colspan="1">Av Alignment Score (PF)</td>
+<td colspan="1">% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>7</td>
+<td>0001</td>
+<td>167397</td>
+<td>69.27</td>
+<td>175.60</td>
+<td>33.31</td>
+<td>0.90</td>
+<td>0.61</td>
+<td>2.48</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0002</td>
+<td>160455</td>
+<td>74.47</td>
+<td>139.78</td>
+<td>29.55</td>
+<td>0.88</td>
+<td>0.59</td>
+<td>2.91</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0003</td>
+<td>161412</td>
+<td>82.17</td>
+<td>112.08</td>
+<td>28.64</td>
+<td>0.85</td>
+<td>0.55</td>
+<td>3.00</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0004</td>
+<td>163624</td>
+<td>101.35</td>
+<td>84.07</td>
+<td>26.10</td>
+<td>0.87</td>
+<td>0.53</td>
+<td>3.76</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0005</td>
+<td>164021</td>
+<td>92.78</td>
+<td>113.18</td>
+<td>26.89</td>
+<td>0.96</td>
+<td>0.65</td>
+<td>3.07</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0006</td>
+<td>156806</td>
+<td>75.62</td>
+<td>117.16</td>
+<td>27.59</td>
+<td>0.86</td>
+<td>0.60</td>
+<td>2.80</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0007</td>
+<td>162038</td>
+<td>73.40</td>
+<td>114.44</td>
+<td>27.61</td>
+<td>0.86</td>
+<td>0.60</td>
+<td>2.45</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0008</td>
+<td>165511</td>
+<td>107.40</td>
+<td>105.26</td>
+<td>35.62</td>
+<td>0.86</td>
+<td>0.56</td>
+<td>2.85</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0009</td>
+<td>163282</td>
+<td>87.62</td>
+<td>129.24</td>
+<td>30.11</td>
+<td>0.81</td>
+<td>0.57</td>
+<td>3.20</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0010</td>
+<td>156992</td>
+<td>68.35</td>
+<td>119.09</td>
+<td>22.63</td>
+<td>0.81</td>
+<td>0.53</td>
+<td>2.96</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0011</td>
+<td>150552</td>
+<td>72.62</td>
+<td>118.73</td>
+<td>25.24</td>
+<td>0.87</td>
+<td>0.60</td>
+<td>2.60</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0012</td>
+<td>160140</td>
+<td>68.35</td>
+<td>105.56</td>
+<td>22.16</td>
+<td>0.72</td>
+<td>0.47</td>
+<td>3.23</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0013</td>
+<td>149302</td>
+<td>85.85</td>
+<td>100.93</td>
+<td>21.86</td>
+<td>0.79</td>
+<td>0.50</td>
+<td>3.30</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0014</td>
+<td>143740</td>
+<td>84.30</td>
+<td>87.37</td>
+<td>23.58</td>
+<td>0.82</td>
+<td>0.57</td>
+<td>2.92</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0015</td>
+<td>139427</td>
+<td>58.95</td>
+<td>157.80</td>
+<td>24.12</td>
+<td>0.92</td>
+<td>0.63</td>
+<td>3.22</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0016</td>
+<td>136177</td>
+<td>72.90</td>
+<td>146.60</td>
+<td>26.28</td>
+<td>0.93</td>
+<td>0.63</td>
+<td>2.91</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0017</td>
+<td>132237</td>
+<td>69.00</td>
+<td>151.45</td>
+<td>25.13</td>
+<td>1.10</td>
+<td>0.79</td>
+<td>2.68</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0018</td>
+<td>142869</td>
+<td>66.30</td>
+<td>171.00</td>
+<td>23.94</td>
+<td>0.99</td>
+<td>0.75</td>
+<td>2.93</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0019</td>
+<td>142456</td>
+<td>69.05</td>
+<td>165.86</td>
+<td>31.97</td>
+<td>0.97</td>
+<td>0.63</td>
+<td>2.91</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0020</td>
+<td>155029</td>
+<td>60.87</td>
+<td>100.82</td>
+<td>28.64</td>
+<td>0.75</td>
+<td>0.52</td>
+<td>3.65</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0021</td>
+<td>154783</td>
+<td>62.23</td>
+<td>154.28</td>
+<td>24.08</td>
+<td>0.73</td>
+<td>0.54</td>
+<td>3.34</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0022</td>
+<td>140060</td>
+<td>54.48</td>
+<td>172.10</td>
+<td>20.64</td>
+<td>1.05</td>
+<td>0.71</td>
+<td>2.94</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0023</td>
+<td>148347</td>
+<td>71.95</td>
+<td>95.55</td>
+<td>29.02</td>
+<td>0.83</td>
+<td>0.58</td>
+<td>2.65</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0024</td>
+<td>148929</td>
+<td>60.38</td>
+<td>114.87</td>
+<td>26.97</td>
+<td>0.80</td>
+<td>0.59</td>
+<td>2.99</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0025</td>
+<td>150950</td>
+<td>67.45</td>
+<td>106.30</td>
+<td>25.61</td>
+<td>0.90</td>
+<td>0.63</td>
+<td>3.29</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0026</td>
+<td>150448</td>
+<td>67.12</td>
+<td>151.32</td>
+<td>26.18</td>
+<td>0.83</td>
+<td>0.60</td>
+<td>3.44</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0027</td>
+<td>157343</td>
+<td>80.08</td>
+<td>155.89</td>
+<td>26.53</td>
+<td>0.82</td>
+<td>0.58</td>
+<td>3.90</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0028</td>
+<td>154919</td>
+<td>76.90</td>
+<td>169.70</td>
+<td>27.22</td>
+<td>0.90</td>
+<td>0.62</td>
+<td>3.35</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0029</td>
+<td>155916</td>
+<td>77.33</td>
+<td>153.28</td>
+<td>29.53</td>
+<td>0.86</td>
+<td>0.60</td>
+<td>3.52</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0030</td>
+<td>153327</td>
+<td>74.33</td>
+<td>98.79</td>
+<td>29.26</td>
+<td>0.83</td>
+<td>0.62</td>
+<td>3.44</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0031</td>
+<td>167377</td>
+<td>101.38</td>
+<td>100.96</td>
+<td>26.85</td>
+<td>0.89</td>
+<td>0.59</td>
+<td>3.32</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0032</td>
+<td>158600</td>
+<td>80.65</td>
+<td>86.73</td>
+<td>33.06</td>
+<td>0.93</td>
+<td>0.62</td>
+<td>3.56</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0033</td>
+<td>156070</td>
+<td>71.68</td>
+<td>169.06</td>
+<td>33.61</td>
+<td>0.94</td>
+<td>0.65</td>
+<td>2.99</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0034</td>
+<td>147991</td>
+<td>59.85</td>
+<td>160.90</td>
+<td>34.16</td>
+<td>1.11</td>
+<td>0.72</td>
+<td>3.15</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0035</td>
+<td>145454</td>
+<td>76.00</td>
+<td>130.00</td>
+<td>31.63</td>
+<td>1.02</td>
+<td>0.68</td>
+<td>2.89</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0036</td>
+<td>164600</td>
+<td>69.88</td>
+<td>89.91</td>
+<td>34.74</td>
+<td>0.70</td>
+<td>0.44</td>
+<td>3.41</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0037</td>
+<td>150892</td>
+<td>73.33</td>
+<td>136.99</td>
+<td>31.62</td>
+<td>0.79</td>
+<td>0.54</td>
+<td>3.98</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0038</td>
+<td>158740</td>
+<td>71.50</td>
+<td>126.50</td>
+<td>31.62</td>
+<td>0.74</td>
+<td>0.58</td>
+<td>3.22</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0039</td>
+<td>159579</td>
+<td>76.23</td>
+<td>117.74</td>
+<td>34.90</td>
+<td>0.82</td>
+<td>0.56</td>
+<td>3.78</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0040</td>
+<td>153009</td>
+<td>73.10</td>
+<td>124.42</td>
+<td>26.48</td>
+<td>1.01</td>
+<td>0.70</td>
+<td>3.34</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0041</td>
+<td>163129</td>
+<td>78.72</td>
+<td>69.58</td>
+<td>35.20</td>
+<td>0.66</td>
+<td>0.43</td>
+<td>3.48</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0042</td>
+<td>156652</td>
+<td>87.90</td>
+<td>121.42</td>
+<td>29.83</td>
+<td>0.79</td>
+<td>0.53</td>
+<td>3.56</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0043</td>
+<td>156757</td>
+<td>83.33</td>
+<td>126.79</td>
+<td>36.07</td>
+<td>0.94</td>
+<td>0.63</td>
+<td>3.16</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0044</td>
+<td>159822</td>
+<td>81.50</td>
+<td>114.72</td>
+<td>35.18</td>
+<td>0.88</td>
+<td>0.59</td>
+<td>2.99</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0045</td>
+<td>157761</td>
+<td>96.48</td>
+<td>106.92</td>
+<td>34.86</td>
+<td>0.98</td>
+<td>0.62</td>
+<td>3.11</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0046</td>
+<td>163550</td>
+<td>82.83</td>
+<td>155.06</td>
+<td>36.16</td>
+<td>1.03</td>
+<td>0.64</td>
+<td>2.59</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0047</td>
+<td>161738</td>
+<td>108.35</td>
+<td>83.71</td>
+<td>35.48</td>
+<td>0.97</td>
+<td>0.60</td>
+<td>3.02</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0048</td>
+<td>157517</td>
+<td>89.12</td>
+<td>125.83</td>
+<td>38.04</td>
+<td>0.97</td>
+<td>0.62</td>
+<td>3.51</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0049</td>
+<td>156268</td>
+<td>84.37</td>
+<td>120.39</td>
+<td>35.93</td>
+<td>0.93</td>
+<td>0.63</td>
+<td>3.00</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0050</td>
+<td>161985</td>
+<td>92.23</td>
+<td>115.94</td>
+<td>38.21</td>
+<td>0.94</td>
+<td>0.61</td>
+<td>3.05</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0051</td>
+<td>164236</td>
+<td>92.08</td>
+<td>118.27</td>
+<td>37.06</td>
+<td>0.96</td>
+<td>0.59</td>
+<td>2.93</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0052</td>
+<td>162032</td>
+<td>87.82</td>
+<td>125.70</td>
+<td>38.33</td>
+<td>0.92</td>
+<td>0.57</td>
+<td>3.20</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0053</td>
+<td>161985</td>
+<td>92.42</td>
+<td>106.98</td>
+<td>38.00</td>
+<td>0.91</td>
+<td>0.57</td>
+<td>3.14</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0054</td>
+<td>156507</td>
+<td>78.40</td>
+<td>109.38</td>
+<td>33.59</td>
+<td>0.91</td>
+<td>0.63</td>
+<td>2.56</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0055</td>
+<td>160991</td>
+<td>99.35</td>
+<td>90.09</td>
+<td>31.61</td>
+<td>0.75</td>
+<td>0.54</td>
+<td>3.26</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0056</td>
+<td>162825</td>
+<td>94.60</td>
+<td>105.84</td>
+<td>35.81</td>
+<td>0.91</td>
+<td>0.60</td>
+<td>3.07</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0057</td>
+<td>163135</td>
+<td>95.25</td>
+<td>103.15</td>
+<td>36.03</td>
+<td>0.88</td>
+<td>0.55</td>
+<td>2.93</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0058</td>
+<td>159693</td>
+<td>85.17</td>
+<td>115.12</td>
+<td>28.95</td>
+<td>0.79</td>
+<td>0.57</td>
+<td>3.45</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0059</td>
+<td>154052</td>
+<td>77.88</td>
+<td>137.17</td>
+<td>37.45</td>
+<td>0.88</td>
+<td>0.58</td>
+<td>3.13</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0060</td>
+<td>161198</td>
+<td>89.47</td>
+<td>108.30</td>
+<td>32.87</td>
+<td>0.79</td>
+<td>0.55</td>
+<td>3.51</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0061</td>
+<td>156782</td>
+<td>76.92</td>
+<td>114.40</td>
+<td>32.30</td>
+<td>0.81</td>
+<td>0.57</td>
+<td>3.58</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0062</td>
+<td>159970</td>
+<td>80.27</td>
+<td>126.28</td>
+<td>29.28</td>
+<td>0.87</td>
+<td>0.60</td>
+<td>3.59</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0063</td>
+<td>160696</td>
+<td>86.85</td>
+<td>105.01</td>
+<td>28.67</td>
+<td>0.74</td>
+<td>0.54</td>
+<td>3.37</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0064</td>
+<td>161082</td>
+<td>89.83</td>
+<td>128.19</td>
+<td>31.12</td>
+<td>0.78</td>
+<td>0.55</td>
+<td>2.98</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0065</td>
+<td>173381</td>
+<td>111.25</td>
+<td>122.36</td>
+<td>25.05</td>
+<td>0.84</td>
+<td>0.57</td>
+<td>3.98</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0066</td>
+<td>160085</td>
+<td>93.40</td>
+<td>86.24</td>
+<td>27.82</td>
+<td>0.82</td>
+<td>0.60</td>
+<td>2.96</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0067</td>
+<td>160301</td>
+<td>80.08</td>
+<td>98.63</td>
+<td>26.39</td>
+<td>0.83</td>
+<td>0.61</td>
+<td>3.07</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0068</td>
+<td>152691</td>
+<td>101.30</td>
+<td>91.19</td>
+<td>29.11</td>
+<td>0.88</td>
+<td>0.59</td>
+<td>3.66</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0069</td>
+<td>148325</td>
+<td>70.78</td>
+<td>150.83</td>
+<td>31.02</td>
+<td>0.88</td>
+<td>0.63</td>
+<td>3.20</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0070</td>
+<td>162125</td>
+<td>85.85</td>
+<td>92.05</td>
+<td>30.62</td>
+<td>0.68</td>
+<td>0.48</td>
+<td>3.06</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0071</td>
+<td>165962</td>
+<td>68.72</td>
+<td>103.56</td>
+<td>32.70</td>
+<td>0.66</td>
+<td>0.46</td>
+<td>3.51</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0072</td>
+<td>166535</td>
+<td>93.93</td>
+<td>124.57</td>
+<td>34.01</td>
+<td>0.80</td>
+<td>0.52</td>
+<td>3.13</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0073</td>
+<td>173264</td>
+<td>106.55</td>
+<td>126.56</td>
+<td>31.72</td>
+<td>0.79</td>
+<td>0.50</td>
+<td>3.45</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0074</td>
+<td>168644</td>
+<td>101.98</td>
+<td>125.55</td>
+<td>29.96</td>
+<td>0.76</td>
+<td>0.54</td>
+<td>3.06</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0075</td>
+<td>156199</td>
+<td>71.35</td>
+<td>151.23</td>
+<td>31.66</td>
+<td>0.89</td>
+<td>0.59</td>
+<td>3.52</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0076</td>
+<td>165594</td>
+<td>70.38</td>
+<td>157.19</td>
+<td>31.08</td>
+<td>0.93</td>
+<td>0.63</td>
+<td>3.48</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0077</td>
+<td>176072</td>
+<td>93.12</td>
+<td>73.80</td>
+<td>34.36</td>
+<td>0.80</td>
+<td>0.50</td>
+<td>3.20</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0078</td>
+<td>174206</td>
+<td>115.92</td>
+<td>96.74</td>
+<td>34.01</td>
+<td>0.80</td>
+<td>0.50</td>
+<td>3.53</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0079</td>
+<td>163065</td>
+<td>92.30</td>
+<td>111.24</td>
+<td>35.11</td>
+<td>0.86</td>
+<td>0.61</td>
+<td>2.78</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0080</td>
+<td>172367</td>
+<td>59.48</td>
+<td>116.86</td>
+<td>34.71</td>
+<td>1.00</td>
+<td>0.64</td>
+<td>3.07</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0081</td>
+<td>160853</td>
+<td>106.10</td>
+<td>116.71</td>
+<td>33.53</td>
+<td>0.93</td>
+<td>0.60</td>
+<td>2.77</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0082</td>
+<td>170809</td>
+<td>67.78</td>
+<td>153.19</td>
+<td>30.68</td>
+<td>0.80</td>
+<td>0.54</td>
+<td>2.83</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0083</td>
+<td>171250</td>
+<td>69.68</td>
+<td>153.50</td>
+<td>28.97</td>
+<td>0.82</td>
+<td>0.55</td>
+<td>2.95</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0084</td>
+<td>172523</td>
+<td>90.85</td>
+<td>116.62</td>
+<td>29.60</td>
+<td>0.89</td>
+<td>0.57</td>
+<td>2.94</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0085</td>
+<td>172083</td>
+<td>97.45</td>
+<td>107.52</td>
+<td>31.45</td>
+<td>0.80</td>
+<td>0.52</td>
+<td>2.91</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0086</td>
+<td>158879</td>
+<td>90.08</td>
+<td>108.60</td>
+<td>25.96</td>
+<td>0.95</td>
+<td>0.63</td>
+<td>3.05</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0087</td>
+<td>169708</td>
+<td>104.50</td>
+<td>114.45</td>
+<td>30.17</td>
+<td>0.77</td>
+<td>0.50</td>
+<td>3.53</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0088</td>
+<td>149451</td>
+<td>68.62</td>
+<td>147.83</td>
+<td>28.24</td>
+<td>0.78</td>
+<td>0.49</td>
+<td>3.16</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0089</td>
+<td>173370</td>
+<td>86.58</td>
+<td>119.55</td>
+<td>26.95</td>
+<td>0.91</td>
+<td>0.63</td>
+<td>2.82</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0090</td>
+<td>168059</td>
+<td>85.48</td>
+<td>160.16</td>
+<td>34.64</td>
+<td>0.90</td>
+<td>0.57</td>
+<td>3.04</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0091</td>
+<td>170018</td>
+<td>89.40</td>
+<td>120.47</td>
+<td>32.40</td>
+<td>0.81</td>
+<td>0.52</td>
+<td>2.71</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0092</td>
+<td>167933</td>
+<td>77.98</td>
+<td>104.17</td>
+<td>30.92</td>
+<td>0.87</td>
+<td>0.61</td>
+<td>2.71</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0093</td>
+<td>169305</td>
+<td>67.32</td>
+<td>132.27</td>
+<td>30.50</td>
+<td>0.90</td>
+<td>0.63</td>
+<td>2.64</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0094</td>
+<td>164209</td>
+<td>75.47</td>
+<td>143.19</td>
+<td>29.49</td>
+<td>0.89</td>
+<td>0.61</td>
+<td>2.61</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0095</td>
+<td>176239</td>
+<td>76.33</td>
+<td>160.83</td>
+<td>38.91</td>
+<td>0.83</td>
+<td>0.56</td>
+<td>2.70</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0096</td>
+<td>170534</td>
+<td>109.00</td>
+<td>82.61</td>
+<td>32.38</td>
+<td>1.00</td>
+<td>0.63</td>
+<td>2.80</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0097</td>
+<td>174053</td>
+<td>113.35</td>
+<td>90.05</td>
+<td>13.00</td>
+<td>0.49</td>
+<td>0.35</td>
+<td>2.45</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0098</td>
+<td>175159</td>
+<td>110.08</td>
+<td>98.09</td>
+<td>29.74</td>
+<td>0.98</td>
+<td>0.65</td>
+<td>2.79</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0099</td>
+<td>179218</td>
+<td>100.78</td>
+<td>130.69</td>
+<td>27.53</td>
+<td>0.94</td>
+<td>0.64</td>
+<td>2.59</td>
+</tr>
+<tr>
+<td>7</td>
+<td>0100</td>
+<td>155500</td>
+<td>88.42</td>
+<td>121.54</td>
+<td>31.60</td>
+<td>0.95</td>
+<td>0.63</td>
+<td>2.33</td>
+</tr>
+</table>
+<a name="Lane"><h2>Lane 8</h2></a><table border="1" cellpadding="5">
+<tr>
+<td colspan="1">Lane </td>
+<td colspan="1">Tile</td>
+<td colspan="1">Clusters (raw)</td>
+<td colspan="1">Av 1st Cycle Int (PF)</td>
+<td colspan="1">Av % intensity after 20 cycles (PF)</td>
+<td colspan="1">% PF Clusters </td>
+<td colspan="1">% Align (PF) </td>
+<td colspan="1">Av Alignment Score (PF)</td>
+<td colspan="1">% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>8</td>
+<td>0001</td>
+<td>181113</td>
+<td>113.72</td>
+<td>71.64</td>
+<td>0.81</td>
+<td>42.07</td>
+<td>37.02</td>
+<td>2.90</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0002</td>
+<td>167526</td>
+<td>104.83</td>
+<td>59.46</td>
+<td>2.21</td>
+<td>36.25</td>
+<td>31.47</td>
+<td>3.80</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0003</td>
+<td>162131</td>
+<td>95.08</td>
+<td>71.29</td>
+<td>1.99</td>
+<td>38.35</td>
+<td>32.69</td>
+<td>3.67</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0004</td>
+<td>174931</td>
+<td>122.20</td>
+<td>56.30</td>
+<td>2.18</td>
+<td>39.64</td>
+<td>29.88</td>
+<td>3.55</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0005</td>
+<td>188914</td>
+<td>111.88</td>
+<td>73.43</td>
+<td>2.71</td>
+<td>40.55</td>
+<td>35.06</td>
+<td>3.68</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0006</td>
+<td>176574</td>
+<td>95.43</td>
+<td>75.37</td>
+<td>3.00</td>
+<td>43.17</td>
+<td>37.84</td>
+<td>3.46</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0007</td>
+<td>177213</td>
+<td>109.32</td>
+<td>59.39</td>
+<td>2.43</td>
+<td>38.56</td>
+<td>33.27</td>
+<td>3.59</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0008</td>
+<td>179148</td>
+<td>99.52</td>
+<td>93.77</td>
+<td>3.16</td>
+<td>48.02</td>
+<td>44.06</td>
+<td>2.89</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0009</td>
+<td>184260</td>
+<td>102.12</td>
+<td>94.66</td>
+<td>3.02</td>
+<td>46.61</td>
+<td>42.16</td>
+<td>3.10</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0010</td>
+<td>161721</td>
+<td>88.95</td>
+<td>65.91</td>
+<td>2.61</td>
+<td>42.64</td>
+<td>38.68</td>
+<td>3.11</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0011</td>
+<td>181269</td>
+<td>102.85</td>
+<td>58.07</td>
+<td>2.57</td>
+<td>35.97</td>
+<td>30.41</td>
+<td>4.29</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0012</td>
+<td>182179</td>
+<td>105.47</td>
+<td>64.92</td>
+<td>2.96</td>
+<td>44.43</td>
+<td>40.58</td>
+<td>3.19</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0013</td>
+<td>167058</td>
+<td>98.97</td>
+<td>72.42</td>
+<td>2.95</td>
+<td>43.82</td>
+<td>38.67</td>
+<td>3.18</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0014</td>
+<td>181070</td>
+<td>103.45</td>
+<td>69.43</td>
+<td>2.99</td>
+<td>44.72</td>
+<td>39.39</td>
+<td>3.40</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0015</td>
+<td>192314</td>
+<td>128.22</td>
+<td>52.41</td>
+<td>2.78</td>
+<td>40.50</td>
+<td>33.40</td>
+<td>3.57</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0016</td>
+<td>198144</td>
+<td>120.30</td>
+<td>56.90</td>
+<td>2.92</td>
+<td>44.39</td>
+<td>37.08</td>
+<td>3.62</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0017</td>
+<td>202972</td>
+<td>130.85</td>
+<td>59.51</td>
+<td>3.12</td>
+<td>47.29</td>
+<td>40.24</td>
+<td>3.47</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0018</td>
+<td>201819</td>
+<td>134.90</td>
+<td>52.71</td>
+<td>2.80</td>
+<td>43.91</td>
+<td>37.45</td>
+<td>3.57</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0019</td>
+<td>209515</td>
+<td>140.47</td>
+<td>47.41</td>
+<td>2.84</td>
+<td>46.16</td>
+<td>39.35</td>
+<td>3.52</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0020</td>
+<td>176152</td>
+<td>111.72</td>
+<td>60.06</td>
+<td>2.60</td>
+<td>40.87</td>
+<td>33.93</td>
+<td>3.67</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0021</td>
+<td>176568</td>
+<td>110.15</td>
+<td>68.32</td>
+<td>2.59</td>
+<td>44.62</td>
+<td>39.06</td>
+<td>3.50</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0022</td>
+<td>169602</td>
+<td>108.75</td>
+<td>75.79</td>
+<td>2.87</td>
+<td>48.08</td>
+<td>43.73</td>
+<td>2.98</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0023</td>
+<td>189324</td>
+<td>102.48</td>
+<td>83.46</td>
+<td>2.88</td>
+<td>47.06</td>
+<td>41.36</td>
+<td>3.52</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0024</td>
+<td>171625</td>
+<td>116.58</td>
+<td>60.63</td>
+<td>2.98</td>
+<td>47.61</td>
+<td>42.47</td>
+<td>3.45</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0025</td>
+<td>162092</td>
+<td>97.65</td>
+<td>114.41</td>
+<td>3.23</td>
+<td>48.32</td>
+<td>39.95</td>
+<td>3.10</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0026</td>
+<td>166734</td>
+<td>106.85</td>
+<td>113.29</td>
+<td>3.35</td>
+<td>50.81</td>
+<td>46.10</td>
+<td>3.18</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0027</td>
+<td>188771</td>
+<td>135.70</td>
+<td>89.90</td>
+<td>3.36</td>
+<td>51.36</td>
+<td>45.20</td>
+<td>3.37</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0028</td>
+<td>208995</td>
+<td>143.78</td>
+<td>74.37</td>
+<td>3.45</td>
+<td>50.66</td>
+<td>44.31</td>
+<td>3.37</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0029</td>
+<td>189249</td>
+<td>102.97</td>
+<td>101.46</td>
+<td>3.50</td>
+<td>50.70</td>
+<td>46.13</td>
+<td>3.16</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0030</td>
+<td>168319</td>
+<td>113.25</td>
+<td>101.50</td>
+<td>3.39</td>
+<td>52.52</td>
+<td>47.69</td>
+<td>3.17</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0031</td>
+<td>207260</td>
+<td>148.28</td>
+<td>65.94</td>
+<td>3.55</td>
+<td>53.16</td>
+<td>47.51</td>
+<td>3.22</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0032</td>
+<td>214286</td>
+<td>117.77</td>
+<td>99.77</td>
+<td>3.03</td>
+<td>50.93</td>
+<td>46.69</td>
+<td>3.12</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0033</td>
+<td>204280</td>
+<td>138.05</td>
+<td>64.51</td>
+<td>3.33</td>
+<td>51.13</td>
+<td>45.23</td>
+<td>3.30</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0034</td>
+<td>218862</td>
+<td>143.27</td>
+<td>49.69</td>
+<td>3.55</td>
+<td>51.46</td>
+<td>45.87</td>
+<td>3.09</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0035</td>
+<td>212945</td>
+<td>126.78</td>
+<td>69.43</td>
+<td>4.04</td>
+<td>53.35</td>
+<td>47.42</td>
+<td>3.14</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0036</td>
+<td>209646</td>
+<td>122.40</td>
+<td>79.74</td>
+<td>4.18</td>
+<td>55.94</td>
+<td>50.40</td>
+<td>2.95</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0037</td>
+<td>200910</td>
+<td>112.30</td>
+<td>88.69</td>
+<td>3.84</td>
+<td>54.07</td>
+<td>49.68</td>
+<td>2.95</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0038</td>
+<td>208228</td>
+<td>123.53</td>
+<td>81.38</td>
+<td>3.92</td>
+<td>55.25</td>
+<td>50.76</td>
+<td>2.99</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0039</td>
+<td>218373</td>
+<td>131.20</td>
+<td>81.63</td>
+<td>3.97</td>
+<td>56.80</td>
+<td>52.26</td>
+<td>2.90</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0040</td>
+<td>210877</td>
+<td>115.60</td>
+<td>85.62</td>
+<td>3.96</td>
+<td>54.54</td>
+<td>49.83</td>
+<td>2.95</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0041</td>
+<td>205484</td>
+<td>116.00</td>
+<td>87.26</td>
+<td>3.78</td>
+<td>52.58</td>
+<td>44.03</td>
+<td>4.66</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0042</td>
+<td>201755</td>
+<td>105.40</td>
+<td>94.12</td>
+<td>3.80</td>
+<td>55.66</td>
+<td>50.72</td>
+<td>3.11</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0043</td>
+<td>199044</td>
+<td>120.75</td>
+<td>80.35</td>
+<td>3.68</td>
+<td>52.99</td>
+<td>47.78</td>
+<td>3.14</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0044</td>
+<td>194716</td>
+<td>120.93</td>
+<td>74.05</td>
+<td>3.68</td>
+<td>53.35</td>
+<td>48.07</td>
+<td>3.23</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0045</td>
+<td>213702</td>
+<td>129.80</td>
+<td>66.41</td>
+<td>3.85</td>
+<td>53.60</td>
+<td>47.91</td>
+<td>3.10</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0046</td>
+<td>212117</td>
+<td>108.75</td>
+<td>94.67</td>
+<td>3.85</td>
+<td>58.02</td>
+<td>53.31</td>
+<td>3.05</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0047</td>
+<td>222320</td>
+<td>108.62</td>
+<td>96.18</td>
+<td>3.64</td>
+<td>58.31</td>
+<td>54.05</td>
+<td>2.86</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0048</td>
+<td>215015</td>
+<td>129.85</td>
+<td>70.45</td>
+<td>4.02</td>
+<td>55.05</td>
+<td>48.91</td>
+<td>3.28</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0049</td>
+<td>212941</td>
+<td>128.05</td>
+<td>67.36</td>
+<td>3.95</td>
+<td>53.58</td>
+<td>47.39</td>
+<td>3.30</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0050</td>
+<td>207426</td>
+<td>119.88</td>
+<td>70.70</td>
+<td>4.27</td>
+<td>54.22</td>
+<td>49.05</td>
+<td>3.14</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0051</td>
+<td>221088</td>
+<td>120.48</td>
+<td>80.27</td>
+<td>4.98</td>
+<td>57.34</td>
+<td>52.49</td>
+<td>3.09</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0052</td>
+<td>206850</td>
+<td>113.85</td>
+<td>77.05</td>
+<td>4.28</td>
+<td>54.50</td>
+<td>50.16</td>
+<td>3.13</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0053</td>
+<td>218985</td>
+<td>128.35</td>
+<td>71.39</td>
+<td>4.41</td>
+<td>55.46</td>
+<td>50.36</td>
+<td>3.15</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0054</td>
+<td>215826</td>
+<td>125.50</td>
+<td>80.32</td>
+<td>4.51</td>
+<td>55.57</td>
+<td>51.03</td>
+<td>3.05</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0055</td>
+<td>217025</td>
+<td>123.75</td>
+<td>81.94</td>
+<td>4.38</td>
+<td>55.06</td>
+<td>50.34</td>
+<td>3.06</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0056</td>
+<td>221504</td>
+<td>133.72</td>
+<td>65.40</td>
+<td>4.17</td>
+<td>53.49</td>
+<td>48.73</td>
+<td>3.11</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0057</td>
+<td>217253</td>
+<td>125.78</td>
+<td>59.09</td>
+<td>4.01</td>
+<td>53.60</td>
+<td>48.37</td>
+<td>3.17</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0058</td>
+<td>217739</td>
+<td>133.20</td>
+<td>59.31</td>
+<td>3.90</td>
+<td>53.23</td>
+<td>46.93</td>
+<td>3.35</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0059</td>
+<td>206901</td>
+<td>119.10</td>
+<td>103.57</td>
+<td>3.59</td>
+<td>51.59</td>
+<td>45.56</td>
+<td>3.32</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0060</td>
+<td>209276</td>
+<td>133.25</td>
+<td>75.55</td>
+<td>3.91</td>
+<td>53.23</td>
+<td>48.59</td>
+<td>3.14</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0061</td>
+<td>206912</td>
+<td>116.42</td>
+<td>80.82</td>
+<td>3.87</td>
+<td>53.37</td>
+<td>48.65</td>
+<td>3.08</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0062</td>
+<td>208293</td>
+<td>130.93</td>
+<td>76.97</td>
+<td>3.99</td>
+<td>53.83</td>
+<td>49.45</td>
+<td>3.02</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0063</td>
+<td>216117</td>
+<td>140.85</td>
+<td>68.02</td>
+<td>4.04</td>
+<td>53.96</td>
+<td>48.52</td>
+<td>3.11</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0064</td>
+<td>221626</td>
+<td>138.38</td>
+<td>68.51</td>
+<td>4.07</td>
+<td>53.99</td>
+<td>48.41</td>
+<td>3.20</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0065</td>
+<td>226495</td>
+<td>119.17</td>
+<td>90.85</td>
+<td>4.26</td>
+<td>56.13</td>
+<td>52.26</td>
+<td>2.98</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0066</td>
+<td>211217</td>
+<td>122.75</td>
+<td>77.13</td>
+<td>4.07</td>
+<td>53.13</td>
+<td>48.26</td>
+<td>3.22</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0067</td>
+<td>207572</td>
+<td>117.97</td>
+<td>85.40</td>
+<td>3.90</td>
+<td>53.48</td>
+<td>48.97</td>
+<td>3.05</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0068</td>
+<td>212274</td>
+<td>130.47</td>
+<td>77.97</td>
+<td>3.78</td>
+<td>50.92</td>
+<td>45.66</td>
+<td>3.15</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0069</td>
+<td>225642</td>
+<td>151.32</td>
+<td>67.64</td>
+<td>3.43</td>
+<td>47.99</td>
+<td>41.14</td>
+<td>3.46</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0070</td>
+<td>206267</td>
+<td>130.85</td>
+<td>44.73</td>
+<td>3.04</td>
+<td>45.20</td>
+<td>39.72</td>
+<td>3.49</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0071</td>
+<td>197697</td>
+<td>116.00</td>
+<td>55.88</td>
+<td>2.87</td>
+<td>44.86</td>
+<td>40.68</td>
+<td>3.36</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0072</td>
+<td>201670</td>
+<td>131.15</td>
+<td>54.33</td>
+<td>3.10</td>
+<td>49.63</td>
+<td>45.22</td>
+<td>3.23</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0073</td>
+<td>199697</td>
+<td>141.85</td>
+<td>52.34</td>
+<td>3.21</td>
+<td>50.81</td>
+<td>47.20</td>
+<td>2.95</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0074</td>
+<td>220224</td>
+<td>146.22</td>
+<td>66.88</td>
+<td>3.10</td>
+<td>50.24</td>
+<td>45.85</td>
+<td>3.01</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0075</td>
+<td>198282</td>
+<td>128.40</td>
+<td>72.59</td>
+<td>3.17</td>
+<td>50.41</td>
+<td>46.14</td>
+<td>3.12</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0076</td>
+<td>187773</td>
+<td>131.55</td>
+<td>66.25</td>
+<td>3.30</td>
+<td>50.96</td>
+<td>45.63</td>
+<td>3.20</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0077</td>
+<td>186366</td>
+<td>113.85</td>
+<td>100.55</td>
+<td>3.13</td>
+<td>50.32</td>
+<td>46.19</td>
+<td>3.15</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0078</td>
+<td>189058</td>
+<td>133.57</td>
+<td>91.37</td>
+<td>2.90</td>
+<td>47.01</td>
+<td>42.99</td>
+<td>3.19</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0079</td>
+<td>213947</td>
+<td>164.30</td>
+<td>57.35</td>
+<td>3.15</td>
+<td>48.49</td>
+<td>44.57</td>
+<td>3.09</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0080</td>
+<td>221739</td>
+<td>121.95</td>
+<td>74.93</td>
+<td>2.71</td>
+<td>44.15</td>
+<td>35.06</td>
+<td>3.23</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0081</td>
+<td>205044</td>
+<td>132.75</td>
+<td>49.51</td>
+<td>2.79</td>
+<td>42.39</td>
+<td>36.71</td>
+<td>3.48</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0082</td>
+<td>210695</td>
+<td>129.43</td>
+<td>80.63</td>
+<td>3.56</td>
+<td>49.50</td>
+<td>44.26</td>
+<td>3.29</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0083</td>
+<td>217007</td>
+<td>139.45</td>
+<td>72.43</td>
+<td>3.47</td>
+<td>48.63</td>
+<td>40.36</td>
+<td>3.69</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0084</td>
+<td>210797</td>
+<td>144.35</td>
+<td>70.66</td>
+<td>3.42</td>
+<td>48.64</td>
+<td>43.35</td>
+<td>3.29</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0085</td>
+<td>211477</td>
+<td>142.22</td>
+<td>73.72</td>
+<td>3.38</td>
+<td>47.64</td>
+<td>36.57</td>
+<td>3.26</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0086</td>
+<td>200320</td>
+<td>117.95</td>
+<td>63.59</td>
+<td>3.03</td>
+<td>45.15</td>
+<td>40.32</td>
+<td>3.25</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0087</td>
+<td>204295</td>
+<td>136.75</td>
+<td>57.18</td>
+<td>3.35</td>
+<td>48.24</td>
+<td>44.39</td>
+<td>3.04</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0088</td>
+<td>203778</td>
+<td>141.18</td>
+<td>65.79</td>
+<td>3.21</td>
+<td>46.79</td>
+<td>42.24</td>
+<td>3.13</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0089</td>
+<td>209681</td>
+<td>124.65</td>
+<td>82.43</td>
+<td>3.22</td>
+<td>47.89</td>
+<td>44.07</td>
+<td>2.95</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0090</td>
+<td>199690</td>
+<td>129.05</td>
+<td>69.82</td>
+<td>2.96</td>
+<td>46.20</td>
+<td>41.84</td>
+<td>3.11</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0091</td>
+<td>202793</td>
+<td>119.60</td>
+<td>79.18</td>
+<td>3.13</td>
+<td>47.41</td>
+<td>42.53</td>
+<td>3.12</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0092</td>
+<td>188850</td>
+<td>109.60</td>
+<td>74.64</td>
+<td>3.17</td>
+<td>44.81</td>
+<td>40.44</td>
+<td>3.26</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0093</td>
+<td>188951</td>
+<td>119.95</td>
+<td>77.43</td>
+<td>2.89</td>
+<td>44.14</td>
+<td>39.45</td>
+<td>3.29</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0094</td>
+<td>177924</td>
+<td>125.05</td>
+<td>71.75</td>
+<td>2.19</td>
+<td>37.05</td>
+<td>29.90</td>
+<td>3.82</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0095</td>
+<td>175164</td>
+<td>103.00</td>
+<td>88.76</td>
+<td>2.79</td>
+<td>40.67</td>
+<td>29.89</td>
+<td>3.75</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0096</td>
+<td>170691</td>
+<td>109.40</td>
+<td>74.77</td>
+<td>1.27</td>
+<td>37.54</td>
+<td>31.24</td>
+<td>4.00</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0097</td>
+<td>177715</td>
+<td>0.00</td>
+<td>N/A</td>
+<td>0.00</td>
+<td>0.00</td>
+<td>0.00</td>
+<td>0.00</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0098</td>
+<td>168260</td>
+<td>121.38</td>
+<td>64.30</td>
+<td>2.14</td>
+<td>36.20</td>
+<td>20.99</td>
+<td>3.23</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0099</td>
+<td>202629</td>
+<td>149.72</td>
+<td>72.23</td>
+<td>2.51</td>
+<td>41.13</td>
+<td>34.74</td>
+<td>3.56</td>
+</tr>
+<tr>
+<td>8</td>
+<td>0100</td>
+<td>162617</td>
+<td>125.72</td>
+<td>66.75</td>
+<td>2.53</td>
+<td>41.07</td>
+<td>31.79</td>
+<td>3.48</td>
+</tr>
+</table>
+<li><h3>IVC Plots</h3></li>
+<a href="../IVC.htm"> click here
+ </a><h3><li>All Intensity Plots</li></h3>
+<a href="../All.htm"> click here
+ </a><h3><li>Error Graphs</li></h3>
+<a href="Error.htm"> click here
+ </a><h3><li>Error Curves</li></h3>
+<a href="Perfect.htm"> click here
+ </a>
+</body></html>
--- /dev/null
+<!--RUN_TIME Thu Nov 13 15:11:29 2008 -->
+<!--SOFTWARE_VERSION @(#) $Id: jerboa.pl,v 1.94 2007/12/04 09:59:07 rshaw Exp $-->
+<html>
+<body>
+
+<a name="Top"><h2><title>080920_HWI-EAS229_0057_30GBJAAXX Summary</title></h2></a>
+<h1>Summary Information For Experiment 080920_HWI-EAS229_0057_30GBJAAXX on Machine unknown</h1>
+<h2><br></br>Chip Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr><td>Machine</td><td>UNKNOWN</td></tr>
+<tr><td>Run Folder</td><td>080920_HWI-EAS229_0057_30GBJAAXX</td></tr>
+<tr><td>Chip ID</td><td>unknown</td></tr>
+</table>
+<h2><br></br>Chip Results Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Clusters</td>
+<td>Clusters (PF)</td>
+<td>Yield (kbases)</td>
+</tr>
+<tr><td>126151880</td>
+<td>95923456</td>
+<td>3549167</td>
+</tr>
+</table>
+<h2><br></br>Lane Parameter Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane</td>
+<td>Sample ID</td>
+<td>Sample Target</td>
+<td>Sample Type</td>
+<td>Length</td>
+<td>Filter</td>
+<td>Num Tiles</td>
+<td>Tiles</td>
+</tr>
+<tr>
+<td>1</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND_PAIR</td>
+<td>37, 37</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane1">Lane 1</a></td>
+</tr>
+<tr>
+<td>2</td>
+<td>unknown</td>
+<td>hg18</td>
+<td>ELAND_PAIR</td>
+<td>37, 37</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane2">Lane 2</a></td>
+</tr>
+<tr>
+<td>3</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND_PAIR</td>
+<td>37, 37</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane3">Lane 3</a></td>
+</tr>
+<tr>
+<td>4</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND_PAIR</td>
+<td>37, 37</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane4">Lane 4</a></td>
+</tr>
+<tr>
+<td>5</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND_PAIR</td>
+<td>37, 37</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane5">Lane 5</a></td>
+</tr>
+<tr>
+<td>6</td>
+<td>unknown</td>
+<td>hg18</td>
+<td>ELAND_PAIR</td>
+<td>37, 37</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane6">Lane 6</a></td>
+</tr>
+<tr>
+<td>7</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND_PAIR</td>
+<td>37, 37</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane7">Lane 7</a></td>
+</tr>
+<tr>
+<td>8</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND_PAIR</td>
+<td>37, 37</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane8">Lane 8</a></td>
+</tr>
+</table>
+<h2><br></br>Lane Results Summary : Read 1<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td colspan="2">Lane Info</td>
+<td colspan="8">Tile Mean +/- SD for Lane</td>
+</tr>
+<tr>
+<td>Lane </td>
+<td>Lane Yield (kbases) </td>
+<td>Clusters (raw)</td>
+<td>Clusters (PF) </td>
+<td>1st Cycle Int (PF) </td>
+<td>% intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Alignment Score (PF) </td>
+<td> % Error Rate (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>277083</td>
+<td>103646 +/- 4515</td>
+<td>74887 +/- 6080</td>
+<td>290 +/- 17</td>
+<td>99.34 +/- 3.52</td>
+<td>72.22 +/- 4.63</td>
+<td>89.19 +/- 0.59</td>
+<td>14.16 +/- 0.63</td>
+<td>0.94 +/- 0.17</td>
+</tr>
+<tr>
+<td>2</td>
+<td>289563</td>
+<td>106678 +/- 4652</td>
+<td>78260 +/- 2539</td>
+<td>294 +/- 16</td>
+<td>98.23 +/- 2.66</td>
+<td>73.43 +/- 2.52</td>
+<td>87.05 +/- 0.64</td>
+<td>16.81 +/- 0.55</td>
+<td>0.92 +/- 0.17</td>
+</tr>
+<tr>
+<td>3</td>
+<td>259242</td>
+<td>84583 +/- 5963</td>
+<td>70065 +/- 4194</td>
+<td>284 +/- 18</td>
+<td>99.82 +/- 3.05</td>
+<td>82.90 +/- 1.32</td>
+<td>89.49 +/- 0.20</td>
+<td>18.13 +/- 0.66</td>
+<td>0.81 +/- 0.13</td>
+</tr>
+<tr>
+<td>4</td>
+<td>210549</td>
+<td>68813 +/- 4782</td>
+<td>56905 +/- 4145</td>
+<td>300 +/- 29</td>
+<td>102.00 +/- 14.74</td>
+<td>82.91 +/- 5.89</td>
+<td>56.93 +/- 0.82</td>
+<td>25.85 +/- 2.30</td>
+<td>0.95 +/- 0.30</td>
+</tr>
+<tr>
+<td>5</td>
+<td>295555</td>
+<td>104854 +/- 4664</td>
+<td>79879 +/- 6270</td>
+<td>281 +/- 19</td>
+<td>98.26 +/- 5.85</td>
+<td>76.34 +/- 6.67</td>
+<td>57.71 +/- 0.30</td>
+<td>26.16 +/- 1.68</td>
+<td>0.97 +/- 0.19</td>
+</tr>
+<tr>
+<td>6</td>
+<td>140401</td>
+<td>43555 +/- 1632</td>
+<td>37946 +/- 2140</td>
+<td>233 +/- 16</td>
+<td>105.74 +/- 8.40</td>
+<td>87.14 +/- 3.87</td>
+<td>89.08 +/- 1.00</td>
+<td>33.53 +/- 2.18</td>
+<td>1.05 +/- 0.21</td>
+</tr>
+<tr>
+<td>7</td>
+<td>154217</td>
+<td>54265 +/- 1588</td>
+<td>41680 +/- 5319</td>
+<td>224 +/- 18</td>
+<td>111.33 +/- 8.90</td>
+<td>76.94 +/- 10.52</td>
+<td>84.50 +/- 1.41</td>
+<td>27.44 +/- 2.33</td>
+<td>1.32 +/- 0.25</td>
+</tr>
+<tr>
+<td>8</td>
+<td>147969</td>
+<td>64363 +/- 2697</td>
+<td>39991 +/- 6785</td>
+<td>248 +/- 43</td>
+<td>109.93 +/- 7.80</td>
+<td>62.45 +/- 12.05</td>
+<td>82.20 +/- 2.08</td>
+<td>24.63 +/- 2.53</td>
+<td>1.57 +/- 0.22</td>
+</tr>
+<tr><td colspan="13">Tile mean across chip</td></tr>
+<tr>
+<td>Av.</td>
+<td></td>
+<td>78844</td>
+<td>59952</td>
+<td>269</td>
+<td>103.08</td>
+<td>76.79</td>
+<td>79.52</td>
+<td>23.34</td>
+<td>1.06</td>
+</tr>
+</table>
+<h2><br></br>Lane Results Summary : Read 2<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td colspan="2">Lane Info</td>
+<td colspan="8">Tile Mean +/- SD for Lane</td>
+</tr>
+<tr>
+<td>Lane </td>
+<td>Lane Yield (kbases) </td>
+<td>Clusters (raw)</td>
+<td>Clusters (PF) </td>
+<td>1st Cycle Int (PF) </td>
+<td>% intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Alignment Score (PF) </td>
+<td> % Error Rate (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>277083</td>
+<td>103647 +/- 4516</td>
+<td>74887 +/- 6080</td>
+<td>277 +/- 17</td>
+<td>94.42 +/- 5.68</td>
+<td>72.22 +/- 4.63</td>
+<td>81.54 +/- 2.13</td>
+<td>42.70 +/- 5.49</td>
+<td>0.89 +/- 0.27</td>
+</tr>
+<tr>
+<td>2</td>
+<td>289563</td>
+<td>106679 +/- 4653</td>
+<td>78260 +/- 2539</td>
+<td>259 +/- 13</td>
+<td>93.57 +/- 2.55</td>
+<td>73.43 +/- 2.52</td>
+<td>82.05 +/- 0.37</td>
+<td>43.98 +/- 3.02</td>
+<td>0.76 +/- 0.15</td>
+</tr>
+<tr>
+<td>3</td>
+<td>259242</td>
+<td>84584 +/- 5964</td>
+<td>70065 +/- 4194</td>
+<td>252 +/- 12</td>
+<td>94.23 +/- 2.19</td>
+<td>82.90 +/- 1.32</td>
+<td>84.94 +/- 0.28</td>
+<td>51.76 +/- 2.29</td>
+<td>0.59 +/- 0.07</td>
+</tr>
+<tr>
+<td>4</td>
+<td>210549</td>
+<td>68814 +/- 4783</td>
+<td>56905 +/- 4145</td>
+<td>226 +/- 16</td>
+<td>96.82 +/- 7.12</td>
+<td>82.91 +/- 5.89</td>
+<td>56.01 +/- 0.99</td>
+<td>27.86 +/- 3.48</td>
+<td>0.95 +/- 0.33</td>
+</tr>
+<tr>
+<td>5</td>
+<td>295555</td>
+<td>104855 +/- 4665</td>
+<td>79879 +/- 6270</td>
+<td>200 +/- 24</td>
+<td>103.56 +/- 15.45</td>
+<td>76.34 +/- 6.67</td>
+<td>56.76 +/- 0.41</td>
+<td>25.68 +/- 2.06</td>
+<td>0.98 +/- 0.17</td>
+</tr>
+<tr>
+<td>6</td>
+<td>140401</td>
+<td>43556 +/- 1633</td>
+<td>37946 +/- 2140</td>
+<td>179 +/- 10</td>
+<td>100.82 +/- 5.47</td>
+<td>87.14 +/- 3.87</td>
+<td>88.64 +/- 1.42</td>
+<td>34.05 +/- 2.60</td>
+<td>0.98 +/- 0.22</td>
+</tr>
+<tr>
+<td>7</td>
+<td>154217</td>
+<td>54266 +/- 1589</td>
+<td>41680 +/- 5319</td>
+<td>184 +/- 5</td>
+<td>103.42 +/- 3.47</td>
+<td>76.94 +/- 10.52</td>
+<td>83.90 +/- 1.32</td>
+<td>27.60 +/- 2.07</td>
+<td>1.26 +/- 0.16</td>
+</tr>
+<tr>
+<td>8</td>
+<td>147969</td>
+<td>64364 +/- 2698</td>
+<td>39991 +/- 6785</td>
+<td>206 +/- 31</td>
+<td>99.48 +/- 3.23</td>
+<td>62.45 +/- 12.05</td>
+<td>79.81 +/- 3.35</td>
+<td>23.06 +/- 2.50</td>
+<td>1.56 +/- 0.23</td>
+</tr>
+<tr><td colspan="13">Tile mean across chip</td></tr>
+<tr>
+<td>Av.</td>
+<td></td>
+<td>78844</td>
+<td>59952</td>
+<td>223</td>
+<td>98.29</td>
+<td>76.79</td>
+<td>76.70</td>
+<td>34.59</td>
+<td>1.00</td>
+</tr>
+</table>
+<h2><br></br>Expanded Lane Summary : Read 1<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+
+<tr><td colspan="2">Lane Info</td>
+<td colspan="2">Phasing Info</td>
+<td colspan="2">Raw Data (tile mean)</td>
+<td colspan="7">Filtered Data (tile mean)</td></tr>
+<td>Lane </td>
+<td>Clusters (tile mean) (raw)</td>
+<td>% Phasing </td>
+<td>% Prephasing </td>
+<td>% Error Rate (raw) </td>
+<td> Equiv Perfect Clusters (raw) </td>
+<td>% retained </td>
+<td>Cycle 2-4 Av Int (PF) </td>
+<td>Cycle 2-10 Av % Loss (PF) </td>
+<td>Cycle 10-20 Av % Loss (PF) </td>
+<td>% Align (PF) </td>
+<td>% Error Rate (PF) </td>
+<td> Equiv Perfect Clusters (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>103646</td>
+<td>0.8600</td>
+<td>0.4900</td>
+<td>1.37</td>
+<td>74813</td>
+<td>72.22</td>
+<td>266 +/- 17</td>
+<td>-0.53 +/- 0.37</td>
+<td>-0.42 +/- 0.21</td>
+<td>89.19</td>
+<td>0.94</td>
+<td>64718</td>
+</tr>
+<tr>
+<td>2</td>
+<td>106678</td>
+<td>0.8600</td>
+<td>0.4900</td>
+<td>1.34</td>
+<td>74842</td>
+<td>73.43</td>
+<td>284 +/- 16</td>
+<td>0.08 +/- 0.43</td>
+<td>-0.17 +/- 0.34</td>
+<td>87.05</td>
+<td>0.92</td>
+<td>65850</td>
+</tr>
+<tr>
+<td>3</td>
+<td>84583</td>
+<td>0.8600</td>
+<td>0.4900</td>
+<td>1.09</td>
+<td>65493</td>
+<td>82.90</td>
+<td>286 +/- 14</td>
+<td>0.29 +/- 0.48</td>
+<td>-0.02 +/- 0.17</td>
+<td>89.49</td>
+<td>0.81</td>
+<td>60899</td>
+</tr>
+<tr>
+<td>4</td>
+<td>68813</td>
+<td>0.8600</td>
+<td>0.4900</td>
+<td>1.19</td>
+<td>33697</td>
+<td>82.91</td>
+<td>286 +/- 23</td>
+<td>-0.01 +/- 0.62</td>
+<td>-0.37 +/- 0.30</td>
+<td>56.93</td>
+<td>0.95</td>
+<td>31080</td>
+</tr>
+<tr>
+<td>5</td>
+<td>104854</td>
+<td>0.8600</td>
+<td>0.4900</td>
+<td>1.32</td>
+<td>50075</td>
+<td>76.34</td>
+<td>258 +/- 25</td>
+<td>-0.03 +/- 0.46</td>
+<td>-0.49 +/- 0.27</td>
+<td>57.71</td>
+<td>0.97</td>
+<td>44149</td>
+</tr>
+<tr>
+<td>6</td>
+<td>43555</td>
+<td>0.8600</td>
+<td>0.4900</td>
+<td>1.24</td>
+<td>34399</td>
+<td>87.14</td>
+<td>231 +/- 14</td>
+<td>-0.19 +/- 0.46</td>
+<td>-0.34 +/- 0.40</td>
+<td>89.08</td>
+<td>1.05</td>
+<td>32302</td>
+</tr>
+<tr>
+<td>7</td>
+<td>54265</td>
+<td>0.8600</td>
+<td>0.4900</td>
+<td>1.67</td>
+<td>38188</td>
+<td>76.94</td>
+<td>224 +/- 14</td>
+<td>-0.41 +/- 0.49</td>
+<td>-0.55 +/- 0.23</td>
+<td>84.50</td>
+<td>1.32</td>
+<td>33435</td>
+</tr>
+<tr>
+<td>8</td>
+<td>64363</td>
+<td>0.8600</td>
+<td>0.4900</td>
+<td>2.15</td>
+<td>38077</td>
+<td>62.45</td>
+<td>247 +/- 42</td>
+<td>-0.52 +/- 0.36</td>
+<td>-0.29 +/- 0.19</td>
+<td>82.20</td>
+<td>1.57</td>
+<td>31036</td>
+</tr>
+</table>
+<h2><br></br>Expanded Lane Summary : Read 2<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+
+<tr><td colspan="2">Lane Info</td>
+<td colspan="2">Phasing Info</td>
+<td colspan="2">Raw Data (tile mean)</td>
+<td colspan="7">Filtered Data (tile mean)</td></tr>
+<td>Lane </td>
+<td>Clusters (tile mean) (raw)</td>
+<td>% Phasing </td>
+<td>% Prephasing </td>
+<td>% Error Rate (raw) </td>
+<td> Equiv Perfect Clusters (raw) </td>
+<td>% retained </td>
+<td>Cycle 2-4 Av Int (PF) </td>
+<td>Cycle 2-10 Av % Loss (PF) </td>
+<td>Cycle 10-20 Av % Loss (PF) </td>
+<td>% Align (PF) </td>
+<td>% Error Rate (PF) </td>
+<td> Equiv Perfect Clusters (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>103646</td>
+<td>0.7900</td>
+<td>0.4600</td>
+<td>1.24</td>
+<td>68870</td>
+<td>72.22</td>
+<td>254 +/- 15</td>
+<td>-0.53 +/- 0.37</td>
+<td>-0.42 +/- 0.21</td>
+<td>81.54</td>
+<td>0.89</td>
+<td>59272</td>
+</tr>
+<tr>
+<td>2</td>
+<td>106678</td>
+<td>0.7900</td>
+<td>0.4600</td>
+<td>1.11</td>
+<td>71980</td>
+<td>73.43</td>
+<td>247 +/- 12</td>
+<td>0.08 +/- 0.43</td>
+<td>-0.17 +/- 0.34</td>
+<td>82.05</td>
+<td>0.76</td>
+<td>62240</td>
+</tr>
+<tr>
+<td>3</td>
+<td>84583</td>
+<td>0.7900</td>
+<td>0.4600</td>
+<td>0.80</td>
+<td>63500</td>
+<td>82.90</td>
+<td>243 +/- 8</td>
+<td>0.29 +/- 0.48</td>
+<td>-0.02 +/- 0.17</td>
+<td>84.94</td>
+<td>0.59</td>
+<td>58029</td>
+</tr>
+<tr>
+<td>4</td>
+<td>68813</td>
+<td>0.7900</td>
+<td>0.4600</td>
+<td>1.12</td>
+<td>33534</td>
+<td>82.91</td>
+<td>210 +/- 19</td>
+<td>-0.01 +/- 0.62</td>
+<td>-0.37 +/- 0.30</td>
+<td>56.01</td>
+<td>0.95</td>
+<td>30548</td>
+</tr>
+<tr>
+<td>5</td>
+<td>104854</td>
+<td>0.7900</td>
+<td>0.4600</td>
+<td>1.24</td>
+<td>49951</td>
+<td>76.34</td>
+<td>193 +/- 12</td>
+<td>-0.03 +/- 0.46</td>
+<td>-0.49 +/- 0.27</td>
+<td>56.76</td>
+<td>0.98</td>
+<td>43366</td>
+</tr>
+<tr>
+<td>6</td>
+<td>43555</td>
+<td>0.7900</td>
+<td>0.4600</td>
+<td>1.12</td>
+<td>34751</td>
+<td>87.14</td>
+<td>174 +/- 7</td>
+<td>-0.19 +/- 0.46</td>
+<td>-0.34 +/- 0.40</td>
+<td>88.64</td>
+<td>0.98</td>
+<td>32208</td>
+</tr>
+<tr>
+<td>7</td>
+<td>54265</td>
+<td>0.7900</td>
+<td>0.4600</td>
+<td>1.55</td>
+<td>38418</td>
+<td>76.94</td>
+<td>178 +/- 4</td>
+<td>-0.41 +/- 0.49</td>
+<td>-0.55 +/- 0.23</td>
+<td>83.90</td>
+<td>1.26</td>
+<td>33240</td>
+</tr>
+<tr>
+<td>8</td>
+<td>64363</td>
+<td>0.7900</td>
+<td>0.4600</td>
+<td>2.07</td>
+<td>36968</td>
+<td>62.45</td>
+<td>198 +/- 32</td>
+<td>-0.52 +/- 0.36</td>
+<td>-0.29 +/- 0.19</td>
+<td>79.81</td>
+<td>1.56</td>
+<td>30181</td>
+</tr>
+</table>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!--RUN_TIME Wed Jul 2 06:47:44 2008 -->
+<!--SOFTWARE_VERSION @(#) $Id: jerboa.pl,v 1.94 2007/12/04 09:59:07 rshaw Exp $-->
+<html>
+<body>
+
+<a name="Top"><h2><title>080627_HWI-EAS229_0036_3055HAXX Summary</title></h2></a>
+<h1>Summary Information For Experiment 080627_HWI-EAS229_0036_3055HAXX on Machine HWI-EAS229</h1>
+<h2><br></br>Chip Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr><td>Machine</td><td>HWI-EAS229</td></tr>
+<tr><td>Run Folder</td><td>080627_HWI-EAS229_0036_3055HAXX</td></tr>
+<tr><td>Chip ID</td><td>unknown</td></tr>
+</table>
+<h2><br></br>Chip Results Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Clusters</td>
+<td>Clusters (PF)</td>
+<td>Yield (kbases)</td>
+</tr>
+<tr><td>80933224</td>
+<td>43577803</td>
+<td>1133022</td>
+</tr>
+</table>
+<h2><br></br>Lane Parameter Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane</td>
+<td>Sample ID</td>
+<td>Sample Target</td>
+<td>Sample Type</td>
+<td>Length</td>
+<td>Filter</td>
+<td>Num Tiles</td>
+<td>Tiles</td>
+</tr>
+<tr>
+<td>1</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane1">Lane 1</a></td>
+</tr>
+<tr>
+<td>2</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane2">Lane 2</a></td>
+</tr>
+<tr>
+<td>3</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane3">Lane 3</a></td>
+</tr>
+<tr>
+<td>4</td>
+<td>unknown</td>
+<td>elegans170</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane4">Lane 4</a></td>
+</tr>
+<tr>
+<td>5</td>
+<td>unknown</td>
+<td>elegans170</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane5">Lane 5</a></td>
+</tr>
+<tr>
+<td>6</td>
+<td>unknown</td>
+<td>elegans170</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane6">Lane 6</a></td>
+</tr>
+<tr>
+<td>7</td>
+<td>unknown</td>
+<td>elegans170</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane7">Lane 7</a></td>
+</tr>
+<tr>
+<td>8</td>
+<td>unknown</td>
+<td>elegans170</td>
+<td>ELAND</td>
+<td>26</td>
+<td>'((CHASTITY>=0.6))'</td>
+<td>100</td>
+<td><a href="#Lane8">Lane 8</a></td>
+</tr>
+</table>
+<h2><br></br>Lane Results Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td colspan="2">Lane Info</td>
+<td colspan="8">Tile Mean +/- SD for Lane</td>
+</tr>
+<tr>
+<td>Lane </td>
+<td>Lane Yield (kbases) </td>
+<td>Clusters (raw)</td>
+<td>Clusters (PF) </td>
+<td>1st Cycle Int (PF) </td>
+<td>% intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Alignment Score (PF) </td>
+<td> % Error Rate (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>158046</td>
+<td>96483 +/- 9074</td>
+<td>60787 +/- 4240</td>
+<td>329 +/- 35</td>
+<td>101.88 +/- 6.03</td>
+<td>63.21 +/- 3.29</td>
+<td>70.33 +/- 0.24</td>
+<td>9054.08 +/- 59.16</td>
+<td>0.46 +/- 0.18</td>
+</tr>
+<tr>
+<td>2</td>
+<td>156564</td>
+<td>133738 +/- 7938</td>
+<td>60217 +/- 1926</td>
+<td>444 +/- 39</td>
+<td>92.62 +/- 7.58</td>
+<td>45.20 +/- 3.31</td>
+<td>51.98 +/- 0.74</td>
+<td>6692.04 +/- 92.49</td>
+<td>0.46 +/- 0.09</td>
+</tr>
+<tr>
+<td>3</td>
+<td>185818</td>
+<td>152142 +/- 10002</td>
+<td>71468 +/- 2827</td>
+<td>366 +/- 36</td>
+<td>91.53 +/- 8.66</td>
+<td>47.19 +/- 3.80</td>
+<td>82.24 +/- 0.44</td>
+<td>10598.68 +/- 64.13</td>
+<td>0.41 +/- 0.04</td>
+</tr>
+<tr>
+<td>4</td>
+<td>34953</td>
+<td>15784 +/- 2162</td>
+<td>13443 +/- 1728</td>
+<td>328 +/- 40</td>
+<td>97.53 +/- 9.87</td>
+<td>85.29 +/- 1.91</td>
+<td>80.02 +/- 0.53</td>
+<td>10368.82 +/- 71.08</td>
+<td>0.15 +/- 0.05</td>
+</tr>
+<tr>
+<td>5</td>
+<td>167936</td>
+<td>119735 +/- 8465</td>
+<td>64590 +/- 2529</td>
+<td>417 +/- 37</td>
+<td>88.69 +/- 14.79</td>
+<td>54.10 +/- 2.59</td>
+<td>76.95 +/- 0.32</td>
+<td>9936.47 +/- 65.75</td>
+<td>0.28 +/- 0.02</td>
+</tr>
+<tr>
+<td>6</td>
+<td>173463</td>
+<td>152177 +/- 8146</td>
+<td>66716 +/- 2493</td>
+<td>372 +/- 39</td>
+<td>87.06 +/- 9.86</td>
+<td>43.98 +/- 3.12</td>
+<td>78.80 +/- 0.43</td>
+<td>10162.28 +/- 49.65</td>
+<td>0.38 +/- 0.03</td>
+</tr>
+<tr>
+<td>7</td>
+<td>149287</td>
+<td>84649 +/- 7325</td>
+<td>57418 +/- 3617</td>
+<td>295 +/- 28</td>
+<td>89.40 +/- 8.23</td>
+<td>67.97 +/- 1.82</td>
+<td>33.38 +/- 0.25</td>
+<td>4247.92 +/- 32.37</td>
+<td>1.00 +/- 0.03</td>
+</tr>
+<tr>
+<td>8</td>
+<td>106953</td>
+<td>54622 +/- 4812</td>
+<td>41136 +/- 3309</td>
+<td>284 +/- 37</td>
+<td>90.21 +/- 9.10</td>
+<td>75.39 +/- 2.27</td>
+<td>48.33 +/- 0.29</td>
+<td>6169.21 +/- 169.50</td>
+<td>0.86 +/- 1.22</td>
+</tr>
+<tr><td colspan="13">Tile mean across chip</td></tr>
+<tr>
+<td>Av.</td>
+<td></td>
+<td>101166</td>
+<td>54472</td>
+<td>354</td>
+<td>92.36</td>
+<td>60.29</td>
+<td>65.25</td>
+<td>8403.69</td>
+<td>0.50</td>
+</tr>
+</table>
+<h2><br></br>Expanded Lane Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+
+<tr><td colspan="2">Lane Info</td>
+<td colspan="2">Phasing Info</td>
+<td colspan="2">Raw Data (tile mean)</td>
+<td colspan="7">Filtered Data (tile mean)</td></tr>
+<td>Lane </td>
+<td>Clusters (tile mean) (raw)</td>
+<td>% Phasing </td>
+<td>% Prephasing </td>
+<td>% Error Rate (raw) </td>
+<td> Equiv Perfect Clusters (raw) </td>
+<td>% retained </td>
+<td>Cycle 2-4 Av Int (PF) </td>
+<td>Cycle 2-10 Av % Loss (PF) </td>
+<td>Cycle 10-20 Av % Loss (PF) </td>
+<td>% Align (PF) </td>
+<td>% Error Rate (PF) </td>
+<td> Equiv Perfect Clusters (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>96483</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.00</td>
+<td>49676</td>
+<td>63.21</td>
+<td>317 +/- 32</td>
+<td>0.13 +/- 0.44</td>
+<td>-1.14 +/- 0.34</td>
+<td>70.33</td>
+<td>0.46</td>
+<td>41758</td>
+</tr>
+<tr>
+<td>2</td>
+<td>133738</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.22</td>
+<td>40467</td>
+<td>45.20</td>
+<td>415 +/- 33</td>
+<td>0.29 +/- 0.40</td>
+<td>-0.79 +/- 0.35</td>
+<td>51.98</td>
+<td>0.46</td>
+<td>30615</td>
+</tr>
+<tr>
+<td>3</td>
+<td>152142</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.30</td>
+<td>78588</td>
+<td>47.19</td>
+<td>344 +/- 26</td>
+<td>0.68 +/- 0.51</td>
+<td>-0.77 +/- 0.42</td>
+<td>82.24</td>
+<td>0.41</td>
+<td>57552</td>
+</tr>
+<tr>
+<td>4</td>
+<td>15784</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>0.29</td>
+<td>11095</td>
+<td>85.29</td>
+<td>306 +/- 34</td>
+<td>0.20 +/- 0.69</td>
+<td>-1.28 +/- 0.66</td>
+<td>80.02</td>
+<td>0.15</td>
+<td>10671</td>
+</tr>
+<tr>
+<td>5</td>
+<td>119735</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>0.85</td>
+<td>60335</td>
+<td>54.10</td>
+<td>380 +/- 32</td>
+<td>0.34 +/- 0.49</td>
+<td>-1.55 +/- 4.69</td>
+<td>76.95</td>
+<td>0.28</td>
+<td>49015</td>
+</tr>
+<tr>
+<td>6</td>
+<td>152177</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.21</td>
+<td>70905</td>
+<td>43.98</td>
+<td>333 +/- 27</td>
+<td>0.57 +/- 0.50</td>
+<td>-0.91 +/- 0.39</td>
+<td>78.80</td>
+<td>0.38</td>
+<td>51663</td>
+</tr>
+<tr>
+<td>7</td>
+<td>84649</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.38</td>
+<td>21069</td>
+<td>67.97</td>
+<td>272 +/- 20</td>
+<td>1.15 +/- 0.52</td>
+<td>-0.84 +/- 0.58</td>
+<td>33.38</td>
+<td>1.00</td>
+<td>18265</td>
+</tr>
+<tr>
+<td>8</td>
+<td>54622</td>
+<td>0.7700</td>
+<td>0.3100</td>
+<td>1.17</td>
+<td>21335</td>
+<td>75.39</td>
+<td>262 +/- 31</td>
+<td>1.10 +/- 0.59</td>
+<td>-1.01 +/- 0.47</td>
+<td>48.33</td>
+<td>0.86</td>
+<td>19104</td>
+</tr>
+</table>
+<b><br></br>IVC Plots</b>
+<p> <a href='IVC.htm' target="_blank"> IVC.htm
+ </a></p>
+<b><br></br>All Intensity Plots</b>
+<p> <a href='All.htm' target="_blank"> All.htm
+ </a></p>
+<b><br></br>Error graphs: </b>
+<p> <a href='Error.htm' target="_blank"> Error.htm
+ </a></p>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane1"><h2><br></br>Lane 1<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>0001</td>
+<td>114972</td>
+<td>326.48</td>
+<td>94.39</td>
+<td>57.44</td>
+<td>70.2</td>
+<td>9038.6</td>
+<td>0.44</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane2"><h2><br></br>Lane 2<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>2</td>
+<td>0001</td>
+<td>147793</td>
+<td>448.12</td>
+<td>83.68</td>
+<td>38.57</td>
+<td>53.7</td>
+<td>6905.4</td>
+<td>0.54</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane3"><h2><br></br>Lane 3<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>3</td>
+<td>0001</td>
+<td>167904</td>
+<td>374.05</td>
+<td>86.91</td>
+<td>40.36</td>
+<td>81.3</td>
+<td>10465.0</td>
+<td>0.47</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane4"><h2><br></br>Lane 4<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>4</td>
+<td>0001</td>
+<td>20308</td>
+<td>276.85</td>
+<td>92.87</td>
+<td>84.26</td>
+<td>80.4</td>
+<td>10413.8</td>
+<td>0.16</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane5"><h2><br></br>Lane 5<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane6"><h2><br></br>Lane 6<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>6</td>
+<td>0001</td>
+<td>166844</td>
+<td>348.12</td>
+<td>77.59</td>
+<td>38.13</td>
+<td>79.7</td>
+<td>10264.4</td>
+<td>0.44</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane7"><h2><br></br>Lane 7<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>7</td>
+<td>0001</td>
+<td>98913</td>
+<td>269.90</td>
+<td>86.66</td>
+<td>64.55</td>
+<td>33.2</td>
+<td>4217.5</td>
+<td>1.02</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+<a name="Lane8"><h2><br></br>Lane 8<br></br></h2></a>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane </td>
+<td>Tile </td>
+<td>Clusters (raw)</td>
+<td>Av 1st Cycle Int (PF) </td>
+<td>Av % intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Av Alignment Score (PF) </td>
+<td>% Error Rate (PF) </td>
+</tr>
+<tr>
+<td>8</td>
+<td>0001</td>
+<td>64972</td>
+<td>243.60</td>
+<td>89.40</td>
+<td>73.17</td>
+<td>48.3</td>
+<td>6182.8</td>
+<td>0.71</td>
+</tr>
+</table>
+<td><a href="#Top">Back to top</a></td>
+</body>
+</html>
--- /dev/null
+<!--RUN_TIME Tue Oct 28 09:45:50 2008 -->
+<!--SOFTWARE_VERSION @(#) $Id: jerboa.pl,v 1.10 2008/07/23 15:18:30 mzerara Exp $-->
+<html>
+<body>
+
+<a name="Top"><h2><title>081017_HWI-EAS229_0062_30J55AAXX Summary</title></h2></a>
+<h1>Summary Information For Experiment 081017_HWI-EAS229_0062_30J55AAXX on Machine HWI-EAS229</h1>
+<h2><br></br>Chip Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr><td>Machine</td><td>HWI-EAS229</td></tr>
+<tr><td>Run Folder</td><td>081017_HWI-EAS229_0062_30J55AAXX</td></tr>
+<tr><td>Chip ID</td><td>unknown</td></tr>
+</table>
+<h2><br></br>Chip Results Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Clusters</td>
+<td>Clusters (PF)</td>
+<td>Yield (kbases)</td>
+</tr>
+<tr><td>162491175</td>
+<td>99622159</td>
+<td>3686019</td>
+</tr>
+</table>
+<h2><br></br>Lane Parameter Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td>Lane</td>
+<td>Sample ID</td>
+<td>Sample Target</td>
+<td>Sample Type</td>
+<td>Length</td>
+<td>Filter</td>
+<td>Chast. Thresh.</td>
+<td>Num Tiles</td>
+<td>Tiles</td>
+</tr>
+<tr>
+<td>1</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1))'</td>
+<td>0.6</td>
+<td>100</td>
+<td><a href="#Lane1">Lane 1</a></td>
+</tr>
+<tr>
+<td>2</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1))'</td>
+<td>0.6</td>
+<td>100</td>
+<td><a href="#Lane2">Lane 2</a></td>
+</tr>
+<tr>
+<td>3</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1))'</td>
+<td>0.6</td>
+<td>100</td>
+<td><a href="#Lane3">Lane 3</a></td>
+</tr>
+<tr>
+<td>4</td>
+<td>unknown</td>
+<td>hg18</td>
+<td>ELAND</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1))'</td>
+<td>0.6</td>
+<td>100</td>
+<td><a href="#Lane4">Lane 4</a></td>
+</tr>
+<tr>
+<td>5</td>
+<td>unknown</td>
+<td>hg18</td>
+<td>ELAND</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1))'</td>
+<td>0.6</td>
+<td>100</td>
+<td><a href="#Lane5">Lane 5</a></td>
+</tr>
+<tr>
+<td>6</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1))'</td>
+<td>0.6</td>
+<td>100</td>
+<td><a href="#Lane6">Lane 6</a></td>
+</tr>
+<tr>
+<td>7</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1))'</td>
+<td>0.6</td>
+<td>100</td>
+<td><a href="#Lane7">Lane 7</a></td>
+</tr>
+<tr>
+<td>8</td>
+<td>unknown</td>
+<td>mm9</td>
+<td>ELAND</td>
+<td>37</td>
+<td>'((FAILED_CHASTITY<=1))'</td>
+<td>0.6</td>
+<td>100</td>
+<td><a href="#Lane8">Lane 8</a></td>
+</tr>
+</table>
+<h2><br></br>Lane Results Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+<td colspan="2">Lane Info</td>
+<td colspan="8">Tile Mean +/- SD for Lane</td>
+</tr>
+<tr>
+<td>Lane </td>
+<td>Lane Yield (kbases) </td>
+<td>Clusters (raw)</td>
+<td>Clusters (PF) </td>
+<td>1st Cycle Int (PF) </td>
+<td>% intensity after 20 cycles (PF) </td>
+<td>% PF Clusters </td>
+<td>% Align (PF) </td>
+<td>Alignment Score (PF) </td>
+<td> % Error Rate (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>435340</td>
+<td>190220 +/- 15118</td>
+<td>117659 +/- 8144</td>
+<td>273 +/- 16</td>
+<td>80.02 +/- 2.52</td>
+<td>62.15 +/- 5.54</td>
+<td>77.18 +/- 0.22</td>
+<td>13447.28 +/- 43.35</td>
+<td>2.78 +/- 0.13</td>
+</tr>
+<tr>
+<td>2</td>
+<td>462364</td>
+<td>190560 +/- 14399</td>
+<td>124963 +/- 5687</td>
+<td>271 +/- 16</td>
+<td>75.73 +/- 2.46</td>
+<td>65.83 +/- 4.12</td>
+<td>70.06 +/- 0.39</td>
+<td>12082.95 +/- 64.81</td>
+<td>3.22 +/- 0.09</td>
+</tr>
+<tr>
+<td>3</td>
+<td>468929</td>
+<td>187597 +/- 12369</td>
+<td>126737 +/- 5549</td>
+<td>274 +/- 16</td>
+<td>72.61 +/- 2.67</td>
+<td>67.69 +/- 2.72</td>
+<td>74.03 +/- 0.22</td>
+<td>12470.18 +/- 50.02</td>
+<td>4.27 +/- 0.08</td>
+</tr>
+<tr>
+<td>4</td>
+<td>491642</td>
+<td>204142 +/- 16877</td>
+<td>132876 +/- 4023</td>
+<td>253 +/- 16</td>
+<td>80.43 +/- 3.10</td>
+<td>65.39 +/- 3.84</td>
+<td>72.95 +/- 0.15</td>
+<td>13273.80 +/- 39.75</td>
+<td>0.78 +/- 0.10</td>
+</tr>
+<tr>
+<td>5</td>
+<td>433033</td>
+<td>247308 +/- 11600</td>
+<td>117036 +/- 4489</td>
+<td>273 +/- 11</td>
+<td>68.60 +/- 2.40</td>
+<td>47.48 +/- 3.63</td>
+<td>66.91 +/- 0.54</td>
+<td>11700.08 +/- 66.33</td>
+<td>2.62 +/- 0.13</td>
+</tr>
+<tr>
+<td>6</td>
+<td>483012</td>
+<td>204298 +/- 15640</td>
+<td>130543 +/- 6972</td>
+<td>254 +/- 11</td>
+<td>81.35 +/- 1.96</td>
+<td>64.14 +/- 4.40</td>
+<td>77.28 +/- 0.11</td>
+<td>14084.01 +/- 23.09</td>
+<td>0.71 +/- 0.03</td>
+</tr>
+<tr>
+<td>7</td>
+<td>474325</td>
+<td>202707 +/- 15404</td>
+<td>128196 +/- 9745</td>
+<td>255 +/- 13</td>
+<td>79.95 +/- 2.08</td>
+<td>63.48 +/- 5.63</td>
+<td>75.78 +/- 0.18</td>
+<td>13758.74 +/- 60.86</td>
+<td>0.88 +/- 0.12</td>
+</tr>
+<tr>
+<td>8</td>
+<td>437372</td>
+<td>198075 +/- 14702</td>
+<td>118208 +/- 14798</td>
+<td>259 +/- 14</td>
+<td>81.80 +/- 2.53</td>
+<td>59.85 +/- 7.67</td>
+<td>74.55 +/- 0.36</td>
+<td>13586.07 +/- 103.97</td>
+<td>0.71 +/- 0.15</td>
+</tr>
+<tr><td colspan="13">Tile mean across chip</td></tr>
+<tr>
+<td>Av.</td>
+<td></td>
+<td>203113</td>
+<td>124527</td>
+<td>264</td>
+<td>77.56</td>
+<td>62.00</td>
+<td>73.59</td>
+<td>13050.39</td>
+<td>2.00</td>
+</tr>
+</table>
+<h2><br></br>Expanded Lane Summary<br></br></h2>
+<table border="1" cellpadding="5">
+<tr>
+
+<tr><td colspan="2">Lane Info</td>
+<td colspan="2">Phasing Info</td>
+<td colspan="2">Raw Data (tile mean)</td>
+<td colspan="7">Filtered Data (tile mean)</td></tr>
+<td>Lane </td>
+<td>Clusters (tile mean) (raw)</td>
+<td>% Phasing </td>
+<td>% Prephasing </td>
+<td>% Error Rate (raw) </td>
+<td> Equiv Perfect Clusters (raw) </td>
+<td>% retained </td>
+<td>Cycle 2-4 Av Int (PF) </td>
+<td>Cycle 2-10 Av % Loss (PF) </td>
+<td>Cycle 10-20 Av % Loss (PF) </td>
+<td>% Align (PF) </td>
+<td>% Error Rate (PF) </td>
+<td> Equiv Perfect Clusters (PF) </td>
+</tr>
+<tr>
+<td>1</td>
+<td>190220</td>
+<td>0.6800</td>
+<td>0.2800</td>
+<td>3.17</td>
+<td>107262</td>
+<td>62.15</td>
+<td>241 +/- 13</td>
+<td>0.56 +/- 0.22</td>
+<td>0.29 +/- 0.14</td>
+<td>77.18</td>
+<td>2.78</td>
+<td>86184</td>
+</tr>
+<tr>
+<td>2</td>
+<td>190560</td>
+<td>0.6800</td>
+<td>0.2800</td>
+<td>3.53</td>
+<td>98678</td>
+<td>65.83</td>
+<td>238 +/- 14</td>
+<td>0.78 +/- 0.15</td>
+<td>0.53 +/- 0.15</td>
+<td>70.06</td>
+<td>3.22</td>
+<td>83090</td>
+</tr>
+<tr>
+<td>3</td>
+<td>187597</td>
+<td>0.6800</td>
+<td>0.2800</td>
+<td>4.44</td>
+<td>104008</td>
+<td>67.69</td>
+<td>233 +/- 14</td>
+<td>0.56 +/- 0.17</td>
+<td>0.59 +/- 0.26</td>
+<td>74.03</td>
+<td>4.27</td>
+<td>89278</td>
+</tr>
+<tr>
+<td>4</td>
+<td>204142</td>
+<td>0.6800</td>
+<td>0.2800</td>
+<td>1.38</td>
+<td>115765</td>
+<td>65.39</td>
+<td>239 +/- 14</td>
+<td>1.28 +/- 0.21</td>
+<td>0.77 +/- 0.21</td>
+<td>72.95</td>
+<td>0.78</td>
+<td>93475</td>
+</tr>
+<tr>
+<td>5</td>
+<td>247308</td>
+<td>0.6800</td>
+<td>0.2800</td>
+<td>3.40</td>
+<td>103006</td>
+<td>47.48</td>
+<td>242 +/- 10</td>
+<td>1.61 +/- 0.39</td>
+<td>1.21 +/- 0.21</td>
+<td>66.91</td>
+<td>2.62</td>
+<td>73768</td>
+</tr>
+<tr>
+<td>6</td>
+<td>204298</td>
+<td>0.6800</td>
+<td>0.2800</td>
+<td>1.33</td>
+<td>122233</td>
+<td>64.14</td>
+<td>242 +/- 12</td>
+<td>1.30 +/- 0.11</td>
+<td>0.73 +/- 0.22</td>
+<td>77.28</td>
+<td>0.71</td>
+<td>97646</td>
+</tr>
+<tr>
+<td>7</td>
+<td>202707</td>
+<td>0.6800</td>
+<td>0.2800</td>
+<td>1.51</td>
+<td>117513</td>
+<td>63.48</td>
+<td>238 +/- 13</td>
+<td>1.27 +/- 0.38</td>
+<td>0.66 +/- 0.22</td>
+<td>75.78</td>
+<td>0.88</td>
+<td>93659</td>
+</tr>
+<tr>
+<td>8</td>
+<td>198075</td>
+<td>0.6800</td>
+<td>0.2800</td>
+<td>1.41</td>
+<td>111115</td>
+<td>59.85</td>
+<td>244 +/- 12</td>
+<td>1.19 +/- 0.16</td>
+<td>0.65 +/- 0.29</td>
+<td>74.55</td>
+<td>0.71</td>
+<td>85327</td>
+</tr>
+</table>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0"?>
+<BaseCallAnalysis>
+ <Run Name="Bustard1.3.2_25-03-2009_diane">
+ <BaseCallParameters>
+ <ChastityThreshold>0.600000</ChastityThreshold>
+ <Matrix Path="/home/diane/gec/090206_HWI-EAS229_0090_311AFAAXX/Data/C1-152_Firecrest1.9.5_14-02-2009_diane/Matrix/s_4_matrix.txt">
+ <AutoFlag>0</AutoFlag>
+ <AutoLane>0</AutoLane>
+ <Cycle>2</Cycle>
+ <CycleOffset>1</CycleOffset>
+ <FirstCycle>1</FirstCycle>
+ <LastCycle>37</LastCycle>
+ <Read>1</Read>
+ </Matrix>
+ <MatrixElements Path="/home/diane/gec/090206_HWI-EAS229_0090_311AFAAXX/Data/C1-152_Firecrest1.9.5_14-02-2009_diane/Matrix/s_4_matrix.txt">
+ <Base>A</Base>
+ <Base>C</Base>
+ <Base>G</Base>
+ <Base>T</Base>
+ <Element>1.270000</Element>
+ <Element>0.210000</Element>
+ <Element>-0.020000</Element>
+ <Element>-0.030000</Element>
+ <Element>0.570000</Element>
+ <Element>0.580000</Element>
+ <Element>-0.010000</Element>
+ <Element>-0.010000</Element>
+ <Element>-0.030000</Element>
+ <Element>-0.040000</Element>
+ <Element>1.510000</Element>
+ <Element>-0.020000</Element>
+ <Element>-0.020000</Element>
+ <Element>-0.020000</Element>
+ <Element>0.800000</Element>
+ <Element>1.070000</Element>
+ </MatrixElements>
+ <Phasing Path="">
+ <AutoFlag>1</AutoFlag>
+ <AutoLane>3</AutoLane>
+ <Cycle>1</Cycle>
+ <CycleOffset>0</CycleOffset>
+ <FirstCycle>1</FirstCycle>
+ <LastCycle>37</LastCycle>
+ <Read>1</Read>
+ </Phasing>
+ <PhasingRestarts />
+ <PrbCompression>none</PrbCompression>
+ <PureBases>25</PureBases>
+ <QhgCompression>none</QhgCompression>
+ <SeqCompression>none</SeqCompression>
+ <Sig2Compression>gzip</Sig2Compression>
+ <SmtFilter>failed-chastity</SmtFilter>
+ <SmtRelation>le</SmtRelation>
+ <SmtThreshold>1.000000</SmtThreshold>
+ </BaseCallParameters>
+ <Cycles First="1" Last="37" Number="37" />
+ <Input Path="C1-37_Firecrest1.3.2_25-03-2009_diane" />
+ <RunParameters>
+ <AutoCycleFlag>1</AutoCycleFlag>
+ <BasecallFlag>1</BasecallFlag>
+ <Compression>gzip</Compression>
+ <CompressionSuffix>.gz</CompressionSuffix>
+ <Deblocked>0</Deblocked>
+ <DebugFlag>0</DebugFlag>
+ <FirstRunOnlyFlag>0</FirstRunOnlyFlag>
+ <ImagingReads Index="1">
+ <FirstCycle>1</FirstCycle>
+ <LastCycle>37</LastCycle>
+ <RunFolder>/zfs1/wold-lab/diane/sequencer/090307_HWI-EAS229_0097_30U0BAAXX</RunFolder>
+ </ImagingReads>
+ <Instrument>HWI-EAS229</Instrument>
+ <IterativeMatrixFlag>0</IterativeMatrixFlag>
+ <MakeFlag>1</MakeFlag>
+ <MaxCycle>-1</MaxCycle>
+ <MinCycle>-1</MinCycle>
+ <Prb></Prb>
+ <Reads Index="1">
+ <FirstCycle>1</FirstCycle>
+ <LastCycle>37</LastCycle>
+ <RunFolder>/zfs1/wold-lab/diane/sequencer/090307_HWI-EAS229_0097_30U0BAAXX</RunFolder>
+ </Reads>
+ <RunFolder>/zfs1/wold-lab/diane/sequencer/090307_HWI-EAS229_0097_30U0BAAXX</RunFolder>
+ <RunFolderDate>090307</RunFolderDate>
+ <RunFolderId>97</RunFolderId>
+ <SelectedFolders />
+ <SelectedTiles />
+ <Sig2></Sig2>
+ </RunParameters>
+ <Software Name="Bustard" Version="1.3.2" />
+ <TileSelection>
+ <Lane Index="1">
+ <Sample>s</Sample>
+ <TileRange Max="100" Min="1" />
+ </Lane>
+ <Lane Index="2">
+ <Sample>s</Sample>
+ <TileRange Max="100" Min="1" />
+ </Lane>
+ <Lane Index="3">
+ <Sample>s</Sample>
+ <TileRange Max="100" Min="1" />
+ </Lane>
+ <Lane Index="4">
+ <Sample>s</Sample>
+ <TileRange Max="100" Min="1" />
+ </Lane>
+ <Lane Index="5">
+ <Sample>s</Sample>
+ <TileRange Max="100" Min="1" />
+ </Lane>
+ <Lane Index="6">
+ <Sample>s</Sample>
+ <TileRange Max="100" Min="1" />
+ </Lane>
+ <Lane Index="7">
+ <Sample>s</Sample>
+ <TileRange Max="100" Min="1" />
+ </Lane>
+ <Lane Index="8">
+ <Sample>s</Sample>
+ <TileRange Max="100" Min="1" />
+ </Lane>
+ </TileSelection>
+ <Time>
+ <Start>25-03-09 15:23:10 PDT</Start>
+ </Time>
+ <User Name="diane" />
+ </Run>
+</BaseCallAnalysis>
--- /dev/null
+<RunParameters>
+<ChipWideRunParameters>
+ <ANALYSIS>default</ANALYSIS>
+ <BAD_LANES></BAD_LANES>
+ <BAD_TILES></BAD_TILES>
+ <CONTAM_DIR></CONTAM_DIR>
+ <CONTAM_FILE></CONTAM_FILE>
+ <ELAND_GENOME>Need_to_specify_ELAND_genome_directory</ELAND_GENOME>
+ <ELAND_MULTIPLE_INSTANCES>8</ELAND_MULTIPLE_INSTANCES>
+ <ELAND_REPEAT></ELAND_REPEAT>
+ <EMAIL_DOMAIN>domain.com</EMAIL_DOMAIN>
+ <EMAIL_LIST>diane</EMAIL_LIST>
+ <EMAIL_SERVER>localhost:25</EMAIL_SERVER>
+ <EXPT_DIR>/home/diane/gec/080416_HWI-EAS229_0024_207BTAAXX/Data/C1-33_Firecrest1.8.28_19-04-2008_diane/Bustard1.8.28_19-04-2008_diane</EXPT_DIR>
+ <EXPT_DIR_ROOT>/home/diane/gec</EXPT_DIR_ROOT>
+ <FORCE>1</FORCE>
+ <GENOME_DIR>/home/diane/proj/SolexaPipeline-0.2.2.6/Goat/../Gerald/../../Genomes</GENOME_DIR>
+ <GENOME_FILE>Need_to_specify_genome_file_name</GENOME_FILE>
+ <HAMSTER_FLAG>genome</HAMSTER_FLAG>
+ <OUT_DIR>/home/diane/gec/080416_HWI-EAS229_0024_207BTAAXX/Data/C1-33_Firecrest1.8.28_19-04-2008_diane/Bustard1.8.28_19-04-2008_diane/GERALD_19-04-2008_diane</OUT_DIR>
+ <POST_RUN_COMMAND></POST_RUN_COMMAND>
+ <PRB_FILE_SUFFIX>_prb.txt</PRB_FILE_SUFFIX>
+ <PURE_BASES>12</PURE_BASES>
+ <QF_PARAMS>'((CHASTITY>=0.6))'</QF_PARAMS>
+ <QHG_FILE_SUFFIX>_qhg.txt</QHG_FILE_SUFFIX>
+ <QUALITY_FORMAT>--symbolic</QUALITY_FORMAT>
+ <READ_LENGTH>32</READ_LENGTH>
+ <SEQUENCE_FORMAT>--scarf</SEQUENCE_FORMAT>
+ <SEQ_FILE_SUFFIX>_seq.txt</SEQ_FILE_SUFFIX>
+ <SIG_FILE_SUFFIX_DEPHASED>_sig2.txt</SIG_FILE_SUFFIX_DEPHASED>
+ <SIG_FILE_SUFFIX_NOT_DEPHASED>_sig.txt</SIG_FILE_SUFFIX_NOT_DEPHASED>
+ <SOFTWARE_VERSION>@(#) Id: GERALD.pl,v 1.68.2.2 2007/06/13 11:08:49 km Exp</SOFTWARE_VERSION>
+ <TILE_REGEX>s_[1-8]_[0-9][0-9][0-9][0-9]</TILE_REGEX>
+ <TILE_ROOT>s</TILE_ROOT>
+ <TIME_STAMP>Sat Apr 19 19:08:30 2008</TIME_STAMP>
+ <TOOLS_DIR>/home/diane/proj/SolexaPipeline-0.2.2.6/Goat/../Gerald</TOOLS_DIR>
+ <USE_BASES>all</USE_BASES>
+ <WEB_DIR_ROOT>http://host.domain.com/yourshare/</WEB_DIR_ROOT>
+</ChipWideRunParameters>
+<LaneSpecificRunParameters>
+ <ANALYSIS>
+ <s_1>eland</s_1>
+ <s_2>eland</s_2>
+ <s_3>eland</s_3>
+ <s_4>eland</s_4>
+ <s_5>eland</s_5>
+ <s_6>eland</s_6>
+ <s_7>eland</s_7>
+ <s_8>eland</s_8>
+ </ANALYSIS>
+ <ELAND_GENOME>
+ <s_1>/g/dm3</s_1>
+ <s_2>/g/equcab1</s_2>
+ <s_3>/g/equcab1</s_3>
+ <s_4>/g/canfam2</s_4>
+ <s_5>/g/hg18</s_5>
+ <s_6>/g/hg18</s_6>
+ <s_7>/g/hg18</s_7>
+ <s_8>/g/hg18</s_8>
+ </ELAND_GENOME>
+ <READ_LENGTH>
+ <s_1>32</s_1>
+ <s_2>32</s_2>
+ <s_3>32</s_3>
+ <s_4>32</s_4>
+ <s_5>32</s_5>
+ <s_6>32</s_6>
+ <s_7>32</s_7>
+ <s_8>32</s_8>
+ </READ_LENGTH>
+ <USE_BASES>
+ <s_1>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_1>
+ <s_2>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_2>
+ <s_3>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_3>
+ <s_4>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_4>
+ <s_5>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_5>
+ <s_6>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_6>
+ <s_7>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_7>
+ <s_8>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_8>
+ </USE_BASES>
+</LaneSpecificRunParameters>
+</RunParameters>
--- /dev/null
+<RunParameters>
+<ChipWideRunParameters>
+ <ANALYSIS>none</ANALYSIS>
+ <BAD_LANES></BAD_LANES>
+ <BAD_LANES></BAD_LANES>
+ <BAD_LANES></BAD_LANES>
+ <BAD_TILES></BAD_TILES>
+ <BIN_DIR>/home/diane/proj/GAPipeline-1.0/Goat/../Gerald/../bin</BIN_DIR>
+ <CMDPREFIX></CMDPREFIX>
+ <CONTAM_DIR></CONTAM_DIR>
+ <CONTAM_FILE></CONTAM_FILE>
+ <ELAND_GENOME>Need_to_specify_ELAND_genome_directory</ELAND_GENOME>
+ <ELAND_MAX_MATCHES></ELAND_MAX_MATCHES>
+ <ELAND_MULTIPLE_INSTANCES>8</ELAND_MULTIPLE_INSTANCES>
+ <ELAND_REPEAT></ELAND_REPEAT>
+ <ELAND_SEED_LENGTH></ELAND_SEED_LENGTH>
+ <EMAIL_DOMAIN>domain.com</EMAIL_DOMAIN>
+ <EMAIL_LIST>diane</EMAIL_LIST>
+ <EMAIL_SERVER>localhost:25</EMAIL_SERVER>
+ <EXPT_DIR>/home/diane/gec/090220_HWI-EAS229_0093_30VR0AAXX/Data/C1-37_Firecrest1.9.5_22-02-2009_diane/Bustard1.9.5_22-02-2009_diane</EXPT_DIR>
+ <EXPT_DIR_ROOT>/home/diane/gec</EXPT_DIR_ROOT>
+ <FORCE>1</FORCE>
+ <GENOME_DIR>/home/diane/proj/GAPipeline-1.0/Goat/../Gerald/../../Genomes</GENOME_DIR>
+ <GENOME_FILE>Need_to_specify_genome_file_name</GENOME_FILE>
+ <GROUP_LANES></GROUP_LANES>
+ <HAMSTER_FLAG>genome</HAMSTER_FLAG>
+ <HAMSTER_FLAG>genome</HAMSTER_FLAG>
+ <HAMSTER_FLAG>genome</HAMSTER_FLAG>
+ <INDEX_BASES></INDEX_BASES>
+ <NUM_LEADING_DIRS_TO_STRIP>2</NUM_LEADING_DIRS_TO_STRIP>
+ <ORIG_READ_LENGTHS>37</ORIG_READ_LENGTHS>
+ <OUT_DIR>/home/diane/gec/090220_HWI-EAS229_0093_30VR0AAXX/Data/C1-37_Firecrest1.9.5_22-02-2009_diane/Bustard1.9.5_22-02-2009_diane/GERALD_22-02-2009_diane</OUT_DIR>
+ <PAIR_PARAMS></PAIR_PARAMS>
+ <POST_RUN_COMMAND></POST_RUN_COMMAND>
+ <PRB_FILE_SUFFIX>_prb.txt</PRB_FILE_SUFFIX>
+ <PURE_BASES>12</PURE_BASES>
+ <QCAL_SOURCE></QCAL_SOURCE>
+ <QCAL_SOURCE1></QCAL_SOURCE1>
+ <QCAL_SOURCE2></QCAL_SOURCE2>
+ <QF_PARAMS>'((CHASTITY>=0.6))'</QF_PARAMS>
+ <QHG_FILE_SUFFIX>_qhg.txt</QHG_FILE_SUFFIX>
+ <QTABLE_PATH></QTABLE_PATH>
+ <QTABLE_PATH1></QTABLE_PATH1>
+ <QTABLE_PATH2></QTABLE_PATH2>
+ <QTABLE_REQUIRED>0</QTABLE_REQUIRED>
+ <QTABLE_REQUIRED1>0</QTABLE_REQUIRED1>
+ <QTABLE_REQUIRED2>0</QTABLE_REQUIRED2>
+ <QUALITY_FORMAT>--symbolic</QUALITY_FORMAT>
+ <READ_LENGTH>37</READ_LENGTH>
+ <READ_LENGTH1>37</READ_LENGTH1>
+ <READ_LENGTH2>0</READ_LENGTH2>
+ <SEQUENCE_FORMAT>--scarf</SEQUENCE_FORMAT>
+ <SEQ_FILE_SUFFIX>_seq.txt</SEQ_FILE_SUFFIX>
+ <SIG_FILE_SUFFIX_DEPHASED>_sig2.txt</SIG_FILE_SUFFIX_DEPHASED>
+ <SIG_FILE_SUFFIX_NOT_DEPHASED>_sig.txt</SIG_FILE_SUFFIX_NOT_DEPHASED>
+ <SMT_FILTER>chastity</SMT_FILTER>
+ <SMT_RELATION>ge</SMT_RELATION>
+ <SMT_THRESHOLD>0.6</SMT_THRESHOLD>
+ <SOFTWARE_VERSION>@(#) Id: GERALD.pl,v 1.171 2008/05/19 17:36:14 mzerara Exp</SOFTWARE_VERSION>
+ <SRF_2ND_CYCLE></SRF_2ND_CYCLE>
+ <SRF_ARCHIVE_REQUIRED></SRF_ARCHIVE_REQUIRED>
+ <SRF_CHASTITY>0.6</SRF_CHASTITY>
+ <SRF_FILE_SUFFIX>_traces.srf</SRF_FILE_SUFFIX>
+ <SRF_PROCESSED>-P</SRF_PROCESSED>
+ <SRF_QCAL></SRF_QCAL>
+ <SRF_RAW>-R</SRF_RAW>
+ <TILE_REGEX>s_[1-8]_[0-9][0-9][0-9][0-9]</TILE_REGEX>
+ <TILE_ROOT>s</TILE_ROOT>
+ <TIME_STAMP>Sun Feb 22 21:15:59 2009</TIME_STAMP>
+ <TOOLS_DIR>/home/diane/proj/GAPipeline-1.0/Goat/../Gerald</TOOLS_DIR>
+ <USE_BASES>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</USE_BASES>
+ <WEB_DIR_ROOT>http://host.domain.com/yourshare/</WEB_DIR_ROOT>
+</ChipWideRunParameters>
+<LaneSpecificRunParameters>
+ <ANALYSIS>
+ <s_1>eland_extended</s_1>
+ <s_2>eland_extended</s_2>
+ <s_3>eland_extended</s_3>
+ <s_4>eland_extended</s_4>
+ <s_5>eland_extended</s_5>
+ <s_6>eland_extended</s_6>
+ <s_7>eland_extended</s_7>
+ <s_8>eland_extended</s_8>
+ </ANALYSIS>
+ <ELAND_GENOME>
+ <s_1>/g/mm9</s_1>
+ <s_2>/g/mm9</s_2>
+ <s_3>/g/elegans190</s_3>
+ <s_4>/g/arabidopsis01222004</s_4>
+ <s_5>/g/mm9</s_5>
+ <s_6>/g/mm9</s_6>
+ <s_7>/g/mm9</s_7>
+ <s_8>/g/mm9</s_8>
+ </ELAND_GENOME>
+ <QTABLE_PATH>
+ <s_1>s_1$(QTABLE_SUFFIX)</s_1>
+ <s_2>s_2$(QTABLE_SUFFIX)</s_2>
+ <s_3>s_3$(QTABLE_SUFFIX)</s_3>
+ <s_4>s_4$(QTABLE_SUFFIX)</s_4>
+ <s_5>s_5$(QTABLE_SUFFIX)</s_5>
+ <s_6>s_6$(QTABLE_SUFFIX)</s_6>
+ <s_7>s_7$(QTABLE_SUFFIX)</s_7>
+ <s_8>s_8$(QTABLE_SUFFIX)</s_8>
+ </QTABLE_PATH>
+ <QTABLE_REQUIRED>
+ <s_1>1</s_1>
+ <s_2>1</s_2>
+ <s_3>1</s_3>
+ <s_4>1</s_4>
+ <s_5>1</s_5>
+ <s_6>1</s_6>
+ <s_7>1</s_7>
+ <s_8>1</s_8>
+ </QTABLE_REQUIRED>
+ <READ_LENGTH>
+ <s_1>37</s_1>
+ <s_2>37</s_2>
+ <s_3>37</s_3>
+ <s_4>37</s_4>
+ <s_5>37</s_5>
+ <s_6>37</s_6>
+ <s_7>37</s_7>
+ <s_8>37</s_8>
+ </READ_LENGTH>
+ <SRF_2ND_CYCLE>
+ <s_1></s_1>
+ <s_2></s_2>
+ <s_3></s_3>
+ <s_4></s_4>
+ <s_5></s_5>
+ <s_6></s_6>
+ <s_7></s_7>
+ <s_8></s_8>
+ </SRF_2ND_CYCLE>
+ <SRF_ARCHIVE_REQUIRED>
+ <s_1></s_1>
+ <s_2></s_2>
+ <s_3></s_3>
+ <s_4></s_4>
+ <s_5></s_5>
+ <s_6></s_6>
+ <s_7></s_7>
+ <s_8></s_8>
+ </SRF_ARCHIVE_REQUIRED>
+ <USE_BASES>
+ <s_1>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_1>
+ <s_2>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_2>
+ <s_3>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_3>
+ <s_4>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_4>
+ <s_5>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_5>
+ <s_6>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_6>
+ <s_7>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_7>
+ <s_8>YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY</s_8>
+ </USE_BASES>
+</LaneSpecificRunParameters>
+</RunParameters>
--- /dev/null
+#
+# The Alphanum Algorithm is an improved sorting algorithm for strings
+# containing numbers. Instead of sorting numbers in ASCII order like
+# a standard sort, this algorithm sorts numbers in numeric order.
+#
+# The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
+#
+#* Python implementation provided by Chris Hulan (chris.hulan@gmail.com)
+#* Distributed under same license as original
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+import re
+import types
+
+#
+# TODO: Make decimal points be considered in the same class as digits
+#
+
+def chunkify(str):
+ """
+ return a list of numbers and non-numeric substrings of +str+
+ the numeric substrings are converted to integer, non-numeric are left as is
+ """
+ if type(str) in types.StringTypes:
+ chunks = re.findall("(\d+|\D+)",str)
+ #convert numeric strings to numbers
+ chunks = [re.match('\d',x) and int(x) or x for x in chunks]
+ return chunks
+ elif type(str) in [types.IntType, types.LongType, types.FloatType]:
+ return [str]
+ else:
+ raise ValueError("Unsupported type %s for input %s" % (type(str), str))
+
+def alphanum(a,b):
+ """
+ breaks +a+ and +b+ into pieces and returns left-to-right comparison of the pieces
+
+ +a+ and +b+ are expected to be strings (for example file names) with numbers and non-numeric characters
+ Split the values into list of numbers and non numeric sub-strings and so comparison of numbers gives
+ Numeric sorting, comparison of non-numeric gives Lexicographic order
+ """
+ # split strings into chunks
+ aChunks = chunkify(a)
+ bChunks = chunkify(b)
+
+ return cmp(aChunks,bChunks) #built in comparison works once data is prepared
+
+
+
+if __name__ == "__main__":
+ unsorted = ["1000X Radonius Maximus","10X Radonius","200X Radonius","20X Radonius","20X Radonius Prime","30X Radonius","40X Radonius","Allegia 50 Clasteron","Allegia 500 Clasteron","Allegia 51 Clasteron","Allegia 51B Clasteron","Allegia 52 Clasteron","Allegia 60 Clasteron","Alpha 100","Alpha 2","Alpha 200","Alpha 2A","Alpha 2A-8000","Alpha 2A-900","Callisto Morphamax","Callisto Morphamax 500","Callisto Morphamax 5000","Callisto Morphamax 600","Callisto Morphamax 700","Callisto Morphamax 7000","Callisto Morphamax 7000 SE","Callisto Morphamax 7000 SE2","QRS-60 Intrinsia Machine","QRS-60F Intrinsia Machine","QRS-62 Intrinsia Machine","QRS-62F Intrinsia Machine","Xiph Xlater 10000","Xiph Xlater 2000","Xiph Xlater 300","Xiph Xlater 40","Xiph Xlater 5","Xiph Xlater 50","Xiph Xlater 500","Xiph Xlater 5000","Xiph Xlater 58"]
+ sorted = unsorted[:]
+ sorted.sort(alphanum)
+ print '+++++Sorted...++++'
+ print '\n'.join(sorted)
--- /dev/null
+"""
+ElementTree helper functions
+"""
+def indent(elem, level=0):
+ """
+ reformat an element tree to be 'pretty' (indented)
+ """
+ i = "\n" + level*" "
+ if len(elem):
+ if not elem.text or not elem.text.strip():
+ elem.text = i + " "
+ for child in elem:
+ indent(child, level+1)
+ # we don't want the closing tag indented too far
+ child.tail = i
+ if not elem.tail or not elem.tail.strip():
+ elem.tail = i
+ else:
+ if level and (not elem.tail or not elem.tail.strip()):
+ elem.tail = i
+
+def flatten(elem, include_tail=0):
+ """
+ Extract the text from an element tree
+ (AKA extract the text that not part of XML tags)
+ """
+ text = elem.text or ""
+ for e in elem:
+ text += flatten(e, 1)
+ if include_tail and elem.tail: text += elem.tail
+ return text
+
--- /dev/null
+"""
+Provide some quick and dirty access and reporting for the fctracker database.
+
+The advantage to this code is that it doesn't depend on django being
+installed, so it can run on machines other than the webserver.
+"""
+import datetime
+import os
+import re
+import sys
+import time
+
+if sys.version_info[0] + sys.version_info[1] * 0.1 >= 2.5:
+ # we're python 2.5
+ import sqlite3
+else:
+ import pysqlite2.dbapi2 as sqlite3
+
+
+class fctracker:
+ """
+ provide a simple way to interact with the flowcell data in fctracker.db
+ """
+ def __init__(self, database):
+ # default to the current directory
+ if database is None:
+ self.database = self._guess_fctracker_path()
+ else:
+ self.database = database
+ self.conn = sqlite3.connect(self.database)
+ self._get_library()
+ self._get_species()
+
+ def _guess_fctracker_path(self):
+ """
+ Guess a few obvious places for the database
+ """
+ fctracker = 'fctracker.db'
+ name = fctracker
+ # is it in the current dir?
+ if os.path.exists(name):
+ return name
+ name = os.path.expanduser(os.path.join('~', fctracker))
+ if os.path.exists(name):
+ return name
+ raise RuntimeError("Can't find fctracker")
+
+ def _make_dict_from_table(self, table_name, pkey_name):
+ """
+ Convert a django table into a dictionary indexed by the primary key.
+ Yes, it really does just load everything into memory, hopefully
+ we stay under a few tens of thousands of runs for a while.
+ """
+ table = {}
+ c = self.conn.cursor()
+ c.execute('select * from %s;' % (table_name))
+ # extract just the field name
+ description = [ f[0] for f in c.description]
+ for row in c:
+ row_dict = dict(zip(description, row))
+ table[row_dict[pkey_name]] = row_dict
+ c.close()
+ return table
+
+ def _add_lanes_to_libraries(self):
+ """
+ add flowcell/lane ids to new attribute 'lanes' in the library dictionary
+ """
+ library_id_re = re.compile('lane_\d_library_id')
+
+ for fc_id, fc in self.flowcells.items():
+ lane_library = [ (x[0][5], x[1]) for x in fc.items()
+ if library_id_re.match(x[0]) ]
+ for lane, library_id in lane_library:
+ if not self.library[library_id].has_key('lanes'):
+ self.library[library_id]['lanes'] = []
+ self.library[library_id]['lanes'].append((fc_id, lane))
+
+ def _get_library(self):
+ """
+ attach the library dictionary to the instance
+ """
+ self.library = self._make_dict_from_table(
+ 'samples_library',
+ 'id')
+
+
+ def _get_species(self):
+ """
+ attach the species dictionary to the instance
+ """
+ self.species = self._make_dict_from_table(
+ 'samples_species',
+ 'id'
+ )
+
+ def _get_flowcells(self, where=None):
+ """
+ attach the flowcell dictionary to the instance
+
+ where is a sql where clause. (eg "where run_date > '2008-1-1'")
+ that can be used to limit what flowcells we select
+ FIXME: please add sanitization code
+ """
+ if where is None:
+ where = ""
+ self.flowcells = {}
+ c = self.conn.cursor()
+ c.execute('select * from experiments_flowcell %s;' % (where))
+ # extract just the field name
+ description = [ f[0] for f in c.description ]
+ for row in c:
+ row_dict = dict(zip(description, row))
+ fcid, status = self._parse_flowcell_id(row_dict)
+ row_dict['flowcell_id'] = fcid
+ row_dict['flowcell_status'] = status
+
+ for lane in [ 'lane_%d_library' % (i) for i in range(1,9) ]:
+ lane_library = self.library[row_dict[lane+"_id"]]
+ species_id = lane_library['library_species_id']
+ lane_library['library_species'] = self.species[species_id]
+ row_dict[lane] = lane_library
+ # some useful parsing
+ run_date = time.strptime(row_dict['run_date'], '%Y-%m-%d %H:%M:%S')
+ run_date = datetime.datetime(*run_date[:6])
+ row_dict['run_date'] = run_date
+ self.flowcells[row_dict['flowcell_id']] = row_dict
+
+ self._add_lanes_to_libraries()
+ return self.flowcells
+
+ def _parse_flowcell_id(self, flowcell_row):
+ """
+ Return flowcell id and status
+
+ We stored the status information in the flowcell id name.
+ this was dumb, but database schemas are hard to update.
+ """
+ fields = flowcell_row['flowcell_id'].split()
+ fcid = None
+ status = None
+ if len(fields) > 0:
+ fcid = fields[0]
+ if len(fields) > 1:
+ status = fields[1]
+ return fcid, status
+
+
+def flowcell_gone(cell):
+ """
+ Use a variety of heuristics to determine if the flowcell drive
+ has been deleted.
+ """
+ status = cell['flowcell_status']
+ if status is None:
+ return False
+ failures = ['failed', 'deleted', 'not run']
+ for f in failures:
+ if re.search(f, status):
+ return True
+ else:
+ return False
+
+def recoverable_drive_report(flowcells):
+ """
+ Attempt to report what flowcells are still on a hard drive
+ """
+ def format_status(status):
+ if status is None:
+ return ""
+ else:
+ return status+" "
+
+ # sort flowcells by run date
+ flowcell_list = []
+ for key, cell in flowcells.items():
+ flowcell_list.append( (cell['run_date'], key) )
+ flowcell_list.sort()
+
+ report = []
+ line = "%(date)s %(id)s %(status)s%(lane)s %(library_name)s (%(library_id)s) "
+ line += "%(species)s"
+ for run_date, flowcell_id in flowcell_list:
+ cell = flowcells[flowcell_id]
+ if flowcell_gone(cell):
+ continue
+ for l in range(1,9):
+ lane = 'lane_%d' % (l)
+ cell_library = cell['%s_library'%(lane)]
+ fields = {
+ 'date': cell['run_date'].strftime('%y-%b-%d'),
+ 'id': cell['flowcell_id'],
+ 'lane': l,
+ 'library_name': cell_library['library_name'],
+ 'library_id': cell['%s_library_id'%(lane)],
+ 'species': cell_library['library_species']['scientific_name'],
+ 'status': format_status(cell['flowcell_status']),
+ }
+ report.append(line % (fields))
+ return os.linesep.join(report)
+
--- /dev/null
+import os
+
+#try:
+import py_sg
+#except:
+# print 'ERROR: Please install py_sg (easy_install py_sg)'
+
+
+def get_hd_serial_num(device):
+ """
+ device = '/dev/sdX'
+
+ returns hard drive serial number for a device; requires read permissions.
+ """
+ fd = os.open(device, os.O_RDONLY)
+
+ # fd: device object
+ # \x12: INQUIRY CMD; \x01: EVPD bit set to 1; \x80: Unit Serial Number page
+ # See http://en.wikipedia.org/wiki/SCSI_Inquiry_Command for helpful chart
+ # ##: # byte buffer for returned data
+ data = py_sg.read(fd, "\x12\x01\x80", 32)
+
+ # Remove extra \x00's, and split remaining data into two chunks,
+ # the 2nd of which is the serial number
+ return data.strip('\x00').split()[1]
--- /dev/null
+"""
+Utility functions to make bedfiles.
+"""
+import os
+import re
+
+__docformat__ = "restructredtext en"
+
+# map eland_result.txt sense
+sense_map = { 'F': '+', 'R': '-'}
+sense_color = { 'F': '0,0,255', 'R': '255,255,0' }
+
+def create_bed_header(name, description):
+ """
+ Produce the headerline for a bedfile
+ """
+ # provide default track names
+ if name is None: name = "track"
+ if description is None: description = "eland result file"
+ bed_header = 'track name="%s" description="%s" visibility=4 itemRgb="ON"' % (name, description)
+ bed_header += os.linesep
+ return bed_header
+
+def make_bed_from_eland_stream(instream, outstream, name, description, chromosome_prefix='chr'):
+ """
+ read an eland result file from instream and write a bedfile to outstream
+
+ :Parameters:
+ - `instream`: stream containing the output from eland
+ - `outstream`: stream to write the bed file too
+ - `name`: name of bed-file (must be unique)
+ - `description`: longer description of the bed file
+ - `chromosome_prefix`: restrict output lines to fasta records that start with this pattern
+ """
+ for line in make_bed_from_eland_generator(instream, name, description, chromosome_prefix):
+ outstream.write(line)
+
+def make_bed_from_eland_generator(instream, name, description, chromosome_prefix='chr'):
+ """
+ read an eland result file from instream and write a bedfile to outstream
+
+ :Parameters:
+ - `instream`: stream containing the output from eland
+ - `name`: name of bed-file (must be unique)
+ - `description`: longer description of the bed file
+ - `chromosome_prefix`: restrict output lines to fasta records that start with this pattern
+
+ :Return: generator which yields lines of bedfile
+ """
+ # indexes into fields in eland_result.txt file
+ SEQ = 1
+ CHR = 6
+ START = 7
+ SENSE = 8
+
+ yield create_bed_header(name, description)
+ prefix_len = len(chromosome_prefix)
+
+ for line in instream:
+ fields = line.split()
+ # we need more than the CHR field, and it needs to match a chromosome
+ if len(fields) <= CHR or fields[CHR][:prefix_len] != chromosome_prefix:
+ continue
+ start = fields[START]
+ stop = int(start) + len(fields[SEQ])
+ # strip off filename extension
+ chromosome = fields[CHR].split('.')[0]
+
+ yield '%s %s %d read 0 %s - - %s%s' % (
+ chromosome,
+ start,
+ stop,
+ sense_map[fields[SENSE]],
+ sense_color[fields[SENSE]],
+ os.linesep
+ )
+
+def make_bed_from_multi_eland_stream(
+ instream,
+ outstream,
+ name,
+ description,
+ chr_prefix='chr',
+ max_reads=255
+ ):
+ """
+ read a multi eland result file from instream and write the bedfile to outstream
+
+ :Parameters:
+ - `instream`: stream containing the output from eland
+ - `outstream`: stream to write the bed file too
+ - `name`: name of bed-file (must be unique)
+ - `description`: longer description of the bed file
+ - `chromosome_prefix`: restrict output lines to fasta records that start with this pattern
+ - `max_reads`: maximum number of reads to write to bed stream
+ """
+ for lane in make_bed_from_multi_eland_generator(instream, name, description, chr_prefix, max_reads):
+ outstream.write(lane)
+
+def make_bed_from_multi_eland_generator(instream, name, description, chr_prefix, max_reads=255):
+ loc_pattern = '(?P<fullloc>(?P<start>[0-9]+)(?P<dir>[FR])(?P<count>[0-9]+))'
+ other_pattern = '(?P<chr>[^:,]+)'
+ split_re = re.compile('(%s|%s)' % (loc_pattern, other_pattern))
+
+ yield create_bed_header(name, description)
+ for line in instream:
+ rec = line.split()
+ if len(rec) > 3:
+ # colony_id = rec[0]
+ seq = rec[1]
+ # number of matches for 0, 1, and 2 mismatches
+ # m0, m1, m2 = [int(x) for x in rec[2].split(':')]
+ compressed_reads = rec[3]
+ cur_chr = ""
+ reads = {0: [], 1: [], 2:[]}
+
+ for token in split_re.finditer(compressed_reads):
+ if token.group('chr') is not None:
+ cur_chr = token.group('chr')
+ # strip off extension if present
+ cur_chr = os.path.splitext(cur_chr)[0]
+ elif token.group('fullloc') is not None:
+ matches = int(token.group('count'))
+ # only emit a bed line if
+ # our current chromosome starts with chromosome pattern
+ if chr_prefix is None or cur_chr.startswith(chr_prefix):
+ start = int(token.group('start'))
+ stop = start + len(seq)
+ orientation = token.group('dir')
+ strand = sense_map[orientation]
+ color = sense_color[orientation]
+ # build up list of reads for this record
+ reads[matches].append((cur_chr, start, stop, strand, color))
+
+ # report up to our max_read threshold reporting the fewer-mismatch
+ # matches first
+ reported_reads = 0
+ keys = [0,1,2]
+ for mismatch, read_list in ((k, reads[k]) for k in keys):
+ reported_reads += len(read_list)
+ if reported_reads <= max_reads:
+ for cur_chr, start, stop, strand, color in read_list:
+ reported_reads += 1
+ yield '%s %d %d read 0 %s - - %s%s' % (
+ cur_chr,
+ start,
+ stop,
+ sense_map[orientation],
+ sense_color[orientation],
+ os.linesep
+ )
+
+def make_description(flowcell_id, lane):
+ """
+ compute a bedfile name and description from the django database
+ """
+ from htsworkflow.frontend.experiments import models as experiments
+
+ lane = int(lane)
+ if lane < 1 or lane > 8:
+ raise RuntimeError("flowcells only have lanes 1-8")
+
+ cell = experiments.FlowCell.objects.get(flowcell_id=flowcell_id)
+
+ name = "%s-%s" % (flowcell_id, lane)
+
+ cell_library = getattr(cell, 'lane_%d_library' %(lane,))
+ cell_library_id = cell_library.library_id
+ description = "%s-%s" % (cell_library.library_name, cell_library_id)
+ return name, description
--- /dev/null
+"""
+Utilities for working with unix-style mounts.
+"""
+import os
+import subprocess
+
+def list_mount_points():
+ """
+ Return list of current mount points
+
+ Note: unix-like OS specific
+ """
+ mount_points = []
+ likely_locations = ['/sbin/mount', '/bin/mount']
+ for mount in likely_locations:
+ if os.path.exists(mount):
+ p = subprocess.Popen(mount, stdout=subprocess.PIPE)
+ p.wait()
+ for l in p.stdout.readlines():
+ rec = l.split()
+ device = rec[0]
+ mount_point = rec[2]
+ assert rec[1] == 'on'
+ # looking at the output of mount on linux, osx, and
+ # sunos, the first 3 elements are always the same
+ # devicename on path
+ # everything after that displays the attributes
+ # of the mount points in wildly differing formats
+ mount_points.append(mount_point)
+ return mount_points
+ else:
+ raise RuntimeError("Couldn't find a mount executable")
+
+def is_mounted(point_to_check):
+ """
+ Return true if argument exactly matches a current mount point.
+ """
+ for mount_point in list_mount_points():
+ if point_to_check == mount_point:
+ return True
+ else:
+ return False
+
+def find_mount_point_for(pathname):
+ """
+ Find the deepest mount point pathname is located on
+ """
+ realpath = os.path.realpath(pathname)
+ mount_points = list_mount_points()
+
+ prefixes = set()
+ for current_mount in mount_points:
+ cp = os.path.commonprefix([current_mount, realpath])
+ prefixes.add((len(cp), cp))
+
+ prefixes = list(prefixes)
+ prefixes.sort()
+ if len(prefixes) == 0:
+ return None
+ else:
+ # return longest common prefix
+ return prefixes[-1][1]
+
+
--- /dev/null
+"""
+Helpful utilities for turning random names/objects into streams.
+"""
+import os
+import gzip
+import bz2
+import types
+import urllib2
+
+def isfilelike(file_ref, mode):
+ """Does file_ref have the core file operations?
+ """
+ # if mode is w/a check to make sure we writeable ops
+ # but always check to see if we can read
+ read_operations = ['read', 'readline', 'readlines']
+ write_operations = [ 'write', 'writelines' ]
+ #random_operations = [ 'seek', 'tell' ]
+ if mode[0] in ('w', 'a'):
+ for o in write_operations:
+ if not hasattr(file_ref, o):
+ return False
+ for o in read_operations:
+ if not hasattr(file_ref, o):
+ return False
+
+ return True
+
+def isurllike(file_ref, mode):
+ """
+ does file_ref look like a url?
+ (AKA does it start with protocol:// ?)
+ """
+ #what if mode is 'w'?
+ parsed = urllib2.urlparse.urlparse(file_ref)
+ schema, netloc, path, params, query, fragment = parsed
+
+ return len(schema) > 0
+
+def autoopen(file_ref, mode='r'):
+ """
+ Attempt to intelligently turn file_ref into a readable stream
+ """
+ # catch being passed a file
+ if type(file_ref) is types.FileType:
+ return file_ref
+ # does it look like a file?
+ elif isfilelike(file_ref, mode):
+ return file_ref
+ elif isurllike(file_ref, mode):
+ return urllib2.urlopen(file_ref)
+ elif os.path.splitext(file_ref)[1] == ".gz":
+ return gzip.open(file_ref, mode)
+ elif os.path.splitext(file_ref)[1] == '.bz2':
+ return bz2.BZ2File(file_ref, mode)
+ else:
+ return open(file_ref,mode)
+
--- /dev/null
+"""
+Run up to N simultanous jobs from provided of commands
+"""
+
+import logging
+import os
+from subprocess import PIPE
+import subprocess
+import select
+import sys
+import time
+
+class QueueCommands(object):
+ """
+ Queue up N commands from cmd_list, launching more jobs as the first
+ finish.
+ """
+
+ def __init__(self, cmd_list, N=0, cwd=None, env=None):
+ """
+ cmd_list is a list of elements suitable for subprocess
+ N is the number of simultanious processes to run.
+ 0 is all of them.
+
+ WARNING: this will not work on windows
+ (It depends on being able to pass local file descriptors to the
+ select call with isn't supported by the Win32 API)
+ """
+ self.to_run = cmd_list[:]
+ self.running = {}
+ self.N = N
+ self.cwd = cwd
+ self.env = env
+
+ def under_process_limit(self):
+ """
+ are we still under the total number of allowable jobs?
+ """
+ if self.N == 0:
+ return True
+
+ if len(self.running) < self.N:
+ return True
+
+ return False
+
+ def start_jobs(self):
+ """
+ Launch jobs until we have the maximum allowable running
+ (or have run out of jobs)
+ """
+ queue_log = logging.getLogger('queue')
+
+ while (len(self.to_run) > 0) and self.under_process_limit():
+ queue_log.info('%d left to run', len(self.to_run))
+ cmd = self.to_run.pop(0)
+ p = subprocess.Popen(cmd,
+ stdout=PIPE,
+ shell=True,
+ cwd=self.cwd,
+ env=self.env)
+ self.running[p.stdout] = p
+ queue_log.info("Created process %d from %s" % (p.pid, str(cmd)))
+
+ def run(self):
+ """
+ run up to N jobs until we run out of jobs
+ """
+ queue_log = logging.getLogger('queue')
+ queue_log.debug('using %s as cwd' % (self.cwd,))
+
+ # to_run slowly gets consumed by start_jobs
+ while len(self.to_run) > 0 or len(self.running) > 0:
+ # fill any empty spots in our job queue
+ self.start_jobs()
+
+ # build a list of file descriptors
+ # fds=file desciptors
+ fds = [ x.stdout for x in self.running.values()]
+
+ # wait for something to finish
+ # wl= write list, xl=exception list (not used so get bad names)
+ read_list, wl, xl = select.select(fds, [], fds, 1 )
+
+ # for everything that might have finished...
+ for pending_fd in read_list:
+ pending = self.running[pending_fd]
+ # if it really did finish, remove it from running jobs
+ if pending.poll() is not None:
+ queue_log.info("Process %d finished [%d]",
+ pending.pid, pending.returncode)
+ del self.running[pending_fd]
+ else:
+ # It's still running, but there's some output
+ buffer = pending_fd.readline()
+ buffer = buffer.strip()
+ msg = "%d:(%d) %s" %(pending.pid, len(buffer), buffer)
+ logging.debug(msg)
+ time.sleep(1)
--- /dev/null
+import copy
+import os
+import unittest
+
+from htsworkflow.util.alphanum import alphanum
+
+class testAlphanum(unittest.TestCase):
+ def test_string(self):
+ unsorted = ['z5', 'b3', 'b10', 'a001', 'a2']
+ sorted = [ 'a001', 'a2', 'b3', 'b10', 'z5']
+ scratch = copy.copy(unsorted)
+ scratch.sort(alphanum)
+
+ for i in xrange(len(scratch)):
+ self.failIfEqual(scratch[i], unsorted[i])
+ for i in xrange(len(scratch)):
+ self.failUnlessEqual(scratch[i], sorted[i])
+
+ def test_numbers(self):
+ unsorted = [5,7,10,18,-1,3]
+ sorted = [-1,3,5,7,10,18]
+ scratch = copy.copy(unsorted)
+ scratch.sort(alphanum)
+
+ for i in xrange(len(scratch)):
+ self.failIfEqual(scratch[i], unsorted[i])
+ for i in xrange(len(scratch)):
+ self.failUnlessEqual(scratch[i], sorted[i])
+
+
+def suite():
+ return unittest.makeSuite(testAlphanum, 'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest='suite')
+
+
+
+
--- /dev/null
+import os
+import unittest
+
+try:
+ from xml.etree import ElementTree
+except ImportError, e:
+ from elementtree import ElementTree
+
+from htsworkflow.util.ethelp import indent, flatten
+
+class testETHelper(unittest.TestCase):
+ def setUp(self):
+ self.foo = '<foo><bar>asdf</bar><br/></foo>'
+ self.foo_tree = ElementTree.fromstring(self.foo)
+
+ def test_indent(self):
+ flat_foo = ElementTree.tostring(self.foo_tree)
+ self.failUnlessEqual(len(flat_foo.split('\n')), 1)
+
+ indent(self.foo_tree)
+ pretty_foo = ElementTree.tostring(self.foo_tree)
+ self.failUnlessEqual(len(pretty_foo.split('\n')), 5)
+
+ def test_flatten(self):
+ self.failUnless(flatten(self.foo_tree), 'asdf')
+
+def suite():
+ return unittest.makeSuite(testETHelper, 'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest='suite')
+
+
+
+
--- /dev/null
+import os
+from StringIO import StringIO
+import unittest
+
+from htsworkflow.util import makebed
+
+class testMakeBed(unittest.TestCase):
+ def test_multi_1_0_0_limit_1(self):
+ instream = StringIO('>HWI-EAS229_26_209LVAAXX:7:3:112:383 TCAAATCTTATGCTANGAATCNCAAATTTTCT 1:0:0 mm9_chr13_random.fa:1240R0')
+ out = StringIO()
+
+ out = list(makebed.make_bed_from_multi_eland_generator(instream, 'name', 'description', 'mm9_chr', 1))
+ self.failUnlessEqual(out[1], 'mm9_chr13_random 1240 1272 read 0 - - - 255,255,0\n')
+
+ def test_multi_1_0_0_limit_255(self):
+ instream = StringIO('>HWI-EAS229_26_209LVAAXX:7:3:112:383 TCAAATCTTATGCTANGAATCNCAAATTTTCT 1:0:0 mm9_chr13_random.fa:1240R0')
+ out = StringIO()
+
+ out = list(makebed.make_bed_from_multi_eland_generator(instream, 'name', 'desc', 'mm9_chr', 255))
+ self.failUnlessEqual(out[1], 'mm9_chr13_random 1240 1272 read 0 - - - 255,255,0\n')
+
+
+ def test_multi_2_0_0_limit_1(self):
+ instream = StringIO('>HWI-EAS229_26_209LVAAXX:7:3:104:586 GTTCTCGCATAAACTNACTCTNAATAGATTCA 2:0:0 mm9_chr4.fa:42995432F0,mm9_chrX.fa:101541458F0')
+ out = StringIO()
+
+ out = list(makebed.make_bed_from_multi_eland_generator(instream, 'name', 'desc', 'mm9_chr', 1))
+ self.failUnlessEqual(len(out), 1)
+
+ def test_multi_2_0_0_limit_255(self):
+ instream = StringIO('>HWI-EAS229_26_209LVAAXX:7:3:104:586 GTTCTCGCATAAACTNACTCTNAATAGATTCA 2:0:0 mm9_chr4.fa:42995432F0,mm9_chrX.fa:101541458F0')
+ out = StringIO()
+
+ out = list(makebed.make_bed_from_multi_eland_generator(instream, 'name', 'desc', 'mm9_chr', 255))
+ self.failUnlessEqual(len(out), 3)
+ self.failUnlessEqual(out[1],
+ 'mm9_chr4 42995432 42995464 read 0 + - - 0,0,255\n')
+ self.failUnlessEqual(out[2],
+ 'mm9_chrX 101541458 101541490 read 0 + - - 0,0,255\n')
+
+ def test_multi_0_2_0_limit_1(self):
+ instream = StringIO('>HWI-EAS229_26_209LVAAXX:7:3:115:495 TCTCCCTGAAAAATANAAGTGNTGTTGGTGAG 0:2:1 mm9_chr14.fa:104434729F2,mm9_chr16.fa:63263818R1,mm9_chr2.fa:52265438R1')
+ out = StringIO()
+
+ out = list(makebed.make_bed_from_multi_eland_generator(instream, 'name', 'desc', 'mm9_chr', 1))
+ print out
+ self.failUnlessEqual(len(out), 1)
+
+def suite():
+ return unittest.makeSuite(testMakeBed, 'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest='suite')
+
+
--- /dev/null
+import os
+import logging
+import time
+import unittest
+
+
+from htsworkflow.util.queuecommands import QueueCommands
+
+class testQueueCommands(unittest.TestCase):
+ def setUp(self):
+ logging.basicConfig(level=logging.DEBUG,
+ format='%(asctime)s %(name)-8s %(message)s')
+
+
+
+ def test_unlimited_run_slow(self):
+ """
+ Run everything at once
+ """
+ cmds = ['/bin/sleep 0',
+ '/bin/sleep 1',
+ '/bin/sleep 2',]
+
+ q = QueueCommands(cmds)
+ start = time.time()
+ q.run()
+ end = time.time()-start
+ # we should only take the length of the longest sleep
+ # pity I had to add a 1 second sleep
+ self.failUnless( end > 2.9 and end < 3.1,
+ "took %s seconds, exected ~3" % (end,))
+
+ def test_limited_run_slow(self):
+ """
+ Run a limited number of jobs
+ """
+ cmds = ['/bin/sleep 1',
+ '/bin/sleep 2',
+ '/bin/sleep 3',]
+
+ q = QueueCommands(cmds, 2)
+
+ start = time.time()
+ q.run()
+ end = time.time()-start
+ # pity I had to add a 1 second sleep
+ self.failUnless( end > 5.9 and end < 6.1,
+ "took %s seconds, expected ~6" % (end,))
+
+def suite():
+ return unittest.makeSuite(testQueueCommands, 'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest='suite')
+
+
+
+
--- /dev/null
+#!/usr/bin/env python
+import os
+import sys
+import re
+from htsworkflow.pipelines.configure_run import *
+from htsworkflow.pipelines import retrieve_config as _rc
+from htsworkflow.pipelines.run_status import startCmdLineStatusMonitor
+
+s_fc = re.compile('FC[0-9]+')
+
+#Turn on built-in command-line parsing.
+_rc.DISABLE_CMDLINE = False
+
+GENOME_DIR = '/data-store01/compbio/genomes/'
+
+
+
+def main(args=None):
+ ci = ConfigInfo()
+ ci.analysis_dir = os.getcwd()
+ ci.base_analysis_dir, junk = os.path.split(ci.analysis_dir)
+
+ #FIXME: make a better command line tool
+ skip_retrieve_config = False
+ if len(args) == 1:
+ arg = args[0]
+
+ #If FC##### found
+ if s_fc.search(arg):
+ cfg_filepath = os.path.abspath('config32auto.txt')
+ flowcell = arg
+ #else, config file provide
+ else:
+ cfg_filepath = os.path.abspath(args[0])
+ skip_retrieve_config = True
+ else:
+ print "usage:\n" \
+ " configure_pipeline FC#####\n" \
+ " or:\n" \
+ " configure_pipeline <conf_filepath>\n"
+ return 3
+
+ genome_dir = GENOME_DIR
+
+ if not skip_retrieve_config:
+ status_retrieve_cfg = retrieve_config(ci, flowcell, cfg_filepath, genome_dir)
+ if status_retrieve_cfg:
+ print "Retrieve config file successful"
+ else:
+ print "Failed to retrieve config file"
+ else:
+ print "Config file %s provided from command-line" % (cfg_filepath)
+ ci.config_filepath = cfg_filepath
+ status_retrieve_cfg = True
+
+ if status_retrieve_cfg:
+ status = configure(ci)
+ if status:
+ print "Configure success"
+ else:
+ print "Configure failed"
+
+ print 'Run Dir:', ci.run_path
+ print 'Bustard Dir:', ci.bustard_path
+
+ if status:
+ # Setup status cmdline status monitor
+ startCmdLineStatusMonitor(ci)
+
+ print 'Running pipeline now!'
+ run_status = run_pipeline(ci)
+ if run_status is True:
+ print 'Pipeline ran successfully.'
+ return 0
+ else:
+ print 'Pipeline run failed.'
+ return 1
+
+ return 2
+
+if __name__ == "__main__":
+ logging.basicConfig(level=logging.DEBUG,
+ format='%(asctime)s %(levelname)-8s %(message)s',
+ datefmt='%a, %d %b %Y %H:%M:%S',
+ #filename='pipeline_main.log',
+ filemode='w')
+
+ sys.exit(main(sys.argv[1:]))
--- /dev/null
+#!/usr/bin/env python
+import sys
+from htsworkflow.automation.copier import main
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
--- /dev/null
+#!/usr/bin/env python
+import optparse
+import os
+import sys
+
+from htsworkflow.pipelines.eland import extract_eland_sequence
+
+def make_parser():
+ usage = "usage: %prog [options] infile [outfile]"
+
+ parser = optparse.OptionParser(usage)
+ parser.add_option("-e", "--extract", dest="slice",
+ default=":",
+ help="provide a python slice operator to select a portion of an eland file")
+ return parser
+
+def main(argv):
+ parser = make_parser()
+
+ (opt, args) = parser.parse_args(argv)
+
+ if len(args) not in (0, 1, 2):
+ parser.error('incorrect number of arguments')
+
+ # get our slice coordinates
+ start, end = opt.slice.split(':')
+ if len(start) > 0:
+ start = int(start)
+ else:
+ start = None
+ if len(end) > 0:
+ end = int(end)
+ else:
+ end = None
+
+ # open infile
+ if len(args) > 0:
+ instream = open(args[0],'r')
+ else:
+ instream = sys.stdin
+
+ if len(args) > 1:
+ outstream = open(args[1],'w')
+ else:
+ outstream = sys.stdout
+
+ extract_eland_sequence(instream, outstream, start, end)
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
+
--- /dev/null
+#!/usr/bin/python
+"""
+Convert a group of eland_result files from a sequencer run to bed files.
+"""
+from glob import glob
+import logging
+import optparse
+import sys
+import os
+
+from htsworkflow.util.makebed import make_bed_from_eland_stream, make_description
+
+def make_bed_for_gerald(eland_dir, output_dir, prefix, database, flowcell):
+ """
+ convert s_[1-8]_eland_result.txt to corresponding bed files
+ """
+ eland_files = glob(os.path.join(eland_dir, 's_[1-8]_eland_result.txt'))
+ out_files = glob(os.path.join(eland_dir, 's_[1-8]_eland_result.bed'))
+ if len(out_files) > 0:
+ raise RuntimeError("please move old bedfiles")
+
+ logging.info('Processing %s using flowcell id %s' % (eland_dir, flowcell))
+ for pathname in eland_files:
+ path, name = os.path.split(pathname)
+ lane = int(name[2])
+ outname = 's_%d_eland_result.bed' %(lane,)
+ logging.info('Converting lane %d to %s' % (lane, outname))
+
+ outpathname = os.path.join(eland_dir, outname)
+ # look up descriptions
+ bed_name, description = make_description(database, flowcell, lane)
+
+ # open files
+ instream = open(pathname,'r')
+ outstream = open(outpathname,'w')
+
+ make_bed_from_eland_stream(
+ instream, outstream, name, description, prefix
+ )
+
+def make_parser():
+ usage = """%prog: --flowcell <flowcell id> directory_name
+
+directory should contain a set of 8 eland result files named like
+s_[12345678]_eland_result.txt"""
+
+
+ parser = optparse.OptionParser(usage)
+
+ parser.add_option('-o', '--output', dest='output',
+ help="destination directory for our bed files" \
+ "defaults to eland directory",
+ default=None)
+ parser.add_option('--chromosome', dest='prefix',
+ help='Set the chromosome prefix name. defaults to "chr"',
+ default='chr')
+ parser.add_option("--database", dest='database',
+ help="specify location of fctracker database",
+ default=None)
+ parser.add_option("--flowcell", dest='flowcell',
+ help="specify the flowcell id for this run",
+ default=None)
+ parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
+ help='increase verbosity',
+ default=False)
+ return parser
+
+def main(command_line=None):
+ logging.basicConfig(level=logging.WARNING)
+ if command_line is None:
+ command_line = sys.argv[1:]
+
+ parser = make_parser()
+ (opts, args) = parser.parse_args(command_line)
+
+ if len(args) != 1:
+ parser.error('Directory name required')
+
+ eland_dir = args[0]
+ if not os.path.isdir(eland_dir):
+ parser.error('%s must be a directory' % (eland_dir,))
+
+ if opts.flowcell is None:
+ parser.error('Flowcell ID required')
+
+ if opts.verbose:
+ logger = logging.getLogger()
+ logger.setLevel(logging.INFO)
+
+ make_bed_for_gerald(eland_dir, opts.output, opts.prefix, opts.database, opts.flowcell)
+
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
+
--- /dev/null
+"""
+Provide some quick and dirty access and reporting for the fctracker database.
+
+The advantage to this code is that it doesn't depend on django being
+installed, so it can run on machines other than the webserver.
+"""
+from optparse import OptionParser
+import sys
+
+from htsworkflow.util import fctracker
+
+def make_parser():
+ """
+ Make parser
+ """
+ parser = OptionParser()
+ parser.add_option("-d", "--database", dest="database",
+ help="path to the fctracker.db",
+ default=None)
+ parser.add_option("-w", "--where", dest="where",
+ help="add a where clause",
+ default=None)
+ return parser
+
+def main(argv=None):
+ if argv is None:
+ argv = []
+ parser = make_parser()
+
+ opt, args = parser.parse_args(argv)
+
+ fc = fctracker.fctracker(opt.database)
+ cells = fc._get_flowcells(opt.where)
+
+ print fctracker.recoverable_drive_report(cells)
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
--- /dev/null
+#!/usr/bin/python
+"""
+Make a tree of symlinks organized by library id.
+"""
+from ConfigParser import SafeConfigParser
+from glob import glob
+import logging
+from optparse import OptionParser
+import logging
+import os
+import stat
+import sys
+
+from htsworkflow.util import fctracker
+
+def find_lanes(flowcell_dir, flowcell_id, lane):
+ lane_name = "s_%s_eland_*" %(lane)
+ pattern = os.path.join(flowcell_dir, flowcell_id, "*", lane_name)
+ lanes = glob(pattern)
+ return lanes
+
+def make_long_lane_name(flowcell_dir, lane_pathname):
+ """
+ make a name from the eland result file name
+ """
+ if flowcell_dir == lane_pathname[0:len(flowcell_dir)]:
+ subpath = lane_pathname[len(flowcell_dir):]
+ long_name = subpath.replace(os.path.sep, "_")
+ return long_name
+ else:
+ return None
+
+def parse_srf_directory(srf_dir):
+ """
+ search srf_dir for *.srf files
+
+ builds a dictionary indexed by flowcell name.
+ """
+ flowcells = {}
+ srfs = glob(os.path.join(srf_dir,'*.srf'))
+ for pathname in srfs:
+ path, filename = os.path.split(pathname)
+ basename, ext = os.path.splitext(filename)
+ record = basename.split('_')
+ if len(record) != 6:
+ logging.error("Unrecognized srf file: %s expected 6 fields got %d" % (pathname,len(record)))
+ continue
+
+ site = record[0]
+ date = record[1]
+ machine = record[2]
+ runid = record[3]
+ flowcellid = record[4]
+ laneid = record[5]
+
+ desc = "_".join([site,date,machine,runid,flowcellid])
+ flowcells[flowcellid] = desc
+ return flowcells
+
+
+def carefully_make_hardlink(source, destination, dry_run=False):
+ """
+ Make a hard link, failing if a different link already exists
+
+ Checking to see if the link already exists and is
+ the same as the link we want to make.
+ If the link already exists and is different, throw an error.
+ """
+ logging.debug("CHECKING: %s -> %s", source, destination)
+
+ if not os.path.exists(source):
+ logging.warning("%s doesn't exist", source)
+ return
+
+ if os.path.exists(destination):
+ if os.path.samefile(source, destination):
+ logging.debug('SAME: %s -> %s' % (source, destination))
+ return
+ else:
+ raise IOError('%s and %s are different files' % \
+ (source, destination))
+ logging.info('Linking: %s -> %s' % (source, destination))
+
+ if dry_run: return
+
+ os.link(source, destination)
+ os.chmod(destination,
+ stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH )
+
+def link_all_eland_lanes(library_path, flowcell_dir, flowcell_id, lane, dry_run):
+ """
+ find eland files at different alignment lengths
+ and put each of those in the file
+ """
+ lanes = find_lanes(flowcell_dir, flowcell_id, lane)
+ for lane_pathname in lanes:
+ long_name = make_long_lane_name(flowcell_dir,
+ lane_pathname)
+ long_pathname = os.path.join(library_path, long_name)
+ carefully_make_hardlink(lane_pathname,
+ long_pathname,
+ dry_run)
+
+def link_srf_lanes(srf_names, library_path, srf_dir, flowcell_id, lane, dry_run):
+ """
+ Link srf files into our library directories.
+
+ the srf files must be named:
+ <site>_<date>_<machine>_<run>_<flowcellid>_<lane>.srf
+ """
+ srf_basename = srf_names.get(flowcell_id, None)
+ if srf_basename is None:
+ logging.info("srf file for %s was not found", flowcell_id)
+ else:
+ srf_filename = "%s_%s.srf" % (srf_basename, lane)
+ source = os.path.join(srf_dir, srf_filename)
+ destination = os.path.join(library_path, srf_filename)
+ carefully_make_hardlink(source, destination, dry_run)
+
+
+def make_library_tree(fcdb, library_dir, flowcell_dir, srfs_dir,
+ dry_run=False):
+ """
+ Iterate over the library
+ """
+ library_dir = os.path.normpath(library_dir) + os.path.sep
+ flowcell_dir = os.path.normpath(flowcell_dir) + os.path.sep
+ srfs_dir = os.path.normpath(srfs_dir) + os.path.sep
+
+ srf_names = parse_srf_directory(srfs_dir)
+
+ for lib_id, lib in fcdb.library.items():
+ library_path = os.path.join(library_dir, str(lib_id))
+ if not os.path.exists(library_path):
+ os.mkdir(library_path)
+
+ for flowcell_id, lane in lib.get('lanes', []):
+ link_all_eland_lanes(library_path,
+ flowcell_dir,
+ flowcell_id,
+ lane,
+ dry_run)
+
+ link_srf_lanes(srf_names,
+ library_path,
+ srfs_dir,
+ flowcell_id,
+ lane,
+ dry_run)
+
+def make_parser():
+ """
+ Make parser
+ """
+ parser = OptionParser()
+ parser.add_option('-c', '--config', default=None,
+ help='path to a configuration file containing a '
+ 'sequence archive section')
+
+ parser.add_option("--database", dest="database",
+ help="path to the fctracker.db",
+ default=None)
+ parser.add_option('-a', '--sequence-archive', default=None,
+ help='path to where the sequence archive lives')
+ parser.add_option("-w", "--where", dest="where",
+ help="add a where clause",
+ default=None)
+
+ parser.add_option('-v', '--verbose', action='store_true', default=False,
+ help='be more verbose')
+ parser.add_option('-d', '--debug', action='store_true', default=False,
+ help='report everything')
+
+ parser.add_option("--dry-run", dest="dry_run", action="store_true",
+ default=False,
+ help="Don't modify the filesystem")
+ return parser
+
+def main(argv=None):
+ FRONTEND_NAME = 'frontend'
+ SECTION_NAME = 'sequence_archive'
+ DATABASE_OPT = 'database_name'
+ ARCHIVE_OPT = 'archive_path'
+
+ if argv is None:
+ argv = []
+ parser = make_parser()
+
+ # parse command line arguments
+ opt, args = parser.parse_args(argv)
+
+ # setup logging
+ level = logging.WARN
+ if opt.verbose:
+ level = logging.INFO
+ if opt.debug:
+ level = logging.DEBUG
+ logging.basicConfig(level=level)
+
+ # figure out what config file to read
+ config_path = [os.path.expanduser('~/.htsworkflow.ini'),
+ '/etc/htsworkflow.ini']
+ if opt.config is not None:
+ config_path = [opt.config]
+
+ # parse options from config file
+ config_file = SafeConfigParser()
+ config_file.read(config_path)
+
+ # load defaults from config file if not overriden by the command line
+ print opt.database
+ if opt.database is None and \
+ config_file.has_option(FRONTEND_NAME, DATABASE_OPT):
+ opt.database = config_file.get(FRONTEND_NAME, DATABASE_OPT)
+
+ if opt.sequence_archive is None and \
+ config_file.has_option(SECTION_NAME, ARCHIVE_OPT):
+ opt.sequence_archive = config_file.get(SECTION_NAME, ARCHIVE_OPT)
+
+ # complain if critical things are missing
+ if opt.database is None:
+ parser.error('Need location of htsworkflow frontend database')
+
+ if opt.sequence_archive is None:
+ parser.error('Need the root path for the sequence archive')
+
+ fcdb = fctracker.fctracker(opt.database)
+ cells = fcdb._get_flowcells(opt.where)
+
+ library_dir = os.path.join(opt.sequence_archive, 'libraries')
+ flowcell_dir = os.path.join(opt.sequence_archive, 'flowcells')
+ srfs_dir = os.path.join(opt.sequence_archive, 'srfs')
+ make_library_tree(fcdb,
+ library_dir, flowcell_dir, srfs_dir,
+ opt.dry_run)
+
+ return 0
+
+if __name__ == "__main__":
+ rv = main(sys.argv[1:])
+ # sys.exit(rv)
--- /dev/null
+#!/usr/bin/python
+import optparse
+import sys
+import os
+
+from htsworkflow.util.opener import autoopen
+from htsworkflow.util.makebed import make_bed_from_eland_stream, make_bed_from_multi_eland_stream, make_description
+
+def make_parser():
+ parser = optparse.OptionParser()
+ parser.add_option('-e', '--eland', dest='inname',
+ help='specify input eland filename')
+ parser.add_option('-b', '--bed', dest='outname',
+ help='specify output befilename')
+ parser.add_option('-n', '--name', dest='name',
+ help='specify the track (short) name.',
+ default=None)
+ parser.add_option('-d', '--description', dest='description',
+ help='specify the track description',
+ default=None)
+ parser.add_option('--chromosome', dest='prefix',
+ help='Set the chromosome prefix name. defaults to "chr"',
+ default='chr')
+ parser.add_option("--database", dest='database',
+ help="specify location of fctracker database",
+ default=None)
+ parser.add_option("--flowcell", dest='flowcell',
+ help="compute name and description from database using flowcell id",
+ default=None)
+ parser.add_option("--lane", dest='lane',
+ help='specify which lane to use when retrieving description from database',
+ default=None)
+
+ multi = optparse.OptionGroup(parser, 'Multi-read ELAND support')
+
+ multi.add_option('-m', '--multi', action='store_true',
+ help='Enable parsing multi-read eland files',
+ default=False)
+ multi.add_option('--reads', type='int',
+ help='limit reporting multi reads to this many reads'
+ '(most usefully --reads=1 will turn a multi-read '
+ 'file into a single read file)',
+ default=255)
+ parser.add_option_group(multi)
+
+ return parser
+
+def main(command_line=None):
+ instream = None
+ outstream = None
+
+ if command_line is None:
+ command_line = sys.argv[1:]
+
+ parser = make_parser()
+ (options, args) = parser.parse_args(command_line)
+
+ if options.inname is None:
+ parser.error("Need eland input file name")
+ return 1
+
+ if options.inname == '-':
+ instream = sys.stdin
+ elif os.path.exists(options.inname):
+ instream = autoopen(options.inname, 'r')
+ else:
+ parser.error('%s was not found' % (options.inname))
+ return 1
+
+ # figure out name for output file
+ if options.outname is None:
+ # if outname wasn't defined, and we're reading from stdout
+ if instream is sys.stdin:
+ # write to stdout
+ outstream = sys.stdout
+ else:
+ # if there's a name write to name.bed
+ options.outname = os.path.splitext(options.inname)[0]+'.bed'
+ print >>sys.stderr, "defaulting to outputname", options.outname
+ elif options.outname == '-':
+ outstream = sys.stdout
+
+ if outstream is None:
+ if os.path.exists(options.outname):
+ parser.error("not overwriting %s" % (options.outname))
+ return 1
+ else:
+ outstream = open(options.outname, 'w')
+
+ if options.flowcell is not None and options.lane is not None:
+ # get our name/description out of the database
+ name, description = make_description(
+ options.database, options.flowcell, options.lane
+ )
+ else:
+ name = options.name
+ description = options.description
+
+ if options.multi:
+ make_bed_from_multi_eland_stream(instream, outstream,
+ name, description,
+ options.prefix,
+ options.reads)
+
+ else:
+ make_bed_from_eland_stream(instream, outstream,
+ name, description,
+ options.prefix)
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
+
--- /dev/null
+#!/usr/bin/env python
+
+#import os
+#os.environ['DJANGO_SETTINGS_MODULE'] = 'htsworkflow.frontend.settings'
+
+from htsworkflow.util.hdquery import get_hd_serial_num
+from htsworkflow.frontend import settings
+
+#from django.conf import settings
+from optparse import OptionParser
+
+import sys
+import urllib2
+
+
+
+def construct_parser():
+ """
+ """
+ parser = OptionParser("usage: %prog -f <flowcell> -d </dev/sdX> OR\n\t %prog -f <flowcell> -s <dev_serial_num>")
+ parser.add_option("-f", "--flowcell", action="store", type="string", dest="flowcell",
+ help="flowcell being archived")
+ parser.add_option("-d", "--device", action="store", type="string", dest="device",
+ help="device flowcell is being archived to")
+ parser.add_option("-s", "--serial", action="store", type="string", dest="serial",
+ help="serial num. of archive device")
+ parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False)
+
+ return parser
+
+
+def update_db(flowcell, serial, debug=False):
+ """
+ Creates link between flowcell and storage device over http
+ """
+ url = settings.LINK_FLOWCELL_STORAGE_DEVICE_URL+'%s/%s/' % (flowcell, serial)
+
+ req = urllib2.Request(url)
+ try:
+ response = urllib2.urlopen(req)
+ except urllib2.URLError, e:
+ print 'ERROR - HTTP OUTPUT (Return Code: %s); use -v/--verbose for more details.' % (e.code)
+ if debug:
+ print e.read()
+ sys.exit(e.code)
+
+ print "DB Update of %s & %s succeeded" % (flowcell, serial)
+ print response.read()
+
+
+def process_args(parser):
+ """
+ returns flowcell and serial#
+ """
+ options, args = parser.parse_args()
+
+ msg = []
+
+ # Only provide device or serial
+ if options.device is not None and options.serial is not None:
+ print "ERROR: Please only provide --device or --serial.\n" \
+ " The serial number is extracted automatically if the device is provided."
+ sys.exit(2)
+
+ print 'Flowcell:', options.flowcell
+ print ' Device:', options.device
+ print ' Serial:', options.serial
+
+ if options.flowcell is None:
+ msg.append(" --flowcell required")
+
+ # if device and serial missing:
+ if options.device is None and options.serial is None:
+ msg.append(" --device OR --serial required")
+
+ if len(msg) > 0:
+ print '\n'.join(msg)
+ sys.exit(3)
+
+ # Update db records
+ if options.device is not None:
+ serial = get_hd_serial_num(options.device)
+ update_db(flowcell=options.flowcell, serial=serial, debug=options.verbose)
+ elif options.serial is not None:
+ update_db(flowcell=options.flowcell, serial=options.serial, debug=options.verbose)
+ else:
+ msg ="FATAL should not happen error occured; i.e. the best kind!"
+ raise ValueError, msg
+
+
+
+def main():
+ """
+ """
+ parser = construct_parser()
+ process_args(parser)
+
+ #print "Database Updated."
+ sys.exit(0)
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python
+
+import logging
+from optparse import OptionParser
+import os
+import subprocess
+import sys
+
+from htsworkflow.pipelines import gerald
+from htsworkflow.pipelines.eland import extract_eland_sequence
+from htsworkflow.pipelines import runfolder
+
+def make_query_filename(eland_obj, output_dir):
+ query_name = '%s_%s_eland_query.txt'
+ query_name %= (eland_obj.sample_name, eland_obj.lane_id)
+
+ query_pathname = os.path.join(output_dir, query_name)
+
+ if os.path.exists(query_pathname):
+ logging.warn("overwriting %s" % (query_pathname,))
+
+ return query_pathname
+
+def make_result_filename(eland_obj, output_dir):
+ result_name = '%s_%s_eland_result.txt'
+ result_name %= (eland_obj.sample_name, eland_obj.lane_id)
+
+ result_pathname = os.path.join(output_dir, result_name)
+
+ if os.path.exists(result_pathname):
+ logging.warn("overwriting %s" % (result_pathname,))
+
+ return result_pathname
+
+def extract_sequence(inpathname, query_pathname, length, dry_run=False):
+ logging.info('extracting %d bases' %(length,))
+ logging.info('extracting from %s' %(inpathname,))
+ logging.info('extracting to %s' %(query_pathname,))
+
+ if not dry_run:
+ try:
+ instream = open(inpathname, 'r')
+ outstream = open(query_pathname, 'w')
+ extract_eland_sequence(instream, outstream, 0, length)
+ finally:
+ outstream.close()
+ instream.close()
+
+def run_eland(length, query_name, genome, result_name, multi=False, dry_run=False):
+ cmdline = ['eland_%d' % (length,), query_name, genome, result_name]
+ if multi:
+ cmdline += ['--multi']
+
+ logging.info('running eland: ' + " ".join(cmdline))
+ if not dry_run:
+ return subprocess.Popen(cmdline)
+ else:
+ return None
+
+
+def rerun(gerald_dir, output_dir, length=25, dry_run=False):
+ """
+ look for eland files in gerald_dir and write a subset to output_dir
+ """
+ logging.info("Extracting %d bp from files in %s" % (length, gerald_dir))
+ g = gerald.gerald(gerald_dir)
+
+ # this will only work if we're only missing the last dir in output_dir
+ if not os.path.exists(output_dir):
+ logging.info("Making %s" %(output_dir,))
+ if not dry_run: os.mkdir(output_dir)
+
+ processes = []
+ for lane_id, lane_param in g.lanes.items():
+ eland = g.eland_results[lane_id]
+
+ inpathname = eland.pathname
+ query_pathname = make_query_filename(eland, output_dir)
+ result_pathname = make_result_filename(eland, output_dir)
+
+ extract_sequence(inpathname, query_pathname, length, dry_run=dry_run)
+
+ p = run_eland(length,
+ query_pathname,
+ lane_param.eland_genome,
+ result_pathname,
+ dry_run=dry_run)
+ if p is not None:
+ processes.append(p)
+
+ for p in processes:
+ p.wait()
+
+def make_parser():
+ usage = '%prog: [options] runfolder'
+
+ parser = OptionParser(usage)
+
+ parser.add_option('--gerald',
+ help='specify location of GERALD directory',
+ default=None)
+ parser.add_option('-o', '--output',
+ help='specify output location of files',
+ default=None)
+ parser.add_option('-l', '--read-length', type='int',
+ help='specify new eland length',
+ dest='length',
+ default=25)
+ parser.add_option('--dry-run', action='store_true',
+ help='only pretend to run',
+ default=False)
+ parser.add_option('-v', '--verbose', action='store_true',
+ help='increase verbosity',
+ default=False)
+
+ return parser
+
+
+def main(cmdline=None):
+ logging.basicConfig(level=logging.WARNING)
+
+ parser = make_parser()
+ opts, args = parser.parse_args(cmdline)
+
+ if opts.length < 16 or opts.length > 32:
+ parser.error("eland can only process reads in the range 16-32")
+
+ if len(args) > 1:
+ parser.error("Can only process one runfolder directory")
+ elif len(args) == 1:
+ runs = runfolder.get_runs(args[0])
+ if len(runs) != 1:
+ parser.error("Not a runfolder")
+ opts.gerald = runs[0].gerald.pathname
+ if opts.output is None:
+ opts.output = os.path.join(
+ runs[0].pathname,
+ 'Data',
+ # pythons 0..n ==> elands 1..n+1
+ 'C1-%d' % (opts.length+1,)
+ )
+
+ elif opts.gerald is None:
+ parser.error("need gerald directory")
+
+ if opts.output is None:
+ parser.error("specify location for the new eland files")
+
+ if opts.verbose:
+ root_logger = logging.getLogger()
+ root_logger.setLevel(logging.INFO)
+
+ rerun(opts.gerald, opts.output, opts.length, dry_run=opts.dry_run)
+
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
--- /dev/null
+#!/usr/bin/env python
+import sys
+from htsworkflow.pipelines.retrieve_config import *
+from htsworkflow.pipelines import retrieve_config
+from htsworkflow.pipelines.genome_mapper import getAvailableGenomes
+from htsworkflow.pipelines.genome_mapper import constructMapperDict
+
+#Turn on built-in command-line parsing.
+retrieve_config.DISABLE_CMDLINE = False
+
+def main(args=None):
+ #Display help if no args are presented
+ if len(sys.argv) == 1:
+ sys.argv.append('-h')
+
+ options = getCombinedOptions()
+ msg_list = ['ERROR MESSAGES:']
+ if options.output_filepath is None:
+ msg_list.append(" Output filepath argument required. -o <filepath> or --output=<filepath>")
+
+ if options.flowcell is None:
+ msg_list.append(" Flow cell argument required. -f <flowcell> or --flowcell=<flowcell>")
+
+ if options.url is None:
+ msg_list.append(" URL argument required (-u <url> or --url=<url>), or entry\n" \
+ " in /etc/ga_frontend/ga_frontend.conf or ~/.ga_frontend.conf")
+ if options.genome_dir is None:
+ msg_list.append(" genome_dir argument required (-g <genome_dir> or \n" \
+ " --genome_dir=<genome_dir>, or entry in \n" \
+ " /etc/ga_frontend/ga_frontend.conf or ~/.ga_frontend.conf")
+
+ if len(msg_list) > 1:
+ print '\n'.join(msg_list)
+ return 1
+
+ saveConfigFile(options.flowcell, options.url, options.output_filepath)
+
+ f = open(options.output_filepath, 'r')
+ data = f.read()
+ f.close()
+
+ genome_dict = getAvailableGenomes(options.genome_dir)
+ mapper_dict = constructMapperDict(genome_dict)
+
+ f = open(options.output_filepath, 'w')
+ f.write(data % (mapper_dict))
+ f.close()
+
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
--- /dev/null
+#!/usr/bin/env python
+"""
+Runfolder.py can generate a xml file capturing all the 'interesting' parameters from a finished pipeline run. (using the -a option). The information currently being captured includes:
+
+ * Flowcell ID
+ * run dates
+ * start/stop cycle numbers
+ * Firecrest, bustard, gerald version numbers
+ * Eland analysis types, and everything in the eland configuration file.
+ * cluster numbers and other values from the Summary.htm
+ LaneSpecificParameters table.
+ * How many reads mapped to a genome from an eland file
+
+The ELAND "mapped reads" counter will also check for eland squashed file
+that were symlinked from another directory. This is so I can track how
+many reads landed on the genome of interest and on the spike ins.
+
+Basically my subdirectories something like:
+
+genomes/hg18
+genomes/hg18/chr*.2bpb <- files for hg18 genome
+genomes/hg18/chr*.vld
+genomes/hg18/VATG.fa.2bp <- symlink to genomes/spikeins
+genomes/spikein
+
+runfolder.py can also spit out a simple summary report (-s option)
+that contains the per lane post filter cluster numbers and the mapped
+read counts. (The report isn't currently very pretty)
+"""
+from glob import glob
+import logging
+import optparse
+import os
+import sys
+
+from htsworkflow.pipelines import runfolder
+from htsworkflow.pipelines.runfolder import ElementTree
+
+def make_parser():
+ usage = 'usage: %prog [options] runfolder_root_dir'
+ parser = optparse.OptionParser(usage)
+
+ parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
+ default=False,
+ help='turn on verbose mode')
+ parser.add_option('--dry-run', action='store_true', default=False,
+ help="Don't delete anything (in clean mode)")
+
+ commands = optparse.OptionGroup(parser, 'Commands')
+
+ commands.add_option('-s', '--summary', dest='summary', action='store_true',
+ default=False,
+ help='produce summary report')
+ commands.add_option('-a', '--archive', dest='archive', action='store_true',
+ default=False,
+ help='generate run configuration archive')
+ commands.add_option('--extract-results', action='store_true',
+ default=False,
+ help='create run-xml summary, compress the eland result files, and '
+ 'copy them and the Summary.htm file into archival directory.')
+ commands.add_option('-c', '--clean', action='store_true', default=False,
+ help='Clean runfolder, preparing it for long-term storage')
+ parser.add_option_group(commands)
+
+ parser.add_option('-o', '--output-dir', default=None,
+ help="specify the default output directory for extract results")
+
+ parser.add_option('-u', '--use-run', dest='use_run', default=None,
+ help='Specify which run to use instead of autoscanning '
+ 'the runfolder. You do this by providing the final '
+ ' GERALD directory, and it assumes the parent '
+ 'directories are the bustard and image processing '
+ 'directories.')
+
+ parser.add_option('--run-xml', dest='run_xml',
+ default=None,
+ help='specify a run_<FlowCell>.xml file for summary reports')
+
+
+ return parser
+
+def main(cmdlist=None):
+ parser = make_parser()
+ opt, args = parser.parse_args(cmdlist)
+
+ logging.basicConfig()
+ if opt.verbose:
+ root_log = logging.getLogger()
+ root_log.setLevel(logging.INFO)
+
+ logging.info('Starting htsworkflow illumina runfolder processing tool.')
+ runs = []
+ if opt.run_xml:
+ # handle ~ shortcut
+ opt.run_xml = os.path.expanduser(opt.run_xml)
+ tree = ElementTree.parse(opt.run_xml).getroot()
+ runs.append(runfolder.PipelineRun(xml=tree))
+
+ # look for manually specified run
+ if opt.use_run is not None:
+ specific_run = runfolder.get_specific_run(opt.use_run)
+ if specific_run is not None:
+ runs.append(specific_run)
+ else:
+ logging.warn("Couldn't find a run in %s" % (opt.use_run,))
+
+ # scan runfolders for runs
+ for run_pattern in args:
+ # expand args on our own if needed
+ for run_dir in glob(run_pattern):
+ runs.extend(runfolder.get_runs(run_dir))
+
+ if len(runs) > 0:
+ command_run = False
+ if opt.summary:
+ print runfolder.summary_report(runs)
+ command_run = True
+ if opt.archive:
+ runfolder.extract_run_parameters(runs)
+ command_run = True
+ if opt.extract_results:
+ runfolder.extract_results(runs, opt.output_dir)
+ command_run = True
+ if opt.clean:
+ runfolder.clean_runs(runs, opt.dry_run)
+ command_run = True
+
+ if command_run == False:
+ print "You need to specify a command."+os.linesep
+ parser.print_help()
+ else:
+ print "You need to specify some run folders to process..."+os.linesep
+ parser.print_help()
+
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
--- /dev/null
+#!/usr/bin/env python
+import sys
+from htsworkflow.automation.runner import main
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
--- /dev/null
+#!/usr/bin/env python
+import sys
+from htsworkflow.automation.spoolwatcher import main
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
--- /dev/null
+#!/usr/bin/python
+
+from glob import glob
+import logging
+import optparse
+import os
+import subprocess
+import sys
+
+from htsworkflow.util import queuecommands
+from htsworkflow.pipelines import runfolder
+
+SOLEXA2SRF = 0
+ILLUMINA2SRF10 = 1
+ILLUMINA2SRF11 = 2
+
+def make_commands(run_name, lanes, site_name, destdir, cmdlevel=ILLUMINA2SRF11):
+ """
+ make a subprocess-friendly list of command line arguments to run solexa2srf
+ generates files like:
+ woldlab:080514_HWI-EAS229_0029_20768AAXX:8.srf
+ site run name lane
+
+ run_name - most of the file name (run folder name is a good choice)
+ lanes - list of integers corresponding to which lanes to process
+ site_name - name of your "sequencing site" or "Individual"
+ destdir - where to write all the srf files
+ """
+ cmd_list = []
+ for lane in lanes:
+ name_prefix = '%s_%%l_%%t_' % (run_name,)
+ destname = '%s_%s_%d.srf' % (site_name, run_name, lane)
+ destdir = os.path.normpath(destdir)
+ dest_path = os.path.join(destdir, destname)
+ seq_pattern = 's_%d_*_seq.txt' % (lane,)
+
+ if cmdlevel == SOLEXA2SRF:
+ cmd = ['solexa2srf',
+ '-N', name_prefix,
+ '-n', '%3x:%3y',
+ '-o', dest_path,
+ seq_pattern]
+ elif cmdlevel == ILLUMINA2SRF10:
+ cmd = ['illumina2srf',
+ '-v1.0',
+ '-o', dest_path,
+ seq_pattern]
+ elif cmdlevel == ILLUMINA2SRF11:
+ seq_pattern = 's_%d_*_qseq.txt' % (lane,)
+ cmd = ['illumina2srf',
+ '-o', dest_path,
+ seq_pattern]
+ else:
+ raise ValueError("Unrecognized run level %d" % (cmdlevel,))
+
+ cmd_list.append(" ".join(cmd))
+ return cmd_list
+
+def pathname_to_run_name(base):
+ """
+ Convert a pathname to a base runfolder name
+ handle the case with a trailing /
+ """
+ name = ""
+ while len(name) == 0:
+ base, name = os.path.split(base)
+ if len(base) == 0:
+ return None
+ return name
+
+def make_parser():
+ usage = '%prog: [options] runfolder -l 1,2,3 [runfolder -l 5,6 ...]'
+
+ parser = optparse.OptionParser(usage)
+ parser.add_option('--dry-run', action='store_true',
+ help='print what would be done',
+ default=False)
+
+ parser.add_option('-d', '--dest-dir', dest='dest_dir',
+ help='location to write srf files to',
+ default='.')
+ parser.add_option('-s', '--site',
+ help='site name',
+ default='Individual')
+ parser.add_option('-l', '--lanes', dest='lanes', action="append",
+ default=[],
+ help='comma seperated list of lanes to add to srf'
+ )
+ parser.add_option('-j', '--jobs', default=1, type='int',
+ help='how many jobs to run simultaneously')
+ parser.add_option('-r', '--runfolder-version', default=ILLUMINA2SRF11, type='int',
+ help='Which class of srf file should we attempt to create\n'
+ '0 = Solexa pipeline 0.2.6 - 0.3\n'
+ '1 = illumina pipeline 1.0\n'
+ '2 = illumina pipeline 1.1rc1 and later \n')
+
+ parser.add_option('-v', '--verbose', dest='verbose',
+ default=False, action='store_true',
+ help='report more about internals (INFO)')
+ parser.add_option('--debug', dest='debug',
+ default=False, action='store_true',
+ help='report even more about internals (DEBUG)')
+
+ return parser
+
+def parse_lane_arg(lane_arg):
+ """
+ Convert comma sperated list of lane ids to a list of integers
+ """
+ lanes = []
+ for lane in lane_arg.split(','):
+ try:
+ lane = int(lane)
+ if lane < 1 or lane > 8:
+ parser.error('Lanes must be in range [1..8]')
+ lanes.append(lane)
+ except ValueError:
+ parser.error('Lane selections must be integers')
+ return lanes
+
+def main(cmdline=None):
+ parser = make_parser()
+ opts, args = parser.parse_args(cmdline)
+
+ if opts.debug:
+ logging.basicConfig(level=logging.DEBUG)
+ elif opts.verbose:
+ logging.basicConfig(level=logging.INFO)
+ else:
+ logging.basicConfig(level=logging.WARNING)
+
+ if len(args) == 0:
+ parser.error('need runfolder arguments')
+
+ # parse lane arguemnts
+ lanes_list = []
+ if len(opts.lanes) == 0:
+ lanes_list = [[1,2,3,4,5,6,7,8]] * len(args)
+ elif len(opts.lanes) == len(args):
+ for lane_arg in opts.lanes:
+ lanes_list.append(parse_lane_arg(lane_arg))
+ else:
+ parser.error(
+ "Number of lane arguments must match number of runfolders"
+ )
+
+ # build list of commands
+ cmds = {}
+ for runfolder_path, lanes in zip(args, lanes_list):
+ # normalize paths, either relative to home dirs or current dir
+ runfolder_path = os.path.abspath(runfolder_path)
+ # the last part of the path should be a runfolder name
+ name = pathname_to_run_name(runfolder_path)
+ # so any bustard directories?
+ runs = runfolder.get_runs(runfolder_path)
+ # give up if there are anything other than 1 run
+ if len(runs) > 1:
+ print 'ERROR: Too many run directories in %s' %(runfolder_path,)
+ return 1
+ elif len(runs) == 1:
+ bustard_dir = runs[0].bustard.pathname
+ cmds[bustard_dir] = make_commands(name, lanes, opts.site, opts.dest_dir, opts.runfolder_version)
+ else:
+ print "ERROR: Couldn't find a bustard directory in", runfolder_path
+ return 1
+
+ if not opts.dry_run:
+ for cwd, cmd_list in cmds.items():
+ curdir = os.getcwd()
+ os.chdir(cwd)
+ q = queuecommands.QueueCommands(cmd_list, opts.jobs)
+ q.run()
+ os.chdir(curdir)
+ else:
+ for cwd, cmd_list in cmds.items():
+ print cwd
+ print cmd_list
+ print 'jobs: ', opts.jobs
+
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
--- /dev/null
+from setuptools import setup
+
+setup(
+ name="htsworkflow",
+ description="some bots and other utilities to help deal with data from an illumina sequencer",
+ author="Diane Trout & Brandon King",
+ author_email="diane@caltech.edu",
+ packages=["htsworkflow",
+ "htsworkflow.pipelines",
+ "htsworkflow.frontend",
+ "htsworkflow.frontend.analysis",
+ "htsworkflow.frontend.eland_config",
+ "htsworkflow.frontend.experiments",
+ "htsworkflow.frontend.inventory",
+ "htsworkflow.frontend.reports",
+ "htsworkflow.frontend.samples",
+ "htsworkflow.automation",
+ "htsworkflow.util"
+ ],
+ scripts=[
+ 'scripts/configure_pipeline',
+ 'scripts/copier',
+ 'scripts/gerald2bed.py',
+ 'scripts/library.py',
+ 'scripts/makebed',
+ 'scripts/rerun_eland.py',
+ 'scripts/retrieve_config',
+ 'scripts/runfolder',
+ 'scripts/runner',
+ 'scripts/spoolwatcher',
+ 'scripts/srf',
+ 'scripts/mark_archived_data'
+ ],
+)
--- /dev/null
+<html>
+ <head>
+ <title>Test Config Form</title>
+ <!--
+ <link rel="stylesheet" type="text/css" href="ext-all.css"/>
+ <script type="text/javascript" src="ext.js"></script>
+ <script type="text/javascript" src="elandifier.js"></script>
+ -->
+ </head>
+ <body>
+ <form method="post" action="">
+ <table>{{ form.as_custom }}</table>
+ <input type="submit" />
+ </form>
+ </body>
+</html>
+
\ No newline at end of file
--- /dev/null
+import unittest
+
+from StringIO import StringIO
+from htsworkflow.automation import copier
+
+class testCopier(unittest.TestCase):
+ def test_runfolder_validate(self):
+ self.failUnlessEqual(copier.runfolder_validate(""), False)
+ self.failUnlessEqual(copier.runfolder_validate("1345_23"), False)
+ self.failUnlessEqual(copier.runfolder_validate("123456_asdf-$23'"), False)
+ self.failUnlessEqual(copier.runfolder_validate("123456_USI-EAS44"), True)
+ self.failUnlessEqual(copier.runfolder_validate("123456_USI-EAS44 "), False)
+
+ def test_empty_config(self):
+ cfg = StringIO("""[fake]
+something: unrelated
+""")
+ bot = copier.CopierBot('fake', configfile=cfg)
+ self.failUnlessRaises(KeyError, bot.read_config)
+
+ def test_full_config(self):
+ cfg = StringIO("""[copier]
+jid: copier@example.fake
+password: badpassword
+authorized_users: user1@example.fake user2@example.fake
+rsync_password_file: ~/.sequencer
+rsync_sources: /tmp/sequencer_source
+rsync_destination: /tmp/sequencer_destination
+notify_users: user3@example.fake
+# who to run to
+#runner:
+""")
+ c = copier.CopierBot("copier", configfile=cfg)
+ c.read_config()
+ c._init_rsync()
+ self.failUnlessEqual(c.jid, 'copier@example.fake')
+ self.failUnlessEqual(c.cfg['password'], 'badpassword')
+ self.failUnlessEqual(len(c.authorized_users), 2)
+ self.failUnlessEqual(c.authorized_users[0], 'user1@example.fake')
+ self.failUnlessEqual(c.authorized_users[1], 'user2@example.fake')
+ self.failUnlessEqual(c.rsync.source_base_list[0],
+ '/tmp/sequencer_source/')
+ self.failUnlessEqual(c.rsync.dest_base, '/tmp/sequencer_destination')
+ self.failUnlessEqual(len(c.notify_users), 1)
+ self.failUnlessEqual(c.notify_users[0], 'user3@example.fake')
+
+ def test_dirlist_filter(self):
+ """
+ test our dir listing parser
+ """
+ # everyone should have a root dir, and since we're not
+ # currently writing files... it should all be good
+ r = copier.rsync('/', '/', '/')
+
+ listing = [
+ 'drwxrwxr-x 0 2007/12/29 12:34:56 071229_USI-EAS229_001_FC1234\n',
+ '-rwxrw-r-- 123268 2007/12/29 17:39:31 2038EAAXX.rtf\n',
+ '-rwxrw-r-- 6 2007/12/29 15:10:29 New Text Document.txt\n',
+ ]
+
+ result = r.list_filter(listing)
+ self.failUnlessEqual(len(result), 1)
+ self.failUnlessEqual(result[0][-1], '4')
+
+def suite():
+ return unittest.makeSuite(testCopier,'test')
+
+if __name__ == "__main__":
+ unittest.main(defaultTest="suite")
--- /dev/null
+#!/usr/bin/env python
+
+"""
+Build a fake directory tree for testing rsync management code.
+"""
+
+import os
+import random
+
+def make_random_string(length=8):
+ """Make a random string, length characters long
+ """
+ symbols = "abcdefhijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ name = []
+ for i in xrange(length):
+ name.append(random.choice(symbols))
+ return "".join(name)
+
+def make_file(pathname):
+ """Make a file with some random stuff in it
+ """
+ stream = open(pathname,'w')
+ stream.write(make_random_string(16))
+ stream.close()
+
+def make_tree(root, depth=3, directories=5, files=10):
+ """
+ Make a tree of random directories and files
+
+ depth is how many levels of subdirectories
+ directories is how many directories each subdirectory should have
+ files is how many files to create in each directory
+ """
+ if not os.path.exists(root):
+ os.mkdir(root)
+
+ paths = []
+ # make files
+ for i in range(files):
+ name = make_random_string()
+ paths.append(name)
+ pathname = os.path.join(root, name)
+ make_file(pathname)
+
+ # make subdirectories if we still have some depth to go
+ if depth > 0:
+ for i in range(directories):
+ name = make_random_string()
+ # paths.append(name)
+ pathname = os.path.join(root, name)
+ subpaths = make_tree(pathname, depth-1, directories, files)
+ paths.extend([ os.path.join(name, x) for x in subpaths ])
+
+ return paths
+
+def generate_paths(root):
+ """Make a list of relative paths like generated by make_tree
+ """
+ paths = []
+ for curdir, subdirs, files in os.walk(root):
+ paths.extend([ os.path.join(curdir, f) for f in files ])
+
+ # an inefficient way of getting the correct common prefix
+ # (e.g. root might not have a trailing /)
+ common_root = os.path.commonprefix(paths)
+ common_len = len(common_root)
+ return [ p[common_len:] for p in paths ]
+
+def compare_tree(root, paths, verbose=False):
+ """Make sure the tree matches our relative list of paths
+ """
+ # what we find when we look
+ experimental_set = set(generate_paths(root))
+ # what we expect
+ theoretical_set = set(paths)
+ # true if the difference of the two sets is the empty set
+ difference = experimental_set - theoretical_set
+ issame = (len(difference) == 0)
+ if verbose and not issame:
+ print difference
+ return issame